1*23b7c7b8SHermès Bélusca-Maïto /*++
2*23b7c7b8SHermès Bélusca-Maïto 
3*23b7c7b8SHermès Bélusca-Maïto Copyright (c) 1989-2000 Microsoft Corporation
4*23b7c7b8SHermès Bélusca-Maïto 
5*23b7c7b8SHermès Bélusca-Maïto Module Name:
6*23b7c7b8SHermès Bélusca-Maïto 
7*23b7c7b8SHermès Bélusca-Maïto     StrucSup.c
8*23b7c7b8SHermès Bélusca-Maïto 
9*23b7c7b8SHermès Bélusca-Maïto Abstract:
10*23b7c7b8SHermès Bélusca-Maïto 
11*23b7c7b8SHermès Bélusca-Maïto     This module implements the Fat in-memory data structure manipulation
12*23b7c7b8SHermès Bélusca-Maïto     routines
13*23b7c7b8SHermès Bélusca-Maïto 
14*23b7c7b8SHermès Bélusca-Maïto 
15*23b7c7b8SHermès Bélusca-Maïto --*/
16*23b7c7b8SHermès Bélusca-Maïto 
17*23b7c7b8SHermès Bélusca-Maïto #include "fatprocs.h"
18*23b7c7b8SHermès Bélusca-Maïto 
19*23b7c7b8SHermès Bélusca-Maïto //
20*23b7c7b8SHermès Bélusca-Maïto //  The Bug check file id for this module
21*23b7c7b8SHermès Bélusca-Maïto //
22*23b7c7b8SHermès Bélusca-Maïto 
23*23b7c7b8SHermès Bélusca-Maïto #define BugCheckFileId                   (FAT_BUG_CHECK_STRUCSUP)
24*23b7c7b8SHermès Bélusca-Maïto 
25*23b7c7b8SHermès Bélusca-Maïto //
26*23b7c7b8SHermès Bélusca-Maïto //  The debug trace level
27*23b7c7b8SHermès Bélusca-Maïto //
28*23b7c7b8SHermès Bélusca-Maïto 
29*23b7c7b8SHermès Bélusca-Maïto #define Dbg                              (DEBUG_TRACE_STRUCSUP)
30*23b7c7b8SHermès Bélusca-Maïto 
31*23b7c7b8SHermès Bélusca-Maïto #define FillMemory(BUF,SIZ,MASK) {                          \
32*23b7c7b8SHermès Bélusca-Maïto     ULONG i;                                                \
33*23b7c7b8SHermès Bélusca-Maïto     for (i = 0; i < (((SIZ)/4) - 1); i += 2) {              \
34*23b7c7b8SHermès Bélusca-Maïto         ((PULONG)(BUF))[i] = (MASK);                        \
35*23b7c7b8SHermès Bélusca-Maïto         ((PULONG)(BUF))[i+1] = (ULONG)PsGetCurrentThread(); \
36*23b7c7b8SHermès Bélusca-Maïto     }                                                       \
37*23b7c7b8SHermès Bélusca-Maïto }
38*23b7c7b8SHermès Bélusca-Maïto 
39*23b7c7b8SHermès Bélusca-Maïto #define IRP_CONTEXT_HEADER (sizeof( IRP_CONTEXT ) * 0x10000 + FAT_NTC_IRP_CONTEXT)
40*23b7c7b8SHermès Bélusca-Maïto 
41*23b7c7b8SHermès Bélusca-Maïto //
42*23b7c7b8SHermès Bélusca-Maïto //  Local macros.
43*23b7c7b8SHermès Bélusca-Maïto //
44*23b7c7b8SHermès Bélusca-Maïto //  Define our lookaside list allocators.  For the time being, and perhaps
45*23b7c7b8SHermès Bélusca-Maïto //  permanently, the paged structures don't come off of lookasides.  This
46*23b7c7b8SHermès Bélusca-Maïto //  is due to complications with clean unload as FAT can be in the paging
47*23b7c7b8SHermès Bélusca-Maïto //  path, making it really hard to find the right time to empty them.
48*23b7c7b8SHermès Bélusca-Maïto //
49*23b7c7b8SHermès Bélusca-Maïto //  Fortunately, the hit rates on the Fcb/Ccb lists weren't stunning.
50*23b7c7b8SHermès Bélusca-Maïto //
51*23b7c7b8SHermès Bélusca-Maïto 
52*23b7c7b8SHermès Bélusca-Maïto #define FAT_FILL_FREE 0
53*23b7c7b8SHermès Bélusca-Maïto 
54*23b7c7b8SHermès Bélusca-Maïto #ifdef __REACTOS__
55*23b7c7b8SHermès Bélusca-Maïto static
56*23b7c7b8SHermès Bélusca-Maïto #endif
57*23b7c7b8SHermès Bélusca-Maïto INLINE
58*23b7c7b8SHermès Bélusca-Maïto PCCB
FatAllocateCcb()59*23b7c7b8SHermès Bélusca-Maïto FatAllocateCcb (
60*23b7c7b8SHermès Bélusca-Maïto     )
61*23b7c7b8SHermès Bélusca-Maïto {
62*23b7c7b8SHermès Bélusca-Maïto     return (PCCB) FsRtlAllocatePoolWithTag( PagedPool, sizeof(CCB), TAG_CCB );
63*23b7c7b8SHermès Bélusca-Maïto }
64*23b7c7b8SHermès Bélusca-Maïto 
65*23b7c7b8SHermès Bélusca-Maïto #ifdef __REACTOS__
66*23b7c7b8SHermès Bélusca-Maïto static
67*23b7c7b8SHermès Bélusca-Maïto #endif
68*23b7c7b8SHermès Bélusca-Maïto INLINE
69*23b7c7b8SHermès Bélusca-Maïto VOID
FatFreeCcb(IN PCCB Ccb)70*23b7c7b8SHermès Bélusca-Maïto FatFreeCcb (
71*23b7c7b8SHermès Bélusca-Maïto     IN PCCB Ccb
72*23b7c7b8SHermès Bélusca-Maïto     )
73*23b7c7b8SHermès Bélusca-Maïto {
74*23b7c7b8SHermès Bélusca-Maïto #if FAT_FILL_FREE
75*23b7c7b8SHermès Bélusca-Maïto     RtlFillMemoryUlong(Ccb, sizeof(CCB), FAT_FILL_FREE);
76*23b7c7b8SHermès Bélusca-Maïto #endif
77*23b7c7b8SHermès Bélusca-Maïto 
78*23b7c7b8SHermès Bélusca-Maïto     ExFreePool( Ccb );
79*23b7c7b8SHermès Bélusca-Maïto }
80*23b7c7b8SHermès Bélusca-Maïto 
81*23b7c7b8SHermès Bélusca-Maïto #ifdef __REACTOS__
82*23b7c7b8SHermès Bélusca-Maïto static
83*23b7c7b8SHermès Bélusca-Maïto #endif
84*23b7c7b8SHermès Bélusca-Maïto INLINE
85*23b7c7b8SHermès Bélusca-Maïto PFCB
FatAllocateFcb()86*23b7c7b8SHermès Bélusca-Maïto FatAllocateFcb (
87*23b7c7b8SHermès Bélusca-Maïto     )
88*23b7c7b8SHermès Bélusca-Maïto {
89*23b7c7b8SHermès Bélusca-Maïto     return (PFCB) FsRtlAllocatePoolWithTag( PagedPool, sizeof(FCB), TAG_FCB );
90*23b7c7b8SHermès Bélusca-Maïto }
91*23b7c7b8SHermès Bélusca-Maïto 
92*23b7c7b8SHermès Bélusca-Maïto #ifdef __REACTOS__
93*23b7c7b8SHermès Bélusca-Maïto static
94*23b7c7b8SHermès Bélusca-Maïto #endif
95*23b7c7b8SHermès Bélusca-Maïto INLINE
96*23b7c7b8SHermès Bélusca-Maïto VOID
FatFreeFcb(IN PFCB Fcb)97*23b7c7b8SHermès Bélusca-Maïto FatFreeFcb (
98*23b7c7b8SHermès Bélusca-Maïto     IN PFCB Fcb
99*23b7c7b8SHermès Bélusca-Maïto     )
100*23b7c7b8SHermès Bélusca-Maïto {
101*23b7c7b8SHermès Bélusca-Maïto #if FAT_FILL_FREE
102*23b7c7b8SHermès Bélusca-Maïto     RtlFillMemoryUlong(Fcb, sizeof(FCB), FAT_FILL_FREE);
103*23b7c7b8SHermès Bélusca-Maïto #endif
104*23b7c7b8SHermès Bélusca-Maïto 
105*23b7c7b8SHermès Bélusca-Maïto     ExFreePool( Fcb );
106*23b7c7b8SHermès Bélusca-Maïto }
107*23b7c7b8SHermès Bélusca-Maïto 
108*23b7c7b8SHermès Bélusca-Maïto #ifdef __REACTOS__
109*23b7c7b8SHermès Bélusca-Maïto static
110*23b7c7b8SHermès Bélusca-Maïto #endif
111*23b7c7b8SHermès Bélusca-Maïto INLINE
112*23b7c7b8SHermès Bélusca-Maïto PNON_PAGED_FCB
FatAllocateNonPagedFcb()113*23b7c7b8SHermès Bélusca-Maïto FatAllocateNonPagedFcb (
114*23b7c7b8SHermès Bélusca-Maïto     )
115*23b7c7b8SHermès Bélusca-Maïto {
116*23b7c7b8SHermès Bélusca-Maïto     return (PNON_PAGED_FCB) ExAllocateFromNPagedLookasideList( &FatNonPagedFcbLookasideList );
117*23b7c7b8SHermès Bélusca-Maïto }
118*23b7c7b8SHermès Bélusca-Maïto 
119*23b7c7b8SHermès Bélusca-Maïto #ifdef __REACTOS__
120*23b7c7b8SHermès Bélusca-Maïto static
121*23b7c7b8SHermès Bélusca-Maïto #endif
122*23b7c7b8SHermès Bélusca-Maïto INLINE
123*23b7c7b8SHermès Bélusca-Maïto VOID
FatFreeNonPagedFcb(PNON_PAGED_FCB NonPagedFcb)124*23b7c7b8SHermès Bélusca-Maïto FatFreeNonPagedFcb (
125*23b7c7b8SHermès Bélusca-Maïto     PNON_PAGED_FCB NonPagedFcb
126*23b7c7b8SHermès Bélusca-Maïto     )
127*23b7c7b8SHermès Bélusca-Maïto {
128*23b7c7b8SHermès Bélusca-Maïto #if FAT_FILL_FREE
129*23b7c7b8SHermès Bélusca-Maïto     RtlFillMemoryUlong(NonPagedFcb, sizeof(NON_PAGED_FCB), FAT_FILL_FREE);
130*23b7c7b8SHermès Bélusca-Maïto #endif
131*23b7c7b8SHermès Bélusca-Maïto 
132*23b7c7b8SHermès Bélusca-Maïto     ExFreeToNPagedLookasideList( &FatNonPagedFcbLookasideList, (PVOID) NonPagedFcb );
133*23b7c7b8SHermès Bélusca-Maïto }
134*23b7c7b8SHermès Bélusca-Maïto 
135*23b7c7b8SHermès Bélusca-Maïto #ifdef __REACTOS__
136*23b7c7b8SHermès Bélusca-Maïto static
137*23b7c7b8SHermès Bélusca-Maïto #endif
138*23b7c7b8SHermès Bélusca-Maïto INLINE
139*23b7c7b8SHermès Bélusca-Maïto PERESOURCE
FatAllocateResource()140*23b7c7b8SHermès Bélusca-Maïto FatAllocateResource (
141*23b7c7b8SHermès Bélusca-Maïto     )
142*23b7c7b8SHermès Bélusca-Maïto {
143*23b7c7b8SHermès Bélusca-Maïto     PERESOURCE Resource;
144*23b7c7b8SHermès Bélusca-Maïto 
145*23b7c7b8SHermès Bélusca-Maïto     Resource = (PERESOURCE) ExAllocateFromNPagedLookasideList( &FatEResourceLookasideList );
146*23b7c7b8SHermès Bélusca-Maïto 
147*23b7c7b8SHermès Bélusca-Maïto     ExInitializeResourceLite( Resource );
148*23b7c7b8SHermès Bélusca-Maïto 
149*23b7c7b8SHermès Bélusca-Maïto     return Resource;
150*23b7c7b8SHermès Bélusca-Maïto }
151*23b7c7b8SHermès Bélusca-Maïto 
152*23b7c7b8SHermès Bélusca-Maïto #ifdef __REACTOS__
153*23b7c7b8SHermès Bélusca-Maïto static
154*23b7c7b8SHermès Bélusca-Maïto #endif
155*23b7c7b8SHermès Bélusca-Maïto INLINE
156*23b7c7b8SHermès Bélusca-Maïto VOID
FatFreeResource(IN PERESOURCE Resource)157*23b7c7b8SHermès Bélusca-Maïto FatFreeResource (
158*23b7c7b8SHermès Bélusca-Maïto     IN PERESOURCE Resource
159*23b7c7b8SHermès Bélusca-Maïto     )
160*23b7c7b8SHermès Bélusca-Maïto {
161*23b7c7b8SHermès Bélusca-Maïto     ExDeleteResourceLite( Resource );
162*23b7c7b8SHermès Bélusca-Maïto 
163*23b7c7b8SHermès Bélusca-Maïto #if FAT_FILL_FREE
164*23b7c7b8SHermès Bélusca-Maïto     RtlFillMemoryUlong(Resource, sizeof(ERESOURCE), FAT_FILL_FREE);
165*23b7c7b8SHermès Bélusca-Maïto #endif
166*23b7c7b8SHermès Bélusca-Maïto 
167*23b7c7b8SHermès Bélusca-Maïto     ExFreeToNPagedLookasideList( &FatEResourceLookasideList, (PVOID) Resource );
168*23b7c7b8SHermès Bélusca-Maïto }
169*23b7c7b8SHermès Bélusca-Maïto 
170*23b7c7b8SHermès Bélusca-Maïto #ifdef __REACTOS__
171*23b7c7b8SHermès Bélusca-Maïto static
172*23b7c7b8SHermès Bélusca-Maïto #endif
173*23b7c7b8SHermès Bélusca-Maïto INLINE
174*23b7c7b8SHermès Bélusca-Maïto PIRP_CONTEXT
FatAllocateIrpContext()175*23b7c7b8SHermès Bélusca-Maïto FatAllocateIrpContext (
176*23b7c7b8SHermès Bélusca-Maïto     )
177*23b7c7b8SHermès Bélusca-Maïto {
178*23b7c7b8SHermès Bélusca-Maïto     return (PIRP_CONTEXT) ExAllocateFromNPagedLookasideList( &FatIrpContextLookasideList );
179*23b7c7b8SHermès Bélusca-Maïto }
180*23b7c7b8SHermès Bélusca-Maïto 
181*23b7c7b8SHermès Bélusca-Maïto #ifdef __REACTOS__
182*23b7c7b8SHermès Bélusca-Maïto static
183*23b7c7b8SHermès Bélusca-Maïto #endif
184*23b7c7b8SHermès Bélusca-Maïto INLINE
185*23b7c7b8SHermès Bélusca-Maïto VOID
FatFreeIrpContext(IN PIRP_CONTEXT IrpContext)186*23b7c7b8SHermès Bélusca-Maïto FatFreeIrpContext (
187*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext
188*23b7c7b8SHermès Bélusca-Maïto     )
189*23b7c7b8SHermès Bélusca-Maïto {
190*23b7c7b8SHermès Bélusca-Maïto #if FAT_FILL_FREE
191*23b7c7b8SHermès Bélusca-Maïto     RtlFillMemoryUlong(IrpContext, sizeof(IRP_CONTEXT), FAT_FILL_FREE);
192*23b7c7b8SHermès Bélusca-Maïto #endif
193*23b7c7b8SHermès Bélusca-Maïto 
194*23b7c7b8SHermès Bélusca-Maïto     ExFreeToNPagedLookasideList( &FatIrpContextLookasideList, (PVOID) IrpContext );
195*23b7c7b8SHermès Bélusca-Maïto }
196*23b7c7b8SHermès Bélusca-Maïto 
197*23b7c7b8SHermès Bélusca-Maïto #ifdef ALLOC_PRAGMA
198*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatInitializeVcb)
199*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatTearDownVcb)
200*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatDeleteVcb)
201*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatCreateRootDcb)
202*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatCreateFcb)
203*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatCreateDcb)
204*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatDeleteFcb)
205*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatCreateCcb)
206*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatDeallocateCcbStrings)
207*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatDeleteCcb)
208*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatGetNextFcbTopDown)
209*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatGetNextFcbBottomUp)
210*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatConstructNamesInFcb)
211*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatCheckFreeDirentBitmap)
212*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatCreateIrpContext)
213*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatDeleteIrpContext_Real)
214*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatIsHandleCountZero)
215*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatAllocateCloseContext)
216*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatPreallocateCloseContext)
217*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatEnsureStringBufferEnough)
218*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatFreeStringBuffer)
219*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatScanForDataTrack)
220*23b7c7b8SHermès Bélusca-Maïto #endif
221*23b7c7b8SHermès Bélusca-Maïto 
222*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)223*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
224*23b7c7b8SHermès Bélusca-Maïto VOID
225*23b7c7b8SHermès Bélusca-Maïto FatInitializeVcb (
226*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
227*23b7c7b8SHermès Bélusca-Maïto     IN OUT PVCB Vcb,
228*23b7c7b8SHermès Bélusca-Maïto     IN PDEVICE_OBJECT TargetDeviceObject,
229*23b7c7b8SHermès Bélusca-Maïto     IN PVPB Vpb,
230*23b7c7b8SHermès Bélusca-Maïto     IN PDEVICE_OBJECT FsDeviceObject
231*23b7c7b8SHermès Bélusca-Maïto     )
232*23b7c7b8SHermès Bélusca-Maïto 
233*23b7c7b8SHermès Bélusca-Maïto /*++
234*23b7c7b8SHermès Bélusca-Maïto 
235*23b7c7b8SHermès Bélusca-Maïto Routine Description:
236*23b7c7b8SHermès Bélusca-Maïto 
237*23b7c7b8SHermès Bélusca-Maïto     This routine initializes and inserts a new Vcb record into the in-memory
238*23b7c7b8SHermès Bélusca-Maïto     data structure.  The Vcb record "hangs" off the end of the Volume device
239*23b7c7b8SHermès Bélusca-Maïto     object and must be allocated by our caller.
240*23b7c7b8SHermès Bélusca-Maïto 
241*23b7c7b8SHermès Bélusca-Maïto Arguments:
242*23b7c7b8SHermès Bélusca-Maïto 
243*23b7c7b8SHermès Bélusca-Maïto     Vcb - Supplies the address of the Vcb record being initialized.
244*23b7c7b8SHermès Bélusca-Maïto 
245*23b7c7b8SHermès Bélusca-Maïto     TargetDeviceObject - Supplies the address of the target device object to
246*23b7c7b8SHermès Bélusca-Maïto         associate with the Vcb record.
247*23b7c7b8SHermès Bélusca-Maïto 
248*23b7c7b8SHermès Bélusca-Maïto     Vpb - Supplies the address of the Vpb to associate with the Vcb record.
249*23b7c7b8SHermès Bélusca-Maïto 
250*23b7c7b8SHermès Bélusca-Maïto     FsDeviceObject - The filesystem device object that the mount was directed
251*23b7c7b8SHermès Bélusca-Maïto                      too.
252*23b7c7b8SHermès Bélusca-Maïto 
253*23b7c7b8SHermès Bélusca-Maïto Return Value:
254*23b7c7b8SHermès Bélusca-Maïto 
255*23b7c7b8SHermès Bélusca-Maïto     None.
256*23b7c7b8SHermès Bélusca-Maïto 
257*23b7c7b8SHermès Bélusca-Maïto --*/
258*23b7c7b8SHermès Bélusca-Maïto 
259*23b7c7b8SHermès Bélusca-Maïto {
260*23b7c7b8SHermès Bélusca-Maïto     CC_FILE_SIZES FileSizes;
261*23b7c7b8SHermès Bélusca-Maïto     PDEVICE_OBJECT RealDevice;
262*23b7c7b8SHermès Bélusca-Maïto     ULONG i;
263*23b7c7b8SHermès Bélusca-Maïto 
264*23b7c7b8SHermès Bélusca-Maïto     STORAGE_HOTPLUG_INFO HotplugInfo;
265*23b7c7b8SHermès Bélusca-Maïto     STORAGE_DEVICE_NUMBER StorDeviceNumber;
266*23b7c7b8SHermès Bélusca-Maïto     NTSTATUS Status;
267*23b7c7b8SHermès Bélusca-Maïto 
268*23b7c7b8SHermès Bélusca-Maïto     //
269*23b7c7b8SHermès Bélusca-Maïto     //  The following variables are used for abnormal unwind
270*23b7c7b8SHermès Bélusca-Maïto     //
271*23b7c7b8SHermès Bélusca-Maïto 
272*23b7c7b8SHermès Bélusca-Maïto     PLIST_ENTRY UnwindEntryList = NULL;
273*23b7c7b8SHermès Bélusca-Maïto     PERESOURCE UnwindResource = NULL;
274*23b7c7b8SHermès Bélusca-Maïto     PERESOURCE UnwindResource2 = NULL;
275*23b7c7b8SHermès Bélusca-Maïto     PFILE_OBJECT UnwindFileObject = NULL;
276*23b7c7b8SHermès Bélusca-Maïto     PFILE_OBJECT UnwindCacheMap = NULL;
277*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN UnwindWeAllocatedMcb = FALSE;
278*23b7c7b8SHermès Bélusca-Maïto     PFILE_SYSTEM_STATISTICS UnwindStatistics = NULL;
279*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN UnwindWeAllocatedBadBlockMap = FALSE;
280*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN CloseContextAllocated = FALSE;
281*23b7c7b8SHermès Bélusca-Maïto 
282*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
283*23b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( FsDeviceObject );
284*23b7c7b8SHermès Bélusca-Maïto 
285*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatInitializeVcb, Vcb = %p\n", Vcb);
286*23b7c7b8SHermès Bélusca-Maïto 
287*23b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
288*23b7c7b8SHermès Bélusca-Maïto 
289*23b7c7b8SHermès Bélusca-Maïto         //
290*23b7c7b8SHermès Bélusca-Maïto         //  We start by first zeroing out all of the VCB, this will guarantee
291*23b7c7b8SHermès Bélusca-Maïto         //  that any stale data is wiped clean
292*23b7c7b8SHermès Bélusca-Maïto         //
293*23b7c7b8SHermès Bélusca-Maïto 
294*23b7c7b8SHermès Bélusca-Maïto         RtlZeroMemory( Vcb, sizeof(VCB) );
295*23b7c7b8SHermès Bélusca-Maïto 
296*23b7c7b8SHermès Bélusca-Maïto         //
297*23b7c7b8SHermès Bélusca-Maïto         //  Set the proper node type code and node byte size
298*23b7c7b8SHermès Bélusca-Maïto         //
299*23b7c7b8SHermès Bélusca-Maïto 
300*23b7c7b8SHermès Bélusca-Maïto         Vcb->VolumeFileHeader.NodeTypeCode = FAT_NTC_VCB;
301*23b7c7b8SHermès Bélusca-Maïto         Vcb->VolumeFileHeader.NodeByteSize = sizeof(VCB);
302*23b7c7b8SHermès Bélusca-Maïto 
303*23b7c7b8SHermès Bélusca-Maïto         //
304*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the tunneling cache
305*23b7c7b8SHermès Bélusca-Maïto         //
306*23b7c7b8SHermès Bélusca-Maïto 
307*23b7c7b8SHermès Bélusca-Maïto         FsRtlInitializeTunnelCache(&Vcb->Tunnel);
308*23b7c7b8SHermès Bélusca-Maïto 
309*23b7c7b8SHermès Bélusca-Maïto         //
310*23b7c7b8SHermès Bélusca-Maïto         //  Insert this Vcb record on the FatData.VcbQueue
311*23b7c7b8SHermès Bélusca-Maïto         //
312*23b7c7b8SHermès Bélusca-Maïto 
313*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
314*23b7c7b8SHermès Bélusca-Maïto 
315*23b7c7b8SHermès Bélusca-Maïto 
316*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
317*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( push )
318*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( disable: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" )
319*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( disable: 28193, "this will always wait" )
320*23b7c7b8SHermès Bélusca-Maïto #endif
321*23b7c7b8SHermès Bélusca-Maïto 
322*23b7c7b8SHermès Bélusca-Maïto         (VOID)FatAcquireExclusiveGlobal( IrpContext );
323*23b7c7b8SHermès Bélusca-Maïto 
324*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
325*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( pop )
326*23b7c7b8SHermès Bélusca-Maïto #endif
327*23b7c7b8SHermès Bélusca-Maïto 
328*23b7c7b8SHermès Bélusca-Maïto         InsertTailList( &FatData.VcbQueue, &Vcb->VcbLinks );
329*23b7c7b8SHermès Bélusca-Maïto         FatReleaseGlobal( IrpContext );
330*23b7c7b8SHermès Bélusca-Maïto         UnwindEntryList = &Vcb->VcbLinks;
331*23b7c7b8SHermès Bélusca-Maïto 
332*23b7c7b8SHermès Bélusca-Maïto         //
333*23b7c7b8SHermès Bélusca-Maïto         //  Set the Target Device Object, Vpb, and Vcb State fields
334*23b7c7b8SHermès Bélusca-Maïto         //
335*23b7c7b8SHermès Bélusca-Maïto 
336*23b7c7b8SHermès Bélusca-Maïto 
337*23b7c7b8SHermès Bélusca-Maïto         ObReferenceObject( TargetDeviceObject );
338*23b7c7b8SHermès Bélusca-Maïto         Vcb->TargetDeviceObject = TargetDeviceObject;
339*23b7c7b8SHermès Bélusca-Maïto         Vcb->Vpb = Vpb;
340*23b7c7b8SHermès Bélusca-Maïto 
341*23b7c7b8SHermès Bélusca-Maïto         Vcb->CurrentDevice = Vpb->RealDevice;
342*23b7c7b8SHermès Bélusca-Maïto 
343*23b7c7b8SHermès Bélusca-Maïto         //
344*23b7c7b8SHermès Bélusca-Maïto         //  Set the removable media and defflush flags based on the storage
345*23b7c7b8SHermès Bélusca-Maïto         //  inquiry and the old characteristic bits.
346*23b7c7b8SHermès Bélusca-Maïto         //
347*23b7c7b8SHermès Bélusca-Maïto 
348*23b7c7b8SHermès Bélusca-Maïto         Status = FatPerformDevIoCtrl( IrpContext,
349*23b7c7b8SHermès Bélusca-Maïto                                       IOCTL_STORAGE_GET_HOTPLUG_INFO,
350*23b7c7b8SHermès Bélusca-Maïto                                       TargetDeviceObject,
351*23b7c7b8SHermès Bélusca-Maïto                                       NULL,
352*23b7c7b8SHermès Bélusca-Maïto                                       0,
353*23b7c7b8SHermès Bélusca-Maïto                                       &HotplugInfo,
354*23b7c7b8SHermès Bélusca-Maïto                                       sizeof(HotplugInfo),
355*23b7c7b8SHermès Bélusca-Maïto                                       FALSE,
356*23b7c7b8SHermès Bélusca-Maïto                                       TRUE,
357*23b7c7b8SHermès Bélusca-Maïto                                       NULL );
358*23b7c7b8SHermès Bélusca-Maïto 
359*23b7c7b8SHermès Bélusca-Maïto         if (NT_SUCCESS( Status )) {
360*23b7c7b8SHermès Bélusca-Maïto 
361*23b7c7b8SHermès Bélusca-Maïto             if (HotplugInfo.MediaRemovable) {
362*23b7c7b8SHermès Bélusca-Maïto 
363*23b7c7b8SHermès Bélusca-Maïto                 SetFlag( Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA );
364*23b7c7b8SHermès Bélusca-Maïto             }
365*23b7c7b8SHermès Bélusca-Maïto 
366*23b7c7b8SHermès Bélusca-Maïto             //
367*23b7c7b8SHermès Bélusca-Maïto             //  If the media or device is hot-pluggable, then set this flag.
368*23b7c7b8SHermès Bélusca-Maïto             //
369*23b7c7b8SHermès Bélusca-Maïto 
370*23b7c7b8SHermès Bélusca-Maïto             if (HotplugInfo.MediaHotplug || HotplugInfo.DeviceHotplug) {
371*23b7c7b8SHermès Bélusca-Maïto 
372*23b7c7b8SHermès Bélusca-Maïto                 SetFlag( Vcb->VcbState, VCB_STATE_FLAG_HOTPLUGGABLE );
373*23b7c7b8SHermès Bélusca-Maïto             }
374*23b7c7b8SHermès Bélusca-Maïto 
375*23b7c7b8SHermès Bélusca-Maïto             if (!HotplugInfo.WriteCacheEnableOverride) {
376*23b7c7b8SHermès Bélusca-Maïto 
377*23b7c7b8SHermès Bélusca-Maïto                 //
378*23b7c7b8SHermès Bélusca-Maïto                 //  If the device or media is hotplug and the override is not
379*23b7c7b8SHermès Bélusca-Maïto                 //  set, force defflush behavior for the device.
380*23b7c7b8SHermès Bélusca-Maïto                 //
381*23b7c7b8SHermès Bélusca-Maïto 
382*23b7c7b8SHermès Bélusca-Maïto                 if (HotplugInfo.MediaHotplug || HotplugInfo.DeviceHotplug) {
383*23b7c7b8SHermès Bélusca-Maïto 
384*23b7c7b8SHermès Bélusca-Maïto                     NT_ASSERT( FlagOn( Vcb->VcbState, VCB_STATE_FLAG_HOTPLUGGABLE ));
385*23b7c7b8SHermès Bélusca-Maïto 
386*23b7c7b8SHermès Bélusca-Maïto                     SetFlag( Vcb->VcbState, VCB_STATE_FLAG_DEFERRED_FLUSH );
387*23b7c7b8SHermès Bélusca-Maïto 
388*23b7c7b8SHermès Bélusca-Maïto                 //
389*23b7c7b8SHermès Bélusca-Maïto                 //  Now, for removables that claim to be lockable, lob a lock
390*23b7c7b8SHermès Bélusca-Maïto                 //  request and see if it works.  There can unfortunately be
391*23b7c7b8SHermès Bélusca-Maïto                 //  transient, media dependent reasons that it can fail.  If
392*23b7c7b8SHermès Bélusca-Maïto                 //  it does not, we must force defflush on.
393*23b7c7b8SHermès Bélusca-Maïto                 //
394*23b7c7b8SHermès Bélusca-Maïto 
395*23b7c7b8SHermès Bélusca-Maïto                 } else if (HotplugInfo.MediaRemovable &&
396*23b7c7b8SHermès Bélusca-Maïto                            !HotplugInfo.MediaHotplug) {
397*23b7c7b8SHermès Bélusca-Maïto 
398*23b7c7b8SHermès Bélusca-Maïto                     Status = FatToggleMediaEjectDisable( IrpContext, Vcb, TRUE );
399*23b7c7b8SHermès Bélusca-Maïto 
400*23b7c7b8SHermès Bélusca-Maïto                     if (!NT_SUCCESS( Status )) {
401*23b7c7b8SHermès Bélusca-Maïto 
402*23b7c7b8SHermès Bélusca-Maïto                         SetFlag( Vcb->VcbState, VCB_STATE_FLAG_DEFERRED_FLUSH );
403*23b7c7b8SHermès Bélusca-Maïto 
404*23b7c7b8SHermès Bélusca-Maïto                     }
405*23b7c7b8SHermès Bélusca-Maïto 
406*23b7c7b8SHermès Bélusca-Maïto                     (VOID)FatToggleMediaEjectDisable( IrpContext, Vcb, FALSE );
407*23b7c7b8SHermès Bélusca-Maïto                 }
408*23b7c7b8SHermès Bélusca-Maïto             }
409*23b7c7b8SHermès Bélusca-Maïto         }
410*23b7c7b8SHermès Bélusca-Maïto 
411*23b7c7b8SHermès Bélusca-Maïto         if (FlagOn(Vpb->RealDevice->Characteristics, FILE_REMOVABLE_MEDIA)) {
412*23b7c7b8SHermès Bélusca-Maïto 
413*23b7c7b8SHermès Bélusca-Maïto             SetFlag( Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA );
414*23b7c7b8SHermès Bélusca-Maïto         }
415*23b7c7b8SHermès Bélusca-Maïto 
416*23b7c7b8SHermès Bélusca-Maïto         //
417*23b7c7b8SHermès Bélusca-Maïto         //  Make sure we turn on deferred flushing for floppies like we always
418*23b7c7b8SHermès Bélusca-Maïto         //  have.
419*23b7c7b8SHermès Bélusca-Maïto         //
420*23b7c7b8SHermès Bélusca-Maïto 
421*23b7c7b8SHermès Bélusca-Maïto         if (FlagOn(Vpb->RealDevice->Characteristics, FILE_FLOPPY_DISKETTE)) {
422*23b7c7b8SHermès Bélusca-Maïto 
423*23b7c7b8SHermès Bélusca-Maïto             SetFlag( Vcb->VcbState, VCB_STATE_FLAG_DEFERRED_FLUSH );
424*23b7c7b8SHermès Bélusca-Maïto         }
425*23b7c7b8SHermès Bélusca-Maïto 
426*23b7c7b8SHermès Bélusca-Maïto         //
427*23b7c7b8SHermès Bélusca-Maïto         //  Query the storage device number.
428*23b7c7b8SHermès Bélusca-Maïto         //
429*23b7c7b8SHermès Bélusca-Maïto 
430*23b7c7b8SHermès Bélusca-Maïto         Status = FatPerformDevIoCtrl( IrpContext,
431*23b7c7b8SHermès Bélusca-Maïto                                       IOCTL_STORAGE_GET_DEVICE_NUMBER,
432*23b7c7b8SHermès Bélusca-Maïto                                       TargetDeviceObject,
433*23b7c7b8SHermès Bélusca-Maïto                                       NULL,
434*23b7c7b8SHermès Bélusca-Maïto                                       0,
435*23b7c7b8SHermès Bélusca-Maïto                                       &StorDeviceNumber,
436*23b7c7b8SHermès Bélusca-Maïto                                       sizeof(StorDeviceNumber),
437*23b7c7b8SHermès Bélusca-Maïto                                       FALSE,
438*23b7c7b8SHermès Bélusca-Maïto                                       TRUE,
439*23b7c7b8SHermès Bélusca-Maïto                                       NULL );
440*23b7c7b8SHermès Bélusca-Maïto 
441*23b7c7b8SHermès Bélusca-Maïto         if (NT_SUCCESS( Status )) {
442*23b7c7b8SHermès Bélusca-Maïto 
443*23b7c7b8SHermès Bélusca-Maïto             Vcb->DeviceNumber = StorDeviceNumber.DeviceNumber;
444*23b7c7b8SHermès Bélusca-Maïto 
445*23b7c7b8SHermès Bélusca-Maïto         } else {
446*23b7c7b8SHermès Bélusca-Maïto 
447*23b7c7b8SHermès Bélusca-Maïto             Vcb->DeviceNumber = (ULONG)(-1);
448*23b7c7b8SHermès Bélusca-Maïto         }
449*23b7c7b8SHermès Bélusca-Maïto 
450*23b7c7b8SHermès Bélusca-Maïto         FatSetVcbCondition( Vcb, VcbGood);
451*23b7c7b8SHermès Bélusca-Maïto 
452*23b7c7b8SHermès Bélusca-Maïto         //
453*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the resource variable for the Vcb
454*23b7c7b8SHermès Bélusca-Maïto         //
455*23b7c7b8SHermès Bélusca-Maïto 
456*23b7c7b8SHermès Bélusca-Maïto         ExInitializeResourceLite( &Vcb->Resource );
457*23b7c7b8SHermès Bélusca-Maïto         UnwindResource = &Vcb->Resource;
458*23b7c7b8SHermès Bélusca-Maïto 
459*23b7c7b8SHermès Bélusca-Maïto         ExInitializeResourceLite( &Vcb->ChangeBitMapResource );
460*23b7c7b8SHermès Bélusca-Maïto         UnwindResource2 = &Vcb->ChangeBitMapResource;
461*23b7c7b8SHermès Bélusca-Maïto 
462*23b7c7b8SHermès Bélusca-Maïto         //
463*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the free cluster bitmap mutex.
464*23b7c7b8SHermès Bélusca-Maïto         //
465*23b7c7b8SHermès Bélusca-Maïto 
466*23b7c7b8SHermès Bélusca-Maïto         ExInitializeFastMutex( &Vcb->FreeClusterBitMapMutex );
467*23b7c7b8SHermès Bélusca-Maïto 
468*23b7c7b8SHermès Bélusca-Maïto         //
469*23b7c7b8SHermès Bélusca-Maïto         //  Create the special file object for the virtual volume file with a close
470*23b7c7b8SHermès Bélusca-Maïto         //  context, its pointers back to the Vcb and the section object pointer.
471*23b7c7b8SHermès Bélusca-Maïto         //
472*23b7c7b8SHermès Bélusca-Maïto         //  We don't have to unwind the close context.  That will happen in the close
473*23b7c7b8SHermès Bélusca-Maïto         //  path automatically.
474*23b7c7b8SHermès Bélusca-Maïto         //
475*23b7c7b8SHermès Bélusca-Maïto 
476*23b7c7b8SHermès Bélusca-Maïto         RealDevice = Vcb->CurrentDevice;
477*23b7c7b8SHermès Bélusca-Maïto 
478*23b7c7b8SHermès Bélusca-Maïto         FatPreallocateCloseContext(Vcb);
479*23b7c7b8SHermès Bélusca-Maïto         CloseContextAllocated = TRUE;
480*23b7c7b8SHermès Bélusca-Maïto 
481*23b7c7b8SHermès Bélusca-Maïto         Vcb->VirtualVolumeFile = UnwindFileObject = IoCreateStreamFileObject( NULL, RealDevice );
482*23b7c7b8SHermès Bélusca-Maïto 
483*23b7c7b8SHermès Bélusca-Maïto         FatSetFileObject( Vcb->VirtualVolumeFile,
484*23b7c7b8SHermès Bélusca-Maïto                           VirtualVolumeFile,
485*23b7c7b8SHermès Bélusca-Maïto                           Vcb,
486*23b7c7b8SHermès Bélusca-Maïto                           NULL );
487*23b7c7b8SHermès Bélusca-Maïto 
488*23b7c7b8SHermès Bélusca-Maïto         //
489*23b7c7b8SHermès Bélusca-Maïto         //  Remember this internal, residual open.
490*23b7c7b8SHermès Bélusca-Maïto         //
491*23b7c7b8SHermès Bélusca-Maïto 
492*23b7c7b8SHermès Bélusca-Maïto         InterlockedIncrement( (LONG*)&(Vcb->InternalOpenCount) );
493*23b7c7b8SHermès Bélusca-Maïto         InterlockedIncrement( (LONG*)&(Vcb->ResidualOpenCount) );
494*23b7c7b8SHermès Bélusca-Maïto 
495*23b7c7b8SHermès Bélusca-Maïto         Vcb->VirtualVolumeFile->SectionObjectPointer = &Vcb->SectionObjectPointers;
496*23b7c7b8SHermès Bélusca-Maïto 
497*23b7c7b8SHermès Bélusca-Maïto         Vcb->VirtualVolumeFile->ReadAccess = TRUE;
498*23b7c7b8SHermès Bélusca-Maïto         Vcb->VirtualVolumeFile->WriteAccess = TRUE;
499*23b7c7b8SHermès Bélusca-Maïto         Vcb->VirtualVolumeFile->DeleteAccess = TRUE;
500*23b7c7b8SHermès Bélusca-Maïto 
501*23b7c7b8SHermès Bélusca-Maïto         //
502*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the notify structures.
503*23b7c7b8SHermès Bélusca-Maïto         //
504*23b7c7b8SHermès Bélusca-Maïto 
505*23b7c7b8SHermès Bélusca-Maïto         InitializeListHead( &Vcb->DirNotifyList );
506*23b7c7b8SHermès Bélusca-Maïto 
507*23b7c7b8SHermès Bélusca-Maïto         FsRtlNotifyInitializeSync( &Vcb->NotifySync );
508*23b7c7b8SHermès Bélusca-Maïto 
509*23b7c7b8SHermès Bélusca-Maïto         //
510*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the Cache Map for the volume file.  The size is
511*23b7c7b8SHermès Bélusca-Maïto         //  initially set to that of our first read.  It will be extended
512*23b7c7b8SHermès Bélusca-Maïto         //  when we know how big the Fat is.
513*23b7c7b8SHermès Bélusca-Maïto         //
514*23b7c7b8SHermès Bélusca-Maïto 
515*23b7c7b8SHermès Bélusca-Maïto         FileSizes.AllocationSize.QuadPart =
516*23b7c7b8SHermès Bélusca-Maïto         FileSizes.FileSize.QuadPart = sizeof(PACKED_BOOT_SECTOR);
517*23b7c7b8SHermès Bélusca-Maïto         FileSizes.ValidDataLength = FatMaxLarge;
518*23b7c7b8SHermès Bélusca-Maïto 
519*23b7c7b8SHermès Bélusca-Maïto         FatInitializeCacheMap( Vcb->VirtualVolumeFile,
520*23b7c7b8SHermès Bélusca-Maïto                                &FileSizes,
521*23b7c7b8SHermès Bélusca-Maïto                                TRUE,
522*23b7c7b8SHermès Bélusca-Maïto                                &FatData.CacheManagerNoOpCallbacks,
523*23b7c7b8SHermès Bélusca-Maïto                                Vcb );
524*23b7c7b8SHermès Bélusca-Maïto 
525*23b7c7b8SHermès Bélusca-Maïto         UnwindCacheMap = Vcb->VirtualVolumeFile;
526*23b7c7b8SHermès Bélusca-Maïto 
527*23b7c7b8SHermès Bélusca-Maïto         //
528*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the structure that will keep track of dirty fat sectors.
529*23b7c7b8SHermès Bélusca-Maïto         //  The largest possible Mcb structures are less than 1K, so we use
530*23b7c7b8SHermès Bélusca-Maïto         //  non paged pool.
531*23b7c7b8SHermès Bélusca-Maïto         //
532*23b7c7b8SHermès Bélusca-Maïto 
533*23b7c7b8SHermès Bélusca-Maïto         FsRtlInitializeLargeMcb( &Vcb->DirtyFatMcb, PagedPool );
534*23b7c7b8SHermès Bélusca-Maïto 
535*23b7c7b8SHermès Bélusca-Maïto         UnwindWeAllocatedMcb = TRUE;
536*23b7c7b8SHermès Bélusca-Maïto 
537*23b7c7b8SHermès Bélusca-Maïto         //
538*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the structure that will keep track of bad clusters on the volume.
539*23b7c7b8SHermès Bélusca-Maïto         //
540*23b7c7b8SHermès Bélusca-Maïto         //  It will be empty until it is populated by FSCTL_GET_RETRIEVAL_POINTERS with a volume handle.
541*23b7c7b8SHermès Bélusca-Maïto         //
542*23b7c7b8SHermès Bélusca-Maïto 
543*23b7c7b8SHermès Bélusca-Maïto         FsRtlInitializeLargeMcb( &Vcb->BadBlockMcb, PagedPool );
544*23b7c7b8SHermès Bélusca-Maïto         UnwindWeAllocatedBadBlockMap = TRUE;
545*23b7c7b8SHermès Bélusca-Maïto 
546*23b7c7b8SHermès Bélusca-Maïto         //
547*23b7c7b8SHermès Bélusca-Maïto         //  Set the cluster index hint to the first valid cluster of a fat: 2
548*23b7c7b8SHermès Bélusca-Maïto         //
549*23b7c7b8SHermès Bélusca-Maïto 
550*23b7c7b8SHermès Bélusca-Maïto         Vcb->ClusterHint = 2;
551*23b7c7b8SHermès Bélusca-Maïto 
552*23b7c7b8SHermès Bélusca-Maïto         //
553*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the directory stream file object creation event.
554*23b7c7b8SHermès Bélusca-Maïto         //  This event is also "borrowed" for async non-cached writes.
555*23b7c7b8SHermès Bélusca-Maïto         //
556*23b7c7b8SHermès Bélusca-Maïto 
557*23b7c7b8SHermès Bélusca-Maïto         ExInitializeFastMutex( &Vcb->DirectoryFileCreationMutex );
558*23b7c7b8SHermès Bélusca-Maïto 
559*23b7c7b8SHermès Bélusca-Maïto         //
560*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the clean volume callback Timer and DPC.
561*23b7c7b8SHermès Bélusca-Maïto         //
562*23b7c7b8SHermès Bélusca-Maïto 
563*23b7c7b8SHermès Bélusca-Maïto         KeInitializeTimer( &Vcb->CleanVolumeTimer );
564*23b7c7b8SHermès Bélusca-Maïto 
565*23b7c7b8SHermès Bélusca-Maïto         KeInitializeDpc( &Vcb->CleanVolumeDpc, FatCleanVolumeDpc, Vcb );
566*23b7c7b8SHermès Bélusca-Maïto 
567*23b7c7b8SHermès Bélusca-Maïto         //
568*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the performance counters.
569*23b7c7b8SHermès Bélusca-Maïto         //
570*23b7c7b8SHermès Bélusca-Maïto 
571*23b7c7b8SHermès Bélusca-Maïto         Vcb->Statistics = FsRtlAllocatePoolWithTag( NonPagedPoolNx,
572*23b7c7b8SHermès Bélusca-Maïto                                                     sizeof(FILE_SYSTEM_STATISTICS) * FatData.NumberProcessors,
573*23b7c7b8SHermès Bélusca-Maïto                                                     TAG_VCB_STATS );
574*23b7c7b8SHermès Bélusca-Maïto         UnwindStatistics = Vcb->Statistics;
575*23b7c7b8SHermès Bélusca-Maïto 
576*23b7c7b8SHermès Bélusca-Maïto         RtlZeroMemory( Vcb->Statistics, sizeof(FILE_SYSTEM_STATISTICS) * FatData.NumberProcessors );
577*23b7c7b8SHermès Bélusca-Maïto 
578*23b7c7b8SHermès Bélusca-Maïto         for (i = 0; i < FatData.NumberProcessors; i += 1) {
579*23b7c7b8SHermès Bélusca-Maïto             Vcb->Statistics[i].Common.FileSystemType = FILESYSTEM_STATISTICS_TYPE_FAT;
580*23b7c7b8SHermès Bélusca-Maïto             Vcb->Statistics[i].Common.Version = 1;
581*23b7c7b8SHermès Bélusca-Maïto             Vcb->Statistics[i].Common.SizeOfCompleteStructure =
582*23b7c7b8SHermès Bélusca-Maïto                 sizeof(FILE_SYSTEM_STATISTICS);
583*23b7c7b8SHermès Bélusca-Maïto         }
584*23b7c7b8SHermès Bélusca-Maïto 
585*23b7c7b8SHermès Bélusca-Maïto         //
586*23b7c7b8SHermès Bélusca-Maïto         //  Pick up a VPB right now so we know we can pull this filesystem stack off
587*23b7c7b8SHermès Bélusca-Maïto         //  of the storage stack on demand.
588*23b7c7b8SHermès Bélusca-Maïto         //
589*23b7c7b8SHermès Bélusca-Maïto 
590*23b7c7b8SHermès Bélusca-Maïto         Vcb->SwapVpb = FsRtlAllocatePoolWithTag( NonPagedPoolNx,
591*23b7c7b8SHermès Bélusca-Maïto                                                  sizeof( VPB ),
592*23b7c7b8SHermès Bélusca-Maïto                                                  TAG_VPB );
593*23b7c7b8SHermès Bélusca-Maïto 
594*23b7c7b8SHermès Bélusca-Maïto         RtlZeroMemory( Vcb->SwapVpb, sizeof( VPB ) );
595*23b7c7b8SHermès Bélusca-Maïto 
596*23b7c7b8SHermès Bélusca-Maïto         //
597*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the close queue listheads.
598*23b7c7b8SHermès Bélusca-Maïto         //
599*23b7c7b8SHermès Bélusca-Maïto 
600*23b7c7b8SHermès Bélusca-Maïto         InitializeListHead( &Vcb->AsyncCloseList );
601*23b7c7b8SHermès Bélusca-Maïto         InitializeListHead( &Vcb->DelayedCloseList );
602*23b7c7b8SHermès Bélusca-Maïto 
603*23b7c7b8SHermès Bélusca-Maïto         //
604*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the Advanced FCB Header
605*23b7c7b8SHermès Bélusca-Maïto         //
606*23b7c7b8SHermès Bélusca-Maïto 
607*23b7c7b8SHermès Bélusca-Maïto         ExInitializeFastMutex( &Vcb->AdvancedFcbHeaderMutex );
608*23b7c7b8SHermès Bélusca-Maïto         FsRtlSetupAdvancedHeader( &Vcb->VolumeFileHeader,
609*23b7c7b8SHermès Bélusca-Maïto                                   &Vcb->AdvancedFcbHeaderMutex );
610*23b7c7b8SHermès Bélusca-Maïto 
611*23b7c7b8SHermès Bélusca-Maïto 
612*23b7c7b8SHermès Bélusca-Maïto         //
613*23b7c7b8SHermès Bélusca-Maïto         //  With the Vcb now set up, set the IrpContext Vcb field.
614*23b7c7b8SHermès Bélusca-Maïto         //
615*23b7c7b8SHermès Bélusca-Maïto 
616*23b7c7b8SHermès Bélusca-Maïto         IrpContext->Vcb = Vcb;
617*23b7c7b8SHermès Bélusca-Maïto 
618*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
619*23b7c7b8SHermès Bélusca-Maïto 
620*23b7c7b8SHermès Bélusca-Maïto         DebugUnwind( FatInitializeVcb );
621*23b7c7b8SHermès Bélusca-Maïto 
622*23b7c7b8SHermès Bélusca-Maïto         //
623*23b7c7b8SHermès Bélusca-Maïto         //  If this is an abnormal termination then undo our work
624*23b7c7b8SHermès Bélusca-Maïto         //
625*23b7c7b8SHermès Bélusca-Maïto 
626*23b7c7b8SHermès Bélusca-Maïto         if (_SEH2_AbnormalTermination()) {
627*23b7c7b8SHermès Bélusca-Maïto 
628*23b7c7b8SHermès Bélusca-Maïto             if (UnwindCacheMap != NULL) { FatSyncUninitializeCacheMap( IrpContext, UnwindCacheMap ); }
629*23b7c7b8SHermès Bélusca-Maïto             if (UnwindFileObject != NULL) { ObDereferenceObject( UnwindFileObject ); }
630*23b7c7b8SHermès Bélusca-Maïto             if (UnwindResource != NULL) { FatDeleteResource( UnwindResource ); }
631*23b7c7b8SHermès Bélusca-Maïto             if (UnwindResource2 != NULL) { FatDeleteResource( UnwindResource2 ); }
632*23b7c7b8SHermès Bélusca-Maïto             if (UnwindWeAllocatedMcb) { FsRtlUninitializeLargeMcb( &Vcb->DirtyFatMcb ); }
633*23b7c7b8SHermès Bélusca-Maïto             if (UnwindWeAllocatedBadBlockMap) { FsRtlUninitializeLargeMcb(&Vcb->BadBlockMcb ); }
634*23b7c7b8SHermès Bélusca-Maïto             if (UnwindEntryList != NULL) {
635*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
636*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" )
637*23b7c7b8SHermès Bélusca-Maïto #endif
638*23b7c7b8SHermès Bélusca-Maïto                 (VOID)FatAcquireExclusiveGlobal( IrpContext );
639*23b7c7b8SHermès Bélusca-Maïto                 RemoveEntryList( UnwindEntryList );
640*23b7c7b8SHermès Bélusca-Maïto                 FatReleaseGlobal( IrpContext );
641*23b7c7b8SHermès Bélusca-Maïto             }
642*23b7c7b8SHermès Bélusca-Maïto             if (UnwindStatistics != NULL) { ExFreePool( UnwindStatistics ); }
643*23b7c7b8SHermès Bélusca-Maïto 
644*23b7c7b8SHermès Bélusca-Maïto             //
645*23b7c7b8SHermès Bélusca-Maïto             // Cleanup the close context we preallocated above.
646*23b7c7b8SHermès Bélusca-Maïto             //
647*23b7c7b8SHermès Bélusca-Maïto 
648*23b7c7b8SHermès Bélusca-Maïto             if (CloseContextAllocated && (Vcb->VirtualVolumeFile == NULL)) {
649*23b7c7b8SHermès Bélusca-Maïto 
650*23b7c7b8SHermès Bélusca-Maïto                 //
651*23b7c7b8SHermès Bélusca-Maïto                 // FatAllocateCloseContext does not allocate memory, it
652*23b7c7b8SHermès Bélusca-Maïto                 // pulls a close context off the preallocated slist queue.
653*23b7c7b8SHermès Bélusca-Maïto                 //
654*23b7c7b8SHermès Bélusca-Maïto                 // Doing this here is necessary to balance out the one we
655*23b7c7b8SHermès Bélusca-Maïto                 // preallocated for the Vcb earlier in this function, but
656*23b7c7b8SHermès Bélusca-Maïto                 // only if we failed to create the virtual volume file.
657*23b7c7b8SHermès Bélusca-Maïto                 //
658*23b7c7b8SHermès Bélusca-Maïto                 // If VirtualVolumeFile is not NULL, then this CloseContext
659*23b7c7b8SHermès Bélusca-Maïto                 // will get cleaned up when the close comes in for it during
660*23b7c7b8SHermès Bélusca-Maïto                 // Vcb teardown.
661*23b7c7b8SHermès Bélusca-Maïto                 //
662*23b7c7b8SHermès Bélusca-Maïto 
663*23b7c7b8SHermès Bélusca-Maïto                 PCLOSE_CONTEXT CloseContext = FatAllocateCloseContext(Vcb);
664*23b7c7b8SHermès Bélusca-Maïto 
665*23b7c7b8SHermès Bélusca-Maïto                 ExFreePool( CloseContext );
666*23b7c7b8SHermès Bélusca-Maïto                 CloseContextAllocated = FALSE;
667*23b7c7b8SHermès Bélusca-Maïto             }
668*23b7c7b8SHermès Bélusca-Maïto         }
669*23b7c7b8SHermès Bélusca-Maïto 
670*23b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatInitializeVcb -> VOID\n", 0);
671*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
672*23b7c7b8SHermès Bélusca-Maïto 
673*23b7c7b8SHermès Bélusca-Maïto     //
674*23b7c7b8SHermès Bélusca-Maïto     //  and return to our caller
675*23b7c7b8SHermès Bélusca-Maïto     //
676*23b7c7b8SHermès Bélusca-Maïto 
677*23b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( IrpContext );
678*23b7c7b8SHermès Bélusca-Maïto 
679*23b7c7b8SHermès Bélusca-Maïto     return;
680*23b7c7b8SHermès Bélusca-Maïto }
681*23b7c7b8SHermès Bélusca-Maïto 
682*23b7c7b8SHermès Bélusca-Maïto 
683*23b7c7b8SHermès Bélusca-Maïto VOID
FatTearDownVcb(IN PIRP_CONTEXT IrpContext,IN PVCB Vcb)684*23b7c7b8SHermès Bélusca-Maïto FatTearDownVcb (
685*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
686*23b7c7b8SHermès Bélusca-Maïto     IN PVCB Vcb
687*23b7c7b8SHermès Bélusca-Maïto     )
688*23b7c7b8SHermès Bélusca-Maïto 
689*23b7c7b8SHermès Bélusca-Maïto /*++
690*23b7c7b8SHermès Bélusca-Maïto 
691*23b7c7b8SHermès Bélusca-Maïto Routine Description:
692*23b7c7b8SHermès Bélusca-Maïto 
693*23b7c7b8SHermès Bélusca-Maïto     This routine tries to remove all internal opens from the volume.
694*23b7c7b8SHermès Bélusca-Maïto 
695*23b7c7b8SHermès Bélusca-Maïto Arguments:
696*23b7c7b8SHermès Bélusca-Maïto 
697*23b7c7b8SHermès Bélusca-Maïto     IrpContext - Supplies the context for the overall request.
698*23b7c7b8SHermès Bélusca-Maïto 
699*23b7c7b8SHermès Bélusca-Maïto     Vcb - Supplies the Vcb to be torn down.
700*23b7c7b8SHermès Bélusca-Maïto 
701*23b7c7b8SHermès Bélusca-Maïto Return Value:
702*23b7c7b8SHermès Bélusca-Maïto 
703*23b7c7b8SHermès Bélusca-Maïto     None
704*23b7c7b8SHermès Bélusca-Maïto 
705*23b7c7b8SHermès Bélusca-Maïto --*/
706*23b7c7b8SHermès Bélusca-Maïto 
707*23b7c7b8SHermès Bélusca-Maïto {
708*23b7c7b8SHermès Bélusca-Maïto     PFILE_OBJECT DirectoryFileObject;
709*23b7c7b8SHermès Bélusca-Maïto 
710*23b7c7b8SHermès Bélusca-Maïto 
711*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
712*23b7c7b8SHermès Bélusca-Maïto 
713*23b7c7b8SHermès Bélusca-Maïto     //
714*23b7c7b8SHermès Bélusca-Maïto     //  Get rid of the virtual volume file, if we need to.
715*23b7c7b8SHermès Bélusca-Maïto     //
716*23b7c7b8SHermès Bélusca-Maïto 
717*23b7c7b8SHermès Bélusca-Maïto     if (Vcb->VirtualVolumeFile != NULL) {
718*23b7c7b8SHermès Bélusca-Maïto 
719*23b7c7b8SHermès Bélusca-Maïto         //
720*23b7c7b8SHermès Bélusca-Maïto         //  Uninitialize the cache
721*23b7c7b8SHermès Bélusca-Maïto         //
722*23b7c7b8SHermès Bélusca-Maïto 
723*23b7c7b8SHermès Bélusca-Maïto         CcUninitializeCacheMap( Vcb->VirtualVolumeFile,
724*23b7c7b8SHermès Bélusca-Maïto                                 &FatLargeZero,
725*23b7c7b8SHermès Bélusca-Maïto                                 NULL );
726*23b7c7b8SHermès Bélusca-Maïto 
727*23b7c7b8SHermès Bélusca-Maïto         FsRtlTeardownPerStreamContexts( &Vcb->VolumeFileHeader );
728*23b7c7b8SHermès Bélusca-Maïto 
729*23b7c7b8SHermès Bélusca-Maïto         ObDereferenceObject( Vcb->VirtualVolumeFile );
730*23b7c7b8SHermès Bélusca-Maïto 
731*23b7c7b8SHermès Bélusca-Maïto         Vcb->VirtualVolumeFile = NULL;
732*23b7c7b8SHermès Bélusca-Maïto     }
733*23b7c7b8SHermès Bélusca-Maïto 
734*23b7c7b8SHermès Bélusca-Maïto     //
735*23b7c7b8SHermès Bélusca-Maïto     //  Close down the EA file.
736*23b7c7b8SHermès Bélusca-Maïto     //
737*23b7c7b8SHermès Bélusca-Maïto 
738*23b7c7b8SHermès Bélusca-Maïto     FatCloseEaFile( IrpContext, Vcb, FALSE );
739*23b7c7b8SHermès Bélusca-Maïto 
740*23b7c7b8SHermès Bélusca-Maïto     //
741*23b7c7b8SHermès Bélusca-Maïto     //  Close down the root directory stream..
742*23b7c7b8SHermès Bélusca-Maïto     //
743*23b7c7b8SHermès Bélusca-Maïto 
744*23b7c7b8SHermès Bélusca-Maïto     if (Vcb->RootDcb != NULL) {
745*23b7c7b8SHermès Bélusca-Maïto 
746*23b7c7b8SHermès Bélusca-Maïto         DirectoryFileObject = Vcb->RootDcb->Specific.Dcb.DirectoryFile;
747*23b7c7b8SHermès Bélusca-Maïto 
748*23b7c7b8SHermès Bélusca-Maïto         if (DirectoryFileObject != NULL) {
749*23b7c7b8SHermès Bélusca-Maïto 
750*23b7c7b8SHermès Bélusca-Maïto             //
751*23b7c7b8SHermès Bélusca-Maïto             //  Tear down this directory file.
752*23b7c7b8SHermès Bélusca-Maïto             //
753*23b7c7b8SHermès Bélusca-Maïto 
754*23b7c7b8SHermès Bélusca-Maïto             CcUninitializeCacheMap( DirectoryFileObject,
755*23b7c7b8SHermès Bélusca-Maïto                                     &FatLargeZero,
756*23b7c7b8SHermès Bélusca-Maïto                                     NULL );
757*23b7c7b8SHermès Bélusca-Maïto 
758*23b7c7b8SHermès Bélusca-Maïto             Vcb->RootDcb->Specific.Dcb.DirectoryFile = NULL;
759*23b7c7b8SHermès Bélusca-Maïto             ObDereferenceObject( DirectoryFileObject );
760*23b7c7b8SHermès Bélusca-Maïto         }
761*23b7c7b8SHermès Bélusca-Maïto     }
762*23b7c7b8SHermès Bélusca-Maïto 
763*23b7c7b8SHermès Bélusca-Maïto     //
764*23b7c7b8SHermès Bélusca-Maïto     //  The VCB can no longer be used.
765*23b7c7b8SHermès Bélusca-Maïto     //
766*23b7c7b8SHermès Bélusca-Maïto 
767*23b7c7b8SHermès Bélusca-Maïto     FatSetVcbCondition( Vcb, VcbBad );
768*23b7c7b8SHermès Bélusca-Maïto }
769*23b7c7b8SHermès Bélusca-Maïto 
770*23b7c7b8SHermès Bélusca-Maïto 
771*23b7c7b8SHermès Bélusca-Maïto VOID
FatDeleteVcb(IN PIRP_CONTEXT IrpContext,IN PVCB Vcb)772*23b7c7b8SHermès Bélusca-Maïto FatDeleteVcb (
773*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
774*23b7c7b8SHermès Bélusca-Maïto     IN PVCB Vcb
775*23b7c7b8SHermès Bélusca-Maïto     )
776*23b7c7b8SHermès Bélusca-Maïto 
777*23b7c7b8SHermès Bélusca-Maïto /*++
778*23b7c7b8SHermès Bélusca-Maïto 
779*23b7c7b8SHermès Bélusca-Maïto Routine Description:
780*23b7c7b8SHermès Bélusca-Maïto 
781*23b7c7b8SHermès Bélusca-Maïto     This routine removes the Vcb record from Fat's in-memory data
782*23b7c7b8SHermès Bélusca-Maïto     structures.  It also will remove all associated underlings
783*23b7c7b8SHermès Bélusca-Maïto     (i.e., FCB records).
784*23b7c7b8SHermès Bélusca-Maïto 
785*23b7c7b8SHermès Bélusca-Maïto Arguments:
786*23b7c7b8SHermès Bélusca-Maïto 
787*23b7c7b8SHermès Bélusca-Maïto     Vcb - Supplies the Vcb to be removed
788*23b7c7b8SHermès Bélusca-Maïto 
789*23b7c7b8SHermès Bélusca-Maïto Return Value:
790*23b7c7b8SHermès Bélusca-Maïto 
791*23b7c7b8SHermès Bélusca-Maïto     None
792*23b7c7b8SHermès Bélusca-Maïto 
793*23b7c7b8SHermès Bélusca-Maïto --*/
794*23b7c7b8SHermès Bélusca-Maïto 
795*23b7c7b8SHermès Bélusca-Maïto {
796*23b7c7b8SHermès Bélusca-Maïto     PFCB Fcb;
797*23b7c7b8SHermès Bélusca-Maïto 
798*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
799*23b7c7b8SHermès Bélusca-Maïto 
800*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatDeleteVcb, Vcb = %p\n", Vcb);
801*23b7c7b8SHermès Bélusca-Maïto 
802*23b7c7b8SHermès Bélusca-Maïto     //
803*23b7c7b8SHermès Bélusca-Maïto     //  If the IrpContext points to the VCB being deleted NULL out the stail
804*23b7c7b8SHermès Bélusca-Maïto     //  pointer.
805*23b7c7b8SHermès Bélusca-Maïto     //
806*23b7c7b8SHermès Bélusca-Maïto 
807*23b7c7b8SHermès Bélusca-Maïto     if (IrpContext->Vcb == Vcb) {
808*23b7c7b8SHermès Bélusca-Maïto 
809*23b7c7b8SHermès Bélusca-Maïto         IrpContext->Vcb = NULL;
810*23b7c7b8SHermès Bélusca-Maïto 
811*23b7c7b8SHermès Bélusca-Maïto     }
812*23b7c7b8SHermès Bélusca-Maïto 
813*23b7c7b8SHermès Bélusca-Maïto     //
814*23b7c7b8SHermès Bélusca-Maïto     //  Chuck the backpocket Vpb we kept just in case.
815*23b7c7b8SHermès Bélusca-Maïto     //
816*23b7c7b8SHermès Bélusca-Maïto 
817*23b7c7b8SHermès Bélusca-Maïto     if (Vcb->SwapVpb) {
818*23b7c7b8SHermès Bélusca-Maïto 
819*23b7c7b8SHermès Bélusca-Maïto         ExFreePool( Vcb->SwapVpb );
820*23b7c7b8SHermès Bélusca-Maïto 
821*23b7c7b8SHermès Bélusca-Maïto     }
822*23b7c7b8SHermès Bélusca-Maïto 
823*23b7c7b8SHermès Bélusca-Maïto     //
824*23b7c7b8SHermès Bélusca-Maïto     //  Free the VPB, if we need to.
825*23b7c7b8SHermès Bélusca-Maïto     //
826*23b7c7b8SHermès Bélusca-Maïto 
827*23b7c7b8SHermès Bélusca-Maïto     if (FlagOn( Vcb->VcbState, VCB_STATE_FLAG_VPB_MUST_BE_FREED )) {
828*23b7c7b8SHermès Bélusca-Maïto 
829*23b7c7b8SHermès Bélusca-Maïto         //
830*23b7c7b8SHermès Bélusca-Maïto         //  We swapped the VPB, so we need to free the main one.
831*23b7c7b8SHermès Bélusca-Maïto         //
832*23b7c7b8SHermès Bélusca-Maïto 
833*23b7c7b8SHermès Bélusca-Maïto         ExFreePool( Vcb->Vpb );
834*23b7c7b8SHermès Bélusca-Maïto     }
835*23b7c7b8SHermès Bélusca-Maïto 
836*23b7c7b8SHermès Bélusca-Maïto     if (Vcb->VolumeGuidPath.Buffer) {
837*23b7c7b8SHermès Bélusca-Maïto         ExFreePool( Vcb->VolumeGuidPath.Buffer );
838*23b7c7b8SHermès Bélusca-Maïto         Vcb->VolumeGuidPath.Buffer = NULL;
839*23b7c7b8SHermès Bélusca-Maïto     }
840*23b7c7b8SHermès Bélusca-Maïto 
841*23b7c7b8SHermès Bélusca-Maïto     //
842*23b7c7b8SHermès Bélusca-Maïto     //  Remove this record from the global list of all Vcb records.
843*23b7c7b8SHermès Bélusca-Maïto     //  Note that the global lock must already be held when calling
844*23b7c7b8SHermès Bélusca-Maïto     //  this function.
845*23b7c7b8SHermès Bélusca-Maïto     //
846*23b7c7b8SHermès Bélusca-Maïto 
847*23b7c7b8SHermès Bélusca-Maïto     RemoveEntryList( &(Vcb->VcbLinks) );
848*23b7c7b8SHermès Bélusca-Maïto 
849*23b7c7b8SHermès Bélusca-Maïto     //
850*23b7c7b8SHermès Bélusca-Maïto     //  Make sure the direct access open count is zero, and the open file count
851*23b7c7b8SHermès Bélusca-Maïto     //  is also zero.
852*23b7c7b8SHermès Bélusca-Maïto     //
853*23b7c7b8SHermès Bélusca-Maïto 
854*23b7c7b8SHermès Bélusca-Maïto     if ((Vcb->DirectAccessOpenCount != 0) || (Vcb->OpenFileCount != 0)) {
855*23b7c7b8SHermès Bélusca-Maïto 
856*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
857*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
858*23b7c7b8SHermès Bélusca-Maïto #endif
859*23b7c7b8SHermès Bélusca-Maïto         FatBugCheck( 0, 0, 0 );
860*23b7c7b8SHermès Bélusca-Maïto     }
861*23b7c7b8SHermès Bélusca-Maïto 
862*23b7c7b8SHermès Bélusca-Maïto     //
863*23b7c7b8SHermès Bélusca-Maïto     //  Remove the EaFcb and dereference the Fcb for the Ea file if it
864*23b7c7b8SHermès Bélusca-Maïto     //  exists.
865*23b7c7b8SHermès Bélusca-Maïto     //
866*23b7c7b8SHermès Bélusca-Maïto 
867*23b7c7b8SHermès Bélusca-Maïto     if (Vcb->EaFcb != NULL) {
868*23b7c7b8SHermès Bélusca-Maïto 
869*23b7c7b8SHermès Bélusca-Maïto         Vcb->EaFcb->OpenCount = 0;
870*23b7c7b8SHermès Bélusca-Maïto         FatDeleteFcb( IrpContext, &Vcb->EaFcb );
871*23b7c7b8SHermès Bélusca-Maïto     }
872*23b7c7b8SHermès Bélusca-Maïto 
873*23b7c7b8SHermès Bélusca-Maïto     //
874*23b7c7b8SHermès Bélusca-Maïto     //  Remove the Root Dcb
875*23b7c7b8SHermès Bélusca-Maïto     //
876*23b7c7b8SHermès Bélusca-Maïto 
877*23b7c7b8SHermès Bélusca-Maïto     if (Vcb->RootDcb != NULL) {
878*23b7c7b8SHermès Bélusca-Maïto 
879*23b7c7b8SHermès Bélusca-Maïto         //
880*23b7c7b8SHermès Bélusca-Maïto         //  Rundown stale child Fcbs that may be hanging around.  Yes, this
881*23b7c7b8SHermès Bélusca-Maïto         //  can happen.  No, the create path isn't perfectly defensive about
882*23b7c7b8SHermès Bélusca-Maïto         //  tearing down branches built up on creates that don't wind up
883*23b7c7b8SHermès Bélusca-Maïto         //  succeeding.  Normal system operation usually winds up having
884*23b7c7b8SHermès Bélusca-Maïto         //  cleaned them out through re-visiting, but ...
885*23b7c7b8SHermès Bélusca-Maïto         //
886*23b7c7b8SHermès Bélusca-Maïto         //  Just pick off Fcbs from the bottom of the tree until we run out.
887*23b7c7b8SHermès Bélusca-Maïto         //  Then we delete the root Dcb.
888*23b7c7b8SHermès Bélusca-Maïto         //
889*23b7c7b8SHermès Bélusca-Maïto 
890*23b7c7b8SHermès Bélusca-Maïto         while( (Fcb = FatGetNextFcbBottomUp( IrpContext, NULL, Vcb->RootDcb )) != Vcb->RootDcb ) {
891*23b7c7b8SHermès Bélusca-Maïto 
892*23b7c7b8SHermès Bélusca-Maïto             FatDeleteFcb( IrpContext, &Fcb );
893*23b7c7b8SHermès Bélusca-Maïto         }
894*23b7c7b8SHermès Bélusca-Maïto 
895*23b7c7b8SHermès Bélusca-Maïto         FatDeleteFcb( IrpContext, &Vcb->RootDcb );
896*23b7c7b8SHermès Bélusca-Maïto     }
897*23b7c7b8SHermès Bélusca-Maïto 
898*23b7c7b8SHermès Bélusca-Maïto     //
899*23b7c7b8SHermès Bélusca-Maïto     //  Uninitialize the notify sychronization object.
900*23b7c7b8SHermès Bélusca-Maïto     //
901*23b7c7b8SHermès Bélusca-Maïto 
902*23b7c7b8SHermès Bélusca-Maïto     FsRtlNotifyUninitializeSync( &Vcb->NotifySync );
903*23b7c7b8SHermès Bélusca-Maïto 
904*23b7c7b8SHermès Bélusca-Maïto     //
905*23b7c7b8SHermès Bélusca-Maïto     //  Uninitialize the resource variable for the Vcb
906*23b7c7b8SHermès Bélusca-Maïto     //
907*23b7c7b8SHermès Bélusca-Maïto 
908*23b7c7b8SHermès Bélusca-Maïto     FatDeleteResource( &Vcb->Resource );
909*23b7c7b8SHermès Bélusca-Maïto     FatDeleteResource( &Vcb->ChangeBitMapResource );
910*23b7c7b8SHermès Bélusca-Maïto 
911*23b7c7b8SHermès Bélusca-Maïto     //
912*23b7c7b8SHermès Bélusca-Maïto     //  If allocation support has been setup, free it.
913*23b7c7b8SHermès Bélusca-Maïto     //
914*23b7c7b8SHermès Bélusca-Maïto 
915*23b7c7b8SHermès Bélusca-Maïto     if (Vcb->FreeClusterBitMap.Buffer != NULL) {
916*23b7c7b8SHermès Bélusca-Maïto 
917*23b7c7b8SHermès Bélusca-Maïto         FatTearDownAllocationSupport( IrpContext, Vcb );
918*23b7c7b8SHermès Bélusca-Maïto     }
919*23b7c7b8SHermès Bélusca-Maïto 
920*23b7c7b8SHermès Bélusca-Maïto     //
921*23b7c7b8SHermès Bélusca-Maïto     //  UnInitialize the Mcb structure that kept track of dirty fat sectors.
922*23b7c7b8SHermès Bélusca-Maïto     //
923*23b7c7b8SHermès Bélusca-Maïto 
924*23b7c7b8SHermès Bélusca-Maïto     FsRtlUninitializeLargeMcb( &Vcb->DirtyFatMcb );
925*23b7c7b8SHermès Bélusca-Maïto 
926*23b7c7b8SHermès Bélusca-Maïto     //
927*23b7c7b8SHermès Bélusca-Maïto     //  Uninitialize the Mcb structure that kept track of bad sectors.
928*23b7c7b8SHermès Bélusca-Maïto     //
929*23b7c7b8SHermès Bélusca-Maïto 
930*23b7c7b8SHermès Bélusca-Maïto     FsRtlUninitializeLargeMcb( &Vcb->BadBlockMcb );
931*23b7c7b8SHermès Bélusca-Maïto 
932*23b7c7b8SHermès Bélusca-Maïto     //
933*23b7c7b8SHermès Bélusca-Maïto     //  Free the pool for the stached copy of the boot sector
934*23b7c7b8SHermès Bélusca-Maïto     //
935*23b7c7b8SHermès Bélusca-Maïto 
936*23b7c7b8SHermès Bélusca-Maïto     if ( Vcb->First0x24BytesOfBootSector ) {
937*23b7c7b8SHermès Bélusca-Maïto 
938*23b7c7b8SHermès Bélusca-Maïto         ExFreePool( Vcb->First0x24BytesOfBootSector );
939*23b7c7b8SHermès Bélusca-Maïto         Vcb->First0x24BytesOfBootSector = NULL;
940*23b7c7b8SHermès Bélusca-Maïto     }
941*23b7c7b8SHermès Bélusca-Maïto 
942*23b7c7b8SHermès Bélusca-Maïto     //
943*23b7c7b8SHermès Bélusca-Maïto     //  Cancel the CleanVolume Timer and Dpc
944*23b7c7b8SHermès Bélusca-Maïto     //
945*23b7c7b8SHermès Bélusca-Maïto 
946*23b7c7b8SHermès Bélusca-Maïto     (VOID)KeCancelTimer( &Vcb->CleanVolumeTimer );
947*23b7c7b8SHermès Bélusca-Maïto 
948*23b7c7b8SHermès Bélusca-Maïto     (VOID)KeRemoveQueueDpc( &Vcb->CleanVolumeDpc );
949*23b7c7b8SHermès Bélusca-Maïto 
950*23b7c7b8SHermès Bélusca-Maïto     //
951*23b7c7b8SHermès Bélusca-Maïto     //  Free the performance counters memory
952*23b7c7b8SHermès Bélusca-Maïto     //
953*23b7c7b8SHermès Bélusca-Maïto 
954*23b7c7b8SHermès Bélusca-Maïto     ExFreePool( Vcb->Statistics );
955*23b7c7b8SHermès Bélusca-Maïto 
956*23b7c7b8SHermès Bélusca-Maïto     //
957*23b7c7b8SHermès Bélusca-Maïto     //  Clean out the tunneling cache
958*23b7c7b8SHermès Bélusca-Maïto     //
959*23b7c7b8SHermès Bélusca-Maïto 
960*23b7c7b8SHermès Bélusca-Maïto     FsRtlDeleteTunnelCache(&Vcb->Tunnel);
961*23b7c7b8SHermès Bélusca-Maïto 
962*23b7c7b8SHermès Bélusca-Maïto     //
963*23b7c7b8SHermès Bélusca-Maïto     // Dereference the target device object.
964*23b7c7b8SHermès Bélusca-Maïto     //
965*23b7c7b8SHermès Bélusca-Maïto 
966*23b7c7b8SHermès Bélusca-Maïto     ObDereferenceObject( Vcb->TargetDeviceObject );
967*23b7c7b8SHermès Bélusca-Maïto 
968*23b7c7b8SHermès Bélusca-Maïto     //
969*23b7c7b8SHermès Bélusca-Maïto     //  We better have used all the close contexts we allocated. There could be
970*23b7c7b8SHermès Bélusca-Maïto     //  one remaining if we're doing teardown due to a final close coming in on
971*23b7c7b8SHermès Bélusca-Maïto     //  a directory file stream object.  It will be freed on the way back up.
972*23b7c7b8SHermès Bélusca-Maïto     //
973*23b7c7b8SHermès Bélusca-Maïto 
974*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( Vcb->CloseContextCount <= 1);
975*23b7c7b8SHermès Bélusca-Maïto 
976*23b7c7b8SHermès Bélusca-Maïto     //
977*23b7c7b8SHermès Bélusca-Maïto     //  And zero out the Vcb, this will help ensure that any stale data is
978*23b7c7b8SHermès Bélusca-Maïto     //  wiped clean
979*23b7c7b8SHermès Bélusca-Maïto     //
980*23b7c7b8SHermès Bélusca-Maïto 
981*23b7c7b8SHermès Bélusca-Maïto     RtlZeroMemory( Vcb, sizeof(VCB) );
982*23b7c7b8SHermès Bélusca-Maïto 
983*23b7c7b8SHermès Bélusca-Maïto     //
984*23b7c7b8SHermès Bélusca-Maïto     //  return and tell the caller
985*23b7c7b8SHermès Bélusca-Maïto     //
986*23b7c7b8SHermès Bélusca-Maïto 
987*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatDeleteVcb -> VOID\n", 0);
988*23b7c7b8SHermès Bélusca-Maïto 
989*23b7c7b8SHermès Bélusca-Maïto     return;
990*23b7c7b8SHermès Bélusca-Maïto }
991*23b7c7b8SHermès Bélusca-Maïto 
992*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)993*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
994*23b7c7b8SHermès Bélusca-Maïto VOID
995*23b7c7b8SHermès Bélusca-Maïto FatCreateRootDcb (
996*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
997*23b7c7b8SHermès Bélusca-Maïto     IN PVCB Vcb
998*23b7c7b8SHermès Bélusca-Maïto     )
999*23b7c7b8SHermès Bélusca-Maïto 
1000*23b7c7b8SHermès Bélusca-Maïto /*++
1001*23b7c7b8SHermès Bélusca-Maïto 
1002*23b7c7b8SHermès Bélusca-Maïto Routine Description:
1003*23b7c7b8SHermès Bélusca-Maïto 
1004*23b7c7b8SHermès Bélusca-Maïto     This routine allocates, initializes, and inserts a new root DCB record
1005*23b7c7b8SHermès Bélusca-Maïto     into the in memory data structure.
1006*23b7c7b8SHermès Bélusca-Maïto 
1007*23b7c7b8SHermès Bélusca-Maïto Arguments:
1008*23b7c7b8SHermès Bélusca-Maïto 
1009*23b7c7b8SHermès Bélusca-Maïto     Vcb - Supplies the Vcb to associate the new DCB under
1010*23b7c7b8SHermès Bélusca-Maïto 
1011*23b7c7b8SHermès Bélusca-Maïto Return Value:
1012*23b7c7b8SHermès Bélusca-Maïto 
1013*23b7c7b8SHermès Bélusca-Maïto     None. The Vcb is modified in-place.
1014*23b7c7b8SHermès Bélusca-Maïto 
1015*23b7c7b8SHermès Bélusca-Maïto --*/
1016*23b7c7b8SHermès Bélusca-Maïto 
1017*23b7c7b8SHermès Bélusca-Maïto {
1018*23b7c7b8SHermès Bélusca-Maïto     PDCB Dcb = NULL;
1019*23b7c7b8SHermès Bélusca-Maïto 
1020*23b7c7b8SHermès Bélusca-Maïto     //
1021*23b7c7b8SHermès Bélusca-Maïto     //  The following variables are used for abnormal unwind
1022*23b7c7b8SHermès Bélusca-Maïto     //
1023*23b7c7b8SHermès Bélusca-Maïto 
1024*23b7c7b8SHermès Bélusca-Maïto     PVOID UnwindStorage[2] = { NULL, NULL };
1025*23b7c7b8SHermès Bélusca-Maïto     PERESOURCE UnwindResource = NULL;
1026*23b7c7b8SHermès Bélusca-Maïto     PERESOURCE UnwindResource2 = NULL;
1027*23b7c7b8SHermès Bélusca-Maïto     PLARGE_MCB UnwindMcb = NULL;
1028*23b7c7b8SHermès Bélusca-Maïto     PFILE_OBJECT UnwindFileObject = NULL;
1029*23b7c7b8SHermès Bélusca-Maïto 
1030*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
1031*23b7c7b8SHermès Bélusca-Maïto 
1032*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatCreateRootDcb, Vcb = %p\n", Vcb);
1033*23b7c7b8SHermès Bélusca-Maïto 
1034*23b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
1035*23b7c7b8SHermès Bélusca-Maïto 
1036*23b7c7b8SHermès Bélusca-Maïto         //
1037*23b7c7b8SHermès Bélusca-Maïto         //  Make sure we don't already have a root dcb for this vcb
1038*23b7c7b8SHermès Bélusca-Maïto         //
1039*23b7c7b8SHermès Bélusca-Maïto 
1040*23b7c7b8SHermès Bélusca-Maïto         if (Vcb->RootDcb != NULL) {
1041*23b7c7b8SHermès Bélusca-Maïto 
1042*23b7c7b8SHermès Bélusca-Maïto             DebugDump("Error trying to create multiple root dcbs\n", 0, Vcb);
1043*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
1044*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
1045*23b7c7b8SHermès Bélusca-Maïto #endif
1046*23b7c7b8SHermès Bélusca-Maïto             FatBugCheck( 0, 0, 0 );
1047*23b7c7b8SHermès Bélusca-Maïto         }
1048*23b7c7b8SHermès Bélusca-Maïto 
1049*23b7c7b8SHermès Bélusca-Maïto         //
1050*23b7c7b8SHermès Bélusca-Maïto         //  Allocate a new DCB and zero it out, we use Dcb locally so we don't
1051*23b7c7b8SHermès Bélusca-Maïto         //  have to continually reference through the Vcb
1052*23b7c7b8SHermès Bélusca-Maïto         //
1053*23b7c7b8SHermès Bélusca-Maïto 
1054*23b7c7b8SHermès Bélusca-Maïto         UnwindStorage[0] = Dcb = Vcb->RootDcb = FsRtlAllocatePoolWithTag( NonPagedPoolNx,
1055*23b7c7b8SHermès Bélusca-Maïto                                                                           sizeof(DCB),
1056*23b7c7b8SHermès Bélusca-Maïto                                                                           TAG_FCB );
1057*23b7c7b8SHermès Bélusca-Maïto 
1058*23b7c7b8SHermès Bélusca-Maïto         RtlZeroMemory( Dcb, sizeof(DCB));
1059*23b7c7b8SHermès Bélusca-Maïto 
1060*23b7c7b8SHermès Bélusca-Maïto         UnwindStorage[1] =
1061*23b7c7b8SHermès Bélusca-Maïto         Dcb->NonPaged = FatAllocateNonPagedFcb();
1062*23b7c7b8SHermès Bélusca-Maïto 
1063*23b7c7b8SHermès Bélusca-Maïto         RtlZeroMemory( Dcb->NonPaged, sizeof( NON_PAGED_FCB ) );
1064*23b7c7b8SHermès Bélusca-Maïto 
1065*23b7c7b8SHermès Bélusca-Maïto         //
1066*23b7c7b8SHermès Bélusca-Maïto         //  Set the proper node type code, node byte size, and call backs
1067*23b7c7b8SHermès Bélusca-Maïto         //
1068*23b7c7b8SHermès Bélusca-Maïto 
1069*23b7c7b8SHermès Bélusca-Maïto         Dcb->Header.NodeTypeCode = FAT_NTC_ROOT_DCB;
1070*23b7c7b8SHermès Bélusca-Maïto         Dcb->Header.NodeByteSize = sizeof(DCB);
1071*23b7c7b8SHermès Bélusca-Maïto 
1072*23b7c7b8SHermès Bélusca-Maïto         Dcb->FcbCondition = FcbGood;
1073*23b7c7b8SHermès Bélusca-Maïto 
1074*23b7c7b8SHermès Bélusca-Maïto         //
1075*23b7c7b8SHermès Bélusca-Maïto         //  The parent Dcb, initial state, open count, dirent location
1076*23b7c7b8SHermès Bélusca-Maïto         //  information, and directory change count fields are already zero so
1077*23b7c7b8SHermès Bélusca-Maïto         //  we can skip setting them
1078*23b7c7b8SHermès Bélusca-Maïto         //
1079*23b7c7b8SHermès Bélusca-Maïto 
1080*23b7c7b8SHermès Bélusca-Maïto         //
1081*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the resource variable
1082*23b7c7b8SHermès Bélusca-Maïto         //
1083*23b7c7b8SHermès Bélusca-Maïto 
1084*23b7c7b8SHermès Bélusca-Maïto         UnwindResource =
1085*23b7c7b8SHermès Bélusca-Maïto         Dcb->Header.Resource = FatAllocateResource();
1086*23b7c7b8SHermès Bélusca-Maïto 
1087*23b7c7b8SHermès Bélusca-Maïto         //
1088*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the PagingIo Resource.  We no longer use the FsRtl common
1089*23b7c7b8SHermès Bélusca-Maïto         //  shared pool because this led to a) deadlocks due to cases where files
1090*23b7c7b8SHermès Bélusca-Maïto         //  and their parent directories shared a resource and b) there is no way
1091*23b7c7b8SHermès Bélusca-Maïto         //  to anticipate inter-driver induced deadlock via recursive operation.
1092*23b7c7b8SHermès Bélusca-Maïto         //
1093*23b7c7b8SHermès Bélusca-Maïto 
1094*23b7c7b8SHermès Bélusca-Maïto         UnwindResource2 =
1095*23b7c7b8SHermès Bélusca-Maïto         Dcb->Header.PagingIoResource = FatAllocateResource();
1096*23b7c7b8SHermès Bélusca-Maïto 
1097*23b7c7b8SHermès Bélusca-Maïto         //
1098*23b7c7b8SHermès Bélusca-Maïto         //  The root Dcb has an empty parent dcb links field
1099*23b7c7b8SHermès Bélusca-Maïto         //
1100*23b7c7b8SHermès Bélusca-Maïto 
1101*23b7c7b8SHermès Bélusca-Maïto         InitializeListHead( &Dcb->ParentDcbLinks );
1102*23b7c7b8SHermès Bélusca-Maïto 
1103*23b7c7b8SHermès Bélusca-Maïto         //
1104*23b7c7b8SHermès Bélusca-Maïto         //  Set the Vcb
1105*23b7c7b8SHermès Bélusca-Maïto         //
1106*23b7c7b8SHermès Bélusca-Maïto 
1107*23b7c7b8SHermès Bélusca-Maïto         Dcb->Vcb = Vcb;
1108*23b7c7b8SHermès Bélusca-Maïto 
1109*23b7c7b8SHermès Bélusca-Maïto         //
1110*23b7c7b8SHermès Bélusca-Maïto         //  initialize the parent dcb queue.
1111*23b7c7b8SHermès Bélusca-Maïto         //
1112*23b7c7b8SHermès Bélusca-Maïto 
1113*23b7c7b8SHermès Bélusca-Maïto         InitializeListHead( &Dcb->Specific.Dcb.ParentDcbQueue );
1114*23b7c7b8SHermès Bélusca-Maïto 
1115*23b7c7b8SHermès Bélusca-Maïto         //
1116*23b7c7b8SHermès Bélusca-Maïto         //  Set the full file name up.
1117*23b7c7b8SHermès Bélusca-Maïto         //
1118*23b7c7b8SHermès Bélusca-Maïto 
1119*23b7c7b8SHermès Bélusca-Maïto         Dcb->FullFileName.Buffer = L"\\";
1120*23b7c7b8SHermès Bélusca-Maïto         Dcb->FullFileName.Length = (USHORT)2;
1121*23b7c7b8SHermès Bélusca-Maïto         Dcb->FullFileName.MaximumLength = (USHORT)4;
1122*23b7c7b8SHermès Bélusca-Maïto 
1123*23b7c7b8SHermès Bélusca-Maïto         Dcb->ShortName.Name.Oem.Buffer = "\\";
1124*23b7c7b8SHermès Bélusca-Maïto         Dcb->ShortName.Name.Oem.Length = (USHORT)1;
1125*23b7c7b8SHermès Bélusca-Maïto         Dcb->ShortName.Name.Oem.MaximumLength = (USHORT)2;
1126*23b7c7b8SHermès Bélusca-Maïto 
1127*23b7c7b8SHermès Bélusca-Maïto         //
1128*23b7c7b8SHermès Bélusca-Maïto         //  Construct a lie about file properties since we don't
1129*23b7c7b8SHermès Bélusca-Maïto         //  have a proper "." entry to look at.
1130*23b7c7b8SHermès Bélusca-Maïto         //
1131*23b7c7b8SHermès Bélusca-Maïto 
1132*23b7c7b8SHermès Bélusca-Maïto         Dcb->DirentFatFlags = FILE_ATTRIBUTE_DIRECTORY;
1133*23b7c7b8SHermès Bélusca-Maïto 
1134*23b7c7b8SHermès Bélusca-Maïto         //
1135*23b7c7b8SHermès Bélusca-Maïto         //  Initialize Advanced FCB Header fields
1136*23b7c7b8SHermès Bélusca-Maïto         //
1137*23b7c7b8SHermès Bélusca-Maïto 
1138*23b7c7b8SHermès Bélusca-Maïto         ExInitializeFastMutex( &Dcb->NonPaged->AdvancedFcbHeaderMutex );
1139*23b7c7b8SHermès Bélusca-Maïto         FsRtlSetupAdvancedHeader( &Dcb->Header,
1140*23b7c7b8SHermès Bélusca-Maïto                                   &Dcb->NonPaged->AdvancedFcbHeaderMutex );
1141*23b7c7b8SHermès Bélusca-Maïto 
1142*23b7c7b8SHermès Bélusca-Maïto         //
1143*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the Mcb, and setup its mapping.  Note that the root
1144*23b7c7b8SHermès Bélusca-Maïto         //  directory is a fixed size so we can set it everything up now.
1145*23b7c7b8SHermès Bélusca-Maïto         //
1146*23b7c7b8SHermès Bélusca-Maïto 
1147*23b7c7b8SHermès Bélusca-Maïto         FsRtlInitializeLargeMcb( &Dcb->Mcb, NonPagedPoolNx );
1148*23b7c7b8SHermès Bélusca-Maïto         UnwindMcb = &Dcb->Mcb;
1149*23b7c7b8SHermès Bélusca-Maïto 
1150*23b7c7b8SHermès Bélusca-Maïto         if (FatIsFat32(Vcb)) {
1151*23b7c7b8SHermès Bélusca-Maïto 
1152*23b7c7b8SHermès Bélusca-Maïto             //
1153*23b7c7b8SHermès Bélusca-Maïto             //  The first cluster of fat32 roots comes from the BPB
1154*23b7c7b8SHermès Bélusca-Maïto             //
1155*23b7c7b8SHermès Bélusca-Maïto 
1156*23b7c7b8SHermès Bélusca-Maïto             Dcb->FirstClusterOfFile = Vcb->Bpb.RootDirFirstCluster;
1157*23b7c7b8SHermès Bélusca-Maïto 
1158*23b7c7b8SHermès Bélusca-Maïto         } else {
1159*23b7c7b8SHermès Bélusca-Maïto 
1160*23b7c7b8SHermès Bélusca-Maïto             FatAddMcbEntry( Vcb, &Dcb->Mcb,
1161*23b7c7b8SHermès Bélusca-Maïto                             0,
1162*23b7c7b8SHermès Bélusca-Maïto                             FatRootDirectoryLbo( &Vcb->Bpb ),
1163*23b7c7b8SHermès Bélusca-Maïto                             FatRootDirectorySize( &Vcb->Bpb ));
1164*23b7c7b8SHermès Bélusca-Maïto         }
1165*23b7c7b8SHermès Bélusca-Maïto 
1166*23b7c7b8SHermès Bélusca-Maïto         if (FatIsFat32(Vcb)) {
1167*23b7c7b8SHermès Bélusca-Maïto 
1168*23b7c7b8SHermès Bélusca-Maïto             //
1169*23b7c7b8SHermès Bélusca-Maïto             //  Find the size of the fat32 root. As a side-effect, this will create
1170*23b7c7b8SHermès Bélusca-Maïto             //  MCBs for the entire root. In the process of doing this, we may
1171*23b7c7b8SHermès Bélusca-Maïto             //  discover that the FAT chain is bogus and raise corruption.
1172*23b7c7b8SHermès Bélusca-Maïto             //
1173*23b7c7b8SHermès Bélusca-Maïto 
1174*23b7c7b8SHermès Bélusca-Maïto             Dcb->Header.AllocationSize.LowPart = 0xFFFFFFFF;
1175*23b7c7b8SHermès Bélusca-Maïto             FatLookupFileAllocationSize( IrpContext, Dcb);
1176*23b7c7b8SHermès Bélusca-Maïto 
1177*23b7c7b8SHermès Bélusca-Maïto             Dcb->Header.FileSize.QuadPart =
1178*23b7c7b8SHermès Bélusca-Maïto                     Dcb->Header.AllocationSize.QuadPart;
1179*23b7c7b8SHermès Bélusca-Maïto         } else {
1180*23b7c7b8SHermès Bélusca-Maïto 
1181*23b7c7b8SHermès Bélusca-Maïto             //
1182*23b7c7b8SHermès Bélusca-Maïto             //  set the allocation size to real size of the root directory
1183*23b7c7b8SHermès Bélusca-Maïto             //
1184*23b7c7b8SHermès Bélusca-Maïto 
1185*23b7c7b8SHermès Bélusca-Maïto             Dcb->Header.FileSize.QuadPart =
1186*23b7c7b8SHermès Bélusca-Maïto             Dcb->Header.AllocationSize.QuadPart = FatRootDirectorySize( &Vcb->Bpb );
1187*23b7c7b8SHermès Bélusca-Maïto 
1188*23b7c7b8SHermès Bélusca-Maïto         }
1189*23b7c7b8SHermès Bélusca-Maïto 
1190*23b7c7b8SHermès Bélusca-Maïto         //
1191*23b7c7b8SHermès Bélusca-Maïto         //  Set our two create dirent aids to represent that we have yet to
1192*23b7c7b8SHermès Bélusca-Maïto         //  enumerate the directory for never used or deleted dirents.
1193*23b7c7b8SHermès Bélusca-Maïto         //
1194*23b7c7b8SHermès Bélusca-Maïto 
1195*23b7c7b8SHermès Bélusca-Maïto         Dcb->Specific.Dcb.UnusedDirentVbo = 0xffffffff;
1196*23b7c7b8SHermès Bélusca-Maïto         Dcb->Specific.Dcb.DeletedDirentHint = 0xffffffff;
1197*23b7c7b8SHermès Bélusca-Maïto 
1198*23b7c7b8SHermès Bélusca-Maïto         //
1199*23b7c7b8SHermès Bélusca-Maïto         //  Setup the free dirent bitmap buffer.
1200*23b7c7b8SHermès Bélusca-Maïto         //
1201*23b7c7b8SHermès Bélusca-Maïto 
1202*23b7c7b8SHermès Bélusca-Maïto         RtlInitializeBitMap( &Dcb->Specific.Dcb.FreeDirentBitmap,
1203*23b7c7b8SHermès Bélusca-Maïto                              NULL,
1204*23b7c7b8SHermès Bélusca-Maïto                              0 );
1205*23b7c7b8SHermès Bélusca-Maïto 
1206*23b7c7b8SHermès Bélusca-Maïto         FatCheckFreeDirentBitmap( IrpContext, Dcb );
1207*23b7c7b8SHermès Bélusca-Maïto 
1208*23b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN8)
1209*23b7c7b8SHermès Bélusca-Maïto         //
1210*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the oplock structure.
1211*23b7c7b8SHermès Bélusca-Maïto         //
1212*23b7c7b8SHermès Bélusca-Maïto 
1213*23b7c7b8SHermès Bélusca-Maïto         FsRtlInitializeOplock( FatGetFcbOplock(Dcb) );
1214*23b7c7b8SHermès Bélusca-Maïto #endif
1215*23b7c7b8SHermès Bélusca-Maïto 
1216*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
1217*23b7c7b8SHermès Bélusca-Maïto 
1218*23b7c7b8SHermès Bélusca-Maïto         DebugUnwind( FatCreateRootDcb );
1219*23b7c7b8SHermès Bélusca-Maïto 
1220*23b7c7b8SHermès Bélusca-Maïto         //
1221*23b7c7b8SHermès Bélusca-Maïto         //  If this is an abnormal termination then undo our work
1222*23b7c7b8SHermès Bélusca-Maïto         //
1223*23b7c7b8SHermès Bélusca-Maïto 
1224*23b7c7b8SHermès Bélusca-Maïto         if (_SEH2_AbnormalTermination()) {
1225*23b7c7b8SHermès Bélusca-Maïto 
1226*23b7c7b8SHermès Bélusca-Maïto             ULONG i;
1227*23b7c7b8SHermès Bélusca-Maïto 
1228*23b7c7b8SHermès Bélusca-Maïto             if (UnwindFileObject != NULL) { ObDereferenceObject( UnwindFileObject ); }
1229*23b7c7b8SHermès Bélusca-Maïto             if (UnwindMcb != NULL) { FsRtlUninitializeLargeMcb( UnwindMcb ); }
1230*23b7c7b8SHermès Bélusca-Maïto             if (UnwindResource != NULL) { FatFreeResource( UnwindResource ); }
1231*23b7c7b8SHermès Bélusca-Maïto             if (UnwindResource2 != NULL) { FatFreeResource( UnwindResource2 ); }
1232*23b7c7b8SHermès Bélusca-Maïto 
1233*23b7c7b8SHermès Bélusca-Maïto             for (i = 0; i < sizeof(UnwindStorage)/sizeof(PVOID); i += 1) {
1234*23b7c7b8SHermès Bélusca-Maïto                 if (UnwindStorage[i] != NULL) { ExFreePool( UnwindStorage[i] ); }
1235*23b7c7b8SHermès Bélusca-Maïto             }
1236*23b7c7b8SHermès Bélusca-Maïto 
1237*23b7c7b8SHermès Bélusca-Maïto             //
1238*23b7c7b8SHermès Bélusca-Maïto             //  Re-zero the entry in the Vcb.
1239*23b7c7b8SHermès Bélusca-Maïto             //
1240*23b7c7b8SHermès Bélusca-Maïto 
1241*23b7c7b8SHermès Bélusca-Maïto             Vcb->RootDcb = NULL;
1242*23b7c7b8SHermès Bélusca-Maïto         }
1243*23b7c7b8SHermès Bélusca-Maïto 
1244*23b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatCreateRootDcb -> %p\n", Dcb);
1245*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
1246*23b7c7b8SHermès Bélusca-Maïto 
1247*23b7c7b8SHermès Bélusca-Maïto     return;
1248*23b7c7b8SHermès Bélusca-Maïto }
1249*23b7c7b8SHermès Bélusca-Maïto 
1250*23b7c7b8SHermès Bélusca-Maïto 
1251*23b7c7b8SHermès Bélusca-Maïto PFCB
FatCreateFcb(IN PIRP_CONTEXT IrpContext,IN PVCB Vcb,IN PDCB ParentDcb,IN ULONG LfnOffsetWithinDirectory,IN ULONG DirentOffsetWithinDirectory,IN PDIRENT Dirent,IN PUNICODE_STRING Lfn OPTIONAL,IN PUNICODE_STRING OrigLfn OPTIONAL,IN BOOLEAN IsPagingFile,IN BOOLEAN SingleResource)1252*23b7c7b8SHermès Bélusca-Maïto FatCreateFcb (
1253*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
1254*23b7c7b8SHermès Bélusca-Maïto     IN PVCB Vcb,
1255*23b7c7b8SHermès Bélusca-Maïto     IN PDCB ParentDcb,
1256*23b7c7b8SHermès Bélusca-Maïto     IN ULONG LfnOffsetWithinDirectory,
1257*23b7c7b8SHermès Bélusca-Maïto     IN ULONG DirentOffsetWithinDirectory,
1258*23b7c7b8SHermès Bélusca-Maïto     IN PDIRENT Dirent,
1259*23b7c7b8SHermès Bélusca-Maïto     IN PUNICODE_STRING Lfn OPTIONAL,
1260*23b7c7b8SHermès Bélusca-Maïto     IN PUNICODE_STRING OrigLfn OPTIONAL,
1261*23b7c7b8SHermès Bélusca-Maïto     IN BOOLEAN IsPagingFile,
1262*23b7c7b8SHermès Bélusca-Maïto     IN BOOLEAN SingleResource
1263*23b7c7b8SHermès Bélusca-Maïto     )
1264*23b7c7b8SHermès Bélusca-Maïto 
1265*23b7c7b8SHermès Bélusca-Maïto /*++
1266*23b7c7b8SHermès Bélusca-Maïto 
1267*23b7c7b8SHermès Bélusca-Maïto Routine Description:
1268*23b7c7b8SHermès Bélusca-Maïto 
1269*23b7c7b8SHermès Bélusca-Maïto     This routine allocates, initializes, and inserts a new Fcb record into
1270*23b7c7b8SHermès Bélusca-Maïto     the in-memory data structures.
1271*23b7c7b8SHermès Bélusca-Maïto 
1272*23b7c7b8SHermès Bélusca-Maïto Arguments:
1273*23b7c7b8SHermès Bélusca-Maïto 
1274*23b7c7b8SHermès Bélusca-Maïto     Vcb - Supplies the Vcb to associate the new FCB under.
1275*23b7c7b8SHermès Bélusca-Maïto 
1276*23b7c7b8SHermès Bélusca-Maïto     ParentDcb - Supplies the parent dcb that the new FCB is under.
1277*23b7c7b8SHermès Bélusca-Maïto 
1278*23b7c7b8SHermès Bélusca-Maïto     LfnOffsetWithinDirectory - Supplies the offset of the LFN.  If there is
1279*23b7c7b8SHermès Bélusca-Maïto         no LFN associated with this file then this value is same as
1280*23b7c7b8SHermès Bélusca-Maïto         DirentOffsetWithinDirectory.
1281*23b7c7b8SHermès Bélusca-Maïto 
1282*23b7c7b8SHermès Bélusca-Maïto     DirentOffsetWithinDirectory - Supplies the offset, in bytes from the
1283*23b7c7b8SHermès Bélusca-Maïto         start of the directory file where the dirent for the fcb is located
1284*23b7c7b8SHermès Bélusca-Maïto 
1285*23b7c7b8SHermès Bélusca-Maïto     Dirent - Supplies the dirent for the fcb being created
1286*23b7c7b8SHermès Bélusca-Maïto 
1287*23b7c7b8SHermès Bélusca-Maïto     Lfn - Supplies a long UNICODE name associated with this file.
1288*23b7c7b8SHermès Bélusca-Maïto 
1289*23b7c7b8SHermès Bélusca-Maïto     IsPagingFile - Indicates if we are creating an FCB for a paging file
1290*23b7c7b8SHermès Bélusca-Maïto         or some other type of file.
1291*23b7c7b8SHermès Bélusca-Maïto 
1292*23b7c7b8SHermès Bélusca-Maïto     SingleResource - Indicates if this Fcb should share a single resource
1293*23b7c7b8SHermès Bélusca-Maïto         as both main and paging.
1294*23b7c7b8SHermès Bélusca-Maïto 
1295*23b7c7b8SHermès Bélusca-Maïto Return Value:
1296*23b7c7b8SHermès Bélusca-Maïto 
1297*23b7c7b8SHermès Bélusca-Maïto     PFCB - Returns a pointer to the newly allocated FCB
1298*23b7c7b8SHermès Bélusca-Maïto 
1299*23b7c7b8SHermès Bélusca-Maïto --*/
1300*23b7c7b8SHermès Bélusca-Maïto 
1301*23b7c7b8SHermès Bélusca-Maïto {
1302*23b7c7b8SHermès Bélusca-Maïto     PFCB Fcb = NULL;
1303*23b7c7b8SHermès Bélusca-Maïto     POOL_TYPE PoolType;
1304*23b7c7b8SHermès Bélusca-Maïto 
1305*23b7c7b8SHermès Bélusca-Maïto     //
1306*23b7c7b8SHermès Bélusca-Maïto     //  The following variables are used for abnormal unwind
1307*23b7c7b8SHermès Bélusca-Maïto     //
1308*23b7c7b8SHermès Bélusca-Maïto 
1309*23b7c7b8SHermès Bélusca-Maïto     PVOID UnwindStorage[2] = { NULL, NULL };
1310*23b7c7b8SHermès Bélusca-Maïto     PERESOURCE UnwindResource = NULL;
1311*23b7c7b8SHermès Bélusca-Maïto     PERESOURCE UnwindResource2 = NULL;
1312*23b7c7b8SHermès Bélusca-Maïto     PLIST_ENTRY UnwindEntryList = NULL;
1313*23b7c7b8SHermès Bélusca-Maïto     PLARGE_MCB UnwindMcb = NULL;
1314*23b7c7b8SHermès Bélusca-Maïto     PFILE_LOCK UnwindFileLock = NULL;
1315*23b7c7b8SHermès Bélusca-Maïto     POPLOCK UnwindOplock = NULL;
1316*23b7c7b8SHermès Bélusca-Maïto 
1317*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
1318*23b7c7b8SHermès Bélusca-Maïto 
1319*23b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( OrigLfn );
1320*23b7c7b8SHermès Bélusca-Maïto 
1321*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatCreateFcb\n", 0);
1322*23b7c7b8SHermès Bélusca-Maïto 
1323*23b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
1324*23b7c7b8SHermès Bélusca-Maïto 
1325*23b7c7b8SHermès Bélusca-Maïto         //
1326*23b7c7b8SHermès Bélusca-Maïto         //  Determine the pool type we should be using for the fcb and the
1327*23b7c7b8SHermès Bélusca-Maïto         //  mcb structure
1328*23b7c7b8SHermès Bélusca-Maïto         //
1329*23b7c7b8SHermès Bélusca-Maïto 
1330*23b7c7b8SHermès Bélusca-Maïto         if (IsPagingFile) {
1331*23b7c7b8SHermès Bélusca-Maïto 
1332*23b7c7b8SHermès Bélusca-Maïto             PoolType = NonPagedPoolNx;
1333*23b7c7b8SHermès Bélusca-Maïto             Fcb = UnwindStorage[0] = FsRtlAllocatePoolWithTag( NonPagedPoolNx,
1334*23b7c7b8SHermès Bélusca-Maïto                                                                sizeof(FCB),
1335*23b7c7b8SHermès Bélusca-Maïto                                                                TAG_FCB );
1336*23b7c7b8SHermès Bélusca-Maïto         } else {
1337*23b7c7b8SHermès Bélusca-Maïto 
1338*23b7c7b8SHermès Bélusca-Maïto             PoolType = PagedPool;
1339*23b7c7b8SHermès Bélusca-Maïto             Fcb = UnwindStorage[0] = FatAllocateFcb();
1340*23b7c7b8SHermès Bélusca-Maïto 
1341*23b7c7b8SHermès Bélusca-Maïto         }
1342*23b7c7b8SHermès Bélusca-Maïto 
1343*23b7c7b8SHermès Bélusca-Maïto         //
1344*23b7c7b8SHermès Bélusca-Maïto         //  ... and zero it out
1345*23b7c7b8SHermès Bélusca-Maïto         //
1346*23b7c7b8SHermès Bélusca-Maïto 
1347*23b7c7b8SHermès Bélusca-Maïto         RtlZeroMemory( Fcb, sizeof(FCB) );
1348*23b7c7b8SHermès Bélusca-Maïto 
1349*23b7c7b8SHermès Bélusca-Maïto         UnwindStorage[1] =
1350*23b7c7b8SHermès Bélusca-Maïto         Fcb->NonPaged = FatAllocateNonPagedFcb();
1351*23b7c7b8SHermès Bélusca-Maïto 
1352*23b7c7b8SHermès Bélusca-Maïto         RtlZeroMemory( Fcb->NonPaged, sizeof( NON_PAGED_FCB ) );
1353*23b7c7b8SHermès Bélusca-Maïto 
1354*23b7c7b8SHermès Bélusca-Maïto         //
1355*23b7c7b8SHermès Bélusca-Maïto         //  Set the proper node type code, node byte size, and call backs
1356*23b7c7b8SHermès Bélusca-Maïto         //
1357*23b7c7b8SHermès Bélusca-Maïto 
1358*23b7c7b8SHermès Bélusca-Maïto         Fcb->Header.NodeTypeCode = FAT_NTC_FCB;
1359*23b7c7b8SHermès Bélusca-Maïto         Fcb->Header.NodeByteSize = sizeof(FCB);
1360*23b7c7b8SHermès Bélusca-Maïto 
1361*23b7c7b8SHermès Bélusca-Maïto         Fcb->FcbCondition = FcbGood;
1362*23b7c7b8SHermès Bélusca-Maïto 
1363*23b7c7b8SHermès Bélusca-Maïto         //
1364*23b7c7b8SHermès Bélusca-Maïto         //  Check to see if we need to set the Fcb state to indicate that this
1365*23b7c7b8SHermès Bélusca-Maïto         //  is a paging/system file.  This will prevent it from being opened
1366*23b7c7b8SHermès Bélusca-Maïto         //  again.
1367*23b7c7b8SHermès Bélusca-Maïto         //
1368*23b7c7b8SHermès Bélusca-Maïto 
1369*23b7c7b8SHermès Bélusca-Maïto         if (IsPagingFile) {
1370*23b7c7b8SHermès Bélusca-Maïto 
1371*23b7c7b8SHermès Bélusca-Maïto             SetFlag( Fcb->FcbState, FCB_STATE_PAGING_FILE | FCB_STATE_SYSTEM_FILE );
1372*23b7c7b8SHermès Bélusca-Maïto         }
1373*23b7c7b8SHermès Bélusca-Maïto 
1374*23b7c7b8SHermès Bélusca-Maïto         //
1375*23b7c7b8SHermès Bélusca-Maïto         //  The initial state, open count, and segment objects fields are already
1376*23b7c7b8SHermès Bélusca-Maïto         //  zero so we can skip setting them
1377*23b7c7b8SHermès Bélusca-Maïto         //
1378*23b7c7b8SHermès Bélusca-Maïto 
1379*23b7c7b8SHermès Bélusca-Maïto         //
1380*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the resource variable
1381*23b7c7b8SHermès Bélusca-Maïto         //
1382*23b7c7b8SHermès Bélusca-Maïto 
1383*23b7c7b8SHermès Bélusca-Maïto 
1384*23b7c7b8SHermès Bélusca-Maïto         UnwindResource =
1385*23b7c7b8SHermès Bélusca-Maïto         Fcb->Header.Resource = FatAllocateResource();
1386*23b7c7b8SHermès Bélusca-Maïto 
1387*23b7c7b8SHermès Bélusca-Maïto         //
1388*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the PagingIo Resource.  We no longer use the FsRtl common
1389*23b7c7b8SHermès Bélusca-Maïto         //  shared pool because this led to a) deadlocks due to cases where files
1390*23b7c7b8SHermès Bélusca-Maïto         //  and their parent directories shared a resource and b) there is no way
1391*23b7c7b8SHermès Bélusca-Maïto         //  to anticipate inter-driver induced deadlock via recursive operation.
1392*23b7c7b8SHermès Bélusca-Maïto         //
1393*23b7c7b8SHermès Bélusca-Maïto 
1394*23b7c7b8SHermès Bélusca-Maïto         if (SingleResource) {
1395*23b7c7b8SHermès Bélusca-Maïto 
1396*23b7c7b8SHermès Bélusca-Maïto             Fcb->Header.PagingIoResource = Fcb->Header.Resource;
1397*23b7c7b8SHermès Bélusca-Maïto 
1398*23b7c7b8SHermès Bélusca-Maïto         } else {
1399*23b7c7b8SHermès Bélusca-Maïto 
1400*23b7c7b8SHermès Bélusca-Maïto             UnwindResource2 =
1401*23b7c7b8SHermès Bélusca-Maïto             Fcb->Header.PagingIoResource = FatAllocateResource();
1402*23b7c7b8SHermès Bélusca-Maïto         }
1403*23b7c7b8SHermès Bélusca-Maïto 
1404*23b7c7b8SHermès Bélusca-Maïto         //
1405*23b7c7b8SHermès Bélusca-Maïto         //  Insert this fcb into our parent dcb's queue.
1406*23b7c7b8SHermès Bélusca-Maïto         //
1407*23b7c7b8SHermès Bélusca-Maïto         //  There is a deep reason why this goes on the tail, to allow us
1408*23b7c7b8SHermès Bélusca-Maïto         //  to easily enumerate all child directories before child files.
1409*23b7c7b8SHermès Bélusca-Maïto         //  This is important to let us maintain whole-volume lockorder
1410*23b7c7b8SHermès Bélusca-Maïto         //  via BottomUp enumeration.
1411*23b7c7b8SHermès Bélusca-Maïto         //
1412*23b7c7b8SHermès Bélusca-Maïto 
1413*23b7c7b8SHermès Bélusca-Maïto         InsertTailList( &ParentDcb->Specific.Dcb.ParentDcbQueue,
1414*23b7c7b8SHermès Bélusca-Maïto                         &Fcb->ParentDcbLinks );
1415*23b7c7b8SHermès Bélusca-Maïto         UnwindEntryList = &Fcb->ParentDcbLinks;
1416*23b7c7b8SHermès Bélusca-Maïto 
1417*23b7c7b8SHermès Bélusca-Maïto         //
1418*23b7c7b8SHermès Bélusca-Maïto         //  Point back to our parent dcb
1419*23b7c7b8SHermès Bélusca-Maïto         //
1420*23b7c7b8SHermès Bélusca-Maïto 
1421*23b7c7b8SHermès Bélusca-Maïto         Fcb->ParentDcb = ParentDcb;
1422*23b7c7b8SHermès Bélusca-Maïto 
1423*23b7c7b8SHermès Bélusca-Maïto         //
1424*23b7c7b8SHermès Bélusca-Maïto         //  Set the Vcb
1425*23b7c7b8SHermès Bélusca-Maïto         //
1426*23b7c7b8SHermès Bélusca-Maïto 
1427*23b7c7b8SHermès Bélusca-Maïto         Fcb->Vcb = Vcb;
1428*23b7c7b8SHermès Bélusca-Maïto 
1429*23b7c7b8SHermès Bélusca-Maïto         //
1430*23b7c7b8SHermès Bélusca-Maïto         //  Set the dirent offset within the directory
1431*23b7c7b8SHermès Bélusca-Maïto         //
1432*23b7c7b8SHermès Bélusca-Maïto 
1433*23b7c7b8SHermès Bélusca-Maïto         Fcb->LfnOffsetWithinDirectory = LfnOffsetWithinDirectory;
1434*23b7c7b8SHermès Bélusca-Maïto         Fcb->DirentOffsetWithinDirectory = DirentOffsetWithinDirectory;
1435*23b7c7b8SHermès Bélusca-Maïto 
1436*23b7c7b8SHermès Bélusca-Maïto         //
1437*23b7c7b8SHermès Bélusca-Maïto         //  Set the DirentFatFlags and LastWriteTime
1438*23b7c7b8SHermès Bélusca-Maïto         //
1439*23b7c7b8SHermès Bélusca-Maïto 
1440*23b7c7b8SHermès Bélusca-Maïto         Fcb->DirentFatFlags = Dirent->Attributes;
1441*23b7c7b8SHermès Bélusca-Maïto 
1442*23b7c7b8SHermès Bélusca-Maïto         Fcb->LastWriteTime = FatFatTimeToNtTime( IrpContext,
1443*23b7c7b8SHermès Bélusca-Maïto                                                  Dirent->LastWriteTime,
1444*23b7c7b8SHermès Bélusca-Maïto                                                  0 );
1445*23b7c7b8SHermès Bélusca-Maïto 
1446*23b7c7b8SHermès Bélusca-Maïto         //
1447*23b7c7b8SHermès Bélusca-Maïto         //  These fields are only non-zero when in Chicago mode.
1448*23b7c7b8SHermès Bélusca-Maïto         //
1449*23b7c7b8SHermès Bélusca-Maïto 
1450*23b7c7b8SHermès Bélusca-Maïto         if (FatData.ChicagoMode) {
1451*23b7c7b8SHermès Bélusca-Maïto 
1452*23b7c7b8SHermès Bélusca-Maïto             LARGE_INTEGER FatSystemJanOne1980 = {0};
1453*23b7c7b8SHermès Bélusca-Maïto 
1454*23b7c7b8SHermès Bélusca-Maïto             //
1455*23b7c7b8SHermès Bélusca-Maïto             //  If either date is possibly zero, get the system
1456*23b7c7b8SHermès Bélusca-Maïto             //  version of 1/1/80.
1457*23b7c7b8SHermès Bélusca-Maïto             //
1458*23b7c7b8SHermès Bélusca-Maïto 
1459*23b7c7b8SHermès Bélusca-Maïto             if ((((PUSHORT)Dirent)[9] & ((PUSHORT)Dirent)[8]) == 0) {
1460*23b7c7b8SHermès Bélusca-Maïto 
1461*23b7c7b8SHermès Bélusca-Maïto                 ExLocalTimeToSystemTime( &FatJanOne1980,
1462*23b7c7b8SHermès Bélusca-Maïto                                          &FatSystemJanOne1980 );
1463*23b7c7b8SHermès Bélusca-Maïto             }
1464*23b7c7b8SHermès Bélusca-Maïto 
1465*23b7c7b8SHermès Bélusca-Maïto             //
1466*23b7c7b8SHermès Bélusca-Maïto             //  Only do the really hard work if this field is non-zero.
1467*23b7c7b8SHermès Bélusca-Maïto             //
1468*23b7c7b8SHermès Bélusca-Maïto 
1469*23b7c7b8SHermès Bélusca-Maïto             if (((PUSHORT)Dirent)[9] != 0) {
1470*23b7c7b8SHermès Bélusca-Maïto 
1471*23b7c7b8SHermès Bélusca-Maïto                 Fcb->LastAccessTime =
1472*23b7c7b8SHermès Bélusca-Maïto                     FatFatDateToNtTime( IrpContext,
1473*23b7c7b8SHermès Bélusca-Maïto                                         Dirent->LastAccessDate );
1474*23b7c7b8SHermès Bélusca-Maïto 
1475*23b7c7b8SHermès Bélusca-Maïto             } else {
1476*23b7c7b8SHermès Bélusca-Maïto 
1477*23b7c7b8SHermès Bélusca-Maïto                 Fcb->LastAccessTime = FatSystemJanOne1980;
1478*23b7c7b8SHermès Bélusca-Maïto             }
1479*23b7c7b8SHermès Bélusca-Maïto 
1480*23b7c7b8SHermès Bélusca-Maïto             //
1481*23b7c7b8SHermès Bélusca-Maïto             //  Only do the really hard work if this field is non-zero.
1482*23b7c7b8SHermès Bélusca-Maïto             //
1483*23b7c7b8SHermès Bélusca-Maïto 
1484*23b7c7b8SHermès Bélusca-Maïto             if (((PUSHORT)Dirent)[8] != 0) {
1485*23b7c7b8SHermès Bélusca-Maïto 
1486*23b7c7b8SHermès Bélusca-Maïto                 Fcb->CreationTime =
1487*23b7c7b8SHermès Bélusca-Maïto                     FatFatTimeToNtTime( IrpContext,
1488*23b7c7b8SHermès Bélusca-Maïto                                         Dirent->CreationTime,
1489*23b7c7b8SHermès Bélusca-Maïto                                         Dirent->CreationMSec );
1490*23b7c7b8SHermès Bélusca-Maïto 
1491*23b7c7b8SHermès Bélusca-Maïto             } else {
1492*23b7c7b8SHermès Bélusca-Maïto 
1493*23b7c7b8SHermès Bélusca-Maïto                 Fcb->CreationTime = FatSystemJanOne1980;
1494*23b7c7b8SHermès Bélusca-Maïto             }
1495*23b7c7b8SHermès Bélusca-Maïto         }
1496*23b7c7b8SHermès Bélusca-Maïto 
1497*23b7c7b8SHermès Bélusca-Maïto         //
1498*23b7c7b8SHermès Bélusca-Maïto         //  Initialize Advanced FCB Header fields
1499*23b7c7b8SHermès Bélusca-Maïto         //
1500*23b7c7b8SHermès Bélusca-Maïto 
1501*23b7c7b8SHermès Bélusca-Maïto         ExInitializeFastMutex( &Fcb->NonPaged->AdvancedFcbHeaderMutex );
1502*23b7c7b8SHermès Bélusca-Maïto         FsRtlSetupAdvancedHeader( &Fcb->Header,
1503*23b7c7b8SHermès Bélusca-Maïto                                   &Fcb->NonPaged->AdvancedFcbHeaderMutex );
1504*23b7c7b8SHermès Bélusca-Maïto 
1505*23b7c7b8SHermès Bélusca-Maïto         //
1506*23b7c7b8SHermès Bélusca-Maïto         //  To make FAT match the present functionality of NTFS, disable
1507*23b7c7b8SHermès Bélusca-Maïto         //  stream contexts on paging files
1508*23b7c7b8SHermès Bélusca-Maïto         //
1509*23b7c7b8SHermès Bélusca-Maïto 
1510*23b7c7b8SHermès Bélusca-Maïto         if (IsPagingFile) {
1511*23b7c7b8SHermès Bélusca-Maïto 
1512*23b7c7b8SHermès Bélusca-Maïto             SetFlag( Fcb->Header.Flags2, FSRTL_FLAG2_IS_PAGING_FILE );
1513*23b7c7b8SHermès Bélusca-Maïto             ClearFlag( Fcb->Header.Flags2, FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS );
1514*23b7c7b8SHermès Bélusca-Maïto         }
1515*23b7c7b8SHermès Bélusca-Maïto 
1516*23b7c7b8SHermès Bélusca-Maïto         //
1517*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the Mcb
1518*23b7c7b8SHermès Bélusca-Maïto         //
1519*23b7c7b8SHermès Bélusca-Maïto 
1520*23b7c7b8SHermès Bélusca-Maïto         FsRtlInitializeLargeMcb( &Fcb->Mcb, PoolType );
1521*23b7c7b8SHermès Bélusca-Maïto         UnwindMcb = &Fcb->Mcb;
1522*23b7c7b8SHermès Bélusca-Maïto 
1523*23b7c7b8SHermès Bélusca-Maïto         //
1524*23b7c7b8SHermès Bélusca-Maïto         //  Set the file size, valid data length, first cluster of file,
1525*23b7c7b8SHermès Bélusca-Maïto         //  and allocation size based on the information stored in the dirent
1526*23b7c7b8SHermès Bélusca-Maïto         //
1527*23b7c7b8SHermès Bélusca-Maïto 
1528*23b7c7b8SHermès Bélusca-Maïto         Fcb->Header.FileSize.LowPart = Dirent->FileSize;
1529*23b7c7b8SHermès Bélusca-Maïto 
1530*23b7c7b8SHermès Bélusca-Maïto         Fcb->Header.ValidDataLength.LowPart = Dirent->FileSize;
1531*23b7c7b8SHermès Bélusca-Maïto 
1532*23b7c7b8SHermès Bélusca-Maïto         Fcb->ValidDataToDisk = Dirent->FileSize;
1533*23b7c7b8SHermès Bélusca-Maïto 
1534*23b7c7b8SHermès Bélusca-Maïto         Fcb->FirstClusterOfFile = (ULONG)Dirent->FirstClusterOfFile;
1535*23b7c7b8SHermès Bélusca-Maïto 
1536*23b7c7b8SHermès Bélusca-Maïto         if ( FatIsFat32(Vcb) ) {
1537*23b7c7b8SHermès Bélusca-Maïto 
1538*23b7c7b8SHermès Bélusca-Maïto             Fcb->FirstClusterOfFile += Dirent->FirstClusterOfFileHi << 16;
1539*23b7c7b8SHermès Bélusca-Maïto         }
1540*23b7c7b8SHermès Bélusca-Maïto 
1541*23b7c7b8SHermès Bélusca-Maïto         if ( Fcb->FirstClusterOfFile == 0 ) {
1542*23b7c7b8SHermès Bélusca-Maïto 
1543*23b7c7b8SHermès Bélusca-Maïto             Fcb->Header.AllocationSize.QuadPart = 0;
1544*23b7c7b8SHermès Bélusca-Maïto 
1545*23b7c7b8SHermès Bélusca-Maïto         } else {
1546*23b7c7b8SHermès Bélusca-Maïto 
1547*23b7c7b8SHermès Bélusca-Maïto             Fcb->Header.AllocationSize.QuadPart = FCB_LOOKUP_ALLOCATIONSIZE_HINT;
1548*23b7c7b8SHermès Bélusca-Maïto         }
1549*23b7c7b8SHermès Bélusca-Maïto 
1550*23b7c7b8SHermès Bélusca-Maïto 
1551*23b7c7b8SHermès Bélusca-Maïto         //
1552*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the Fcb's file lock record
1553*23b7c7b8SHermès Bélusca-Maïto         //
1554*23b7c7b8SHermès Bélusca-Maïto 
1555*23b7c7b8SHermès Bélusca-Maïto         FsRtlInitializeFileLock( &Fcb->Specific.Fcb.FileLock, NULL, NULL );
1556*23b7c7b8SHermès Bélusca-Maïto         UnwindFileLock = &Fcb->Specific.Fcb.FileLock;
1557*23b7c7b8SHermès Bélusca-Maïto 
1558*23b7c7b8SHermès Bélusca-Maïto         //
1559*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the oplock structure.
1560*23b7c7b8SHermès Bélusca-Maïto         //
1561*23b7c7b8SHermès Bélusca-Maïto 
1562*23b7c7b8SHermès Bélusca-Maïto         FsRtlInitializeOplock( FatGetFcbOplock(Fcb) );
1563*23b7c7b8SHermès Bélusca-Maïto         UnwindOplock = FatGetFcbOplock(Fcb);
1564*23b7c7b8SHermès Bélusca-Maïto 
1565*23b7c7b8SHermès Bélusca-Maïto         //
1566*23b7c7b8SHermès Bélusca-Maïto         //  Indicate that Fast I/O is possible
1567*23b7c7b8SHermès Bélusca-Maïto         //
1568*23b7c7b8SHermès Bélusca-Maïto 
1569*23b7c7b8SHermès Bélusca-Maïto         Fcb->Header.IsFastIoPossible = TRUE;
1570*23b7c7b8SHermès Bélusca-Maïto 
1571*23b7c7b8SHermès Bélusca-Maïto         //
1572*23b7c7b8SHermès Bélusca-Maïto         //  Set the file names.  This must be the last thing we do.
1573*23b7c7b8SHermès Bélusca-Maïto         //
1574*23b7c7b8SHermès Bélusca-Maïto 
1575*23b7c7b8SHermès Bélusca-Maïto         FatConstructNamesInFcb( IrpContext,
1576*23b7c7b8SHermès Bélusca-Maïto                                 Fcb,
1577*23b7c7b8SHermès Bélusca-Maïto                                 Dirent,
1578*23b7c7b8SHermès Bélusca-Maïto                                 Lfn );
1579*23b7c7b8SHermès Bélusca-Maïto 
1580*23b7c7b8SHermès Bélusca-Maïto         //
1581*23b7c7b8SHermès Bélusca-Maïto         //  Drop the shortname hint so prefix searches can figure out
1582*23b7c7b8SHermès Bélusca-Maïto         //  what they found
1583*23b7c7b8SHermès Bélusca-Maïto         //
1584*23b7c7b8SHermès Bélusca-Maïto 
1585*23b7c7b8SHermès Bélusca-Maïto         Fcb->ShortName.FileNameDos = TRUE;
1586*23b7c7b8SHermès Bélusca-Maïto 
1587*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
1588*23b7c7b8SHermès Bélusca-Maïto 
1589*23b7c7b8SHermès Bélusca-Maïto         DebugUnwind( FatCreateFcb );
1590*23b7c7b8SHermès Bélusca-Maïto 
1591*23b7c7b8SHermès Bélusca-Maïto         //
1592*23b7c7b8SHermès Bélusca-Maïto         //  If this is an abnormal termination then undo our work
1593*23b7c7b8SHermès Bélusca-Maïto         //
1594*23b7c7b8SHermès Bélusca-Maïto 
1595*23b7c7b8SHermès Bélusca-Maïto         if (_SEH2_AbnormalTermination()) {
1596*23b7c7b8SHermès Bélusca-Maïto 
1597*23b7c7b8SHermès Bélusca-Maïto             ULONG i;
1598*23b7c7b8SHermès Bélusca-Maïto 
1599*23b7c7b8SHermès Bélusca-Maïto             if (UnwindOplock != NULL) { FsRtlUninitializeOplock( UnwindOplock ); }
1600*23b7c7b8SHermès Bélusca-Maïto             if (UnwindFileLock != NULL) { FsRtlUninitializeFileLock( UnwindFileLock ); }
1601*23b7c7b8SHermès Bélusca-Maïto             if (UnwindMcb != NULL) { FsRtlUninitializeLargeMcb( UnwindMcb ); }
1602*23b7c7b8SHermès Bélusca-Maïto             if (UnwindEntryList != NULL) { RemoveEntryList( UnwindEntryList ); }
1603*23b7c7b8SHermès Bélusca-Maïto             if (UnwindResource != NULL) { FatFreeResource( UnwindResource ); }
1604*23b7c7b8SHermès Bélusca-Maïto             if (UnwindResource2 != NULL) { FatFreeResource( UnwindResource2 ); }
1605*23b7c7b8SHermès Bélusca-Maïto 
1606*23b7c7b8SHermès Bélusca-Maïto             for (i = 0; i < sizeof(UnwindStorage)/sizeof(PVOID); i += 1) {
1607*23b7c7b8SHermès Bélusca-Maïto                 if (UnwindStorage[i] != NULL) { ExFreePool( UnwindStorage[i] ); }
1608*23b7c7b8SHermès Bélusca-Maïto             }
1609*23b7c7b8SHermès Bélusca-Maïto         }
1610*23b7c7b8SHermès Bélusca-Maïto 
1611*23b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatCreateFcb -> %p\n", Fcb);
1612*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
1613*23b7c7b8SHermès Bélusca-Maïto 
1614*23b7c7b8SHermès Bélusca-Maïto     //
1615*23b7c7b8SHermès Bélusca-Maïto     //  return and tell the caller
1616*23b7c7b8SHermès Bélusca-Maïto     //
1617*23b7c7b8SHermès Bélusca-Maïto 
1618*23b7c7b8SHermès Bélusca-Maïto     return Fcb;
1619*23b7c7b8SHermès Bélusca-Maïto }
1620*23b7c7b8SHermès Bélusca-Maïto 
1621*23b7c7b8SHermès Bélusca-Maïto 
1622*23b7c7b8SHermès Bélusca-Maïto PDCB
FatCreateDcb(IN PIRP_CONTEXT IrpContext,IN PVCB Vcb,IN PDCB ParentDcb,IN ULONG LfnOffsetWithinDirectory,IN ULONG DirentOffsetWithinDirectory,IN PDIRENT Dirent,IN PUNICODE_STRING Lfn OPTIONAL)1623*23b7c7b8SHermès Bélusca-Maïto FatCreateDcb (
1624*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
1625*23b7c7b8SHermès Bélusca-Maïto     IN PVCB Vcb,
1626*23b7c7b8SHermès Bélusca-Maïto     IN PDCB ParentDcb,
1627*23b7c7b8SHermès Bélusca-Maïto     IN ULONG LfnOffsetWithinDirectory,
1628*23b7c7b8SHermès Bélusca-Maïto     IN ULONG DirentOffsetWithinDirectory,
1629*23b7c7b8SHermès Bélusca-Maïto     IN PDIRENT Dirent,
1630*23b7c7b8SHermès Bélusca-Maïto     IN PUNICODE_STRING Lfn OPTIONAL
1631*23b7c7b8SHermès Bélusca-Maïto     )
1632*23b7c7b8SHermès Bélusca-Maïto 
1633*23b7c7b8SHermès Bélusca-Maïto /*++
1634*23b7c7b8SHermès Bélusca-Maïto 
1635*23b7c7b8SHermès Bélusca-Maïto Routine Description:
1636*23b7c7b8SHermès Bélusca-Maïto 
1637*23b7c7b8SHermès Bélusca-Maïto     This routine allocates, initializes, and inserts a new Dcb record into
1638*23b7c7b8SHermès Bélusca-Maïto     the in memory data structures.
1639*23b7c7b8SHermès Bélusca-Maïto 
1640*23b7c7b8SHermès Bélusca-Maïto Arguments:
1641*23b7c7b8SHermès Bélusca-Maïto 
1642*23b7c7b8SHermès Bélusca-Maïto     Vcb - Supplies the Vcb to associate the new DCB under.
1643*23b7c7b8SHermès Bélusca-Maïto 
1644*23b7c7b8SHermès Bélusca-Maïto     ParentDcb - Supplies the parent dcb that the new DCB is under.
1645*23b7c7b8SHermès Bélusca-Maïto 
1646*23b7c7b8SHermès Bélusca-Maïto     LfnOffsetWithinDirectory - Supplies the offset of the LFN.  If there is
1647*23b7c7b8SHermès Bélusca-Maïto         no LFN associated with this file then this value is same as
1648*23b7c7b8SHermès Bélusca-Maïto         DirentOffsetWithinDirectory.
1649*23b7c7b8SHermès Bélusca-Maïto 
1650*23b7c7b8SHermès Bélusca-Maïto     DirentOffsetWithinDirectory - Supplies the offset, in bytes from the
1651*23b7c7b8SHermès Bélusca-Maïto         start of the directory file where the dirent for the fcb is located
1652*23b7c7b8SHermès Bélusca-Maïto 
1653*23b7c7b8SHermès Bélusca-Maïto     Dirent - Supplies the dirent for the dcb being created
1654*23b7c7b8SHermès Bélusca-Maïto 
1655*23b7c7b8SHermès Bélusca-Maïto     FileName - Supplies the file name of the file relative to the directory
1656*23b7c7b8SHermès Bélusca-Maïto         it's in (e.g., the file \config.sys is called "CONFIG.SYS" without
1657*23b7c7b8SHermès Bélusca-Maïto         the preceding backslash).
1658*23b7c7b8SHermès Bélusca-Maïto 
1659*23b7c7b8SHermès Bélusca-Maïto     Lfn - Supplies a long UNICODE name associated with this directory.
1660*23b7c7b8SHermès Bélusca-Maïto 
1661*23b7c7b8SHermès Bélusca-Maïto Return Value:
1662*23b7c7b8SHermès Bélusca-Maïto 
1663*23b7c7b8SHermès Bélusca-Maïto     PDCB - Returns a pointer to the newly allocated DCB
1664*23b7c7b8SHermès Bélusca-Maïto 
1665*23b7c7b8SHermès Bélusca-Maïto --*/
1666*23b7c7b8SHermès Bélusca-Maïto 
1667*23b7c7b8SHermès Bélusca-Maïto {
1668*23b7c7b8SHermès Bélusca-Maïto     PDCB Dcb = NULL;
1669*23b7c7b8SHermès Bélusca-Maïto 
1670*23b7c7b8SHermès Bélusca-Maïto     //
1671*23b7c7b8SHermès Bélusca-Maïto     //  The following variables are used for abnormal unwind
1672*23b7c7b8SHermès Bélusca-Maïto     //
1673*23b7c7b8SHermès Bélusca-Maïto 
1674*23b7c7b8SHermès Bélusca-Maïto     PVOID UnwindStorage[2] = { NULL, NULL  };
1675*23b7c7b8SHermès Bélusca-Maïto     PERESOURCE UnwindResource = NULL;
1676*23b7c7b8SHermès Bélusca-Maïto     PERESOURCE UnwindResource2 = NULL;
1677*23b7c7b8SHermès Bélusca-Maïto     PLIST_ENTRY UnwindEntryList = NULL;
1678*23b7c7b8SHermès Bélusca-Maïto     PLARGE_MCB UnwindMcb = NULL;
1679*23b7c7b8SHermès Bélusca-Maïto     POPLOCK UnwindOplock = NULL;
1680*23b7c7b8SHermès Bélusca-Maïto 
1681*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
1682*23b7c7b8SHermès Bélusca-Maïto 
1683*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatCreateDcb\n", 0);
1684*23b7c7b8SHermès Bélusca-Maïto 
1685*23b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
1686*23b7c7b8SHermès Bélusca-Maïto 
1687*23b7c7b8SHermès Bélusca-Maïto         //
1688*23b7c7b8SHermès Bélusca-Maïto         //  assert that the only time we are called is if wait is true
1689*23b7c7b8SHermès Bélusca-Maïto         //
1690*23b7c7b8SHermès Bélusca-Maïto 
1691*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
1692*23b7c7b8SHermès Bélusca-Maïto 
1693*23b7c7b8SHermès Bélusca-Maïto         //
1694*23b7c7b8SHermès Bélusca-Maïto         //  Allocate a new DCB, and zero it out
1695*23b7c7b8SHermès Bélusca-Maïto         //
1696*23b7c7b8SHermès Bélusca-Maïto 
1697*23b7c7b8SHermès Bélusca-Maïto         UnwindStorage[0] = Dcb = FatAllocateFcb();
1698*23b7c7b8SHermès Bélusca-Maïto 
1699*23b7c7b8SHermès Bélusca-Maïto         RtlZeroMemory( Dcb, sizeof(DCB) );
1700*23b7c7b8SHermès Bélusca-Maïto 
1701*23b7c7b8SHermès Bélusca-Maïto         UnwindStorage[1] =
1702*23b7c7b8SHermès Bélusca-Maïto         Dcb->NonPaged = FatAllocateNonPagedFcb();
1703*23b7c7b8SHermès Bélusca-Maïto 
1704*23b7c7b8SHermès Bélusca-Maïto         RtlZeroMemory( Dcb->NonPaged, sizeof( NON_PAGED_FCB ) );
1705*23b7c7b8SHermès Bélusca-Maïto 
1706*23b7c7b8SHermès Bélusca-Maïto         //
1707*23b7c7b8SHermès Bélusca-Maïto         //  Set the proper node type code, node byte size and call backs
1708*23b7c7b8SHermès Bélusca-Maïto         //
1709*23b7c7b8SHermès Bélusca-Maïto 
1710*23b7c7b8SHermès Bélusca-Maïto         Dcb->Header.NodeTypeCode = FAT_NTC_DCB;
1711*23b7c7b8SHermès Bélusca-Maïto         Dcb->Header.NodeByteSize = sizeof(DCB);
1712*23b7c7b8SHermès Bélusca-Maïto 
1713*23b7c7b8SHermès Bélusca-Maïto         Dcb->FcbCondition = FcbGood;
1714*23b7c7b8SHermès Bélusca-Maïto 
1715*23b7c7b8SHermès Bélusca-Maïto         //
1716*23b7c7b8SHermès Bélusca-Maïto         //  The initial state, open count, and directory change count fields are
1717*23b7c7b8SHermès Bélusca-Maïto         //  already zero so we can skip setting them
1718*23b7c7b8SHermès Bélusca-Maïto         //
1719*23b7c7b8SHermès Bélusca-Maïto 
1720*23b7c7b8SHermès Bélusca-Maïto         //
1721*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the resource variable
1722*23b7c7b8SHermès Bélusca-Maïto         //
1723*23b7c7b8SHermès Bélusca-Maïto 
1724*23b7c7b8SHermès Bélusca-Maïto 
1725*23b7c7b8SHermès Bélusca-Maïto         UnwindResource =
1726*23b7c7b8SHermès Bélusca-Maïto         Dcb->Header.Resource = FatAllocateResource();
1727*23b7c7b8SHermès Bélusca-Maïto 
1728*23b7c7b8SHermès Bélusca-Maïto         //
1729*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the PagingIo Resource.  We no longer use the FsRtl common
1730*23b7c7b8SHermès Bélusca-Maïto         //  shared pool because this led to a) deadlocks due to cases where files
1731*23b7c7b8SHermès Bélusca-Maïto         //  and their parent directories shared a resource and b) there is no way
1732*23b7c7b8SHermès Bélusca-Maïto         //  to anticipate inter-driver induced deadlock via recursive operation.
1733*23b7c7b8SHermès Bélusca-Maïto         //
1734*23b7c7b8SHermès Bélusca-Maïto 
1735*23b7c7b8SHermès Bélusca-Maïto         UnwindResource2 =
1736*23b7c7b8SHermès Bélusca-Maïto         Dcb->Header.PagingIoResource = FatAllocateResource();
1737*23b7c7b8SHermès Bélusca-Maïto 
1738*23b7c7b8SHermès Bélusca-Maïto         //
1739*23b7c7b8SHermès Bélusca-Maïto         //  Insert this Dcb into our parent dcb's queue
1740*23b7c7b8SHermès Bélusca-Maïto         //
1741*23b7c7b8SHermès Bélusca-Maïto         //  There is a deep reason why this goes on the head, to allow us
1742*23b7c7b8SHermès Bélusca-Maïto         //  to easily enumerate all child directories before child files.
1743*23b7c7b8SHermès Bélusca-Maïto         //  This is important to let us maintain whole-volume lockorder
1744*23b7c7b8SHermès Bélusca-Maïto         //  via BottomUp enumeration.
1745*23b7c7b8SHermès Bélusca-Maïto         //
1746*23b7c7b8SHermès Bélusca-Maïto 
1747*23b7c7b8SHermès Bélusca-Maïto         InsertHeadList( &ParentDcb->Specific.Dcb.ParentDcbQueue,
1748*23b7c7b8SHermès Bélusca-Maïto                         &Dcb->ParentDcbLinks );
1749*23b7c7b8SHermès Bélusca-Maïto         UnwindEntryList = &Dcb->ParentDcbLinks;
1750*23b7c7b8SHermès Bélusca-Maïto 
1751*23b7c7b8SHermès Bélusca-Maïto         //
1752*23b7c7b8SHermès Bélusca-Maïto         //  Point back to our parent dcb
1753*23b7c7b8SHermès Bélusca-Maïto         //
1754*23b7c7b8SHermès Bélusca-Maïto 
1755*23b7c7b8SHermès Bélusca-Maïto         Dcb->ParentDcb = ParentDcb;
1756*23b7c7b8SHermès Bélusca-Maïto 
1757*23b7c7b8SHermès Bélusca-Maïto         //
1758*23b7c7b8SHermès Bélusca-Maïto         //  Set the Vcb
1759*23b7c7b8SHermès Bélusca-Maïto         //
1760*23b7c7b8SHermès Bélusca-Maïto 
1761*23b7c7b8SHermès Bélusca-Maïto         Dcb->Vcb = Vcb;
1762*23b7c7b8SHermès Bélusca-Maïto 
1763*23b7c7b8SHermès Bélusca-Maïto         //
1764*23b7c7b8SHermès Bélusca-Maïto         //  Set the dirent offset within the directory
1765*23b7c7b8SHermès Bélusca-Maïto         //
1766*23b7c7b8SHermès Bélusca-Maïto 
1767*23b7c7b8SHermès Bélusca-Maïto         Dcb->LfnOffsetWithinDirectory = LfnOffsetWithinDirectory;
1768*23b7c7b8SHermès Bélusca-Maïto         Dcb->DirentOffsetWithinDirectory = DirentOffsetWithinDirectory;
1769*23b7c7b8SHermès Bélusca-Maïto 
1770*23b7c7b8SHermès Bélusca-Maïto         //
1771*23b7c7b8SHermès Bélusca-Maïto         //  Set the DirentFatFlags and LastWriteTime
1772*23b7c7b8SHermès Bélusca-Maïto         //
1773*23b7c7b8SHermès Bélusca-Maïto 
1774*23b7c7b8SHermès Bélusca-Maïto         Dcb->DirentFatFlags = Dirent->Attributes;
1775*23b7c7b8SHermès Bélusca-Maïto 
1776*23b7c7b8SHermès Bélusca-Maïto         Dcb->LastWriteTime = FatFatTimeToNtTime( IrpContext,
1777*23b7c7b8SHermès Bélusca-Maïto                                                  Dirent->LastWriteTime,
1778*23b7c7b8SHermès Bélusca-Maïto                                                  0 );
1779*23b7c7b8SHermès Bélusca-Maïto 
1780*23b7c7b8SHermès Bélusca-Maïto         //
1781*23b7c7b8SHermès Bélusca-Maïto         //  These fields are only non-zero when in Chicago mode.
1782*23b7c7b8SHermès Bélusca-Maïto         //
1783*23b7c7b8SHermès Bélusca-Maïto 
1784*23b7c7b8SHermès Bélusca-Maïto         if (FatData.ChicagoMode) {
1785*23b7c7b8SHermès Bélusca-Maïto 
1786*23b7c7b8SHermès Bélusca-Maïto             LARGE_INTEGER FatSystemJanOne1980 = {0};
1787*23b7c7b8SHermès Bélusca-Maïto 
1788*23b7c7b8SHermès Bélusca-Maïto             //
1789*23b7c7b8SHermès Bélusca-Maïto             //  If either date is possibly zero, get the system
1790*23b7c7b8SHermès Bélusca-Maïto             //  version of 1/1/80.
1791*23b7c7b8SHermès Bélusca-Maïto             //
1792*23b7c7b8SHermès Bélusca-Maïto 
1793*23b7c7b8SHermès Bélusca-Maïto             if ((((PUSHORT)Dirent)[9] & ((PUSHORT)Dirent)[8]) == 0) {
1794*23b7c7b8SHermès Bélusca-Maïto 
1795*23b7c7b8SHermès Bélusca-Maïto                 ExLocalTimeToSystemTime( &FatJanOne1980,
1796*23b7c7b8SHermès Bélusca-Maïto                                          &FatSystemJanOne1980 );
1797*23b7c7b8SHermès Bélusca-Maïto             }
1798*23b7c7b8SHermès Bélusca-Maïto 
1799*23b7c7b8SHermès Bélusca-Maïto             //
1800*23b7c7b8SHermès Bélusca-Maïto             //  Only do the really hard work if this field is non-zero.
1801*23b7c7b8SHermès Bélusca-Maïto             //
1802*23b7c7b8SHermès Bélusca-Maïto 
1803*23b7c7b8SHermès Bélusca-Maïto             if (((PUSHORT)Dirent)[9] != 0) {
1804*23b7c7b8SHermès Bélusca-Maïto 
1805*23b7c7b8SHermès Bélusca-Maïto                 Dcb->LastAccessTime =
1806*23b7c7b8SHermès Bélusca-Maïto                     FatFatDateToNtTime( IrpContext,
1807*23b7c7b8SHermès Bélusca-Maïto                                         Dirent->LastAccessDate );
1808*23b7c7b8SHermès Bélusca-Maïto 
1809*23b7c7b8SHermès Bélusca-Maïto             } else {
1810*23b7c7b8SHermès Bélusca-Maïto 
1811*23b7c7b8SHermès Bélusca-Maïto                 Dcb->LastAccessTime = FatSystemJanOne1980;
1812*23b7c7b8SHermès Bélusca-Maïto             }
1813*23b7c7b8SHermès Bélusca-Maïto 
1814*23b7c7b8SHermès Bélusca-Maïto             //
1815*23b7c7b8SHermès Bélusca-Maïto             //  Only do the really hard work if this field is non-zero.
1816*23b7c7b8SHermès Bélusca-Maïto             //
1817*23b7c7b8SHermès Bélusca-Maïto 
1818*23b7c7b8SHermès Bélusca-Maïto             if (((PUSHORT)Dirent)[8] != 0) {
1819*23b7c7b8SHermès Bélusca-Maïto 
1820*23b7c7b8SHermès Bélusca-Maïto                 Dcb->CreationTime =
1821*23b7c7b8SHermès Bélusca-Maïto                     FatFatTimeToNtTime( IrpContext,
1822*23b7c7b8SHermès Bélusca-Maïto                                         Dirent->CreationTime,
1823*23b7c7b8SHermès Bélusca-Maïto                                         Dirent->CreationMSec );
1824*23b7c7b8SHermès Bélusca-Maïto 
1825*23b7c7b8SHermès Bélusca-Maïto             } else {
1826*23b7c7b8SHermès Bélusca-Maïto 
1827*23b7c7b8SHermès Bélusca-Maïto                 Dcb->CreationTime = FatSystemJanOne1980;
1828*23b7c7b8SHermès Bélusca-Maïto             }
1829*23b7c7b8SHermès Bélusca-Maïto         }
1830*23b7c7b8SHermès Bélusca-Maïto 
1831*23b7c7b8SHermès Bélusca-Maïto         //
1832*23b7c7b8SHermès Bélusca-Maïto         //  Initialize Advanced FCB Header fields
1833*23b7c7b8SHermès Bélusca-Maïto         //
1834*23b7c7b8SHermès Bélusca-Maïto 
1835*23b7c7b8SHermès Bélusca-Maïto         ExInitializeFastMutex( &Dcb->NonPaged->AdvancedFcbHeaderMutex );
1836*23b7c7b8SHermès Bélusca-Maïto         FsRtlSetupAdvancedHeader( &Dcb->Header,
1837*23b7c7b8SHermès Bélusca-Maïto                                   &Dcb->NonPaged->AdvancedFcbHeaderMutex );
1838*23b7c7b8SHermès Bélusca-Maïto 
1839*23b7c7b8SHermès Bélusca-Maïto         //
1840*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the Mcb
1841*23b7c7b8SHermès Bélusca-Maïto         //
1842*23b7c7b8SHermès Bélusca-Maïto 
1843*23b7c7b8SHermès Bélusca-Maïto         FsRtlInitializeLargeMcb( &Dcb->Mcb, PagedPool );
1844*23b7c7b8SHermès Bélusca-Maïto         UnwindMcb = &Dcb->Mcb;
1845*23b7c7b8SHermès Bélusca-Maïto 
1846*23b7c7b8SHermès Bélusca-Maïto         //
1847*23b7c7b8SHermès Bélusca-Maïto         //  Set the file size, first cluster of file, and allocation size
1848*23b7c7b8SHermès Bélusca-Maïto         //  based on the information stored in the dirent
1849*23b7c7b8SHermès Bélusca-Maïto         //
1850*23b7c7b8SHermès Bélusca-Maïto 
1851*23b7c7b8SHermès Bélusca-Maïto         Dcb->FirstClusterOfFile = (ULONG)Dirent->FirstClusterOfFile;
1852*23b7c7b8SHermès Bélusca-Maïto 
1853*23b7c7b8SHermès Bélusca-Maïto         if ( FatIsFat32(Dcb->Vcb) ) {
1854*23b7c7b8SHermès Bélusca-Maïto 
1855*23b7c7b8SHermès Bélusca-Maïto             Dcb->FirstClusterOfFile += Dirent->FirstClusterOfFileHi << 16;
1856*23b7c7b8SHermès Bélusca-Maïto         }
1857*23b7c7b8SHermès Bélusca-Maïto 
1858*23b7c7b8SHermès Bélusca-Maïto         if ( Dcb->FirstClusterOfFile == 0 ) {
1859*23b7c7b8SHermès Bélusca-Maïto 
1860*23b7c7b8SHermès Bélusca-Maïto             Dcb->Header.AllocationSize.QuadPart = 0;
1861*23b7c7b8SHermès Bélusca-Maïto 
1862*23b7c7b8SHermès Bélusca-Maïto         } else {
1863*23b7c7b8SHermès Bélusca-Maïto 
1864*23b7c7b8SHermès Bélusca-Maïto             Dcb->Header.AllocationSize.QuadPart = FCB_LOOKUP_ALLOCATIONSIZE_HINT;
1865*23b7c7b8SHermès Bélusca-Maïto         }
1866*23b7c7b8SHermès Bélusca-Maïto 
1867*23b7c7b8SHermès Bélusca-Maïto 
1868*23b7c7b8SHermès Bélusca-Maïto         //  initialize the notify queues, and the parent dcb queue.
1869*23b7c7b8SHermès Bélusca-Maïto         //
1870*23b7c7b8SHermès Bélusca-Maïto 
1871*23b7c7b8SHermès Bélusca-Maïto         InitializeListHead( &Dcb->Specific.Dcb.ParentDcbQueue );
1872*23b7c7b8SHermès Bélusca-Maïto 
1873*23b7c7b8SHermès Bélusca-Maïto         //
1874*23b7c7b8SHermès Bélusca-Maïto         //  Setup the free dirent bitmap buffer.  Since we don't know the
1875*23b7c7b8SHermès Bélusca-Maïto         //  size of the directory, leave it zero for now.
1876*23b7c7b8SHermès Bélusca-Maïto         //
1877*23b7c7b8SHermès Bélusca-Maïto 
1878*23b7c7b8SHermès Bélusca-Maïto         RtlInitializeBitMap( &Dcb->Specific.Dcb.FreeDirentBitmap,
1879*23b7c7b8SHermès Bélusca-Maïto                              NULL,
1880*23b7c7b8SHermès Bélusca-Maïto                              0 );
1881*23b7c7b8SHermès Bélusca-Maïto 
1882*23b7c7b8SHermès Bélusca-Maïto         //
1883*23b7c7b8SHermès Bélusca-Maïto         //  Set our two create dirent aids to represent that we have yet to
1884*23b7c7b8SHermès Bélusca-Maïto         //  enumerate the directory for never used or deleted dirents.
1885*23b7c7b8SHermès Bélusca-Maïto         //
1886*23b7c7b8SHermès Bélusca-Maïto 
1887*23b7c7b8SHermès Bélusca-Maïto         Dcb->Specific.Dcb.UnusedDirentVbo = 0xffffffff;
1888*23b7c7b8SHermès Bélusca-Maïto         Dcb->Specific.Dcb.DeletedDirentHint = 0xffffffff;
1889*23b7c7b8SHermès Bélusca-Maïto 
1890*23b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN8)
1891*23b7c7b8SHermès Bélusca-Maïto         //
1892*23b7c7b8SHermès Bélusca-Maïto         //  Initialize the oplock structure.
1893*23b7c7b8SHermès Bélusca-Maïto         //
1894*23b7c7b8SHermès Bélusca-Maïto 
1895*23b7c7b8SHermès Bélusca-Maïto         FsRtlInitializeOplock( FatGetFcbOplock(Dcb) );
1896*23b7c7b8SHermès Bélusca-Maïto         UnwindOplock = FatGetFcbOplock(Dcb);
1897*23b7c7b8SHermès Bélusca-Maïto #endif
1898*23b7c7b8SHermès Bélusca-Maïto 
1899*23b7c7b8SHermès Bélusca-Maïto         //
1900*23b7c7b8SHermès Bélusca-Maïto         //  Postpone initializing the cache map until we need to do a read/write
1901*23b7c7b8SHermès Bélusca-Maïto         //  of the directory file.
1902*23b7c7b8SHermès Bélusca-Maïto 
1903*23b7c7b8SHermès Bélusca-Maïto 
1904*23b7c7b8SHermès Bélusca-Maïto         //
1905*23b7c7b8SHermès Bélusca-Maïto         //  set the file names.  This must be the last thing we do.
1906*23b7c7b8SHermès Bélusca-Maïto         //
1907*23b7c7b8SHermès Bélusca-Maïto 
1908*23b7c7b8SHermès Bélusca-Maïto         FatConstructNamesInFcb( IrpContext,
1909*23b7c7b8SHermès Bélusca-Maïto                                 Dcb,
1910*23b7c7b8SHermès Bélusca-Maïto                                 Dirent,
1911*23b7c7b8SHermès Bélusca-Maïto                                 Lfn );
1912*23b7c7b8SHermès Bélusca-Maïto 
1913*23b7c7b8SHermès Bélusca-Maïto         Dcb->ShortName.FileNameDos = TRUE;
1914*23b7c7b8SHermès Bélusca-Maïto 
1915*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
1916*23b7c7b8SHermès Bélusca-Maïto 
1917*23b7c7b8SHermès Bélusca-Maïto         DebugUnwind( FatCreateDcb );
1918*23b7c7b8SHermès Bélusca-Maïto 
1919*23b7c7b8SHermès Bélusca-Maïto         //
1920*23b7c7b8SHermès Bélusca-Maïto         //  If this is an abnormal termination then undo our work
1921*23b7c7b8SHermès Bélusca-Maïto         //
1922*23b7c7b8SHermès Bélusca-Maïto 
1923*23b7c7b8SHermès Bélusca-Maïto         if (_SEH2_AbnormalTermination()) {
1924*23b7c7b8SHermès Bélusca-Maïto 
1925*23b7c7b8SHermès Bélusca-Maïto             ULONG i;
1926*23b7c7b8SHermès Bélusca-Maïto 
1927*23b7c7b8SHermès Bélusca-Maïto             if (UnwindOplock != NULL) { FsRtlUninitializeOplock( UnwindOplock ); }
1928*23b7c7b8SHermès Bélusca-Maïto             if (UnwindMcb != NULL) { FsRtlUninitializeLargeMcb( UnwindMcb ); }
1929*23b7c7b8SHermès Bélusca-Maïto             if (UnwindEntryList != NULL) { RemoveEntryList( UnwindEntryList ); }
1930*23b7c7b8SHermès Bélusca-Maïto             if (UnwindResource != NULL) { FatFreeResource( UnwindResource ); }
1931*23b7c7b8SHermès Bélusca-Maïto             if (UnwindResource2 != NULL) { FatFreeResource( UnwindResource2 ); }
1932*23b7c7b8SHermès Bélusca-Maïto 
1933*23b7c7b8SHermès Bélusca-Maïto             for (i = 0; i < sizeof(UnwindStorage)/sizeof(PVOID); i += 1) {
1934*23b7c7b8SHermès Bélusca-Maïto                 if (UnwindStorage[i] != NULL) { ExFreePool( UnwindStorage[i] ); }
1935*23b7c7b8SHermès Bélusca-Maïto             }
1936*23b7c7b8SHermès Bélusca-Maïto         }
1937*23b7c7b8SHermès Bélusca-Maïto 
1938*23b7c7b8SHermès Bélusca-Maïto         DebugTrace(-1, Dbg, "FatCreateDcb -> %p\n", Dcb);
1939*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
1940*23b7c7b8SHermès Bélusca-Maïto 
1941*23b7c7b8SHermès Bélusca-Maïto     //
1942*23b7c7b8SHermès Bélusca-Maïto     //  return and tell the caller
1943*23b7c7b8SHermès Bélusca-Maïto     //
1944*23b7c7b8SHermès Bélusca-Maïto 
1945*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatCreateDcb -> %p\n", Dcb);
1946*23b7c7b8SHermès Bélusca-Maïto 
1947*23b7c7b8SHermès Bélusca-Maïto     return Dcb;
1948*23b7c7b8SHermès Bélusca-Maïto }
1949*23b7c7b8SHermès Bélusca-Maïto 
1950*23b7c7b8SHermès Bélusca-Maïto 
1951*23b7c7b8SHermès Bélusca-Maïto VOID
FatDeleteFcb(IN PIRP_CONTEXT IrpContext,IN PFCB * FcbPtr)1952*23b7c7b8SHermès Bélusca-Maïto FatDeleteFcb (
1953*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
1954*23b7c7b8SHermès Bélusca-Maïto     IN PFCB *FcbPtr
1955*23b7c7b8SHermès Bélusca-Maïto     )
1956*23b7c7b8SHermès Bélusca-Maïto 
1957*23b7c7b8SHermès Bélusca-Maïto /*++
1958*23b7c7b8SHermès Bélusca-Maïto 
1959*23b7c7b8SHermès Bélusca-Maïto Routine Description:
1960*23b7c7b8SHermès Bélusca-Maïto 
1961*23b7c7b8SHermès Bélusca-Maïto     This routine deallocates and removes an FCB, DCB, or ROOT DCB record
1962*23b7c7b8SHermès Bélusca-Maïto     from Fat's in-memory data structures.  It also will remove all
1963*23b7c7b8SHermès Bélusca-Maïto     associated underlings (i.e., Notify irps, and child FCB/DCB records).
1964*23b7c7b8SHermès Bélusca-Maïto 
1965*23b7c7b8SHermès Bélusca-Maïto Arguments:
1966*23b7c7b8SHermès Bélusca-Maïto 
1967*23b7c7b8SHermès Bélusca-Maïto     Fcb - Supplies the FCB/DCB/ROOT DCB to be removed
1968*23b7c7b8SHermès Bélusca-Maïto 
1969*23b7c7b8SHermès Bélusca-Maïto Return Value:
1970*23b7c7b8SHermès Bélusca-Maïto 
1971*23b7c7b8SHermès Bélusca-Maïto     None
1972*23b7c7b8SHermès Bélusca-Maïto 
1973*23b7c7b8SHermès Bélusca-Maïto --*/
1974*23b7c7b8SHermès Bélusca-Maïto 
1975*23b7c7b8SHermès Bélusca-Maïto {
1976*23b7c7b8SHermès Bélusca-Maïto     PFCB Fcb = *FcbPtr;
1977*23b7c7b8SHermès Bélusca-Maïto 
1978*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
1979*23b7c7b8SHermès Bélusca-Maïto 
1980*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatDeleteFcb, Fcb = %p\n", Fcb);
1981*23b7c7b8SHermès Bélusca-Maïto 
1982*23b7c7b8SHermès Bélusca-Maïto     //
1983*23b7c7b8SHermès Bélusca-Maïto     //  We can only delete this record if the open count is zero.
1984*23b7c7b8SHermès Bélusca-Maïto     //
1985*23b7c7b8SHermès Bélusca-Maïto 
1986*23b7c7b8SHermès Bélusca-Maïto     if (Fcb->OpenCount != 0) {
1987*23b7c7b8SHermès Bélusca-Maïto 
1988*23b7c7b8SHermès Bélusca-Maïto         DebugDump("Error deleting Fcb, Still Open\n", 0, Fcb);
1989*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
1990*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
1991*23b7c7b8SHermès Bélusca-Maïto #endif
1992*23b7c7b8SHermès Bélusca-Maïto         FatBugCheck( 0, 0, 0 );
1993*23b7c7b8SHermès Bélusca-Maïto     }
1994*23b7c7b8SHermès Bélusca-Maïto 
1995*23b7c7b8SHermès Bélusca-Maïto     //
1996*23b7c7b8SHermès Bélusca-Maïto     //  Better be an FCB/DCB.
1997*23b7c7b8SHermès Bélusca-Maïto     //
1998*23b7c7b8SHermès Bélusca-Maïto 
1999*23b7c7b8SHermès Bélusca-Maïto     if ((Fcb->Header.NodeTypeCode != FAT_NTC_DCB) &&
2000*23b7c7b8SHermès Bélusca-Maïto         (Fcb->Header.NodeTypeCode != FAT_NTC_ROOT_DCB) &&
2001*23b7c7b8SHermès Bélusca-Maïto         (Fcb->Header.NodeTypeCode != FAT_NTC_FCB)) {
2002*23b7c7b8SHermès Bélusca-Maïto 
2003*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
2004*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
2005*23b7c7b8SHermès Bélusca-Maïto #endif
2006*23b7c7b8SHermès Bélusca-Maïto         FatBugCheck( 0, 0, 0 );
2007*23b7c7b8SHermès Bélusca-Maïto     }
2008*23b7c7b8SHermès Bélusca-Maïto 
2009*23b7c7b8SHermès Bélusca-Maïto     //
2010*23b7c7b8SHermès Bélusca-Maïto     //  If this is a DCB then remove every Notify record from the two
2011*23b7c7b8SHermès Bélusca-Maïto     //  notify queues
2012*23b7c7b8SHermès Bélusca-Maïto     //
2013*23b7c7b8SHermès Bélusca-Maïto 
2014*23b7c7b8SHermès Bélusca-Maïto     if ((Fcb->Header.NodeTypeCode == FAT_NTC_DCB) ||
2015*23b7c7b8SHermès Bélusca-Maïto         (Fcb->Header.NodeTypeCode == FAT_NTC_ROOT_DCB)) {
2016*23b7c7b8SHermès Bélusca-Maïto 
2017*23b7c7b8SHermès Bélusca-Maïto         //
2018*23b7c7b8SHermès Bélusca-Maïto         //  If we allocated a free dirent bitmap buffer, free it.
2019*23b7c7b8SHermès Bélusca-Maïto         //
2020*23b7c7b8SHermès Bélusca-Maïto 
2021*23b7c7b8SHermès Bélusca-Maïto         if ((Fcb->Specific.Dcb.FreeDirentBitmap.Buffer != NULL) &&
2022*23b7c7b8SHermès Bélusca-Maïto             (Fcb->Specific.Dcb.FreeDirentBitmap.Buffer !=
2023*23b7c7b8SHermès Bélusca-Maïto              &Fcb->Specific.Dcb.FreeDirentBitmapBuffer[0])) {
2024*23b7c7b8SHermès Bélusca-Maïto 
2025*23b7c7b8SHermès Bélusca-Maïto             ExFreePool(Fcb->Specific.Dcb.FreeDirentBitmap.Buffer);
2026*23b7c7b8SHermès Bélusca-Maïto         }
2027*23b7c7b8SHermès Bélusca-Maïto 
2028*23b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN8)
2029*23b7c7b8SHermès Bélusca-Maïto         //
2030*23b7c7b8SHermès Bélusca-Maïto         //  Uninitialize the oplock.
2031*23b7c7b8SHermès Bélusca-Maïto         //
2032*23b7c7b8SHermès Bélusca-Maïto 
2033*23b7c7b8SHermès Bélusca-Maïto         FsRtlUninitializeOplock( FatGetFcbOplock(Fcb) );
2034*23b7c7b8SHermès Bélusca-Maïto #endif
2035*23b7c7b8SHermès Bélusca-Maïto 
2036*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( Fcb->Specific.Dcb.DirectoryFileOpenCount == 0 );
2037*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue) );
2038*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( NULL == Fcb->Specific.Dcb.DirectoryFile);
2039*23b7c7b8SHermès Bélusca-Maïto 
2040*23b7c7b8SHermès Bélusca-Maïto     } else {
2041*23b7c7b8SHermès Bélusca-Maïto 
2042*23b7c7b8SHermès Bélusca-Maïto         //
2043*23b7c7b8SHermès Bélusca-Maïto         //  Uninitialize the byte range file locks and opportunistic locks
2044*23b7c7b8SHermès Bélusca-Maïto         //
2045*23b7c7b8SHermès Bélusca-Maïto 
2046*23b7c7b8SHermès Bélusca-Maïto         FsRtlUninitializeFileLock( &Fcb->Specific.Fcb.FileLock );
2047*23b7c7b8SHermès Bélusca-Maïto         FsRtlUninitializeOplock( FatGetFcbOplock(Fcb) );
2048*23b7c7b8SHermès Bélusca-Maïto     }
2049*23b7c7b8SHermès Bélusca-Maïto 
2050*23b7c7b8SHermès Bélusca-Maïto 
2051*23b7c7b8SHermès Bélusca-Maïto     //
2052*23b7c7b8SHermès Bélusca-Maïto     //  Release any Filter Context structures associated with this FCB
2053*23b7c7b8SHermès Bélusca-Maïto     //
2054*23b7c7b8SHermès Bélusca-Maïto 
2055*23b7c7b8SHermès Bélusca-Maïto     FsRtlTeardownPerStreamContexts( &Fcb->Header );
2056*23b7c7b8SHermès Bélusca-Maïto 
2057*23b7c7b8SHermès Bélusca-Maïto     //
2058*23b7c7b8SHermès Bélusca-Maïto     //  Uninitialize the Mcb
2059*23b7c7b8SHermès Bélusca-Maïto     //
2060*23b7c7b8SHermès Bélusca-Maïto 
2061*23b7c7b8SHermès Bélusca-Maïto     FsRtlUninitializeLargeMcb( &Fcb->Mcb );
2062*23b7c7b8SHermès Bélusca-Maïto 
2063*23b7c7b8SHermès Bélusca-Maïto     //
2064*23b7c7b8SHermès Bélusca-Maïto     //  If this is not the root dcb then we need to remove ourselves from
2065*23b7c7b8SHermès Bélusca-Maïto     //  our parents Dcb queue
2066*23b7c7b8SHermès Bélusca-Maïto     //
2067*23b7c7b8SHermès Bélusca-Maïto 
2068*23b7c7b8SHermès Bélusca-Maïto     if (Fcb->Header.NodeTypeCode != FAT_NTC_ROOT_DCB) {
2069*23b7c7b8SHermès Bélusca-Maïto 
2070*23b7c7b8SHermès Bélusca-Maïto         RemoveEntryList( &(Fcb->ParentDcbLinks) );
2071*23b7c7b8SHermès Bélusca-Maïto     }
2072*23b7c7b8SHermès Bélusca-Maïto 
2073*23b7c7b8SHermès Bélusca-Maïto     //
2074*23b7c7b8SHermès Bélusca-Maïto     //  Remove the entry from the splay table if there is still is one.
2075*23b7c7b8SHermès Bélusca-Maïto     //
2076*23b7c7b8SHermès Bélusca-Maïto 
2077*23b7c7b8SHermès Bélusca-Maïto     if (FlagOn( Fcb->FcbState, FCB_STATE_NAMES_IN_SPLAY_TREE )) {
2078*23b7c7b8SHermès Bélusca-Maïto 
2079*23b7c7b8SHermès Bélusca-Maïto         FatRemoveNames( IrpContext, Fcb );
2080*23b7c7b8SHermès Bélusca-Maïto     }
2081*23b7c7b8SHermès Bélusca-Maïto 
2082*23b7c7b8SHermès Bélusca-Maïto     //
2083*23b7c7b8SHermès Bélusca-Maïto     //  Free the file name pool if allocated.
2084*23b7c7b8SHermès Bélusca-Maïto     //
2085*23b7c7b8SHermès Bélusca-Maïto 
2086*23b7c7b8SHermès Bélusca-Maïto     if (Fcb->Header.NodeTypeCode != FAT_NTC_ROOT_DCB) {
2087*23b7c7b8SHermès Bélusca-Maïto 
2088*23b7c7b8SHermès Bélusca-Maïto         //
2089*23b7c7b8SHermès Bélusca-Maïto         //  If we blew up at inconvenient times, the shortname
2090*23b7c7b8SHermès Bélusca-Maïto         //  could be null even though you will *never* see this
2091*23b7c7b8SHermès Bélusca-Maïto         //  normally.  Rename is a good example of this case.
2092*23b7c7b8SHermès Bélusca-Maïto         //
2093*23b7c7b8SHermès Bélusca-Maïto 
2094*23b7c7b8SHermès Bélusca-Maïto         if (Fcb->ShortName.Name.Oem.Buffer) {
2095*23b7c7b8SHermès Bélusca-Maïto 
2096*23b7c7b8SHermès Bélusca-Maïto             ExFreePool( Fcb->ShortName.Name.Oem.Buffer );
2097*23b7c7b8SHermès Bélusca-Maïto         }
2098*23b7c7b8SHermès Bélusca-Maïto 
2099*23b7c7b8SHermès Bélusca-Maïto         if (Fcb->FullFileName.Buffer) {
2100*23b7c7b8SHermès Bélusca-Maïto 
2101*23b7c7b8SHermès Bélusca-Maïto             ExFreePool( Fcb->FullFileName.Buffer );
2102*23b7c7b8SHermès Bélusca-Maïto         }
2103*23b7c7b8SHermès Bélusca-Maïto     }
2104*23b7c7b8SHermès Bélusca-Maïto 
2105*23b7c7b8SHermès Bélusca-Maïto     if (Fcb->ExactCaseLongName.Buffer) {
2106*23b7c7b8SHermès Bélusca-Maïto 
2107*23b7c7b8SHermès Bélusca-Maïto         ExFreePool(Fcb->ExactCaseLongName.Buffer);
2108*23b7c7b8SHermès Bélusca-Maïto     }
2109*23b7c7b8SHermès Bélusca-Maïto 
2110*23b7c7b8SHermès Bélusca-Maïto #ifdef SYSCACHE_COMPILE
2111*23b7c7b8SHermès Bélusca-Maïto 
2112*23b7c7b8SHermès Bélusca-Maïto     if (Fcb->WriteMask) {
2113*23b7c7b8SHermès Bélusca-Maïto 
2114*23b7c7b8SHermès Bélusca-Maïto         ExFreePool( Fcb->WriteMask );
2115*23b7c7b8SHermès Bélusca-Maïto     }
2116*23b7c7b8SHermès Bélusca-Maïto 
2117*23b7c7b8SHermès Bélusca-Maïto #endif
2118*23b7c7b8SHermès Bélusca-Maïto 
2119*23b7c7b8SHermès Bélusca-Maïto     //
2120*23b7c7b8SHermès Bélusca-Maïto     //  Finally deallocate the Fcb and non-paged fcb records
2121*23b7c7b8SHermès Bélusca-Maïto     //
2122*23b7c7b8SHermès Bélusca-Maïto 
2123*23b7c7b8SHermès Bélusca-Maïto     FatFreeResource( Fcb->Header.Resource );
2124*23b7c7b8SHermès Bélusca-Maïto 
2125*23b7c7b8SHermès Bélusca-Maïto     if (Fcb->Header.PagingIoResource != Fcb->Header.Resource) {
2126*23b7c7b8SHermès Bélusca-Maïto 
2127*23b7c7b8SHermès Bélusca-Maïto         FatFreeResource( Fcb->Header.PagingIoResource );
2128*23b7c7b8SHermès Bélusca-Maïto     }
2129*23b7c7b8SHermès Bélusca-Maïto 
2130*23b7c7b8SHermès Bélusca-Maïto     //
2131*23b7c7b8SHermès Bélusca-Maïto     //  If an Event was allocated, get rid of it.
2132*23b7c7b8SHermès Bélusca-Maïto     //
2133*23b7c7b8SHermès Bélusca-Maïto 
2134*23b7c7b8SHermès Bélusca-Maïto     if (Fcb->NonPaged->OutstandingAsyncEvent) {
2135*23b7c7b8SHermès Bélusca-Maïto 
2136*23b7c7b8SHermès Bélusca-Maïto         ExFreePool( Fcb->NonPaged->OutstandingAsyncEvent );
2137*23b7c7b8SHermès Bélusca-Maïto     }
2138*23b7c7b8SHermès Bélusca-Maïto 
2139*23b7c7b8SHermès Bélusca-Maïto     FatFreeNonPagedFcb( Fcb->NonPaged );
2140*23b7c7b8SHermès Bélusca-Maïto 
2141*23b7c7b8SHermès Bélusca-Maïto     Fcb->Header.NodeTypeCode = NTC_UNDEFINED;
2142*23b7c7b8SHermès Bélusca-Maïto 
2143*23b7c7b8SHermès Bélusca-Maïto     FatFreeFcb( Fcb );
2144*23b7c7b8SHermès Bélusca-Maïto     *FcbPtr = NULL;
2145*23b7c7b8SHermès Bélusca-Maïto 
2146*23b7c7b8SHermès Bélusca-Maïto     //
2147*23b7c7b8SHermès Bélusca-Maïto     //  and return to our caller
2148*23b7c7b8SHermès Bélusca-Maïto     //
2149*23b7c7b8SHermès Bélusca-Maïto 
2150*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatDeleteFcb -> VOID\n", 0);
2151*23b7c7b8SHermès Bélusca-Maïto }
2152*23b7c7b8SHermès Bélusca-Maïto 
2153*23b7c7b8SHermès Bélusca-Maïto 
2154*23b7c7b8SHermès Bélusca-Maïto PCCB
FatCreateCcb(IN PIRP_CONTEXT IrpContext)2155*23b7c7b8SHermès Bélusca-Maïto FatCreateCcb (
2156*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext
2157*23b7c7b8SHermès Bélusca-Maïto     )
2158*23b7c7b8SHermès Bélusca-Maïto 
2159*23b7c7b8SHermès Bélusca-Maïto /*++
2160*23b7c7b8SHermès Bélusca-Maïto 
2161*23b7c7b8SHermès Bélusca-Maïto Routine Description:
2162*23b7c7b8SHermès Bélusca-Maïto 
2163*23b7c7b8SHermès Bélusca-Maïto     This routine creates a new CCB record
2164*23b7c7b8SHermès Bélusca-Maïto 
2165*23b7c7b8SHermès Bélusca-Maïto Arguments:
2166*23b7c7b8SHermès Bélusca-Maïto 
2167*23b7c7b8SHermès Bélusca-Maïto Return Value:
2168*23b7c7b8SHermès Bélusca-Maïto 
2169*23b7c7b8SHermès Bélusca-Maïto     CCB - returns a pointer to the newly allocate CCB
2170*23b7c7b8SHermès Bélusca-Maïto 
2171*23b7c7b8SHermès Bélusca-Maïto --*/
2172*23b7c7b8SHermès Bélusca-Maïto 
2173*23b7c7b8SHermès Bélusca-Maïto {
2174*23b7c7b8SHermès Bélusca-Maïto     PCCB Ccb;
2175*23b7c7b8SHermès Bélusca-Maïto 
2176*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
2177*23b7c7b8SHermès Bélusca-Maïto 
2178*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatCreateCcb\n", 0);
2179*23b7c7b8SHermès Bélusca-Maïto 
2180*23b7c7b8SHermès Bélusca-Maïto     //
2181*23b7c7b8SHermès Bélusca-Maïto     //  Allocate a new CCB Record
2182*23b7c7b8SHermès Bélusca-Maïto     //
2183*23b7c7b8SHermès Bélusca-Maïto 
2184*23b7c7b8SHermès Bélusca-Maïto     Ccb = FatAllocateCcb();
2185*23b7c7b8SHermès Bélusca-Maïto 
2186*23b7c7b8SHermès Bélusca-Maïto     RtlZeroMemory( Ccb, sizeof(CCB) );
2187*23b7c7b8SHermès Bélusca-Maïto 
2188*23b7c7b8SHermès Bélusca-Maïto     //
2189*23b7c7b8SHermès Bélusca-Maïto     //  Set the proper node type code and node byte size
2190*23b7c7b8SHermès Bélusca-Maïto     //
2191*23b7c7b8SHermès Bélusca-Maïto 
2192*23b7c7b8SHermès Bélusca-Maïto     Ccb->NodeTypeCode = FAT_NTC_CCB;
2193*23b7c7b8SHermès Bélusca-Maïto     Ccb->NodeByteSize = sizeof(CCB);
2194*23b7c7b8SHermès Bélusca-Maïto 
2195*23b7c7b8SHermès Bélusca-Maïto     //
2196*23b7c7b8SHermès Bélusca-Maïto     //  return and tell the caller
2197*23b7c7b8SHermès Bélusca-Maïto     //
2198*23b7c7b8SHermès Bélusca-Maïto 
2199*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatCreateCcb -> %p\n", Ccb);
2200*23b7c7b8SHermès Bélusca-Maïto 
2201*23b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( IrpContext );
2202*23b7c7b8SHermès Bélusca-Maïto 
2203*23b7c7b8SHermès Bélusca-Maïto     return Ccb;
2204*23b7c7b8SHermès Bélusca-Maïto }
2205*23b7c7b8SHermès Bélusca-Maïto 
2206*23b7c7b8SHermès Bélusca-Maïto 
2207*23b7c7b8SHermès Bélusca-Maïto 
2208*23b7c7b8SHermès Bélusca-Maïto VOID
FatDeallocateCcbStrings(IN PCCB Ccb)2209*23b7c7b8SHermès Bélusca-Maïto FatDeallocateCcbStrings(
2210*23b7c7b8SHermès Bélusca-Maïto     IN PCCB Ccb
2211*23b7c7b8SHermès Bélusca-Maïto     )
2212*23b7c7b8SHermès Bélusca-Maïto /*++
2213*23b7c7b8SHermès Bélusca-Maïto 
2214*23b7c7b8SHermès Bélusca-Maïto Routine Description:
2215*23b7c7b8SHermès Bélusca-Maïto 
2216*23b7c7b8SHermès Bélusca-Maïto     This routine deallocates CCB query templates
2217*23b7c7b8SHermès Bélusca-Maïto 
2218*23b7c7b8SHermès Bélusca-Maïto Arguments:
2219*23b7c7b8SHermès Bélusca-Maïto 
2220*23b7c7b8SHermès Bélusca-Maïto     Ccb - Supplies the CCB
2221*23b7c7b8SHermès Bélusca-Maïto 
2222*23b7c7b8SHermès Bélusca-Maïto Return Value:
2223*23b7c7b8SHermès Bélusca-Maïto 
2224*23b7c7b8SHermès Bélusca-Maïto     None
2225*23b7c7b8SHermès Bélusca-Maïto 
2226*23b7c7b8SHermès Bélusca-Maïto --*/
2227*23b7c7b8SHermès Bélusca-Maïto {
2228*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
2229*23b7c7b8SHermès Bélusca-Maïto 
2230*23b7c7b8SHermès Bélusca-Maïto     //
2231*23b7c7b8SHermès Bélusca-Maïto     //  If we allocated query template buffers, deallocate them now.
2232*23b7c7b8SHermès Bélusca-Maïto     //
2233*23b7c7b8SHermès Bélusca-Maïto 
2234*23b7c7b8SHermès Bélusca-Maïto     if (FlagOn(Ccb->Flags, CCB_FLAG_FREE_UNICODE)) {
2235*23b7c7b8SHermès Bélusca-Maïto 
2236*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( Ccb->UnicodeQueryTemplate.Buffer);
2237*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( !FlagOn( Ccb->Flags, CCB_FLAG_CLOSE_CONTEXT));
2238*23b7c7b8SHermès Bélusca-Maïto         RtlFreeUnicodeString( &Ccb->UnicodeQueryTemplate );
2239*23b7c7b8SHermès Bélusca-Maïto     }
2240*23b7c7b8SHermès Bélusca-Maïto 
2241*23b7c7b8SHermès Bélusca-Maïto     if (FlagOn(Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT)) {
2242*23b7c7b8SHermès Bélusca-Maïto 
2243*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( Ccb->OemQueryTemplate.Wild.Buffer );
2244*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( !FlagOn( Ccb->Flags, CCB_FLAG_CLOSE_CONTEXT));
2245*23b7c7b8SHermès Bélusca-Maïto         RtlFreeOemString( &Ccb->OemQueryTemplate.Wild );
2246*23b7c7b8SHermès Bélusca-Maïto     }
2247*23b7c7b8SHermès Bélusca-Maïto 
2248*23b7c7b8SHermès Bélusca-Maïto     ClearFlag( Ccb->Flags, CCB_FLAG_FREE_OEM_BEST_FIT | CCB_FLAG_FREE_UNICODE);
2249*23b7c7b8SHermès Bélusca-Maïto }
2250*23b7c7b8SHermès Bélusca-Maïto 
2251*23b7c7b8SHermès Bélusca-Maïto 
2252*23b7c7b8SHermès Bélusca-Maïto 
2253*23b7c7b8SHermès Bélusca-Maïto VOID
FatDeleteCcb(IN PIRP_CONTEXT IrpContext,IN PCCB * Ccb)2254*23b7c7b8SHermès Bélusca-Maïto FatDeleteCcb (
2255*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
2256*23b7c7b8SHermès Bélusca-Maïto     IN PCCB *Ccb
2257*23b7c7b8SHermès Bélusca-Maïto     )
2258*23b7c7b8SHermès Bélusca-Maïto 
2259*23b7c7b8SHermès Bélusca-Maïto /*++
2260*23b7c7b8SHermès Bélusca-Maïto 
2261*23b7c7b8SHermès Bélusca-Maïto Routine Description:
2262*23b7c7b8SHermès Bélusca-Maïto 
2263*23b7c7b8SHermès Bélusca-Maïto     This routine deallocates and removes the specified CCB record
2264*23b7c7b8SHermès Bélusca-Maïto     from the Fat in memory data structures
2265*23b7c7b8SHermès Bélusca-Maïto 
2266*23b7c7b8SHermès Bélusca-Maïto Arguments:
2267*23b7c7b8SHermès Bélusca-Maïto 
2268*23b7c7b8SHermès Bélusca-Maïto     Ccb - Supplies the CCB to remove
2269*23b7c7b8SHermès Bélusca-Maïto 
2270*23b7c7b8SHermès Bélusca-Maïto Return Value:
2271*23b7c7b8SHermès Bélusca-Maïto 
2272*23b7c7b8SHermès Bélusca-Maïto     None
2273*23b7c7b8SHermès Bélusca-Maïto 
2274*23b7c7b8SHermès Bélusca-Maïto --*/
2275*23b7c7b8SHermès Bélusca-Maïto 
2276*23b7c7b8SHermès Bélusca-Maïto {
2277*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
2278*23b7c7b8SHermès Bélusca-Maïto 
2279*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatDeleteCcb, Ccb = %p\n", *Ccb);
2280*23b7c7b8SHermès Bélusca-Maïto 
2281*23b7c7b8SHermès Bélusca-Maïto     FatDeallocateCcbStrings( *Ccb);
2282*23b7c7b8SHermès Bélusca-Maïto 
2283*23b7c7b8SHermès Bélusca-Maïto     //
2284*23b7c7b8SHermès Bélusca-Maïto     //  Deallocate the Ccb record
2285*23b7c7b8SHermès Bélusca-Maïto     //
2286*23b7c7b8SHermès Bélusca-Maïto 
2287*23b7c7b8SHermès Bélusca-Maïto     FatFreeCcb( *Ccb );
2288*23b7c7b8SHermès Bélusca-Maïto     *Ccb = NULL;
2289*23b7c7b8SHermès Bélusca-Maïto 
2290*23b7c7b8SHermès Bélusca-Maïto     //
2291*23b7c7b8SHermès Bélusca-Maïto     //  return and tell the caller
2292*23b7c7b8SHermès Bélusca-Maïto     //
2293*23b7c7b8SHermès Bélusca-Maïto 
2294*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatDeleteCcb -> VOID\n", 0);
2295*23b7c7b8SHermès Bélusca-Maïto 
2296*23b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( IrpContext );
2297*23b7c7b8SHermès Bélusca-Maïto }
2298*23b7c7b8SHermès Bélusca-Maïto 
2299*23b7c7b8SHermès Bélusca-Maïto 
2300*23b7c7b8SHermès Bélusca-Maïto PIRP_CONTEXT
FatCreateIrpContext(IN PIRP Irp,IN BOOLEAN Wait)2301*23b7c7b8SHermès Bélusca-Maïto FatCreateIrpContext (
2302*23b7c7b8SHermès Bélusca-Maïto     IN PIRP Irp,
2303*23b7c7b8SHermès Bélusca-Maïto     IN BOOLEAN Wait
2304*23b7c7b8SHermès Bélusca-Maïto     )
2305*23b7c7b8SHermès Bélusca-Maïto 
2306*23b7c7b8SHermès Bélusca-Maïto /*++
2307*23b7c7b8SHermès Bélusca-Maïto 
2308*23b7c7b8SHermès Bélusca-Maïto Routine Description:
2309*23b7c7b8SHermès Bélusca-Maïto 
2310*23b7c7b8SHermès Bélusca-Maïto     This routine creates a new IRP_CONTEXT record
2311*23b7c7b8SHermès Bélusca-Maïto 
2312*23b7c7b8SHermès Bélusca-Maïto Arguments:
2313*23b7c7b8SHermès Bélusca-Maïto 
2314*23b7c7b8SHermès Bélusca-Maïto     Irp - Supplies the originating Irp.
2315*23b7c7b8SHermès Bélusca-Maïto 
2316*23b7c7b8SHermès Bélusca-Maïto     Wait - Supplies the wait value to store in the context
2317*23b7c7b8SHermès Bélusca-Maïto 
2318*23b7c7b8SHermès Bélusca-Maïto Return Value:
2319*23b7c7b8SHermès Bélusca-Maïto 
2320*23b7c7b8SHermès Bélusca-Maïto     PIRP_CONTEXT - returns a pointer to the newly allocate IRP_CONTEXT Record
2321*23b7c7b8SHermès Bélusca-Maïto 
2322*23b7c7b8SHermès Bélusca-Maïto --*/
2323*23b7c7b8SHermès Bélusca-Maïto 
2324*23b7c7b8SHermès Bélusca-Maïto {
2325*23b7c7b8SHermès Bélusca-Maïto     PIRP_CONTEXT IrpContext;
2326*23b7c7b8SHermès Bélusca-Maïto     PIO_STACK_LOCATION IrpSp;
2327*23b7c7b8SHermès Bélusca-Maïto 
2328*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
2329*23b7c7b8SHermès Bélusca-Maïto 
2330*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatCreateIrpContext\n", 0);
2331*23b7c7b8SHermès Bélusca-Maïto 
2332*23b7c7b8SHermès Bélusca-Maïto     IrpSp = IoGetCurrentIrpStackLocation( Irp );
2333*23b7c7b8SHermès Bélusca-Maïto 
2334*23b7c7b8SHermès Bélusca-Maïto     //
2335*23b7c7b8SHermès Bélusca-Maïto     //  The only operations a filesystem device object should ever receive
2336*23b7c7b8SHermès Bélusca-Maïto     //  are create/teardown of fsdo handles and operations which do not
2337*23b7c7b8SHermès Bélusca-Maïto     //  occur in the context of fileobjects (i.e., mount).
2338*23b7c7b8SHermès Bélusca-Maïto     //
2339*23b7c7b8SHermès Bélusca-Maïto 
2340*23b7c7b8SHermès Bélusca-Maïto     if (FatDeviceIsFatFsdo( IrpSp->DeviceObject))  {
2341*23b7c7b8SHermès Bélusca-Maïto 
2342*23b7c7b8SHermès Bélusca-Maïto         if (IrpSp->FileObject != NULL &&
2343*23b7c7b8SHermès Bélusca-Maïto             IrpSp->MajorFunction != IRP_MJ_CREATE &&
2344*23b7c7b8SHermès Bélusca-Maïto             IrpSp->MajorFunction != IRP_MJ_CLEANUP &&
2345*23b7c7b8SHermès Bélusca-Maïto             IrpSp->MajorFunction != IRP_MJ_CLOSE) {
2346*23b7c7b8SHermès Bélusca-Maïto 
2347*23b7c7b8SHermès Bélusca-Maïto             ExRaiseStatus( STATUS_INVALID_DEVICE_REQUEST );
2348*23b7c7b8SHermès Bélusca-Maïto         }
2349*23b7c7b8SHermès Bélusca-Maïto 
2350*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( IrpSp->FileObject != NULL ||
2351*23b7c7b8SHermès Bélusca-Maïto 
2352*23b7c7b8SHermès Bélusca-Maïto                 (IrpSp->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL &&
2353*23b7c7b8SHermès Bélusca-Maïto                  IrpSp->MinorFunction == IRP_MN_USER_FS_REQUEST &&
2354*23b7c7b8SHermès Bélusca-Maïto                  IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_INVALIDATE_VOLUMES) ||
2355*23b7c7b8SHermès Bélusca-Maïto 
2356*23b7c7b8SHermès Bélusca-Maïto                 (IrpSp->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL &&
2357*23b7c7b8SHermès Bélusca-Maïto                  IrpSp->MinorFunction == IRP_MN_MOUNT_VOLUME ) ||
2358*23b7c7b8SHermès Bélusca-Maïto 
2359*23b7c7b8SHermès Bélusca-Maïto                 IrpSp->MajorFunction == IRP_MJ_SHUTDOWN );
2360*23b7c7b8SHermès Bélusca-Maïto     }
2361*23b7c7b8SHermès Bélusca-Maïto 
2362*23b7c7b8SHermès Bélusca-Maïto     //
2363*23b7c7b8SHermès Bélusca-Maïto     //  Attemtp to allocate from the region first and failing that allocate
2364*23b7c7b8SHermès Bélusca-Maïto     //  from pool.
2365*23b7c7b8SHermès Bélusca-Maïto     //
2366*23b7c7b8SHermès Bélusca-Maïto 
2367*23b7c7b8SHermès Bélusca-Maïto     DebugDoit( FatFsdEntryCount += 1);
2368*23b7c7b8SHermès Bélusca-Maïto 
2369*23b7c7b8SHermès Bélusca-Maïto     IrpContext = FatAllocateIrpContext();
2370*23b7c7b8SHermès Bélusca-Maïto 
2371*23b7c7b8SHermès Bélusca-Maïto     //
2372*23b7c7b8SHermès Bélusca-Maïto     //  Zero out the irp context.
2373*23b7c7b8SHermès Bélusca-Maïto     //
2374*23b7c7b8SHermès Bélusca-Maïto 
2375*23b7c7b8SHermès Bélusca-Maïto     RtlZeroMemory( IrpContext, sizeof(IRP_CONTEXT) );
2376*23b7c7b8SHermès Bélusca-Maïto 
2377*23b7c7b8SHermès Bélusca-Maïto     //
2378*23b7c7b8SHermès Bélusca-Maïto     //  Set the proper node type code and node byte size
2379*23b7c7b8SHermès Bélusca-Maïto     //
2380*23b7c7b8SHermès Bélusca-Maïto 
2381*23b7c7b8SHermès Bélusca-Maïto     IrpContext->NodeTypeCode = FAT_NTC_IRP_CONTEXT;
2382*23b7c7b8SHermès Bélusca-Maïto     IrpContext->NodeByteSize = sizeof(IRP_CONTEXT);
2383*23b7c7b8SHermès Bélusca-Maïto 
2384*23b7c7b8SHermès Bélusca-Maïto     //
2385*23b7c7b8SHermès Bélusca-Maïto     //  Set the originating Irp field
2386*23b7c7b8SHermès Bélusca-Maïto     //
2387*23b7c7b8SHermès Bélusca-Maïto 
2388*23b7c7b8SHermès Bélusca-Maïto     IrpContext->OriginatingIrp = Irp;
2389*23b7c7b8SHermès Bélusca-Maïto 
2390*23b7c7b8SHermès Bélusca-Maïto     //
2391*23b7c7b8SHermès Bélusca-Maïto     //  Major/Minor Function codes
2392*23b7c7b8SHermès Bélusca-Maïto     //
2393*23b7c7b8SHermès Bélusca-Maïto 
2394*23b7c7b8SHermès Bélusca-Maïto     IrpContext->MajorFunction = IrpSp->MajorFunction;
2395*23b7c7b8SHermès Bélusca-Maïto     IrpContext->MinorFunction = IrpSp->MinorFunction;
2396*23b7c7b8SHermès Bélusca-Maïto 
2397*23b7c7b8SHermès Bélusca-Maïto     //
2398*23b7c7b8SHermès Bélusca-Maïto     //  Copy RealDevice for workque algorithms, and also set Write Through
2399*23b7c7b8SHermès Bélusca-Maïto     //  and Removable Media if there is a file object.  Only file system
2400*23b7c7b8SHermès Bélusca-Maïto     //  control Irps won't have a file object, and they should all have
2401*23b7c7b8SHermès Bélusca-Maïto     //  a Vpb as the first IrpSp location.
2402*23b7c7b8SHermès Bélusca-Maïto     //
2403*23b7c7b8SHermès Bélusca-Maïto 
2404*23b7c7b8SHermès Bélusca-Maïto     if (IrpSp->FileObject != NULL) {
2405*23b7c7b8SHermès Bélusca-Maïto 
2406*23b7c7b8SHermès Bélusca-Maïto         PFILE_OBJECT FileObject = IrpSp->FileObject;
2407*23b7c7b8SHermès Bélusca-Maïto 
2408*23b7c7b8SHermès Bélusca-Maïto         IrpContext->RealDevice = FileObject->DeviceObject;
2409*23b7c7b8SHermès Bélusca-Maïto         IrpContext->Vcb = &((PVOLUME_DEVICE_OBJECT)(IrpSp->DeviceObject))->Vcb;
2410*23b7c7b8SHermès Bélusca-Maïto 
2411*23b7c7b8SHermès Bélusca-Maïto         //
2412*23b7c7b8SHermès Bélusca-Maïto         //  See if the request is Write Through. Look for both FileObjects opened
2413*23b7c7b8SHermès Bélusca-Maïto         //  as write through, and non-cached requests with the SL_WRITE_THROUGH flag set.
2414*23b7c7b8SHermès Bélusca-Maïto         //
2415*23b7c7b8SHermès Bélusca-Maïto         //  The latter can only originate from kernel components. (Note - NtWriteFile()
2416*23b7c7b8SHermès Bélusca-Maïto         //  does redundantly set the SL_W_T flag for all requests it issues on write
2417*23b7c7b8SHermès Bélusca-Maïto         //  through file objects)
2418*23b7c7b8SHermès Bélusca-Maïto         //
2419*23b7c7b8SHermès Bélusca-Maïto 
2420*23b7c7b8SHermès Bélusca-Maïto         if (IsFileWriteThrough( FileObject, IrpContext->Vcb ) ||
2421*23b7c7b8SHermès Bélusca-Maïto             ( (IrpSp->MajorFunction == IRP_MJ_WRITE) &&
2422*23b7c7b8SHermès Bélusca-Maïto               BooleanFlagOn( Irp->Flags, IRP_NOCACHE) &&
2423*23b7c7b8SHermès Bélusca-Maïto               BooleanFlagOn( IrpSp->Flags, SL_WRITE_THROUGH))) {
2424*23b7c7b8SHermès Bélusca-Maïto 
2425*23b7c7b8SHermès Bélusca-Maïto             SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH);
2426*23b7c7b8SHermès Bélusca-Maïto         }
2427*23b7c7b8SHermès Bélusca-Maïto     } else if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) {
2428*23b7c7b8SHermès Bélusca-Maïto 
2429*23b7c7b8SHermès Bélusca-Maïto         IrpContext->RealDevice = IrpSp->Parameters.MountVolume.Vpb->RealDevice;
2430*23b7c7b8SHermès Bélusca-Maïto     }
2431*23b7c7b8SHermès Bélusca-Maïto 
2432*23b7c7b8SHermès Bélusca-Maïto     //
2433*23b7c7b8SHermès Bélusca-Maïto     //  Set the wait parameter
2434*23b7c7b8SHermès Bélusca-Maïto     //
2435*23b7c7b8SHermès Bélusca-Maïto 
2436*23b7c7b8SHermès Bélusca-Maïto     if (Wait) { SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); }
2437*23b7c7b8SHermès Bélusca-Maïto 
2438*23b7c7b8SHermès Bélusca-Maïto     //
2439*23b7c7b8SHermès Bélusca-Maïto     //  Set the recursive file system call parameter.  We set it true if
2440*23b7c7b8SHermès Bélusca-Maïto     //  the TopLevelIrp field in the thread local storage is not the current
2441*23b7c7b8SHermès Bélusca-Maïto     //  irp, otherwise we leave it as FALSE.
2442*23b7c7b8SHermès Bélusca-Maïto     //
2443*23b7c7b8SHermès Bélusca-Maïto 
2444*23b7c7b8SHermès Bélusca-Maïto     if ( IoGetTopLevelIrp() != Irp) {
2445*23b7c7b8SHermès Bélusca-Maïto 
2446*23b7c7b8SHermès Bélusca-Maïto         SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL);
2447*23b7c7b8SHermès Bélusca-Maïto     }
2448*23b7c7b8SHermès Bélusca-Maïto 
2449*23b7c7b8SHermès Bélusca-Maïto     //
2450*23b7c7b8SHermès Bélusca-Maïto     //  return and tell the caller
2451*23b7c7b8SHermès Bélusca-Maïto     //
2452*23b7c7b8SHermès Bélusca-Maïto 
2453*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatCreateIrpContext -> %p\n", IrpContext);
2454*23b7c7b8SHermès Bélusca-Maïto 
2455*23b7c7b8SHermès Bélusca-Maïto     return IrpContext;
2456*23b7c7b8SHermès Bélusca-Maïto }
2457*23b7c7b8SHermès Bélusca-Maïto 
2458*23b7c7b8SHermès Bélusca-Maïto 
2459*23b7c7b8SHermès Bélusca-Maïto 
2460*23b7c7b8SHermès Bélusca-Maïto VOID
FatDeleteIrpContext_Real(IN PIRP_CONTEXT IrpContext)2461*23b7c7b8SHermès Bélusca-Maïto FatDeleteIrpContext_Real (
2462*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext
2463*23b7c7b8SHermès Bélusca-Maïto     )
2464*23b7c7b8SHermès Bélusca-Maïto 
2465*23b7c7b8SHermès Bélusca-Maïto /*++
2466*23b7c7b8SHermès Bélusca-Maïto 
2467*23b7c7b8SHermès Bélusca-Maïto Routine Description:
2468*23b7c7b8SHermès Bélusca-Maïto 
2469*23b7c7b8SHermès Bélusca-Maïto     This routine deallocates and removes the specified IRP_CONTEXT record
2470*23b7c7b8SHermès Bélusca-Maïto     from the Fat in memory data structures.  It should only be called
2471*23b7c7b8SHermès Bélusca-Maïto     by FatCompleteRequest.
2472*23b7c7b8SHermès Bélusca-Maïto 
2473*23b7c7b8SHermès Bélusca-Maïto Arguments:
2474*23b7c7b8SHermès Bélusca-Maïto 
2475*23b7c7b8SHermès Bélusca-Maïto     IrpContext - Supplies the IRP_CONTEXT to remove
2476*23b7c7b8SHermès Bélusca-Maïto 
2477*23b7c7b8SHermès Bélusca-Maïto Return Value:
2478*23b7c7b8SHermès Bélusca-Maïto 
2479*23b7c7b8SHermès Bélusca-Maïto     None
2480*23b7c7b8SHermès Bélusca-Maïto 
2481*23b7c7b8SHermès Bélusca-Maïto --*/
2482*23b7c7b8SHermès Bélusca-Maïto 
2483*23b7c7b8SHermès Bélusca-Maïto {
2484*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
2485*23b7c7b8SHermès Bélusca-Maïto 
2486*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(+1, Dbg, "FatDeleteIrpContext, IrpContext = %p\n", IrpContext);
2487*23b7c7b8SHermès Bélusca-Maïto 
2488*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( IrpContext->NodeTypeCode == FAT_NTC_IRP_CONTEXT );
2489*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( IrpContext->PinCount == 0 );
2490*23b7c7b8SHermès Bélusca-Maïto 
2491*23b7c7b8SHermès Bélusca-Maïto 
2492*23b7c7b8SHermès Bélusca-Maïto     //
2493*23b7c7b8SHermès Bélusca-Maïto     //  If there is a FatIoContext that was allocated, free it.
2494*23b7c7b8SHermès Bélusca-Maïto     //
2495*23b7c7b8SHermès Bélusca-Maïto 
2496*23b7c7b8SHermès Bélusca-Maïto     if (IrpContext->FatIoContext != NULL) {
2497*23b7c7b8SHermès Bélusca-Maïto 
2498*23b7c7b8SHermès Bélusca-Maïto         if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_STACK_IO_CONTEXT)) {
2499*23b7c7b8SHermès Bélusca-Maïto 
2500*23b7c7b8SHermès Bélusca-Maïto             if (IrpContext->FatIoContext->ZeroMdl) {
2501*23b7c7b8SHermès Bélusca-Maïto                 IoFreeMdl( IrpContext->FatIoContext->ZeroMdl );
2502*23b7c7b8SHermès Bélusca-Maïto             }
2503*23b7c7b8SHermès Bélusca-Maïto 
2504*23b7c7b8SHermès Bélusca-Maïto             ExFreePool( IrpContext->FatIoContext );
2505*23b7c7b8SHermès Bélusca-Maïto         }
2506*23b7c7b8SHermès Bélusca-Maïto     }
2507*23b7c7b8SHermès Bélusca-Maïto 
2508*23b7c7b8SHermès Bélusca-Maïto     //
2509*23b7c7b8SHermès Bélusca-Maïto     //  Drop the IrpContext.
2510*23b7c7b8SHermès Bélusca-Maïto     //
2511*23b7c7b8SHermès Bélusca-Maïto 
2512*23b7c7b8SHermès Bélusca-Maïto     FatFreeIrpContext( IrpContext );
2513*23b7c7b8SHermès Bélusca-Maïto 
2514*23b7c7b8SHermès Bélusca-Maïto     //
2515*23b7c7b8SHermès Bélusca-Maïto     //  return and tell the caller
2516*23b7c7b8SHermès Bélusca-Maïto     //
2517*23b7c7b8SHermès Bélusca-Maïto 
2518*23b7c7b8SHermès Bélusca-Maïto     DebugTrace(-1, Dbg, "FatDeleteIrpContext -> VOID\n", 0);
2519*23b7c7b8SHermès Bélusca-Maïto 
2520*23b7c7b8SHermès Bélusca-Maïto     return;
2521*23b7c7b8SHermès Bélusca-Maïto }
2522*23b7c7b8SHermès Bélusca-Maïto 
2523*23b7c7b8SHermès Bélusca-Maïto 
2524*23b7c7b8SHermès Bélusca-Maïto PFCB
FatGetNextFcbBottomUp(IN PIRP_CONTEXT IrpContext,IN PFCB Fcb OPTIONAL,IN PFCB TerminationFcb)2525*23b7c7b8SHermès Bélusca-Maïto FatGetNextFcbBottomUp (
2526*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
2527*23b7c7b8SHermès Bélusca-Maïto     IN PFCB Fcb OPTIONAL,
2528*23b7c7b8SHermès Bélusca-Maïto     IN PFCB TerminationFcb
2529*23b7c7b8SHermès Bélusca-Maïto     )
2530*23b7c7b8SHermès Bélusca-Maïto 
2531*23b7c7b8SHermès Bélusca-Maïto /*++
2532*23b7c7b8SHermès Bélusca-Maïto 
2533*23b7c7b8SHermès Bélusca-Maïto Routine Description:
2534*23b7c7b8SHermès Bélusca-Maïto 
2535*23b7c7b8SHermès Bélusca-Maïto     This routine is used to iterate through Fcbs in a tree.  In order to match
2536*23b7c7b8SHermès Bélusca-Maïto     the lockorder for getting multiple Fcbs (so this can be used for acquiring
2537*23b7c7b8SHermès Bélusca-Maïto     all Fcbs), this version does a bottom-up enumeration.
2538*23b7c7b8SHermès Bélusca-Maïto 
2539*23b7c7b8SHermès Bélusca-Maïto     This is different than the old one, now called TopDown. The problem with
2540*23b7c7b8SHermès Bélusca-Maïto     lockorder was very well hidden.
2541*23b7c7b8SHermès Bélusca-Maïto 
2542*23b7c7b8SHermès Bélusca-Maïto     The transition rule is still pretty simple:
2543*23b7c7b8SHermès Bélusca-Maïto 
2544*23b7c7b8SHermès Bélusca-Maïto         A) If you have an adjacent sibling, go to it
2545*23b7c7b8SHermès Bélusca-Maïto             1) Descend to its leftmost child
2546*23b7c7b8SHermès Bélusca-Maïto         B) Else go to your parent
2547*23b7c7b8SHermès Bélusca-Maïto 
2548*23b7c7b8SHermès Bélusca-Maïto     If this routine is called with in invalid TerminationFcb it will fail,
2549*23b7c7b8SHermès Bélusca-Maïto     badly.
2550*23b7c7b8SHermès Bélusca-Maïto 
2551*23b7c7b8SHermès Bélusca-Maïto     The TerminationFcb is the last Fcb returned in the enumeration.
2552*23b7c7b8SHermès Bélusca-Maïto 
2553*23b7c7b8SHermès Bélusca-Maïto     This method is incompatible with the possibility that ancestors may vanish
2554*23b7c7b8SHermès Bélusca-Maïto     based on operations done on the last returned node.  For instance,
2555*23b7c7b8SHermès Bélusca-Maïto     FatPurgeReferencedFileObjects cannot use BottomUp enumeration.
2556*23b7c7b8SHermès Bélusca-Maïto 
2557*23b7c7b8SHermès Bélusca-Maïto Arguments:
2558*23b7c7b8SHermès Bélusca-Maïto 
2559*23b7c7b8SHermès Bélusca-Maïto     Fcb - Supplies the current Fcb.  This is NULL if enumeration is starting.
2560*23b7c7b8SHermès Bélusca-Maïto 
2561*23b7c7b8SHermès Bélusca-Maïto     TerminationFcb - The root Fcb of the tree in which the enumeration starts
2562*23b7c7b8SHermès Bélusca-Maïto         and at which it inclusively stops.
2563*23b7c7b8SHermès Bélusca-Maïto 
2564*23b7c7b8SHermès Bélusca-Maïto Return Value:
2565*23b7c7b8SHermès Bélusca-Maïto 
2566*23b7c7b8SHermès Bélusca-Maïto     The next Fcb in the enumeration, or NULL if Fcb was the final one.
2567*23b7c7b8SHermès Bélusca-Maïto 
2568*23b7c7b8SHermès Bélusca-Maïto --*/
2569*23b7c7b8SHermès Bélusca-Maïto 
2570*23b7c7b8SHermès Bélusca-Maïto {
2571*23b7c7b8SHermès Bélusca-Maïto     PFCB NextFcb;
2572*23b7c7b8SHermès Bélusca-Maïto 
2573*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
2574*23b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( IrpContext );
2575*23b7c7b8SHermès Bélusca-Maïto 
2576*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( FatVcbAcquiredExclusive( IrpContext, TerminationFcb->Vcb ) ||
2577*23b7c7b8SHermès Bélusca-Maïto             FlagOn( TerminationFcb->Vcb->VcbState, VCB_STATE_FLAG_LOCKED ) );
2578*23b7c7b8SHermès Bélusca-Maïto 
2579*23b7c7b8SHermès Bélusca-Maïto     //
2580*23b7c7b8SHermès Bélusca-Maïto     //  Do we need to begin the enumeration?
2581*23b7c7b8SHermès Bélusca-Maïto     //
2582*23b7c7b8SHermès Bélusca-Maïto 
2583*23b7c7b8SHermès Bélusca-Maïto     if (Fcb != NULL) {
2584*23b7c7b8SHermès Bélusca-Maïto 
2585*23b7c7b8SHermès Bélusca-Maïto         //
2586*23b7c7b8SHermès Bélusca-Maïto         //  Did we complete?
2587*23b7c7b8SHermès Bélusca-Maïto         //
2588*23b7c7b8SHermès Bélusca-Maïto 
2589*23b7c7b8SHermès Bélusca-Maïto         if (Fcb == TerminationFcb) {
2590*23b7c7b8SHermès Bélusca-Maïto 
2591*23b7c7b8SHermès Bélusca-Maïto             return NULL;
2592*23b7c7b8SHermès Bélusca-Maïto         }
2593*23b7c7b8SHermès Bélusca-Maïto 
2594*23b7c7b8SHermès Bélusca-Maïto         //
2595*23b7c7b8SHermès Bélusca-Maïto         //  Do we have a sibling to return?
2596*23b7c7b8SHermès Bélusca-Maïto         //
2597*23b7c7b8SHermès Bélusca-Maïto 
2598*23b7c7b8SHermès Bélusca-Maïto         NextFcb = FatGetNextSibling( Fcb );
2599*23b7c7b8SHermès Bélusca-Maïto 
2600*23b7c7b8SHermès Bélusca-Maïto         //
2601*23b7c7b8SHermès Bélusca-Maïto         //  If not, return our parent.  We are done with this branch.
2602*23b7c7b8SHermès Bélusca-Maïto         //
2603*23b7c7b8SHermès Bélusca-Maïto 
2604*23b7c7b8SHermès Bélusca-Maïto         if (NextFcb == NULL) {
2605*23b7c7b8SHermès Bélusca-Maïto 
2606*23b7c7b8SHermès Bélusca-Maïto             return Fcb->ParentDcb;
2607*23b7c7b8SHermès Bélusca-Maïto         }
2608*23b7c7b8SHermès Bélusca-Maïto 
2609*23b7c7b8SHermès Bélusca-Maïto     } else {
2610*23b7c7b8SHermès Bélusca-Maïto 
2611*23b7c7b8SHermès Bélusca-Maïto         NextFcb = TerminationFcb;
2612*23b7c7b8SHermès Bélusca-Maïto     }
2613*23b7c7b8SHermès Bélusca-Maïto 
2614*23b7c7b8SHermès Bélusca-Maïto     //
2615*23b7c7b8SHermès Bélusca-Maïto     //  Decend to its furthest child (if it exists) and return it.
2616*23b7c7b8SHermès Bélusca-Maïto     //
2617*23b7c7b8SHermès Bélusca-Maïto 
2618*23b7c7b8SHermès Bélusca-Maïto     for (;
2619*23b7c7b8SHermès Bélusca-Maïto          NodeType( NextFcb ) != FAT_NTC_FCB && FatGetFirstChild( NextFcb ) != NULL;
2620*23b7c7b8SHermès Bélusca-Maïto          NextFcb = FatGetFirstChild( NextFcb )) {
2621*23b7c7b8SHermès Bélusca-Maïto     }
2622*23b7c7b8SHermès Bélusca-Maïto 
2623*23b7c7b8SHermès Bélusca-Maïto     return NextFcb;
2624*23b7c7b8SHermès Bélusca-Maïto }
2625*23b7c7b8SHermès Bélusca-Maïto 
2626*23b7c7b8SHermès Bélusca-Maïto PFCB
FatGetNextFcbTopDown(IN PIRP_CONTEXT IrpContext,IN PFCB Fcb,IN PFCB TerminationFcb)2627*23b7c7b8SHermès Bélusca-Maïto FatGetNextFcbTopDown (
2628*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
2629*23b7c7b8SHermès Bélusca-Maïto     IN PFCB Fcb,
2630*23b7c7b8SHermès Bélusca-Maïto     IN PFCB TerminationFcb
2631*23b7c7b8SHermès Bélusca-Maïto     )
2632*23b7c7b8SHermès Bélusca-Maïto 
2633*23b7c7b8SHermès Bélusca-Maïto /*++
2634*23b7c7b8SHermès Bélusca-Maïto 
2635*23b7c7b8SHermès Bélusca-Maïto Routine Description:
2636*23b7c7b8SHermès Bélusca-Maïto 
2637*23b7c7b8SHermès Bélusca-Maïto     This routine is used to iterate through Fcbs in a tree, from the top down.
2638*23b7c7b8SHermès Bélusca-Maïto 
2639*23b7c7b8SHermès Bélusca-Maïto     The rule is very simple:
2640*23b7c7b8SHermès Bélusca-Maïto 
2641*23b7c7b8SHermès Bélusca-Maïto         A) If you have a child, go to it, else
2642*23b7c7b8SHermès Bélusca-Maïto         B) If you have an older sibling, go to it, else
2643*23b7c7b8SHermès Bélusca-Maïto         C) Go to your parent's older sibling.
2644*23b7c7b8SHermès Bélusca-Maïto 
2645*23b7c7b8SHermès Bélusca-Maïto     If this routine is called with in invalid TerminationFcb it will fail,
2646*23b7c7b8SHermès Bélusca-Maïto     badly.
2647*23b7c7b8SHermès Bélusca-Maïto 
2648*23b7c7b8SHermès Bélusca-Maïto     The Termination Fcb is never returned.  If it is the root of the tree you
2649*23b7c7b8SHermès Bélusca-Maïto     are traversing, visit it first.
2650*23b7c7b8SHermès Bélusca-Maïto 
2651*23b7c7b8SHermès Bélusca-Maïto     This routine never returns direct ancestors of Fcb, and thus is useful when
2652*23b7c7b8SHermès Bélusca-Maïto     making Fcb's go away (which may tear up the tree).
2653*23b7c7b8SHermès Bélusca-Maïto 
2654*23b7c7b8SHermès Bélusca-Maïto Arguments:
2655*23b7c7b8SHermès Bélusca-Maïto 
2656*23b7c7b8SHermès Bélusca-Maïto     Fcb - Supplies the current Fcb
2657*23b7c7b8SHermès Bélusca-Maïto 
2658*23b7c7b8SHermès Bélusca-Maïto     TerminationFcb - The Fcb at which the enumeration should (non-inclusivly)
2659*23b7c7b8SHermès Bélusca-Maïto         stop.  Assumed to be a directory.
2660*23b7c7b8SHermès Bélusca-Maïto 
2661*23b7c7b8SHermès Bélusca-Maïto Return Value:
2662*23b7c7b8SHermès Bélusca-Maïto 
2663*23b7c7b8SHermès Bélusca-Maïto     The next Fcb in the enumeration, or NULL if Fcb was the final one.
2664*23b7c7b8SHermès Bélusca-Maïto 
2665*23b7c7b8SHermès Bélusca-Maïto --*/
2666*23b7c7b8SHermès Bélusca-Maïto 
2667*23b7c7b8SHermès Bélusca-Maïto {
2668*23b7c7b8SHermès Bélusca-Maïto     PFCB Sibling;
2669*23b7c7b8SHermès Bélusca-Maïto 
2670*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
2671*23b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( IrpContext );
2672*23b7c7b8SHermès Bélusca-Maïto 
2673*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( FatVcbAcquiredExclusive( IrpContext, Fcb->Vcb ) ||
2674*23b7c7b8SHermès Bélusca-Maïto             FlagOn( Fcb->Vcb->VcbState, VCB_STATE_FLAG_LOCKED ) );
2675*23b7c7b8SHermès Bélusca-Maïto 
2676*23b7c7b8SHermès Bélusca-Maïto     //
2677*23b7c7b8SHermès Bélusca-Maïto     //  If this was a directory (ie. not a file), get the child.  If
2678*23b7c7b8SHermès Bélusca-Maïto     //  there aren't any children and this is our termination Fcb,
2679*23b7c7b8SHermès Bélusca-Maïto     //  return NULL.
2680*23b7c7b8SHermès Bélusca-Maïto     //
2681*23b7c7b8SHermès Bélusca-Maïto 
2682*23b7c7b8SHermès Bélusca-Maïto     if ( ((NodeType(Fcb) == FAT_NTC_DCB) ||
2683*23b7c7b8SHermès Bélusca-Maïto           (NodeType(Fcb) == FAT_NTC_ROOT_DCB)) &&
2684*23b7c7b8SHermès Bélusca-Maïto          !IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue) ) {
2685*23b7c7b8SHermès Bélusca-Maïto 
2686*23b7c7b8SHermès Bélusca-Maïto         return FatGetFirstChild( Fcb );
2687*23b7c7b8SHermès Bélusca-Maïto     }
2688*23b7c7b8SHermès Bélusca-Maïto 
2689*23b7c7b8SHermès Bélusca-Maïto     //
2690*23b7c7b8SHermès Bélusca-Maïto     //  Were we only meant to do one iteration?
2691*23b7c7b8SHermès Bélusca-Maïto     //
2692*23b7c7b8SHermès Bélusca-Maïto 
2693*23b7c7b8SHermès Bélusca-Maïto     if ( Fcb == TerminationFcb ) {
2694*23b7c7b8SHermès Bélusca-Maïto 
2695*23b7c7b8SHermès Bélusca-Maïto         return NULL;
2696*23b7c7b8SHermès Bélusca-Maïto     }
2697*23b7c7b8SHermès Bélusca-Maïto 
2698*23b7c7b8SHermès Bélusca-Maïto     Sibling = FatGetNextSibling(Fcb);
2699*23b7c7b8SHermès Bélusca-Maïto 
2700*23b7c7b8SHermès Bélusca-Maïto     while (TRUE) {
2701*23b7c7b8SHermès Bélusca-Maïto 
2702*23b7c7b8SHermès Bélusca-Maïto         //
2703*23b7c7b8SHermès Bélusca-Maïto         //  Do we still have an "older" sibling in this directory who is
2704*23b7c7b8SHermès Bélusca-Maïto         //  not the termination Fcb?
2705*23b7c7b8SHermès Bélusca-Maïto         //
2706*23b7c7b8SHermès Bélusca-Maïto 
2707*23b7c7b8SHermès Bélusca-Maïto         if ( Sibling != NULL ) {
2708*23b7c7b8SHermès Bélusca-Maïto 
2709*23b7c7b8SHermès Bélusca-Maïto             return (Sibling != TerminationFcb) ? Sibling : NULL;
2710*23b7c7b8SHermès Bélusca-Maïto         }
2711*23b7c7b8SHermès Bélusca-Maïto 
2712*23b7c7b8SHermès Bélusca-Maïto         //
2713*23b7c7b8SHermès Bélusca-Maïto         //  OK, let's move on to out parent and see if he is the termination
2714*23b7c7b8SHermès Bélusca-Maïto         //  node or has any older siblings.
2715*23b7c7b8SHermès Bélusca-Maïto         //
2716*23b7c7b8SHermès Bélusca-Maïto 
2717*23b7c7b8SHermès Bélusca-Maïto         if ( Fcb->ParentDcb == TerminationFcb ) {
2718*23b7c7b8SHermès Bélusca-Maïto 
2719*23b7c7b8SHermès Bélusca-Maïto             return NULL;
2720*23b7c7b8SHermès Bélusca-Maïto         }
2721*23b7c7b8SHermès Bélusca-Maïto 
2722*23b7c7b8SHermès Bélusca-Maïto         Fcb = Fcb->ParentDcb;
2723*23b7c7b8SHermès Bélusca-Maïto 
2724*23b7c7b8SHermès Bélusca-Maïto         Sibling = FatGetNextSibling(Fcb);
2725*23b7c7b8SHermès Bélusca-Maïto     }
2726*23b7c7b8SHermès Bélusca-Maïto }
2727*23b7c7b8SHermès Bélusca-Maïto 
2728*23b7c7b8SHermès Bélusca-Maïto 
2729*23b7c7b8SHermès Bélusca-Maïto BOOLEAN
FatSwapVpb(IN PIRP_CONTEXT IrpContext,PVCB Vcb)2730*23b7c7b8SHermès Bélusca-Maïto FatSwapVpb (
2731*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
2732*23b7c7b8SHermès Bélusca-Maïto     PVCB Vcb
2733*23b7c7b8SHermès Bélusca-Maïto     )
2734*23b7c7b8SHermès Bélusca-Maïto 
2735*23b7c7b8SHermès Bélusca-Maïto /*++
2736*23b7c7b8SHermès Bélusca-Maïto 
2737*23b7c7b8SHermès Bélusca-Maïto Routine Description:
2738*23b7c7b8SHermès Bélusca-Maïto 
2739*23b7c7b8SHermès Bélusca-Maïto     This routine swaps the VPB for this VCB if it has not been done already.
2740*23b7c7b8SHermès Bélusca-Maïto     This means the device object will get our spare VPB and we will cleanup
2741*23b7c7b8SHermès Bélusca-Maïto     the one used while the volume was mounted.
2742*23b7c7b8SHermès Bélusca-Maïto 
2743*23b7c7b8SHermès Bélusca-Maïto Arguments:
2744*23b7c7b8SHermès Bélusca-Maïto 
2745*23b7c7b8SHermès Bélusca-Maïto     IrpContext - Supplies the context for the overall request.
2746*23b7c7b8SHermès Bélusca-Maïto 
2747*23b7c7b8SHermès Bélusca-Maïto     Vcb - Supplies the VCB to swap the VPB on.
2748*23b7c7b8SHermès Bélusca-Maïto 
2749*23b7c7b8SHermès Bélusca-Maïto Return Value:
2750*23b7c7b8SHermès Bélusca-Maïto 
2751*23b7c7b8SHermès Bélusca-Maïto     TRUE - If the VPB was actually swapped.
2752*23b7c7b8SHermès Bélusca-Maïto 
2753*23b7c7b8SHermès Bélusca-Maïto     FALSE - If the VPB was already swapped.
2754*23b7c7b8SHermès Bélusca-Maïto 
2755*23b7c7b8SHermès Bélusca-Maïto --*/
2756*23b7c7b8SHermès Bélusca-Maïto 
2757*23b7c7b8SHermès Bélusca-Maïto {
2758*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN Result = FALSE;
2759*23b7c7b8SHermès Bélusca-Maïto     PVPB OldVpb;
2760*23b7c7b8SHermès Bélusca-Maïto     PIO_STACK_LOCATION IrpSp;
2761*23b7c7b8SHermès Bélusca-Maïto 
2762*23b7c7b8SHermès Bélusca-Maïto 
2763*23b7c7b8SHermès Bélusca-Maïto     //
2764*23b7c7b8SHermès Bélusca-Maïto     //  Make sure we have not already swapped it.
2765*23b7c7b8SHermès Bélusca-Maïto     //
2766*23b7c7b8SHermès Bélusca-Maïto 
2767*23b7c7b8SHermès Bélusca-Maïto     OldVpb = Vcb->Vpb;
2768*23b7c7b8SHermès Bélusca-Maïto 
2769*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
2770*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( push )
2771*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( disable: 28175, "touching Vpb is ok for a filesystem" )
2772*23b7c7b8SHermès Bélusca-Maïto #endif
2773*23b7c7b8SHermès Bélusca-Maïto 
2774*23b7c7b8SHermès Bélusca-Maïto     if (!FlagOn( Vcb->VcbState, VCB_STATE_FLAG_VPB_MUST_BE_FREED ) && OldVpb->RealDevice->Vpb == OldVpb) {
2775*23b7c7b8SHermès Bélusca-Maïto 
2776*23b7c7b8SHermès Bélusca-Maïto         //
2777*23b7c7b8SHermès Bélusca-Maïto         //  If not the final reference and we are forcing the disconnect,
2778*23b7c7b8SHermès Bélusca-Maïto         //  then swap out the Vpb.  We must preserve the REMOVE_PENDING flag
2779*23b7c7b8SHermès Bélusca-Maïto         //  so that the device is not remounted in the middle of a PnP remove
2780*23b7c7b8SHermès Bélusca-Maïto         //  operation.
2781*23b7c7b8SHermès Bélusca-Maïto         //
2782*23b7c7b8SHermès Bélusca-Maïto 
2783*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( Vcb->SwapVpb != NULL );
2784*23b7c7b8SHermès Bélusca-Maïto 
2785*23b7c7b8SHermès Bélusca-Maïto         Vcb->SwapVpb->Type = IO_TYPE_VPB;
2786*23b7c7b8SHermès Bélusca-Maïto         Vcb->SwapVpb->Size = sizeof( VPB );
2787*23b7c7b8SHermès Bélusca-Maïto         Vcb->SwapVpb->RealDevice = OldVpb->RealDevice;
2788*23b7c7b8SHermès Bélusca-Maïto 
2789*23b7c7b8SHermès Bélusca-Maïto         Vcb->SwapVpb->RealDevice->Vpb = Vcb->SwapVpb;
2790*23b7c7b8SHermès Bélusca-Maïto 
2791*23b7c7b8SHermès Bélusca-Maïto         Vcb->SwapVpb->Flags = FlagOn( OldVpb->Flags, VPB_REMOVE_PENDING );
2792*23b7c7b8SHermès Bélusca-Maïto 
2793*23b7c7b8SHermès Bélusca-Maïto         //
2794*23b7c7b8SHermès Bélusca-Maïto         //  If we are working on a mount request, we need to make sure we update
2795*23b7c7b8SHermès Bélusca-Maïto         //  the VPB in the IRP, since the one it points to may no longer be valid.
2796*23b7c7b8SHermès Bélusca-Maïto         //
2797*23b7c7b8SHermès Bélusca-Maïto 
2798*23b7c7b8SHermès Bélusca-Maïto         if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL && IrpContext->MinorFunction == IRP_MN_MOUNT_VOLUME) {
2799*23b7c7b8SHermès Bélusca-Maïto 
2800*23b7c7b8SHermès Bélusca-Maïto             //
2801*23b7c7b8SHermès Bélusca-Maïto             //  Get the IRP stack.
2802*23b7c7b8SHermès Bélusca-Maïto             //
2803*23b7c7b8SHermès Bélusca-Maïto 
2804*23b7c7b8SHermès Bélusca-Maïto             IrpSp = IoGetCurrentIrpStackLocation( IrpContext->OriginatingIrp );
2805*23b7c7b8SHermès Bélusca-Maïto 
2806*23b7c7b8SHermès Bélusca-Maïto             NT_ASSERT( IrpSp->FileObject == NULL );
2807*23b7c7b8SHermès Bélusca-Maïto 
2808*23b7c7b8SHermès Bélusca-Maïto             //
2809*23b7c7b8SHermès Bélusca-Maïto             //  Check the VPB in the IRP to see if it is the one we are swapping.
2810*23b7c7b8SHermès Bélusca-Maïto             //
2811*23b7c7b8SHermès Bélusca-Maïto 
2812*23b7c7b8SHermès Bélusca-Maïto             if (IrpSp->Parameters.MountVolume.Vpb == OldVpb) {
2813*23b7c7b8SHermès Bélusca-Maïto 
2814*23b7c7b8SHermès Bélusca-Maïto                 //
2815*23b7c7b8SHermès Bélusca-Maïto                 //  Change the IRP to point to the swap VPB.
2816*23b7c7b8SHermès Bélusca-Maïto                 //
2817*23b7c7b8SHermès Bélusca-Maïto 
2818*23b7c7b8SHermès Bélusca-Maïto                 IrpSp->Parameters.MountVolume.Vpb = Vcb->SwapVpb;
2819*23b7c7b8SHermès Bélusca-Maïto             }
2820*23b7c7b8SHermès Bélusca-Maïto         }
2821*23b7c7b8SHermès Bélusca-Maïto 
2822*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
2823*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( pop )
2824*23b7c7b8SHermès Bélusca-Maïto #endif
2825*23b7c7b8SHermès Bélusca-Maïto 
2826*23b7c7b8SHermès Bélusca-Maïto         //
2827*23b7c7b8SHermès Bélusca-Maïto         //  We place the volume in the Bad state (as opposed to NotMounted) so
2828*23b7c7b8SHermès Bélusca-Maïto         //  that it is not eligible for a remount.  Also indicate we used up
2829*23b7c7b8SHermès Bélusca-Maïto         //  the swap.
2830*23b7c7b8SHermès Bélusca-Maïto         //
2831*23b7c7b8SHermès Bélusca-Maïto 
2832*23b7c7b8SHermès Bélusca-Maïto         Vcb->SwapVpb = NULL;
2833*23b7c7b8SHermès Bélusca-Maïto         FatSetVcbCondition( Vcb, VcbBad);
2834*23b7c7b8SHermès Bélusca-Maïto         SetFlag( Vcb->VcbState, VCB_STATE_FLAG_VPB_MUST_BE_FREED );
2835*23b7c7b8SHermès Bélusca-Maïto 
2836*23b7c7b8SHermès Bélusca-Maïto         Result = TRUE;
2837*23b7c7b8SHermès Bélusca-Maïto     }
2838*23b7c7b8SHermès Bélusca-Maïto 
2839*23b7c7b8SHermès Bélusca-Maïto     return Result;
2840*23b7c7b8SHermès Bélusca-Maïto }
2841*23b7c7b8SHermès Bélusca-Maïto 
2842*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)2843*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
2844*23b7c7b8SHermès Bélusca-Maïto BOOLEAN
2845*23b7c7b8SHermès Bélusca-Maïto FatCheckForDismount (
2846*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
2847*23b7c7b8SHermès Bélusca-Maïto     PVCB Vcb,
2848*23b7c7b8SHermès Bélusca-Maïto     IN BOOLEAN Force
2849*23b7c7b8SHermès Bélusca-Maïto     )
2850*23b7c7b8SHermès Bélusca-Maïto 
2851*23b7c7b8SHermès Bélusca-Maïto /*++
2852*23b7c7b8SHermès Bélusca-Maïto 
2853*23b7c7b8SHermès Bélusca-Maïto Routine Description:
2854*23b7c7b8SHermès Bélusca-Maïto 
2855*23b7c7b8SHermès Bélusca-Maïto     This routine determines if a volume is ready for deletion.  It
2856*23b7c7b8SHermès Bélusca-Maïto     correctly synchronizes with creates en-route to the file system.
2857*23b7c7b8SHermès Bélusca-Maïto 
2858*23b7c7b8SHermès Bélusca-Maïto Arguments:
2859*23b7c7b8SHermès Bélusca-Maïto 
2860*23b7c7b8SHermès Bélusca-Maïto     Vcb - Supplies the volume to examine
2861*23b7c7b8SHermès Bélusca-Maïto 
2862*23b7c7b8SHermès Bélusca-Maïto     Force - Specifies whether we want this Vcb forcibly disconnected
2863*23b7c7b8SHermès Bélusca-Maïto         from the driver stack if it will not be deleted (a new vpb will
2864*23b7c7b8SHermès Bélusca-Maïto         be installed if neccesary).  Caller is responsible for making
2865*23b7c7b8SHermès Bélusca-Maïto         sure that the volume has been marked in such a way that attempts
2866*23b7c7b8SHermès Bélusca-Maïto         to operate through the realdevice are blocked (i.e., move the vcb
2867*23b7c7b8SHermès Bélusca-Maïto         out of the mounted state).
2868*23b7c7b8SHermès Bélusca-Maïto 
2869*23b7c7b8SHermès Bélusca-Maïto Return Value:
2870*23b7c7b8SHermès Bélusca-Maïto 
2871*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN - TRUE if the volume was deleted, FALSE otherwise.
2872*23b7c7b8SHermès Bélusca-Maïto 
2873*23b7c7b8SHermès Bélusca-Maïto --*/
2874*23b7c7b8SHermès Bélusca-Maïto 
2875*23b7c7b8SHermès Bélusca-Maïto {
2876*23b7c7b8SHermès Bélusca-Maïto     KIRQL SavedIrql;
2877*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN VcbDeleted = FALSE;
2878*23b7c7b8SHermès Bélusca-Maïto 
2879*23b7c7b8SHermès Bélusca-Maïto 
2880*23b7c7b8SHermès Bélusca-Maïto     //
2881*23b7c7b8SHermès Bélusca-Maïto     //  If the VCB condition is good and we are not forcing, just return.
2882*23b7c7b8SHermès Bélusca-Maïto     //
2883*23b7c7b8SHermès Bélusca-Maïto 
2884*23b7c7b8SHermès Bélusca-Maïto     if (Vcb->VcbCondition == VcbGood && !Force) {
2885*23b7c7b8SHermès Bélusca-Maïto 
2886*23b7c7b8SHermès Bélusca-Maïto         return FALSE;
2887*23b7c7b8SHermès Bélusca-Maïto     }
2888*23b7c7b8SHermès Bélusca-Maïto 
2889*23b7c7b8SHermès Bélusca-Maïto     //
2890*23b7c7b8SHermès Bélusca-Maïto     //  Now check for a zero Vpb count on an unmounted volume.  These
2891*23b7c7b8SHermès Bélusca-Maïto     //  volumes will be deleted as they now have no file objects and
2892*23b7c7b8SHermès Bélusca-Maïto     //  there are no creates en route to this volume.
2893*23b7c7b8SHermès Bélusca-Maïto     //
2894*23b7c7b8SHermès Bélusca-Maïto 
2895*23b7c7b8SHermès Bélusca-Maïto     IoAcquireVpbSpinLock( &SavedIrql );
2896*23b7c7b8SHermès Bélusca-Maïto 
2897*23b7c7b8SHermès Bélusca-Maïto     if (Vcb->Vpb->ReferenceCount == Vcb->ResidualOpenCount && Vcb->OpenFileCount == 0) {
2898*23b7c7b8SHermès Bélusca-Maïto 
2899*23b7c7b8SHermès Bélusca-Maïto         PVPB Vpb = Vcb->Vpb;
2900*23b7c7b8SHermès Bélusca-Maïto 
2901*23b7c7b8SHermès Bélusca-Maïto #if DBG
2902*23b7c7b8SHermès Bélusca-Maïto         UNICODE_STRING VolumeLabel;
2903*23b7c7b8SHermès Bélusca-Maïto 
2904*23b7c7b8SHermès Bélusca-Maïto         //
2905*23b7c7b8SHermès Bélusca-Maïto         //  Setup the VolumeLabel string
2906*23b7c7b8SHermès Bélusca-Maïto         //
2907*23b7c7b8SHermès Bélusca-Maïto 
2908*23b7c7b8SHermès Bélusca-Maïto         VolumeLabel.Length = Vcb->Vpb->VolumeLabelLength;
2909*23b7c7b8SHermès Bélusca-Maïto         VolumeLabel.MaximumLength = MAXIMUM_VOLUME_LABEL_LENGTH;
2910*23b7c7b8SHermès Bélusca-Maïto         VolumeLabel.Buffer = &Vcb->Vpb->VolumeLabel[0];
2911*23b7c7b8SHermès Bélusca-Maïto 
2912*23b7c7b8SHermès Bélusca-Maïto         KdPrintEx((DPFLTR_FASTFAT_ID,
2913*23b7c7b8SHermès Bélusca-Maïto                    DPFLTR_INFO_LEVEL,
2914*23b7c7b8SHermès Bélusca-Maïto                    "FASTFAT: Dismounting Volume %Z\n",
2915*23b7c7b8SHermès Bélusca-Maïto                    &VolumeLabel));
2916*23b7c7b8SHermès Bélusca-Maïto #endif // DBG
2917*23b7c7b8SHermès Bélusca-Maïto 
2918*23b7c7b8SHermès Bélusca-Maïto         //
2919*23b7c7b8SHermès Bélusca-Maïto         //  Swap this VCB's VPB.
2920*23b7c7b8SHermès Bélusca-Maïto         //
2921*23b7c7b8SHermès Bélusca-Maïto 
2922*23b7c7b8SHermès Bélusca-Maïto         FatSwapVpb( IrpContext,
2923*23b7c7b8SHermès Bélusca-Maïto                     Vcb );
2924*23b7c7b8SHermès Bélusca-Maïto 
2925*23b7c7b8SHermès Bélusca-Maïto         //
2926*23b7c7b8SHermès Bélusca-Maïto         //  Clear the VPB_MOUNTED bit.  New opens should not come in due
2927*23b7c7b8SHermès Bélusca-Maïto         //  to the swapped VPB, but having the flag cleared helps debugging.
2928*23b7c7b8SHermès Bélusca-Maïto         //  Note that we must leave the Vpb->DeviceObject field set until
2929*23b7c7b8SHermès Bélusca-Maïto         //  after the FatTearDownVcb call as closes will have to make their
2930*23b7c7b8SHermès Bélusca-Maïto         //  way back to us.
2931*23b7c7b8SHermès Bélusca-Maïto         //
2932*23b7c7b8SHermès Bélusca-Maïto 
2933*23b7c7b8SHermès Bélusca-Maïto         ClearFlag( Vpb->Flags, VPB_MOUNTED );
2934*23b7c7b8SHermès Bélusca-Maïto 
2935*23b7c7b8SHermès Bélusca-Maïto         //
2936*23b7c7b8SHermès Bélusca-Maïto         //  If this Vpb was locked, clear this flag now.
2937*23b7c7b8SHermès Bélusca-Maïto         //
2938*23b7c7b8SHermès Bélusca-Maïto 
2939*23b7c7b8SHermès Bélusca-Maïto         ClearFlag( Vpb->Flags, (VPB_LOCKED | VPB_DIRECT_WRITES_ALLOWED) );
2940*23b7c7b8SHermès Bélusca-Maïto 
2941*23b7c7b8SHermès Bélusca-Maïto         IoReleaseVpbSpinLock( SavedIrql );
2942*23b7c7b8SHermès Bélusca-Maïto 
2943*23b7c7b8SHermès Bélusca-Maïto         //
2944*23b7c7b8SHermès Bélusca-Maïto         //  We are going to attempt the dismount, so mark the VCB as having
2945*23b7c7b8SHermès Bélusca-Maïto         //  a dismount in progress.
2946*23b7c7b8SHermès Bélusca-Maïto         //
2947*23b7c7b8SHermès Bélusca-Maïto 
2948*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( !FlagOn( Vcb->VcbState, VCB_STATE_FLAG_DISMOUNT_IN_PROGRESS ) );
2949*23b7c7b8SHermès Bélusca-Maïto         SetFlag( Vcb->VcbState, VCB_STATE_FLAG_DISMOUNT_IN_PROGRESS );
2950*23b7c7b8SHermès Bélusca-Maïto 
2951*23b7c7b8SHermès Bélusca-Maïto         //
2952*23b7c7b8SHermès Bélusca-Maïto         //  Close down our internal opens.
2953*23b7c7b8SHermès Bélusca-Maïto         //
2954*23b7c7b8SHermès Bélusca-Maïto 
2955*23b7c7b8SHermès Bélusca-Maïto         FatTearDownVcb( IrpContext,
2956*23b7c7b8SHermès Bélusca-Maïto                         Vcb );
2957*23b7c7b8SHermès Bélusca-Maïto 
2958*23b7c7b8SHermès Bélusca-Maïto         //
2959*23b7c7b8SHermès Bélusca-Maïto         //  Process any delayed closes.
2960*23b7c7b8SHermès Bélusca-Maïto         //
2961*23b7c7b8SHermès Bélusca-Maïto 
2962*23b7c7b8SHermès Bélusca-Maïto         FatFspClose( Vcb );
2963*23b7c7b8SHermès Bélusca-Maïto 
2964*23b7c7b8SHermès Bélusca-Maïto         //
2965*23b7c7b8SHermès Bélusca-Maïto         //  Grab the VPB lock again so that we can recheck our counts.
2966*23b7c7b8SHermès Bélusca-Maïto         //
2967*23b7c7b8SHermès Bélusca-Maïto 
2968*23b7c7b8SHermès Bélusca-Maïto         IoAcquireVpbSpinLock( &SavedIrql );
2969*23b7c7b8SHermès Bélusca-Maïto 
2970*23b7c7b8SHermès Bélusca-Maïto         //
2971*23b7c7b8SHermès Bélusca-Maïto         //  See if we can delete this VCB.
2972*23b7c7b8SHermès Bélusca-Maïto         //
2973*23b7c7b8SHermès Bélusca-Maïto 
2974*23b7c7b8SHermès Bélusca-Maïto         if (Vcb->Vpb->ReferenceCount == 0 && Vcb->InternalOpenCount == 0) {
2975*23b7c7b8SHermès Bélusca-Maïto 
2976*23b7c7b8SHermès Bélusca-Maïto             Vpb->DeviceObject = NULL;
2977*23b7c7b8SHermès Bélusca-Maïto 
2978*23b7c7b8SHermès Bélusca-Maïto             IoReleaseVpbSpinLock( SavedIrql );
2979*23b7c7b8SHermès Bélusca-Maïto 
2980*23b7c7b8SHermès Bélusca-Maïto             FatDeleteVcb( IrpContext, Vcb );
2981*23b7c7b8SHermès Bélusca-Maïto 
2982*23b7c7b8SHermès Bélusca-Maïto             IoDeleteDevice( (PDEVICE_OBJECT)
2983*23b7c7b8SHermès Bélusca-Maïto                             CONTAINING_RECORD( Vcb,
2984*23b7c7b8SHermès Bélusca-Maïto                                                VOLUME_DEVICE_OBJECT,
2985*23b7c7b8SHermès Bélusca-Maïto                                                Vcb ) );
2986*23b7c7b8SHermès Bélusca-Maïto 
2987*23b7c7b8SHermès Bélusca-Maïto             VcbDeleted = TRUE;
2988*23b7c7b8SHermès Bélusca-Maïto 
2989*23b7c7b8SHermès Bélusca-Maïto         } else {
2990*23b7c7b8SHermès Bélusca-Maïto 
2991*23b7c7b8SHermès Bélusca-Maïto             IoReleaseVpbSpinLock( SavedIrql );
2992*23b7c7b8SHermès Bélusca-Maïto 
2993*23b7c7b8SHermès Bélusca-Maïto             NT_ASSERT( FlagOn( Vcb->VcbState, VCB_STATE_FLAG_DISMOUNT_IN_PROGRESS ) );
2994*23b7c7b8SHermès Bélusca-Maïto             ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_DISMOUNT_IN_PROGRESS );
2995*23b7c7b8SHermès Bélusca-Maïto         }
2996*23b7c7b8SHermès Bélusca-Maïto 
2997*23b7c7b8SHermès Bélusca-Maïto     } else if (Force) {
2998*23b7c7b8SHermès Bélusca-Maïto 
2999*23b7c7b8SHermès Bélusca-Maïto         //
3000*23b7c7b8SHermès Bélusca-Maïto         //  The requester is forcing the issue.  We need to swap the VPB with our spare.
3001*23b7c7b8SHermès Bélusca-Maïto         //
3002*23b7c7b8SHermès Bélusca-Maïto 
3003*23b7c7b8SHermès Bélusca-Maïto         FatSwapVpb( IrpContext,
3004*23b7c7b8SHermès Bélusca-Maïto                     Vcb );
3005*23b7c7b8SHermès Bélusca-Maïto 
3006*23b7c7b8SHermès Bélusca-Maïto         IoReleaseVpbSpinLock( SavedIrql );
3007*23b7c7b8SHermès Bélusca-Maïto 
3008*23b7c7b8SHermès Bélusca-Maïto     } else {
3009*23b7c7b8SHermès Bélusca-Maïto 
3010*23b7c7b8SHermès Bélusca-Maïto         //
3011*23b7c7b8SHermès Bélusca-Maïto         //  Just drop the Vpb spinlock.
3012*23b7c7b8SHermès Bélusca-Maïto         //
3013*23b7c7b8SHermès Bélusca-Maïto 
3014*23b7c7b8SHermès Bélusca-Maïto         IoReleaseVpbSpinLock( SavedIrql );
3015*23b7c7b8SHermès Bélusca-Maïto     }
3016*23b7c7b8SHermès Bélusca-Maïto 
3017*23b7c7b8SHermès Bélusca-Maïto     return VcbDeleted;
3018*23b7c7b8SHermès Bélusca-Maïto }
3019*23b7c7b8SHermès Bélusca-Maïto 
3020*23b7c7b8SHermès Bélusca-Maïto 
3021*23b7c7b8SHermès Bélusca-Maïto VOID
FatConstructNamesInFcb(IN PIRP_CONTEXT IrpContext,PFCB Fcb,PDIRENT Dirent,PUNICODE_STRING Lfn OPTIONAL)3022*23b7c7b8SHermès Bélusca-Maïto FatConstructNamesInFcb (
3023*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
3024*23b7c7b8SHermès Bélusca-Maïto     PFCB Fcb,
3025*23b7c7b8SHermès Bélusca-Maïto     PDIRENT Dirent,
3026*23b7c7b8SHermès Bélusca-Maïto     PUNICODE_STRING Lfn OPTIONAL
3027*23b7c7b8SHermès Bélusca-Maïto     )
3028*23b7c7b8SHermès Bélusca-Maïto 
3029*23b7c7b8SHermès Bélusca-Maïto /*++
3030*23b7c7b8SHermès Bélusca-Maïto 
3031*23b7c7b8SHermès Bélusca-Maïto Routine Description:
3032*23b7c7b8SHermès Bélusca-Maïto 
3033*23b7c7b8SHermès Bélusca-Maïto     This routine places the short name in the dirent in the first set of
3034*23b7c7b8SHermès Bélusca-Maïto     STRINGs in the Fcb.  If a long file name (Lfn) was specified, then
3035*23b7c7b8SHermès Bélusca-Maïto     we must decide whether we will store its Oem equivolent in the same
3036*23b7c7b8SHermès Bélusca-Maïto     prefix table as the short name, or rather just save the upcased
3037*23b7c7b8SHermès Bélusca-Maïto     version of the UNICODE string in the FCB.
3038*23b7c7b8SHermès Bélusca-Maïto 
3039*23b7c7b8SHermès Bélusca-Maïto     For looking up Fcbs, the first approach will be faster, so we want to
3040*23b7c7b8SHermès Bélusca-Maïto     do this as much as possible.  Here are the rules that I have thought
3041*23b7c7b8SHermès Bélusca-Maïto     through extensively to determine when it is safe to store only Oem
3042*23b7c7b8SHermès Bélusca-Maïto     version of the UNICODE name.
3043*23b7c7b8SHermès Bélusca-Maïto 
3044*23b7c7b8SHermès Bélusca-Maïto     - If the UNICODE name contains no extended characters (>0x80), use Oem.
3045*23b7c7b8SHermès Bélusca-Maïto 
3046*23b7c7b8SHermès Bélusca-Maïto     - Let U be the upcased version of the UNICODE name.
3047*23b7c7b8SHermès Bélusca-Maïto       Let Up(x) be the function that upcases a UNICODE string.
3048*23b7c7b8SHermès Bélusca-Maïto       Let Down(x) be the function that upcases a UNICODE string.
3049*23b7c7b8SHermès Bélusca-Maïto       Let OemToUni(x) be the function that converts an Oem string to Unicode.
3050*23b7c7b8SHermès Bélusca-Maïto       Let UniToOem(x) be the function that converts a Unicode string to Oem.
3051*23b7c7b8SHermès Bélusca-Maïto       Let BestOemFit(x) be the function that creates the Best uppercase Oem
3052*23b7c7b8SHermès Bélusca-Maïto         fit for the UNICODE string x.
3053*23b7c7b8SHermès Bélusca-Maïto 
3054*23b7c7b8SHermès Bélusca-Maïto       BestOemFit(x) = UniToOem(Up(OemToUni(UniToOem(x))))   <1>
3055*23b7c7b8SHermès Bélusca-Maïto 
3056*23b7c7b8SHermès Bélusca-Maïto       if (BestOemFit(U) == BestOemFit(Down(U))              <2>
3057*23b7c7b8SHermès Bélusca-Maïto 
3058*23b7c7b8SHermès Bélusca-Maïto           then I know that there exists no UNICODE string Y such that:
3059*23b7c7b8SHermès Bélusca-Maïto 
3060*23b7c7b8SHermès Bélusca-Maïto               Up(Y) == Up(U)                                <3>
3061*23b7c7b8SHermès Bélusca-Maïto 
3062*23b7c7b8SHermès Bélusca-Maïto               AND
3063*23b7c7b8SHermès Bélusca-Maïto 
3064*23b7c7b8SHermès Bélusca-Maïto               BestOemFit(U) != BestOemFit(Y)                <4>
3065*23b7c7b8SHermès Bélusca-Maïto 
3066*23b7c7b8SHermès Bélusca-Maïto       Consider string U as a collection of one character strings.  The
3067*23b7c7b8SHermès Bélusca-Maïto       conjecture is clearly true for each sub-string, thus it is true
3068*23b7c7b8SHermès Bélusca-Maïto       for the entire string.
3069*23b7c7b8SHermès Bélusca-Maïto 
3070*23b7c7b8SHermès Bélusca-Maïto       Equation <1> is what we use to convert an incoming unicode name in
3071*23b7c7b8SHermès Bélusca-Maïto       FatCommonCreate() to Oem.  The double conversion is done to provide
3072*23b7c7b8SHermès Bélusca-Maïto       better visual best fitting for characters in the Ansi code page but
3073*23b7c7b8SHermès Bélusca-Maïto       not in the Oem code page.  A single Nls routine is provided to do
3074*23b7c7b8SHermès Bélusca-Maïto       this conversion efficiently.
3075*23b7c7b8SHermès Bélusca-Maïto 
3076*23b7c7b8SHermès Bélusca-Maïto       The idea is that with U, I only have to worry about a case varient Y
3077*23b7c7b8SHermès Bélusca-Maïto       matching it in a unicode compare, and I have shown that any case varient
3078*23b7c7b8SHermès Bélusca-Maïto       of U (the set Y defined in equation <3>), when filtered through <1>
3079*23b7c7b8SHermès Bélusca-Maïto       (as in create), will match the Oem string defined in <1>.
3080*23b7c7b8SHermès Bélusca-Maïto 
3081*23b7c7b8SHermès Bélusca-Maïto       Thus I do not have to worry about another UNICODE string missing in
3082*23b7c7b8SHermès Bélusca-Maïto       the prefix lookup, but matching when comparing LFNs in the directory.
3083*23b7c7b8SHermès Bélusca-Maïto 
3084*23b7c7b8SHermès Bélusca-Maïto Arguments:
3085*23b7c7b8SHermès Bélusca-Maïto 
3086*23b7c7b8SHermès Bélusca-Maïto     Fcb - The Fcb we are supposed to fill in.  Note that ParentDcb must
3087*23b7c7b8SHermès Bélusca-Maïto         already be filled in.
3088*23b7c7b8SHermès Bélusca-Maïto 
3089*23b7c7b8SHermès Bélusca-Maïto     Dirent - The gives up the short name.
3090*23b7c7b8SHermès Bélusca-Maïto 
3091*23b7c7b8SHermès Bélusca-Maïto     Lfn - If provided, this gives us the long name.
3092*23b7c7b8SHermès Bélusca-Maïto 
3093*23b7c7b8SHermès Bélusca-Maïto Return Value:
3094*23b7c7b8SHermès Bélusca-Maïto 
3095*23b7c7b8SHermès Bélusca-Maïto     None
3096*23b7c7b8SHermès Bélusca-Maïto 
3097*23b7c7b8SHermès Bélusca-Maïto --*/
3098*23b7c7b8SHermès Bélusca-Maïto 
3099*23b7c7b8SHermès Bélusca-Maïto {
3100*23b7c7b8SHermès Bélusca-Maïto #ifndef __REACTOS__
3101*23b7c7b8SHermès Bélusca-Maïto     NTSTATUS Status;
3102*23b7c7b8SHermès Bélusca-Maïto #endif
3103*23b7c7b8SHermès Bélusca-Maïto     ULONG i;
3104*23b7c7b8SHermès Bélusca-Maïto 
3105*23b7c7b8SHermès Bélusca-Maïto #ifndef __REACTOS__
3106*23b7c7b8SHermès Bélusca-Maïto     OEM_STRING OemA;
3107*23b7c7b8SHermès Bélusca-Maïto     OEM_STRING OemB;
3108*23b7c7b8SHermès Bélusca-Maïto #endif
3109*23b7c7b8SHermès Bélusca-Maïto     UNICODE_STRING Unicode;
3110*23b7c7b8SHermès Bélusca-Maïto     POEM_STRING ShortName;
3111*23b7c7b8SHermès Bélusca-Maïto     POEM_STRING LongOemName;
3112*23b7c7b8SHermès Bélusca-Maïto     PUNICODE_STRING LongUniName;
3113*23b7c7b8SHermès Bélusca-Maïto 
3114*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
3115*23b7c7b8SHermès Bélusca-Maïto 
3116*23b7c7b8SHermès Bélusca-Maïto     ShortName = &Fcb->ShortName.Name.Oem;
3117*23b7c7b8SHermès Bélusca-Maïto 
3118*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( ShortName->Buffer == NULL );
3119*23b7c7b8SHermès Bélusca-Maïto 
3120*23b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
3121*23b7c7b8SHermès Bélusca-Maïto 
3122*23b7c7b8SHermès Bélusca-Maïto         //
3123*23b7c7b8SHermès Bélusca-Maïto         //  First do the short name.
3124*23b7c7b8SHermès Bélusca-Maïto         //
3125*23b7c7b8SHermès Bélusca-Maïto 
3126*23b7c7b8SHermès Bélusca-Maïto         //
3127*23b7c7b8SHermès Bélusca-Maïto         //  Copy over the case flags for the short name of the file
3128*23b7c7b8SHermès Bélusca-Maïto         //
3129*23b7c7b8SHermès Bélusca-Maïto 
3130*23b7c7b8SHermès Bélusca-Maïto         if (FlagOn(Dirent->NtByte, FAT_DIRENT_NT_BYTE_8_LOWER_CASE)) {
3131*23b7c7b8SHermès Bélusca-Maïto 
3132*23b7c7b8SHermès Bélusca-Maïto             SetFlag(Fcb->FcbState, FCB_STATE_8_LOWER_CASE);
3133*23b7c7b8SHermès Bélusca-Maïto 
3134*23b7c7b8SHermès Bélusca-Maïto         } else {
3135*23b7c7b8SHermès Bélusca-Maïto 
3136*23b7c7b8SHermès Bélusca-Maïto             ClearFlag(Fcb->FcbState, FCB_STATE_8_LOWER_CASE);
3137*23b7c7b8SHermès Bélusca-Maïto         }
3138*23b7c7b8SHermès Bélusca-Maïto 
3139*23b7c7b8SHermès Bélusca-Maïto         if (FlagOn(Dirent->NtByte, FAT_DIRENT_NT_BYTE_3_LOWER_CASE)) {
3140*23b7c7b8SHermès Bélusca-Maïto 
3141*23b7c7b8SHermès Bélusca-Maïto             SetFlag(Fcb->FcbState, FCB_STATE_3_LOWER_CASE);
3142*23b7c7b8SHermès Bélusca-Maïto 
3143*23b7c7b8SHermès Bélusca-Maïto         } else {
3144*23b7c7b8SHermès Bélusca-Maïto 
3145*23b7c7b8SHermès Bélusca-Maïto             ClearFlag(Fcb->FcbState, FCB_STATE_3_LOWER_CASE);
3146*23b7c7b8SHermès Bélusca-Maïto         }
3147*23b7c7b8SHermès Bélusca-Maïto 
3148*23b7c7b8SHermès Bélusca-Maïto         ShortName->MaximumLength = 16;
3149*23b7c7b8SHermès Bélusca-Maïto         ShortName->Buffer = FsRtlAllocatePoolWithTag( PagedPool,
3150*23b7c7b8SHermès Bélusca-Maïto                                                       16,
3151*23b7c7b8SHermès Bélusca-Maïto                                                       TAG_FILENAME_BUFFER );
3152*23b7c7b8SHermès Bélusca-Maïto 
3153*23b7c7b8SHermès Bélusca-Maïto         Fat8dot3ToString( IrpContext, Dirent, FALSE, ShortName );
3154*23b7c7b8SHermès Bélusca-Maïto 
3155*23b7c7b8SHermès Bélusca-Maïto         Fcb->ShortName.FileNameDos = TRUE;
3156*23b7c7b8SHermès Bélusca-Maïto 
3157*23b7c7b8SHermès Bélusca-Maïto         //
3158*23b7c7b8SHermès Bélusca-Maïto         //  If no Lfn was specified, we are done.  In either case, set the
3159*23b7c7b8SHermès Bélusca-Maïto         //  final name length.
3160*23b7c7b8SHermès Bélusca-Maïto         //
3161*23b7c7b8SHermès Bélusca-Maïto 
3162*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( Fcb->ExactCaseLongName.Buffer == NULL );
3163*23b7c7b8SHermès Bélusca-Maïto 
3164*23b7c7b8SHermès Bélusca-Maïto         if (!ARGUMENT_PRESENT(Lfn) || (Lfn->Length == 0)) {
3165*23b7c7b8SHermès Bélusca-Maïto 
3166*23b7c7b8SHermès Bélusca-Maïto             Fcb->FinalNameLength = (USHORT) RtlOemStringToCountedUnicodeSize( ShortName );
3167*23b7c7b8SHermès Bélusca-Maïto             Fcb->ExactCaseLongName.Length = Fcb->ExactCaseLongName.MaximumLength = 0;
3168*23b7c7b8SHermès Bélusca-Maïto 
3169*23b7c7b8SHermès Bélusca-Maïto             try_return( NOTHING );
3170*23b7c7b8SHermès Bélusca-Maïto         }
3171*23b7c7b8SHermès Bélusca-Maïto 
3172*23b7c7b8SHermès Bélusca-Maïto         //
3173*23b7c7b8SHermès Bélusca-Maïto         //  If we already set up the full filename, we could be in trouble.  If the fast
3174*23b7c7b8SHermès Bélusca-Maïto         //  path for doing it already fired, FatSetFullFileNameInFcb, it will have missed
3175*23b7c7b8SHermès Bélusca-Maïto         //  this and could have built the full filename out of the shortname of the file.
3176*23b7c7b8SHermès Bélusca-Maïto         //
3177*23b7c7b8SHermès Bélusca-Maïto         //  At that point, disaster could be inevitable since the final name length will not
3178*23b7c7b8SHermès Bélusca-Maïto         //  match.  We use this to tell the notify package what to do - FatNotifyReportChange.
3179*23b7c7b8SHermès Bélusca-Maïto         //
3180*23b7c7b8SHermès Bélusca-Maïto 
3181*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( Fcb->FullFileName.Buffer == NULL );
3182*23b7c7b8SHermès Bélusca-Maïto 
3183*23b7c7b8SHermès Bélusca-Maïto         //
3184*23b7c7b8SHermès Bélusca-Maïto         //  We know now we have an Lfn, save away a copy.
3185*23b7c7b8SHermès Bélusca-Maïto         //
3186*23b7c7b8SHermès Bélusca-Maïto 
3187*23b7c7b8SHermès Bélusca-Maïto         Fcb->FinalNameLength = Lfn->Length;
3188*23b7c7b8SHermès Bélusca-Maïto 
3189*23b7c7b8SHermès Bélusca-Maïto         Fcb->ExactCaseLongName.Length = Fcb->ExactCaseLongName.MaximumLength = Lfn->Length;
3190*23b7c7b8SHermès Bélusca-Maïto         Fcb->ExactCaseLongName.Buffer = FsRtlAllocatePoolWithTag( PagedPool,
3191*23b7c7b8SHermès Bélusca-Maïto                                                                   Lfn->Length,
3192*23b7c7b8SHermès Bélusca-Maïto                                                                   TAG_FILENAME_BUFFER );
3193*23b7c7b8SHermès Bélusca-Maïto         RtlCopyMemory(Fcb->ExactCaseLongName.Buffer, Lfn->Buffer, Lfn->Length);
3194*23b7c7b8SHermès Bélusca-Maïto 
3195*23b7c7b8SHermès Bélusca-Maïto         //
3196*23b7c7b8SHermès Bélusca-Maïto         //  First check for no extended characters.
3197*23b7c7b8SHermès Bélusca-Maïto         //
3198*23b7c7b8SHermès Bélusca-Maïto 
3199*23b7c7b8SHermès Bélusca-Maïto         for (i=0; i < Lfn->Length/sizeof(WCHAR); i++) {
3200*23b7c7b8SHermès Bélusca-Maïto 
3201*23b7c7b8SHermès Bélusca-Maïto             if (Lfn->Buffer[i] >= 0x80) {
3202*23b7c7b8SHermès Bélusca-Maïto 
3203*23b7c7b8SHermès Bélusca-Maïto                 break;
3204*23b7c7b8SHermès Bélusca-Maïto             }
3205*23b7c7b8SHermès Bélusca-Maïto         }
3206*23b7c7b8SHermès Bélusca-Maïto 
3207*23b7c7b8SHermès Bélusca-Maïto         if (i == Lfn->Length/sizeof(WCHAR)) {
3208*23b7c7b8SHermès Bélusca-Maïto 
3209*23b7c7b8SHermès Bélusca-Maïto             //
3210*23b7c7b8SHermès Bélusca-Maïto             //  Cool, I can go with the Oem, upcase it fast by hand.
3211*23b7c7b8SHermès Bélusca-Maïto             //
3212*23b7c7b8SHermès Bélusca-Maïto 
3213*23b7c7b8SHermès Bélusca-Maïto             LongOemName = &Fcb->LongName.Oem.Name.Oem;
3214*23b7c7b8SHermès Bélusca-Maïto 
3215*23b7c7b8SHermès Bélusca-Maïto 
3216*23b7c7b8SHermès Bélusca-Maïto             LongOemName->Buffer = FsRtlAllocatePoolWithTag( PagedPool,
3217*23b7c7b8SHermès Bélusca-Maïto                                                             Lfn->Length/sizeof(WCHAR),
3218*23b7c7b8SHermès Bélusca-Maïto                                                             TAG_FILENAME_BUFFER );
3219*23b7c7b8SHermès Bélusca-Maïto             LongOemName->Length =
3220*23b7c7b8SHermès Bélusca-Maïto             LongOemName->MaximumLength = Lfn->Length/sizeof(WCHAR);
3221*23b7c7b8SHermès Bélusca-Maïto 
3222*23b7c7b8SHermès Bélusca-Maïto             for (i=0; i < Lfn->Length/sizeof(WCHAR); i++) {
3223*23b7c7b8SHermès Bélusca-Maïto 
3224*23b7c7b8SHermès Bélusca-Maïto                 WCHAR c;
3225*23b7c7b8SHermès Bélusca-Maïto 
3226*23b7c7b8SHermès Bélusca-Maïto                 c = Lfn->Buffer[i];
3227*23b7c7b8SHermès Bélusca-Maïto 
3228*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
3229*23b7c7b8SHermès Bélusca-Maïto #pragma warning( push )
3230*23b7c7b8SHermès Bélusca-Maïto #pragma warning( disable:4244 )
3231*23b7c7b8SHermès Bélusca-Maïto #endif
3232*23b7c7b8SHermès Bélusca-Maïto                 LongOemName->Buffer[i] = c < 'a' ?
3233*23b7c7b8SHermès Bélusca-Maïto                                          (UCHAR)c :
3234*23b7c7b8SHermès Bélusca-Maïto                                          c <= 'z' ?
3235*23b7c7b8SHermès Bélusca-Maïto                                          c - (UCHAR)('a'-'A') :
3236*23b7c7b8SHermès Bélusca-Maïto                                          (UCHAR)c;
3237*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
3238*23b7c7b8SHermès Bélusca-Maïto #pragma warning( pop )
3239*23b7c7b8SHermès Bélusca-Maïto #endif
3240*23b7c7b8SHermès Bélusca-Maïto             }
3241*23b7c7b8SHermès Bélusca-Maïto 
3242*23b7c7b8SHermès Bélusca-Maïto             //
3243*23b7c7b8SHermès Bélusca-Maïto             //  If this name happens to be exactly the same as the short
3244*23b7c7b8SHermès Bélusca-Maïto             //  name, don't add it to the splay table.
3245*23b7c7b8SHermès Bélusca-Maïto             //
3246*23b7c7b8SHermès Bélusca-Maïto 
3247*23b7c7b8SHermès Bélusca-Maïto             if (FatAreNamesEqual(IrpContext, *ShortName, *LongOemName) ||
3248*23b7c7b8SHermès Bélusca-Maïto                 (FatFindFcb( IrpContext,
3249*23b7c7b8SHermès Bélusca-Maïto                              &Fcb->ParentDcb->Specific.Dcb.RootOemNode,
3250*23b7c7b8SHermès Bélusca-Maïto                              LongOemName,
3251*23b7c7b8SHermès Bélusca-Maïto                              NULL) != NULL)) {
3252*23b7c7b8SHermès Bélusca-Maïto 
3253*23b7c7b8SHermès Bélusca-Maïto                 ExFreePool( LongOemName->Buffer );
3254*23b7c7b8SHermès Bélusca-Maïto 
3255*23b7c7b8SHermès Bélusca-Maïto                 LongOemName->Buffer = NULL;
3256*23b7c7b8SHermès Bélusca-Maïto                 LongOemName->Length =
3257*23b7c7b8SHermès Bélusca-Maïto                 LongOemName->MaximumLength = 0;
3258*23b7c7b8SHermès Bélusca-Maïto 
3259*23b7c7b8SHermès Bélusca-Maïto             } else {
3260*23b7c7b8SHermès Bélusca-Maïto 
3261*23b7c7b8SHermès Bélusca-Maïto                 SetFlag( Fcb->FcbState, FCB_STATE_HAS_OEM_LONG_NAME );
3262*23b7c7b8SHermès Bélusca-Maïto             }
3263*23b7c7b8SHermès Bélusca-Maïto 
3264*23b7c7b8SHermès Bélusca-Maïto             try_return( NOTHING );
3265*23b7c7b8SHermès Bélusca-Maïto         }
3266*23b7c7b8SHermès Bélusca-Maïto 
3267*23b7c7b8SHermès Bélusca-Maïto         //
3268*23b7c7b8SHermès Bélusca-Maïto         //  Now we have the fun part.  Make a copy of the Lfn.
3269*23b7c7b8SHermès Bélusca-Maïto         //
3270*23b7c7b8SHermès Bélusca-Maïto 
3271*23b7c7b8SHermès Bélusca-Maïto #ifndef __REACTOS__
3272*23b7c7b8SHermès Bélusca-Maïto         OemA.Buffer = NULL;
3273*23b7c7b8SHermès Bélusca-Maïto         OemB.Buffer = NULL;
3274*23b7c7b8SHermès Bélusca-Maïto #endif
3275*23b7c7b8SHermès Bélusca-Maïto         Unicode.Buffer = NULL;
3276*23b7c7b8SHermès Bélusca-Maïto 
3277*23b7c7b8SHermès Bélusca-Maïto         Unicode.Length =
3278*23b7c7b8SHermès Bélusca-Maïto         Unicode.MaximumLength = Lfn->Length;
3279*23b7c7b8SHermès Bélusca-Maïto         Unicode.Buffer = FsRtlAllocatePoolWithTag( PagedPool,
3280*23b7c7b8SHermès Bélusca-Maïto                                                    Lfn->Length,
3281*23b7c7b8SHermès Bélusca-Maïto                                                    TAG_FILENAME_BUFFER );
3282*23b7c7b8SHermès Bélusca-Maïto 
3283*23b7c7b8SHermès Bélusca-Maïto         RtlCopyMemory( Unicode.Buffer, Lfn->Buffer, Lfn->Length );
3284*23b7c7b8SHermès Bélusca-Maïto 
3285*23b7c7b8SHermès Bélusca-Maïto #ifndef __REACTOS__
3286*23b7c7b8SHermès Bélusca-Maïto         Status = STATUS_SUCCESS;
3287*23b7c7b8SHermès Bélusca-Maïto #endif
3288*23b7c7b8SHermès Bélusca-Maïto 
3289*23b7c7b8SHermès Bélusca-Maïto #if TRUE
3290*23b7c7b8SHermès Bélusca-Maïto         //
3291*23b7c7b8SHermès Bélusca-Maïto         //  Unfortunately, this next block of code breaks down when you have
3292*23b7c7b8SHermès Bélusca-Maïto         //  two long Unicode filenames that both map to the same Oem (and are,
3293*23b7c7b8SHermès Bélusca-Maïto         //  well, long, i.e. are not the short names). In this case, with one
3294*23b7c7b8SHermès Bélusca-Maïto         //  in the prefix table first, the other will hit the common Oem
3295*23b7c7b8SHermès Bélusca-Maïto         //  representation.  This leads to several forms of user astonishment.
3296*23b7c7b8SHermès Bélusca-Maïto         //
3297*23b7c7b8SHermès Bélusca-Maïto         //  It isn't worth it, or probably even possible, to try to figure out
3298*23b7c7b8SHermès Bélusca-Maïto         //  when this is really safe to go through.  Simply omit the attempt.
3299*23b7c7b8SHermès Bélusca-Maïto         //
3300*23b7c7b8SHermès Bélusca-Maïto         //  Ex: ANSI 0x82 and 0x84 in the 1252 ANSI->UNI and 437 UNI->OEM codepages.
3301*23b7c7b8SHermès Bélusca-Maïto         //
3302*23b7c7b8SHermès Bélusca-Maïto         //      0x82 => 0x201a => 0x2c
3303*23b7c7b8SHermès Bélusca-Maïto         //      0x84 => 0x201e => 0x2c
3304*23b7c7b8SHermès Bélusca-Maïto         //
3305*23b7c7b8SHermès Bélusca-Maïto         //  0x2c is comma, so is FAT Oem illegal and forces shortname generation.
3306*23b7c7b8SHermès Bélusca-Maïto         //  Since it is otherwise well-formed by the rules articulated previously,
3307*23b7c7b8SHermès Bélusca-Maïto         //  we would have put 0x2c in the Oem prefix tree.  In terms of the
3308*23b7c7b8SHermès Bélusca-Maïto         //  argument given above, even though there exist no Y and U s.t.
3309*23b7c7b8SHermès Bélusca-Maïto         //
3310*23b7c7b8SHermès Bélusca-Maïto         //  Up(Y) == Up(U) && BestOemFit(U) != BestOemFit(Y)
3311*23b7c7b8SHermès Bélusca-Maïto         //
3312*23b7c7b8SHermès Bélusca-Maïto         //  there most certainly exist Y and U s.t.
3313*23b7c7b8SHermès Bélusca-Maïto         //
3314*23b7c7b8SHermès Bélusca-Maïto         //  Up(Y) != Up(U) && BestOemFit(U) == BestOemFit(Y)
3315*23b7c7b8SHermès Bélusca-Maïto         //
3316*23b7c7b8SHermès Bélusca-Maïto         //  and that is enough to keep us from doing this.  Note that the < 0x80
3317*23b7c7b8SHermès Bélusca-Maïto         //  case is OK since we know that the mapping in the OEM codepages are
3318*23b7c7b8SHermès Bélusca-Maïto         //  the identity in that range.
3319*23b7c7b8SHermès Bélusca-Maïto         //
3320*23b7c7b8SHermès Bélusca-Maïto         //  We still need to monocase it, though.  Do this through a full down/up
3321*23b7c7b8SHermès Bélusca-Maïto         //  transition.
3322*23b7c7b8SHermès Bélusca-Maïto         //
3323*23b7c7b8SHermès Bélusca-Maïto 
3324*23b7c7b8SHermès Bélusca-Maïto         (VOID)RtlDowncaseUnicodeString( &Unicode, &Unicode, FALSE );
3325*23b7c7b8SHermès Bélusca-Maïto         (VOID)RtlUpcaseUnicodeString( &Unicode, &Unicode, FALSE );
3326*23b7c7b8SHermès Bélusca-Maïto #else
3327*23b7c7b8SHermès Bélusca-Maïto         //
3328*23b7c7b8SHermès Bélusca-Maïto         //  Downcase and convert to upcased Oem.  Only continue if we can
3329*23b7c7b8SHermès Bélusca-Maïto         //  convert without error.  Any error other than UNMAPPABLE_CHAR
3330*23b7c7b8SHermès Bélusca-Maïto         //  is a fatal error and we raise.
3331*23b7c7b8SHermès Bélusca-Maïto         //
3332*23b7c7b8SHermès Bélusca-Maïto         //  Note that even if the conversion fails, we must leave Unicode
3333*23b7c7b8SHermès Bélusca-Maïto         //  in an upcased state.
3334*23b7c7b8SHermès Bélusca-Maïto         //
3335*23b7c7b8SHermès Bélusca-Maïto         //  NB: The Rtl doesn't NULL .Buffer on error.
3336*23b7c7b8SHermès Bélusca-Maïto         //
3337*23b7c7b8SHermès Bélusca-Maïto 
3338*23b7c7b8SHermès Bélusca-Maïto         (VOID)RtlDowncaseUnicodeString( &Unicode, &Unicode, FALSE );
3339*23b7c7b8SHermès Bélusca-Maïto         Status = RtlUpcaseUnicodeStringToCountedOemString( &OemA, &Unicode, TRUE );
3340*23b7c7b8SHermès Bélusca-Maïto         (VOID)RtlUpcaseUnicodeString( &Unicode, &Unicode, FALSE );
3341*23b7c7b8SHermès Bélusca-Maïto 
3342*23b7c7b8SHermès Bélusca-Maïto         if (!NT_SUCCESS(Status)) {
3343*23b7c7b8SHermès Bélusca-Maïto 
3344*23b7c7b8SHermès Bélusca-Maïto             if (Status != STATUS_UNMAPPABLE_CHARACTER) {
3345*23b7c7b8SHermès Bélusca-Maïto 
3346*23b7c7b8SHermès Bélusca-Maïto                 NT_ASSERT( Status == STATUS_NO_MEMORY );
3347*23b7c7b8SHermès Bélusca-Maïto                 ExFreePool(Unicode.Buffer);
3348*23b7c7b8SHermès Bélusca-Maïto                 FatNormalizeAndRaiseStatus( IrpContext, Status );
3349*23b7c7b8SHermès Bélusca-Maïto             }
3350*23b7c7b8SHermès Bélusca-Maïto 
3351*23b7c7b8SHermès Bélusca-Maïto         } else {
3352*23b7c7b8SHermès Bélusca-Maïto 
3353*23b7c7b8SHermès Bélusca-Maïto             //
3354*23b7c7b8SHermès Bélusca-Maïto             //  The same as above except upcase.
3355*23b7c7b8SHermès Bélusca-Maïto             //
3356*23b7c7b8SHermès Bélusca-Maïto 
3357*23b7c7b8SHermès Bélusca-Maïto             Status = RtlUpcaseUnicodeStringToCountedOemString( &OemB, &Unicode, TRUE );
3358*23b7c7b8SHermès Bélusca-Maïto 
3359*23b7c7b8SHermès Bélusca-Maïto             if (!NT_SUCCESS(Status)) {
3360*23b7c7b8SHermès Bélusca-Maïto 
3361*23b7c7b8SHermès Bélusca-Maïto                 RtlFreeOemString( &OemA );
3362*23b7c7b8SHermès Bélusca-Maïto 
3363*23b7c7b8SHermès Bélusca-Maïto                 if (Status != STATUS_UNMAPPABLE_CHARACTER) {
3364*23b7c7b8SHermès Bélusca-Maïto 
3365*23b7c7b8SHermès Bélusca-Maïto                     NT_ASSERT( Status == STATUS_NO_MEMORY );
3366*23b7c7b8SHermès Bélusca-Maïto                     ExFreePool(Unicode.Buffer);
3367*23b7c7b8SHermès Bélusca-Maïto                     FatNormalizeAndRaiseStatus( IrpContext, Status );
3368*23b7c7b8SHermès Bélusca-Maïto                 }
3369*23b7c7b8SHermès Bélusca-Maïto             }
3370*23b7c7b8SHermès Bélusca-Maïto         }
3371*23b7c7b8SHermès Bélusca-Maïto 
3372*23b7c7b8SHermès Bélusca-Maïto         //
3373*23b7c7b8SHermès Bélusca-Maïto         //  If the final OemNames are equal, I can use save only the Oem
3374*23b7c7b8SHermès Bélusca-Maïto         //  name.  If the name did not map, then I have to go with the UNICODE
3375*23b7c7b8SHermès Bélusca-Maïto         //  name because I could get a case varient that didn't convert
3376*23b7c7b8SHermès Bélusca-Maïto         //  in create, but did match the LFN.
3377*23b7c7b8SHermès Bélusca-Maïto         //
3378*23b7c7b8SHermès Bélusca-Maïto 
3379*23b7c7b8SHermès Bélusca-Maïto         if (NT_SUCCESS(Status) && FatAreNamesEqual( IrpContext, OemA, OemB )) {
3380*23b7c7b8SHermès Bélusca-Maïto 
3381*23b7c7b8SHermès Bélusca-Maïto             //
3382*23b7c7b8SHermès Bélusca-Maïto             //  Cool, I can go with the Oem.  If we didn't convert correctly,
3383*23b7c7b8SHermès Bélusca-Maïto             //  get a fresh convert from the original LFN.
3384*23b7c7b8SHermès Bélusca-Maïto             //
3385*23b7c7b8SHermès Bélusca-Maïto 
3386*23b7c7b8SHermès Bélusca-Maïto             ExFreePool(Unicode.Buffer);
3387*23b7c7b8SHermès Bélusca-Maïto 
3388*23b7c7b8SHermès Bélusca-Maïto             RtlFreeOemString( &OemB );
3389*23b7c7b8SHermès Bélusca-Maïto 
3390*23b7c7b8SHermès Bélusca-Maïto             Fcb->LongName.Oem.Name.Oem = OemA;
3391*23b7c7b8SHermès Bélusca-Maïto 
3392*23b7c7b8SHermès Bélusca-Maïto             //
3393*23b7c7b8SHermès Bélusca-Maïto             //  If this name happens to be exactly the same as the short
3394*23b7c7b8SHermès Bélusca-Maïto             //  name, or a similar short name already exists don't add it
3395*23b7c7b8SHermès Bélusca-Maïto             //  to the splay table (note the final condition implies a
3396*23b7c7b8SHermès Bélusca-Maïto             //  corrupt disk.
3397*23b7c7b8SHermès Bélusca-Maïto             //
3398*23b7c7b8SHermès Bélusca-Maïto 
3399*23b7c7b8SHermès Bélusca-Maïto             if (FatAreNamesEqual(IrpContext, *ShortName, OemA) ||
3400*23b7c7b8SHermès Bélusca-Maïto                 (FatFindFcb( IrpContext,
3401*23b7c7b8SHermès Bélusca-Maïto                              &Fcb->ParentDcb->Specific.Dcb.RootOemNode,
3402*23b7c7b8SHermès Bélusca-Maïto                              &OemA,
3403*23b7c7b8SHermès Bélusca-Maïto                              NULL) != NULL)) {
3404*23b7c7b8SHermès Bélusca-Maïto 
3405*23b7c7b8SHermès Bélusca-Maïto                 RtlFreeOemString( &OemA );
3406*23b7c7b8SHermès Bélusca-Maïto 
3407*23b7c7b8SHermès Bélusca-Maïto             } else {
3408*23b7c7b8SHermès Bélusca-Maïto 
3409*23b7c7b8SHermès Bélusca-Maïto                 SetFlag( Fcb->FcbState, FCB_STATE_HAS_OEM_LONG_NAME );
3410*23b7c7b8SHermès Bélusca-Maïto             }
3411*23b7c7b8SHermès Bélusca-Maïto 
3412*23b7c7b8SHermès Bélusca-Maïto             try_return( NOTHING );
3413*23b7c7b8SHermès Bélusca-Maïto         }
3414*23b7c7b8SHermès Bélusca-Maïto 
3415*23b7c7b8SHermès Bélusca-Maïto         //
3416*23b7c7b8SHermès Bélusca-Maïto         //  The long name must be left in UNICODE.  Free the two Oem strings
3417*23b7c7b8SHermès Bélusca-Maïto         //  if we got here just because they weren't equal.
3418*23b7c7b8SHermès Bélusca-Maïto         //
3419*23b7c7b8SHermès Bélusca-Maïto 
3420*23b7c7b8SHermès Bélusca-Maïto         if (NT_SUCCESS(Status)) {
3421*23b7c7b8SHermès Bélusca-Maïto 
3422*23b7c7b8SHermès Bélusca-Maïto             RtlFreeOemString( &OemA );
3423*23b7c7b8SHermès Bélusca-Maïto             RtlFreeOemString( &OemB );
3424*23b7c7b8SHermès Bélusca-Maïto         }
3425*23b7c7b8SHermès Bélusca-Maïto #endif
3426*23b7c7b8SHermès Bélusca-Maïto 
3427*23b7c7b8SHermès Bélusca-Maïto         LongUniName = &Fcb->LongName.Unicode.Name.Unicode;
3428*23b7c7b8SHermès Bélusca-Maïto 
3429*23b7c7b8SHermès Bélusca-Maïto         LongUniName->Length =
3430*23b7c7b8SHermès Bélusca-Maïto         LongUniName->MaximumLength = Unicode.Length;
3431*23b7c7b8SHermès Bélusca-Maïto         LongUniName->Buffer = Unicode.Buffer;
3432*23b7c7b8SHermès Bélusca-Maïto 
3433*23b7c7b8SHermès Bélusca-Maïto         SetFlag(Fcb->FcbState, FCB_STATE_HAS_UNICODE_LONG_NAME);
3434*23b7c7b8SHermès Bélusca-Maïto 
3435*23b7c7b8SHermès Bélusca-Maïto     try_exit: NOTHING;
3436*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_FINALLY {
3437*23b7c7b8SHermès Bélusca-Maïto 
3438*23b7c7b8SHermès Bélusca-Maïto         if (_SEH2_AbnormalTermination()) {
3439*23b7c7b8SHermès Bélusca-Maïto 
3440*23b7c7b8SHermès Bélusca-Maïto             if (ShortName->Buffer != NULL) {
3441*23b7c7b8SHermès Bélusca-Maïto 
3442*23b7c7b8SHermès Bélusca-Maïto                 ExFreePool( ShortName->Buffer );
3443*23b7c7b8SHermès Bélusca-Maïto                 ShortName->Buffer = NULL;
3444*23b7c7b8SHermès Bélusca-Maïto             }
3445*23b7c7b8SHermès Bélusca-Maïto 
3446*23b7c7b8SHermès Bélusca-Maïto         } else {
3447*23b7c7b8SHermès Bélusca-Maïto 
3448*23b7c7b8SHermès Bélusca-Maïto             //
3449*23b7c7b8SHermès Bélusca-Maïto             //  Creating all the names worked, so add all the names
3450*23b7c7b8SHermès Bélusca-Maïto             //  to the splay tree.
3451*23b7c7b8SHermès Bélusca-Maïto             //
3452*23b7c7b8SHermès Bélusca-Maïto 
3453*23b7c7b8SHermès Bélusca-Maïto             FatInsertName( IrpContext,
3454*23b7c7b8SHermès Bélusca-Maïto                            &Fcb->ParentDcb->Specific.Dcb.RootOemNode,
3455*23b7c7b8SHermès Bélusca-Maïto                            &Fcb->ShortName );
3456*23b7c7b8SHermès Bélusca-Maïto 
3457*23b7c7b8SHermès Bélusca-Maïto             Fcb->ShortName.Fcb = Fcb;
3458*23b7c7b8SHermès Bélusca-Maïto 
3459*23b7c7b8SHermès Bélusca-Maïto             if (FlagOn(Fcb->FcbState, FCB_STATE_HAS_OEM_LONG_NAME)) {
3460*23b7c7b8SHermès Bélusca-Maïto 
3461*23b7c7b8SHermès Bélusca-Maïto                 FatInsertName( IrpContext,
3462*23b7c7b8SHermès Bélusca-Maïto                                &Fcb->ParentDcb->Specific.Dcb.RootOemNode,
3463*23b7c7b8SHermès Bélusca-Maïto                                &Fcb->LongName.Oem );
3464*23b7c7b8SHermès Bélusca-Maïto 
3465*23b7c7b8SHermès Bélusca-Maïto                 Fcb->LongName.Oem.Fcb = Fcb;
3466*23b7c7b8SHermès Bélusca-Maïto             }
3467*23b7c7b8SHermès Bélusca-Maïto 
3468*23b7c7b8SHermès Bélusca-Maïto             if (FlagOn(Fcb->FcbState, FCB_STATE_HAS_UNICODE_LONG_NAME)) {
3469*23b7c7b8SHermès Bélusca-Maïto 
3470*23b7c7b8SHermès Bélusca-Maïto                 FatInsertName( IrpContext,
3471*23b7c7b8SHermès Bélusca-Maïto                                &Fcb->ParentDcb->Specific.Dcb.RootUnicodeNode,
3472*23b7c7b8SHermès Bélusca-Maïto                                &Fcb->LongName.Unicode );
3473*23b7c7b8SHermès Bélusca-Maïto 
3474*23b7c7b8SHermès Bélusca-Maïto                 Fcb->LongName.Unicode.Fcb = Fcb;
3475*23b7c7b8SHermès Bélusca-Maïto             }
3476*23b7c7b8SHermès Bélusca-Maïto 
3477*23b7c7b8SHermès Bélusca-Maïto             SetFlag(Fcb->FcbState, FCB_STATE_NAMES_IN_SPLAY_TREE);
3478*23b7c7b8SHermès Bélusca-Maïto         }
3479*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
3480*23b7c7b8SHermès Bélusca-Maïto 
3481*23b7c7b8SHermès Bélusca-Maïto     return;
3482*23b7c7b8SHermès Bélusca-Maïto }
3483*23b7c7b8SHermès Bélusca-Maïto 
3484*23b7c7b8SHermès Bélusca-Maïto 
_Requires_lock_held_(_Global_critical_region_)3485*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
3486*23b7c7b8SHermès Bélusca-Maïto VOID
3487*23b7c7b8SHermès Bélusca-Maïto FatCheckFreeDirentBitmap (
3488*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
3489*23b7c7b8SHermès Bélusca-Maïto     IN PDCB Dcb
3490*23b7c7b8SHermès Bélusca-Maïto     )
3491*23b7c7b8SHermès Bélusca-Maïto 
3492*23b7c7b8SHermès Bélusca-Maïto /*++
3493*23b7c7b8SHermès Bélusca-Maïto 
3494*23b7c7b8SHermès Bélusca-Maïto Routine Description:
3495*23b7c7b8SHermès Bélusca-Maïto 
3496*23b7c7b8SHermès Bélusca-Maïto     This routine checks if the size of the free dirent bitmap is
3497*23b7c7b8SHermès Bélusca-Maïto     sufficient to for the current directory size.  It is called
3498*23b7c7b8SHermès Bélusca-Maïto     whenever we grow a directory.
3499*23b7c7b8SHermès Bélusca-Maïto 
3500*23b7c7b8SHermès Bélusca-Maïto Arguments:
3501*23b7c7b8SHermès Bélusca-Maïto 
3502*23b7c7b8SHermès Bélusca-Maïto     Dcb -  Supplies the directory in question.
3503*23b7c7b8SHermès Bélusca-Maïto 
3504*23b7c7b8SHermès Bélusca-Maïto Return Value:
3505*23b7c7b8SHermès Bélusca-Maïto 
3506*23b7c7b8SHermès Bélusca-Maïto     None
3507*23b7c7b8SHermès Bélusca-Maïto 
3508*23b7c7b8SHermès Bélusca-Maïto --*/
3509*23b7c7b8SHermès Bélusca-Maïto 
3510*23b7c7b8SHermès Bélusca-Maïto {
3511*23b7c7b8SHermès Bélusca-Maïto     ULONG OldNumberOfDirents;
3512*23b7c7b8SHermès Bélusca-Maïto     ULONG NewNumberOfDirents;
3513*23b7c7b8SHermès Bélusca-Maïto 
3514*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
3515*23b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( IrpContext );
3516*23b7c7b8SHermès Bélusca-Maïto 
3517*23b7c7b8SHermès Bélusca-Maïto     //
3518*23b7c7b8SHermès Bélusca-Maïto     //  Setup the Bitmap buffer if it is not big enough already
3519*23b7c7b8SHermès Bélusca-Maïto     //
3520*23b7c7b8SHermès Bélusca-Maïto 
3521*23b7c7b8SHermès Bélusca-Maïto     NT_ASSERT( Dcb->Header.AllocationSize.QuadPart != FCB_LOOKUP_ALLOCATIONSIZE_HINT );
3522*23b7c7b8SHermès Bélusca-Maïto 
3523*23b7c7b8SHermès Bélusca-Maïto     OldNumberOfDirents = Dcb->Specific.Dcb.FreeDirentBitmap.SizeOfBitMap;
3524*23b7c7b8SHermès Bélusca-Maïto     NewNumberOfDirents = Dcb->Header.AllocationSize.LowPart / sizeof(DIRENT);
3525*23b7c7b8SHermès Bélusca-Maïto 
3526*23b7c7b8SHermès Bélusca-Maïto     //
3527*23b7c7b8SHermès Bélusca-Maïto     //  Do the usual unsync/sync check.
3528*23b7c7b8SHermès Bélusca-Maïto     //
3529*23b7c7b8SHermès Bélusca-Maïto 
3530*23b7c7b8SHermès Bélusca-Maïto     if (NewNumberOfDirents > OldNumberOfDirents) {
3531*23b7c7b8SHermès Bélusca-Maïto 
3532*23b7c7b8SHermès Bélusca-Maïto         FatAcquireDirectoryFileMutex( Dcb->Vcb );
3533*23b7c7b8SHermès Bélusca-Maïto 
3534*23b7c7b8SHermès Bélusca-Maïto         _SEH2_TRY {
3535*23b7c7b8SHermès Bélusca-Maïto 
3536*23b7c7b8SHermès Bélusca-Maïto             PULONG OldBitmapBuffer;
3537*23b7c7b8SHermès Bélusca-Maïto             PULONG BitmapBuffer;
3538*23b7c7b8SHermès Bélusca-Maïto 
3539*23b7c7b8SHermès Bélusca-Maïto             ULONG BytesInBitmapBuffer;
3540*23b7c7b8SHermès Bélusca-Maïto             ULONG BytesInOldBitmapBuffer;
3541*23b7c7b8SHermès Bélusca-Maïto 
3542*23b7c7b8SHermès Bélusca-Maïto             OldNumberOfDirents = Dcb->Specific.Dcb.FreeDirentBitmap.SizeOfBitMap;
3543*23b7c7b8SHermès Bélusca-Maïto             NewNumberOfDirents = Dcb->Header.AllocationSize.LowPart / sizeof(DIRENT);
3544*23b7c7b8SHermès Bélusca-Maïto 
3545*23b7c7b8SHermès Bélusca-Maïto             if (NewNumberOfDirents > OldNumberOfDirents) {
3546*23b7c7b8SHermès Bélusca-Maïto 
3547*23b7c7b8SHermès Bélusca-Maïto                 //
3548*23b7c7b8SHermès Bélusca-Maïto                 //  Remember the old bitmap
3549*23b7c7b8SHermès Bélusca-Maïto                 //
3550*23b7c7b8SHermès Bélusca-Maïto 
3551*23b7c7b8SHermès Bélusca-Maïto                 OldBitmapBuffer = Dcb->Specific.Dcb.FreeDirentBitmap.Buffer;
3552*23b7c7b8SHermès Bélusca-Maïto 
3553*23b7c7b8SHermès Bélusca-Maïto                 //
3554*23b7c7b8SHermès Bélusca-Maïto                 //  Now make a new bitmap bufffer
3555*23b7c7b8SHermès Bélusca-Maïto                 //
3556*23b7c7b8SHermès Bélusca-Maïto 
3557*23b7c7b8SHermès Bélusca-Maïto                 BytesInBitmapBuffer = NewNumberOfDirents / 8;
3558*23b7c7b8SHermès Bélusca-Maïto 
3559*23b7c7b8SHermès Bélusca-Maïto                 BytesInOldBitmapBuffer = OldNumberOfDirents / 8;
3560*23b7c7b8SHermès Bélusca-Maïto 
3561*23b7c7b8SHermès Bélusca-Maïto                 if (DCB_UNION_SLACK_SPACE >= BytesInBitmapBuffer) {
3562*23b7c7b8SHermès Bélusca-Maïto 
3563*23b7c7b8SHermès Bélusca-Maïto                     BitmapBuffer = &Dcb->Specific.Dcb.FreeDirentBitmapBuffer[0];
3564*23b7c7b8SHermès Bélusca-Maïto 
3565*23b7c7b8SHermès Bélusca-Maïto                 } else {
3566*23b7c7b8SHermès Bélusca-Maïto 
3567*23b7c7b8SHermès Bélusca-Maïto                     BitmapBuffer = FsRtlAllocatePoolWithTag( PagedPool,
3568*23b7c7b8SHermès Bélusca-Maïto                                                              BytesInBitmapBuffer,
3569*23b7c7b8SHermès Bélusca-Maïto                                                              TAG_DIRENT_BITMAP );
3570*23b7c7b8SHermès Bélusca-Maïto                 }
3571*23b7c7b8SHermès Bélusca-Maïto 
3572*23b7c7b8SHermès Bélusca-Maïto                 //
3573*23b7c7b8SHermès Bélusca-Maïto                 //  Copy the old buffer to the new buffer, free the old one, and zero
3574*23b7c7b8SHermès Bélusca-Maïto                 //  the rest of the new one.  Only do the first two steps though if
3575*23b7c7b8SHermès Bélusca-Maïto                 //  we moved out of the initial buffer.
3576*23b7c7b8SHermès Bélusca-Maïto                 //
3577*23b7c7b8SHermès Bélusca-Maïto 
3578*23b7c7b8SHermès Bélusca-Maïto                 if ((OldNumberOfDirents != 0) &&
3579*23b7c7b8SHermès Bélusca-Maïto                     (BitmapBuffer != &Dcb->Specific.Dcb.FreeDirentBitmapBuffer[0])) {
3580*23b7c7b8SHermès Bélusca-Maïto 
3581*23b7c7b8SHermès Bélusca-Maïto                     RtlCopyMemory( BitmapBuffer,
3582*23b7c7b8SHermès Bélusca-Maïto                                    OldBitmapBuffer,
3583*23b7c7b8SHermès Bélusca-Maïto                                    BytesInOldBitmapBuffer );
3584*23b7c7b8SHermès Bélusca-Maïto 
3585*23b7c7b8SHermès Bélusca-Maïto                     if (OldBitmapBuffer != &Dcb->Specific.Dcb.FreeDirentBitmapBuffer[0]) {
3586*23b7c7b8SHermès Bélusca-Maïto 
3587*23b7c7b8SHermès Bélusca-Maïto                         ExFreePool( OldBitmapBuffer );
3588*23b7c7b8SHermès Bélusca-Maïto                     }
3589*23b7c7b8SHermès Bélusca-Maïto                 }
3590*23b7c7b8SHermès Bélusca-Maïto 
3591*23b7c7b8SHermès Bélusca-Maïto                 NT_ASSERT( BytesInBitmapBuffer > BytesInOldBitmapBuffer );
3592*23b7c7b8SHermès Bélusca-Maïto 
3593*23b7c7b8SHermès Bélusca-Maïto                 RtlZeroMemory( (PUCHAR)BitmapBuffer + BytesInOldBitmapBuffer,
3594*23b7c7b8SHermès Bélusca-Maïto                                BytesInBitmapBuffer - BytesInOldBitmapBuffer );
3595*23b7c7b8SHermès Bélusca-Maïto 
3596*23b7c7b8SHermès Bélusca-Maïto                 //
3597*23b7c7b8SHermès Bélusca-Maïto                 //  Now initialize the new bitmap.
3598*23b7c7b8SHermès Bélusca-Maïto                 //
3599*23b7c7b8SHermès Bélusca-Maïto 
3600*23b7c7b8SHermès Bélusca-Maïto                 RtlInitializeBitMap( &Dcb->Specific.Dcb.FreeDirentBitmap,
3601*23b7c7b8SHermès Bélusca-Maïto                                      BitmapBuffer,
3602*23b7c7b8SHermès Bélusca-Maïto                                      NewNumberOfDirents );
3603*23b7c7b8SHermès Bélusca-Maïto             }
3604*23b7c7b8SHermès Bélusca-Maïto 
3605*23b7c7b8SHermès Bélusca-Maïto         } _SEH2_FINALLY {
3606*23b7c7b8SHermès Bélusca-Maïto 
3607*23b7c7b8SHermès Bélusca-Maïto             FatReleaseDirectoryFileMutex( Dcb->Vcb );
3608*23b7c7b8SHermès Bélusca-Maïto         } _SEH2_END;
3609*23b7c7b8SHermès Bélusca-Maïto     }
3610*23b7c7b8SHermès Bélusca-Maïto }
3611*23b7c7b8SHermès Bélusca-Maïto 
3612*23b7c7b8SHermès Bélusca-Maïto 
3613*23b7c7b8SHermès Bélusca-Maïto BOOLEAN
FatIsHandleCountZero(IN PIRP_CONTEXT IrpContext,IN PVCB Vcb)3614*23b7c7b8SHermès Bélusca-Maïto FatIsHandleCountZero (
3615*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
3616*23b7c7b8SHermès Bélusca-Maïto     IN PVCB Vcb
3617*23b7c7b8SHermès Bélusca-Maïto     )
3618*23b7c7b8SHermès Bélusca-Maïto 
3619*23b7c7b8SHermès Bélusca-Maïto /*++
3620*23b7c7b8SHermès Bélusca-Maïto 
3621*23b7c7b8SHermès Bélusca-Maïto Routine Description:
3622*23b7c7b8SHermès Bélusca-Maïto 
3623*23b7c7b8SHermès Bélusca-Maïto     This routine decides if the handle count on the volume is zero.
3624*23b7c7b8SHermès Bélusca-Maïto 
3625*23b7c7b8SHermès Bélusca-Maïto Arguments:
3626*23b7c7b8SHermès Bélusca-Maïto 
3627*23b7c7b8SHermès Bélusca-Maïto     Vcb - The volume in question
3628*23b7c7b8SHermès Bélusca-Maïto 
3629*23b7c7b8SHermès Bélusca-Maïto Return Value:
3630*23b7c7b8SHermès Bélusca-Maïto 
3631*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN - TRUE if there are no open handles on the volume, FALSE
3632*23b7c7b8SHermès Bélusca-Maïto               otherwise.
3633*23b7c7b8SHermès Bélusca-Maïto 
3634*23b7c7b8SHermès Bélusca-Maïto --*/
3635*23b7c7b8SHermès Bélusca-Maïto 
3636*23b7c7b8SHermès Bélusca-Maïto {
3637*23b7c7b8SHermès Bélusca-Maïto     PFCB Fcb;
3638*23b7c7b8SHermès Bélusca-Maïto 
3639*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
3640*23b7c7b8SHermès Bélusca-Maïto 
3641*23b7c7b8SHermès Bélusca-Maïto     Fcb = Vcb->RootDcb;
3642*23b7c7b8SHermès Bélusca-Maïto 
3643*23b7c7b8SHermès Bélusca-Maïto     while (Fcb != NULL) {
3644*23b7c7b8SHermès Bélusca-Maïto 
3645*23b7c7b8SHermès Bélusca-Maïto         if (Fcb->UncleanCount != 0) {
3646*23b7c7b8SHermès Bélusca-Maïto 
3647*23b7c7b8SHermès Bélusca-Maïto             return FALSE;
3648*23b7c7b8SHermès Bélusca-Maïto         }
3649*23b7c7b8SHermès Bélusca-Maïto 
3650*23b7c7b8SHermès Bélusca-Maïto         Fcb = FatGetNextFcbTopDown(IrpContext, Fcb, Vcb->RootDcb);
3651*23b7c7b8SHermès Bélusca-Maïto     }
3652*23b7c7b8SHermès Bélusca-Maïto 
3653*23b7c7b8SHermès Bélusca-Maïto     return TRUE;
3654*23b7c7b8SHermès Bélusca-Maïto }
3655*23b7c7b8SHermès Bélusca-Maïto 
3656*23b7c7b8SHermès Bélusca-Maïto 
3657*23b7c7b8SHermès Bélusca-Maïto PCLOSE_CONTEXT
3658*23b7c7b8SHermès Bélusca-Maïto 
FatAllocateCloseContext(OPTIONAL PVCB Vcb)3659*23b7c7b8SHermès Bélusca-Maïto FatAllocateCloseContext(
3660*23b7c7b8SHermès Bélusca-Maïto     OPTIONAL PVCB Vcb
3661*23b7c7b8SHermès Bélusca-Maïto     )
3662*23b7c7b8SHermès Bélusca-Maïto /*++
3663*23b7c7b8SHermès Bélusca-Maïto 
3664*23b7c7b8SHermès Bélusca-Maïto Routine Description:
3665*23b7c7b8SHermès Bélusca-Maïto 
3666*23b7c7b8SHermès Bélusca-Maïto     This routine preallocates a close context, presumeably on behalf
3667*23b7c7b8SHermès Bélusca-Maïto     of a fileobject which does not have a structure we can embed one
3668*23b7c7b8SHermès Bélusca-Maïto     in.
3669*23b7c7b8SHermès Bélusca-Maïto 
3670*23b7c7b8SHermès Bélusca-Maïto Arguments:
3671*23b7c7b8SHermès Bélusca-Maïto 
3672*23b7c7b8SHermès Bélusca-Maïto     None.
3673*23b7c7b8SHermès Bélusca-Maïto 
3674*23b7c7b8SHermès Bélusca-Maïto Return Value:
3675*23b7c7b8SHermès Bélusca-Maïto 
3676*23b7c7b8SHermès Bélusca-Maïto     None.
3677*23b7c7b8SHermès Bélusca-Maïto 
3678*23b7c7b8SHermès Bélusca-Maïto --*/
3679*23b7c7b8SHermès Bélusca-Maïto {
3680*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
3681*23b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( Vcb );
3682*23b7c7b8SHermès Bélusca-Maïto 
3683*23b7c7b8SHermès Bélusca-Maïto #if DBG
3684*23b7c7b8SHermès Bélusca-Maïto     if (ARGUMENT_PRESENT(Vcb)) {
3685*23b7c7b8SHermès Bélusca-Maïto 
3686*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( 0 != Vcb->CloseContextCount);
3687*23b7c7b8SHermès Bélusca-Maïto         InterlockedDecrement( (LONG*)&Vcb->CloseContextCount);
3688*23b7c7b8SHermès Bélusca-Maïto     }
3689*23b7c7b8SHermès Bélusca-Maïto #endif
3690*23b7c7b8SHermès Bélusca-Maïto     return (PCLOSE_CONTEXT)ExInterlockedPopEntrySList( &FatCloseContextSList,
3691*23b7c7b8SHermès Bélusca-Maïto                                                        &FatData.GeneralSpinLock );
3692*23b7c7b8SHermès Bélusca-Maïto }
3693*23b7c7b8SHermès Bélusca-Maïto 
3694*23b7c7b8SHermès Bélusca-Maïto 
3695*23b7c7b8SHermès Bélusca-Maïto VOID
FatPreallocateCloseContext(PVCB Vcb)3696*23b7c7b8SHermès Bélusca-Maïto FatPreallocateCloseContext (
3697*23b7c7b8SHermès Bélusca-Maïto     PVCB Vcb
3698*23b7c7b8SHermès Bélusca-Maïto     )
3699*23b7c7b8SHermès Bélusca-Maïto 
3700*23b7c7b8SHermès Bélusca-Maïto /*++
3701*23b7c7b8SHermès Bélusca-Maïto 
3702*23b7c7b8SHermès Bélusca-Maïto Routine Description:
3703*23b7c7b8SHermès Bélusca-Maïto 
3704*23b7c7b8SHermès Bélusca-Maïto     This routine preallocates a close context, presumeably on behalf
3705*23b7c7b8SHermès Bélusca-Maïto     of a fileobject which does not have a structure we can embed one
3706*23b7c7b8SHermès Bélusca-Maïto     in.
3707*23b7c7b8SHermès Bélusca-Maïto 
3708*23b7c7b8SHermès Bélusca-Maïto Arguments:
3709*23b7c7b8SHermès Bélusca-Maïto 
3710*23b7c7b8SHermès Bélusca-Maïto     None.
3711*23b7c7b8SHermès Bélusca-Maïto 
3712*23b7c7b8SHermès Bélusca-Maïto Return Value:
3713*23b7c7b8SHermès Bélusca-Maïto 
3714*23b7c7b8SHermès Bélusca-Maïto     None.
3715*23b7c7b8SHermès Bélusca-Maïto 
3716*23b7c7b8SHermès Bélusca-Maïto --*/
3717*23b7c7b8SHermès Bélusca-Maïto 
3718*23b7c7b8SHermès Bélusca-Maïto {
3719*23b7c7b8SHermès Bélusca-Maïto     PCLOSE_CONTEXT CloseContext;
3720*23b7c7b8SHermès Bélusca-Maïto 
3721*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
3722*23b7c7b8SHermès Bélusca-Maïto 
3723*23b7c7b8SHermès Bélusca-Maïto     UNREFERENCED_PARAMETER( Vcb );
3724*23b7c7b8SHermès Bélusca-Maïto 
3725*23b7c7b8SHermès Bélusca-Maïto     CloseContext = FsRtlAllocatePoolWithTag( PagedPool,
3726*23b7c7b8SHermès Bélusca-Maïto                                              sizeof(CLOSE_CONTEXT),
3727*23b7c7b8SHermès Bélusca-Maïto                                              TAG_FAT_CLOSE_CONTEXT );
3728*23b7c7b8SHermès Bélusca-Maïto 
3729*23b7c7b8SHermès Bélusca-Maïto     ExInterlockedPushEntrySList( &FatCloseContextSList,
3730*23b7c7b8SHermès Bélusca-Maïto                                  (PSLIST_ENTRY) CloseContext,
3731*23b7c7b8SHermès Bélusca-Maïto                                  &FatData.GeneralSpinLock );
3732*23b7c7b8SHermès Bélusca-Maïto 
3733*23b7c7b8SHermès Bélusca-Maïto     DbgDoit( InterlockedIncrement( (LONG*)&Vcb->CloseContextCount));
3734*23b7c7b8SHermès Bélusca-Maïto }
3735*23b7c7b8SHermès Bélusca-Maïto 
3736*23b7c7b8SHermès Bélusca-Maïto 
3737*23b7c7b8SHermès Bélusca-Maïto 
3738*23b7c7b8SHermès Bélusca-Maïto VOID
FatEnsureStringBufferEnough(_Inout_ PVOID String,_In_ USHORT DesiredBufferSize)3739*23b7c7b8SHermès Bélusca-Maïto FatEnsureStringBufferEnough (
3740*23b7c7b8SHermès Bélusca-Maïto     _Inout_ PVOID String,
3741*23b7c7b8SHermès Bélusca-Maïto     _In_ USHORT DesiredBufferSize
3742*23b7c7b8SHermès Bélusca-Maïto     )
3743*23b7c7b8SHermès Bélusca-Maïto 
3744*23b7c7b8SHermès Bélusca-Maïto /*++
3745*23b7c7b8SHermès Bélusca-Maïto 
3746*23b7c7b8SHermès Bélusca-Maïto Routine Description:
3747*23b7c7b8SHermès Bélusca-Maïto 
3748*23b7c7b8SHermès Bélusca-Maïto     Ensures that a string string (STRING, UNICODE_STRING, ANSI_STRING, OEM_STRING)
3749*23b7c7b8SHermès Bélusca-Maïto     has a buffer >= DesiredBufferSize,  allocating from pool if neccessary.  Any
3750*23b7c7b8SHermès Bélusca-Maïto     existing pool buffer will be freed if a new one is allocated.
3751*23b7c7b8SHermès Bélusca-Maïto 
3752*23b7c7b8SHermès Bélusca-Maïto     NOTE: No copy of old buffer contents is performed on reallocation.
3753*23b7c7b8SHermès Bélusca-Maïto 
3754*23b7c7b8SHermès Bélusca-Maïto     Will raise on allocation failure.
3755*23b7c7b8SHermès Bélusca-Maïto 
3756*23b7c7b8SHermès Bélusca-Maïto Arguments:
3757*23b7c7b8SHermès Bélusca-Maïto 
3758*23b7c7b8SHermès Bélusca-Maïto     String - pointer to string structure
3759*23b7c7b8SHermès Bélusca-Maïto 
3760*23b7c7b8SHermès Bélusca-Maïto     DesiredBufferSize - (bytes) minimum required buffer size
3761*23b7c7b8SHermès Bélusca-Maïto 
3762*23b7c7b8SHermès Bélusca-Maïto --*/
3763*23b7c7b8SHermès Bélusca-Maïto 
3764*23b7c7b8SHermès Bélusca-Maïto {
3765*23b7c7b8SHermès Bélusca-Maïto     PSTRING LocalString = String;
3766*23b7c7b8SHermès Bélusca-Maïto 
3767*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
3768*23b7c7b8SHermès Bélusca-Maïto 
3769*23b7c7b8SHermès Bélusca-Maïto     if (LocalString->MaximumLength < DesiredBufferSize)  {
3770*23b7c7b8SHermès Bélusca-Maïto 
3771*23b7c7b8SHermès Bélusca-Maïto         FatFreeStringBuffer( LocalString);
3772*23b7c7b8SHermès Bélusca-Maïto 
3773*23b7c7b8SHermès Bélusca-Maïto         LocalString->Buffer = FsRtlAllocatePoolWithTag( PagedPool,
3774*23b7c7b8SHermès Bélusca-Maïto                                                         DesiredBufferSize,
3775*23b7c7b8SHermès Bélusca-Maïto                                                         TAG_DYNAMIC_NAME_BUFFER);
3776*23b7c7b8SHermès Bélusca-Maïto         NT_ASSERT( LocalString->Buffer);
3777*23b7c7b8SHermès Bélusca-Maïto 
3778*23b7c7b8SHermès Bélusca-Maïto         LocalString->MaximumLength = DesiredBufferSize;
3779*23b7c7b8SHermès Bélusca-Maïto     }
3780*23b7c7b8SHermès Bélusca-Maïto }
3781*23b7c7b8SHermès Bélusca-Maïto 
3782*23b7c7b8SHermès Bélusca-Maïto 
3783*23b7c7b8SHermès Bélusca-Maïto VOID
FatFreeStringBuffer(_Inout_ PVOID String)3784*23b7c7b8SHermès Bélusca-Maïto FatFreeStringBuffer (
3785*23b7c7b8SHermès Bélusca-Maïto     _Inout_ PVOID String
3786*23b7c7b8SHermès Bélusca-Maïto     )
3787*23b7c7b8SHermès Bélusca-Maïto 
3788*23b7c7b8SHermès Bélusca-Maïto /*++
3789*23b7c7b8SHermès Bélusca-Maïto 
3790*23b7c7b8SHermès Bélusca-Maïto Routine Description:
3791*23b7c7b8SHermès Bélusca-Maïto 
3792*23b7c7b8SHermès Bélusca-Maïto     Frees the buffer of an string (STRING, UNICODE_STRING, ANSI_STRING, OEM_STRING)
3793*23b7c7b8SHermès Bélusca-Maïto     structure if it is not within the current thread's stack limits.
3794*23b7c7b8SHermès Bélusca-Maïto 
3795*23b7c7b8SHermès Bélusca-Maïto     Regardless of action performed,  on exit String->Buffer will be set to NULL and
3796*23b7c7b8SHermès Bélusca-Maïto     String->MaximumLength to zero.
3797*23b7c7b8SHermès Bélusca-Maïto 
3798*23b7c7b8SHermès Bélusca-Maïto Arguments:
3799*23b7c7b8SHermès Bélusca-Maïto 
3800*23b7c7b8SHermès Bélusca-Maïto     String - pointer to string structure
3801*23b7c7b8SHermès Bélusca-Maïto 
3802*23b7c7b8SHermès Bélusca-Maïto --*/
3803*23b7c7b8SHermès Bélusca-Maïto 
3804*23b7c7b8SHermès Bélusca-Maïto {
3805*23b7c7b8SHermès Bélusca-Maïto     ULONG_PTR High, Low;
3806*23b7c7b8SHermès Bélusca-Maïto     PSTRING LocalString = String;
3807*23b7c7b8SHermès Bélusca-Maïto 
3808*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
3809*23b7c7b8SHermès Bélusca-Maïto 
3810*23b7c7b8SHermès Bélusca-Maïto     if (NULL != LocalString->Buffer)  {
3811*23b7c7b8SHermès Bélusca-Maïto 
3812*23b7c7b8SHermès Bélusca-Maïto         IoGetStackLimits( &Low, &High );
3813*23b7c7b8SHermès Bélusca-Maïto 
3814*23b7c7b8SHermès Bélusca-Maïto         if (((ULONG_PTR)(LocalString->Buffer) < Low) ||
3815*23b7c7b8SHermès Bélusca-Maïto             ((ULONG_PTR)(LocalString->Buffer) > High))  {
3816*23b7c7b8SHermès Bélusca-Maïto 
3817*23b7c7b8SHermès Bélusca-Maïto             ExFreePool( LocalString->Buffer);
3818*23b7c7b8SHermès Bélusca-Maïto         }
3819*23b7c7b8SHermès Bélusca-Maïto 
3820*23b7c7b8SHermès Bélusca-Maïto         LocalString->Buffer = NULL;
3821*23b7c7b8SHermès Bélusca-Maïto     }
3822*23b7c7b8SHermès Bélusca-Maïto 
3823*23b7c7b8SHermès Bélusca-Maïto     LocalString->MaximumLength = LocalString->Length = 0;
3824*23b7c7b8SHermès Bélusca-Maïto }
3825*23b7c7b8SHermès Bélusca-Maïto 
3826*23b7c7b8SHermès Bélusca-Maïto 
3827*23b7c7b8SHermès Bélusca-Maïto BOOLEAN
FatScanForDataTrack(IN PIRP_CONTEXT IrpContext,IN PDEVICE_OBJECT TargetDeviceObject)3828*23b7c7b8SHermès Bélusca-Maïto FatScanForDataTrack(
3829*23b7c7b8SHermès Bélusca-Maïto     IN PIRP_CONTEXT IrpContext,
3830*23b7c7b8SHermès Bélusca-Maïto     IN PDEVICE_OBJECT TargetDeviceObject
3831*23b7c7b8SHermès Bélusca-Maïto     )
3832*23b7c7b8SHermès Bélusca-Maïto 
3833*23b7c7b8SHermès Bélusca-Maïto /*++
3834*23b7c7b8SHermès Bélusca-Maïto 
3835*23b7c7b8SHermès Bélusca-Maïto Routine Description:
3836*23b7c7b8SHermès Bélusca-Maïto 
3837*23b7c7b8SHermès Bélusca-Maïto     This routine is called to verify and process the TOC for this disk.
3838*23b7c7b8SHermès Bélusca-Maïto 
3839*23b7c7b8SHermès Bélusca-Maïto     FAT queries for the TOC to avoid trying to mount on CD-DA/CD-E media,  Doing data reads on
3840*23b7c7b8SHermès Bélusca-Maïto     audio/leadin of that media sends a lot of drives into what could charitably be called
3841*23b7c7b8SHermès Bélusca-Maïto     "conniptions" which take a couple seconds to clear and would also convince FAT that the
3842*23b7c7b8SHermès Bélusca-Maïto     device was busted, and fail the mount (not letting CDFS get its crack).
3843*23b7c7b8SHermès Bélusca-Maïto 
3844*23b7c7b8SHermès Bélusca-Maïto     There is special handling of PD media.  These things fail the TOC read, but return
3845*23b7c7b8SHermès Bélusca-Maïto     a special error code so FAT knows to continue to try the mount anyway.
3846*23b7c7b8SHermès Bélusca-Maïto 
3847*23b7c7b8SHermès Bélusca-Maïto Arguments:
3848*23b7c7b8SHermès Bélusca-Maïto 
3849*23b7c7b8SHermès Bélusca-Maïto     TargetDeviceObject - Device object to send TOC request to.
3850*23b7c7b8SHermès Bélusca-Maïto 
3851*23b7c7b8SHermès Bélusca-Maïto Return Value:
3852*23b7c7b8SHermès Bélusca-Maïto 
3853*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN - TRUE if we found a TOC with a single data track.
3854*23b7c7b8SHermès Bélusca-Maïto 
3855*23b7c7b8SHermès Bélusca-Maïto --*/
3856*23b7c7b8SHermès Bélusca-Maïto 
3857*23b7c7b8SHermès Bélusca-Maïto {
3858*23b7c7b8SHermès Bélusca-Maïto     NTSTATUS Status;
3859*23b7c7b8SHermès Bélusca-Maïto     IO_STATUS_BLOCK Iosb;
3860*23b7c7b8SHermès Bélusca-Maïto 
3861*23b7c7b8SHermès Bélusca-Maïto     ULONG LocalTrackCount;
3862*23b7c7b8SHermès Bélusca-Maïto     ULONG LocalTocLength;
3863*23b7c7b8SHermès Bélusca-Maïto 
3864*23b7c7b8SHermès Bélusca-Maïto     PCDROM_TOC CdromToc;
3865*23b7c7b8SHermès Bélusca-Maïto     BOOLEAN Result = FALSE;
3866*23b7c7b8SHermès Bélusca-Maïto 
3867*23b7c7b8SHermès Bélusca-Maïto     PAGED_CODE();
3868*23b7c7b8SHermès Bélusca-Maïto 
3869*23b7c7b8SHermès Bélusca-Maïto     CdromToc = FsRtlAllocatePoolWithTag( PagedPool,
3870*23b7c7b8SHermès Bélusca-Maïto                                          sizeof( CDROM_TOC ),
3871*23b7c7b8SHermès Bélusca-Maïto                                          TAG_IO_BUFFER );
3872*23b7c7b8SHermès Bélusca-Maïto 
3873*23b7c7b8SHermès Bélusca-Maïto     RtlZeroMemory( CdromToc, sizeof( CDROM_TOC ));
3874*23b7c7b8SHermès Bélusca-Maïto 
3875*23b7c7b8SHermès Bélusca-Maïto     _SEH2_TRY {
3876*23b7c7b8SHermès Bélusca-Maïto 
3877*23b7c7b8SHermès Bélusca-Maïto         //
3878*23b7c7b8SHermès Bélusca-Maïto         //  Go ahead and read the table of contents
3879*23b7c7b8SHermès Bélusca-Maïto         //
3880*23b7c7b8SHermès Bélusca-Maïto 
3881*23b7c7b8SHermès Bélusca-Maïto         Status = FatPerformDevIoCtrl( IrpContext,
3882*23b7c7b8SHermès Bélusca-Maïto                                      IOCTL_CDROM_READ_TOC,
3883*23b7c7b8SHermès Bélusca-Maïto                                      TargetDeviceObject,
3884*23b7c7b8SHermès Bélusca-Maïto                                      NULL,
3885*23b7c7b8SHermès Bélusca-Maïto                                      0,
3886*23b7c7b8SHermès Bélusca-Maïto                                      CdromToc,
3887*23b7c7b8SHermès Bélusca-Maïto                                      sizeof( CDROM_TOC ),
3888*23b7c7b8SHermès Bélusca-Maïto                                      FALSE,
3889*23b7c7b8SHermès Bélusca-Maïto                                      TRUE,
3890*23b7c7b8SHermès Bélusca-Maïto                                      &Iosb );
3891*23b7c7b8SHermès Bélusca-Maïto 
3892*23b7c7b8SHermès Bélusca-Maïto         //
3893*23b7c7b8SHermès Bélusca-Maïto         //  Nothing to process if this request fails.
3894*23b7c7b8SHermès Bélusca-Maïto         //
3895*23b7c7b8SHermès Bélusca-Maïto 
3896*23b7c7b8SHermès Bélusca-Maïto         if (Status != STATUS_SUCCESS) {
3897*23b7c7b8SHermès Bélusca-Maïto 
3898*23b7c7b8SHermès Bélusca-Maïto             //
3899*23b7c7b8SHermès Bélusca-Maïto             //  If we get the special error indicating a failed TOC read on PD media just
3900*23b7c7b8SHermès Bélusca-Maïto             //  plow ahead with the mount (see comments above).
3901*23b7c7b8SHermès Bélusca-Maïto             //
3902*23b7c7b8SHermès Bélusca-Maïto 
3903*23b7c7b8SHermès Bélusca-Maïto             if ((Status == STATUS_IO_DEVICE_ERROR) || (Status == STATUS_INVALID_DEVICE_REQUEST)) {
3904*23b7c7b8SHermès Bélusca-Maïto 
3905*23b7c7b8SHermès Bélusca-Maïto                 Result = TRUE;
3906*23b7c7b8SHermès Bélusca-Maïto 
3907*23b7c7b8SHermès Bélusca-Maïto             }
3908*23b7c7b8SHermès Bélusca-Maïto 
3909*23b7c7b8SHermès Bélusca-Maïto             try_leave( NOTHING );
3910*23b7c7b8SHermès Bélusca-Maïto         }
3911*23b7c7b8SHermès Bélusca-Maïto 
3912*23b7c7b8SHermès Bélusca-Maïto         //
3913*23b7c7b8SHermès Bélusca-Maïto         //  Get the number of tracks and stated size of this structure.
3914*23b7c7b8SHermès Bélusca-Maïto         //
3915*23b7c7b8SHermès Bélusca-Maïto 
3916*23b7c7b8SHermès Bélusca-Maïto         LocalTrackCount = CdromToc->LastTrack - CdromToc->FirstTrack + 1;
3917*23b7c7b8SHermès Bélusca-Maïto         LocalTocLength = PtrOffset( CdromToc, &CdromToc->TrackData[LocalTrackCount + 1] );
3918*23b7c7b8SHermès Bélusca-Maïto 
3919*23b7c7b8SHermès Bélusca-Maïto         //
3920*23b7c7b8SHermès Bélusca-Maïto         //  Get out if there is an immediate problem with the TOC,  or more than
3921*23b7c7b8SHermès Bélusca-Maïto         //  one track.
3922*23b7c7b8SHermès Bélusca-Maïto         //
3923*23b7c7b8SHermès Bélusca-Maïto 
3924*23b7c7b8SHermès Bélusca-Maïto         if ((LocalTocLength > Iosb.Information) ||
3925*23b7c7b8SHermès Bélusca-Maïto             (CdromToc->FirstTrack > CdromToc->LastTrack) ||
3926*23b7c7b8SHermès Bélusca-Maïto             (LocalTrackCount != 1)) {
3927*23b7c7b8SHermès Bélusca-Maïto 
3928*23b7c7b8SHermès Bélusca-Maïto             try_leave( NOTHING);
3929*23b7c7b8SHermès Bélusca-Maïto         }
3930*23b7c7b8SHermès Bélusca-Maïto 
3931*23b7c7b8SHermès Bélusca-Maïto         //
3932*23b7c7b8SHermès Bélusca-Maïto         //  Is it a data track?  DVD-RAM reports single,  data,  track.
3933*23b7c7b8SHermès Bélusca-Maïto         //
3934*23b7c7b8SHermès Bélusca-Maïto 
3935*23b7c7b8SHermès Bélusca-Maïto         Result = BooleanFlagOn( CdromToc->TrackData[ 0].Control, 0x04 );
3936*23b7c7b8SHermès Bélusca-Maïto     }
3937*23b7c7b8SHermès Bélusca-Maïto     _SEH2_FINALLY {
3938*23b7c7b8SHermès Bélusca-Maïto 
3939*23b7c7b8SHermès Bélusca-Maïto         ExFreePool( CdromToc);
3940*23b7c7b8SHermès Bélusca-Maïto     } _SEH2_END;
3941*23b7c7b8SHermès Bélusca-Maïto 
3942*23b7c7b8SHermès Bélusca-Maïto     return Result;
3943*23b7c7b8SHermès Bélusca-Maïto }
3944*23b7c7b8SHermès Bélusca-Maïto 
3945*23b7c7b8SHermès Bélusca-Maïto 
3946