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