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 Close.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 File Close routine for Fat called by the
12*23b7c7b8SHermès Bélusca-Maïto dispatch driver.
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_CLOSE)
24*23b7c7b8SHermès Bélusca-Maïto
25*23b7c7b8SHermès Bélusca-Maïto //
26*23b7c7b8SHermès Bélusca-Maïto // The local 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_CLOSE)
30*23b7c7b8SHermès Bélusca-Maïto
31*23b7c7b8SHermès Bélusca-Maïto ULONG FatMaxDelayedCloseCount;
32*23b7c7b8SHermès Bélusca-Maïto
33*23b7c7b8SHermès Bélusca-Maïto
34*23b7c7b8SHermès Bélusca-Maïto #define FatAcquireCloseMutex() { \
35*23b7c7b8SHermès Bélusca-Maïto NT_ASSERT(KeAreApcsDisabled()); \
36*23b7c7b8SHermès Bélusca-Maïto ExAcquireFastMutexUnsafe( &FatCloseQueueMutex ); \
37*23b7c7b8SHermès Bélusca-Maïto }
38*23b7c7b8SHermès Bélusca-Maïto
39*23b7c7b8SHermès Bélusca-Maïto #define FatReleaseCloseMutex() { \
40*23b7c7b8SHermès Bélusca-Maïto NT_ASSERT(KeAreApcsDisabled()); \
41*23b7c7b8SHermès Bélusca-Maïto ExReleaseFastMutexUnsafe( &FatCloseQueueMutex ); \
42*23b7c7b8SHermès Bélusca-Maïto }
43*23b7c7b8SHermès Bélusca-Maïto
44*23b7c7b8SHermès Bélusca-Maïto //
45*23b7c7b8SHermès Bélusca-Maïto // Local procedure prototypes
46*23b7c7b8SHermès Bélusca-Maïto //
47*23b7c7b8SHermès Bélusca-Maïto
48*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
49*23b7c7b8SHermès Bélusca-Maïto VOID
50*23b7c7b8SHermès Bélusca-Maïto FatQueueClose (
51*23b7c7b8SHermès Bélusca-Maïto IN PCLOSE_CONTEXT CloseContext,
52*23b7c7b8SHermès Bélusca-Maïto IN BOOLEAN DelayClose
53*23b7c7b8SHermès Bélusca-Maïto );
54*23b7c7b8SHermès Bélusca-Maïto
55*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
56*23b7c7b8SHermès Bélusca-Maïto PCLOSE_CONTEXT
57*23b7c7b8SHermès Bélusca-Maïto FatRemoveClose (
58*23b7c7b8SHermès Bélusca-Maïto PVCB Vcb OPTIONAL,
59*23b7c7b8SHermès Bélusca-Maïto PVCB LastVcbHint OPTIONAL
60*23b7c7b8SHermès Bélusca-Maïto );
61*23b7c7b8SHermès Bélusca-Maïto
62*23b7c7b8SHermès Bélusca-Maïto IO_WORKITEM_ROUTINE FatCloseWorker;
63*23b7c7b8SHermès Bélusca-Maïto
64*23b7c7b8SHermès Bélusca-Maïto VOID
65*23b7c7b8SHermès Bélusca-Maïto NTAPI
66*23b7c7b8SHermès Bélusca-Maïto FatCloseWorker (
67*23b7c7b8SHermès Bélusca-Maïto _In_ PDEVICE_OBJECT DeviceObject,
68*23b7c7b8SHermès Bélusca-Maïto _In_opt_ PVOID Context
69*23b7c7b8SHermès Bélusca-Maïto );
70*23b7c7b8SHermès Bélusca-Maïto
71*23b7c7b8SHermès Bélusca-Maïto #ifdef ALLOC_PRAGMA
72*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatFsdClose)
73*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatFspClose)
74*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatRemoveClose)
75*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatCommonClose)
76*23b7c7b8SHermès Bélusca-Maïto #pragma alloc_text(PAGE, FatCloseWorker)
77*23b7c7b8SHermès Bélusca-Maïto #endif
78*23b7c7b8SHermès Bélusca-Maïto
79*23b7c7b8SHermès Bélusca-Maïto
80*23b7c7b8SHermès Bélusca-Maïto _Function_class_(IRP_MJ_CLOSE)
_Function_class_(DRIVER_DISPATCH)81*23b7c7b8SHermès Bélusca-Maïto _Function_class_(DRIVER_DISPATCH)
82*23b7c7b8SHermès Bélusca-Maïto NTSTATUS
83*23b7c7b8SHermès Bélusca-Maïto NTAPI
84*23b7c7b8SHermès Bélusca-Maïto FatFsdClose (
85*23b7c7b8SHermès Bélusca-Maïto _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
86*23b7c7b8SHermès Bélusca-Maïto _Inout_ PIRP Irp
87*23b7c7b8SHermès Bélusca-Maïto )
88*23b7c7b8SHermès Bélusca-Maïto
89*23b7c7b8SHermès Bélusca-Maïto /*++
90*23b7c7b8SHermès Bélusca-Maïto
91*23b7c7b8SHermès Bélusca-Maïto Routine Description:
92*23b7c7b8SHermès Bélusca-Maïto
93*23b7c7b8SHermès Bélusca-Maïto This routine implements the FSD part of Close.
94*23b7c7b8SHermès Bélusca-Maïto
95*23b7c7b8SHermès Bélusca-Maïto Arguments:
96*23b7c7b8SHermès Bélusca-Maïto
97*23b7c7b8SHermès Bélusca-Maïto VolumeDeviceObject - Supplies the volume device object where the
98*23b7c7b8SHermès Bélusca-Maïto file exists
99*23b7c7b8SHermès Bélusca-Maïto
100*23b7c7b8SHermès Bélusca-Maïto Irp - Supplies the Irp being processed
101*23b7c7b8SHermès Bélusca-Maïto
102*23b7c7b8SHermès Bélusca-Maïto Return Value:
103*23b7c7b8SHermès Bélusca-Maïto
104*23b7c7b8SHermès Bélusca-Maïto NTSTATUS - The FSD status for the IRP
105*23b7c7b8SHermès Bélusca-Maïto
106*23b7c7b8SHermès Bélusca-Maïto --*/
107*23b7c7b8SHermès Bélusca-Maïto
108*23b7c7b8SHermès Bélusca-Maïto {
109*23b7c7b8SHermès Bélusca-Maïto NTSTATUS Status = STATUS_SUCCESS;
110*23b7c7b8SHermès Bélusca-Maïto PIO_STACK_LOCATION IrpSp;
111*23b7c7b8SHermès Bélusca-Maïto PFILE_OBJECT FileObject;
112*23b7c7b8SHermès Bélusca-Maïto
113*23b7c7b8SHermès Bélusca-Maïto PVCB Vcb;
114*23b7c7b8SHermès Bélusca-Maïto PFCB Fcb;
115*23b7c7b8SHermès Bélusca-Maïto PCCB Ccb;
116*23b7c7b8SHermès Bélusca-Maïto TYPE_OF_OPEN TypeOfOpen;
117*23b7c7b8SHermès Bélusca-Maïto
118*23b7c7b8SHermès Bélusca-Maïto BOOLEAN TopLevel;
119*23b7c7b8SHermès Bélusca-Maïto BOOLEAN VcbDeleted = FALSE;
120*23b7c7b8SHermès Bélusca-Maïto
121*23b7c7b8SHermès Bélusca-Maïto PAGED_CODE();
122*23b7c7b8SHermès Bélusca-Maïto
123*23b7c7b8SHermès Bélusca-Maïto //
124*23b7c7b8SHermès Bélusca-Maïto // If we were called with our file system device object instead of a
125*23b7c7b8SHermès Bélusca-Maïto // volume device object, just complete this request with STATUS_SUCCESS
126*23b7c7b8SHermès Bélusca-Maïto //
127*23b7c7b8SHermès Bélusca-Maïto
128*23b7c7b8SHermès Bélusca-Maïto if (FatDeviceIsFatFsdo( VolumeDeviceObject)) {
129*23b7c7b8SHermès Bélusca-Maïto
130*23b7c7b8SHermès Bélusca-Maïto Irp->IoStatus.Status = STATUS_SUCCESS;
131*23b7c7b8SHermès Bélusca-Maïto Irp->IoStatus.Information = FILE_OPENED;
132*23b7c7b8SHermès Bélusca-Maïto
133*23b7c7b8SHermès Bélusca-Maïto IoCompleteRequest( Irp, IO_DISK_INCREMENT );
134*23b7c7b8SHermès Bélusca-Maïto
135*23b7c7b8SHermès Bélusca-Maïto return STATUS_SUCCESS;
136*23b7c7b8SHermès Bélusca-Maïto }
137*23b7c7b8SHermès Bélusca-Maïto
138*23b7c7b8SHermès Bélusca-Maïto DebugTrace(+1, Dbg, "FatFsdClose\n", 0);
139*23b7c7b8SHermès Bélusca-Maïto
140*23b7c7b8SHermès Bélusca-Maïto //
141*23b7c7b8SHermès Bélusca-Maïto // Call the common Close routine
142*23b7c7b8SHermès Bélusca-Maïto //
143*23b7c7b8SHermès Bélusca-Maïto
144*23b7c7b8SHermès Bélusca-Maïto FsRtlEnterFileSystem();
145*23b7c7b8SHermès Bélusca-Maïto
146*23b7c7b8SHermès Bélusca-Maïto TopLevel = FatIsIrpTopLevel( Irp );
147*23b7c7b8SHermès Bélusca-Maïto
148*23b7c7b8SHermès Bélusca-Maïto //
149*23b7c7b8SHermès Bélusca-Maïto // Get a pointer to the current stack location and the file object
150*23b7c7b8SHermès Bélusca-Maïto //
151*23b7c7b8SHermès Bélusca-Maïto
152*23b7c7b8SHermès Bélusca-Maïto IrpSp = IoGetCurrentIrpStackLocation( Irp );
153*23b7c7b8SHermès Bélusca-Maïto
154*23b7c7b8SHermès Bélusca-Maïto FileObject = IrpSp->FileObject;
155*23b7c7b8SHermès Bélusca-Maïto
156*23b7c7b8SHermès Bélusca-Maïto //
157*23b7c7b8SHermès Bélusca-Maïto // Decode the file object and set the read-only bit in the Ccb.
158*23b7c7b8SHermès Bélusca-Maïto //
159*23b7c7b8SHermès Bélusca-Maïto
160*23b7c7b8SHermès Bélusca-Maïto TypeOfOpen = FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb );
161*23b7c7b8SHermès Bélusca-Maïto
162*23b7c7b8SHermès Bélusca-Maïto if (Ccb && IsFileObjectReadOnly(FileObject)) {
163*23b7c7b8SHermès Bélusca-Maïto
164*23b7c7b8SHermès Bélusca-Maïto SetFlag( Ccb->Flags, CCB_FLAG_READ_ONLY );
165*23b7c7b8SHermès Bélusca-Maïto }
166*23b7c7b8SHermès Bélusca-Maïto
167*23b7c7b8SHermès Bélusca-Maïto _SEH2_TRY {
168*23b7c7b8SHermès Bélusca-Maïto
169*23b7c7b8SHermès Bélusca-Maïto PCLOSE_CONTEXT CloseContext = NULL;
170*23b7c7b8SHermès Bélusca-Maïto
171*23b7c7b8SHermès Bélusca-Maïto //
172*23b7c7b8SHermès Bélusca-Maïto // If we are top level, WAIT can be TRUE, otherwise make it FALSE
173*23b7c7b8SHermès Bélusca-Maïto // to avoid deadlocks, unless this is a top
174*23b7c7b8SHermès Bélusca-Maïto // level request not originating from the system process.
175*23b7c7b8SHermès Bélusca-Maïto //
176*23b7c7b8SHermès Bélusca-Maïto
177*23b7c7b8SHermès Bélusca-Maïto BOOLEAN Wait = TopLevel && (PsGetCurrentProcess() != FatData.OurProcess);
178*23b7c7b8SHermès Bélusca-Maïto
179*23b7c7b8SHermès Bélusca-Maïto #if (NTDDI_VERSION >= NTDDI_WIN8)
180*23b7c7b8SHermès Bélusca-Maïto
181*23b7c7b8SHermès Bélusca-Maïto //
182*23b7c7b8SHermès Bélusca-Maïto // To catch the odd case where a close comes in without a preceding cleanup,
183*23b7c7b8SHermès Bélusca-Maïto // call the oplock package to get rid of any oplock state. This can only
184*23b7c7b8SHermès Bélusca-Maïto // be safely done in the FSD path.
185*23b7c7b8SHermès Bélusca-Maïto //
186*23b7c7b8SHermès Bélusca-Maïto
187*23b7c7b8SHermès Bélusca-Maïto if ((Fcb != NULL) &&
188*23b7c7b8SHermès Bélusca-Maïto !FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE ) &&
189*23b7c7b8SHermès Bélusca-Maïto FatIsFileOplockable( Fcb )) {
190*23b7c7b8SHermès Bélusca-Maïto
191*23b7c7b8SHermès Bélusca-Maïto //
192*23b7c7b8SHermès Bélusca-Maïto // This is equivalent to handling cleanup, and it always cleans up any
193*23b7c7b8SHermès Bélusca-Maïto // oplock immediately. Also, we don't need any locking of the FCB here;
194*23b7c7b8SHermès Bélusca-Maïto // the oplock's own lock will be sufficient for this purpose.
195*23b7c7b8SHermès Bélusca-Maïto //
196*23b7c7b8SHermès Bélusca-Maïto
197*23b7c7b8SHermès Bélusca-Maïto FsRtlCheckOplockEx( FatGetFcbOplock(Fcb),
198*23b7c7b8SHermès Bélusca-Maïto Irp,
199*23b7c7b8SHermès Bélusca-Maïto 0,
200*23b7c7b8SHermès Bélusca-Maïto NULL,
201*23b7c7b8SHermès Bélusca-Maïto NULL,
202*23b7c7b8SHermès Bélusca-Maïto NULL );
203*23b7c7b8SHermès Bélusca-Maïto }
204*23b7c7b8SHermès Bélusca-Maïto #endif
205*23b7c7b8SHermès Bélusca-Maïto
206*23b7c7b8SHermès Bélusca-Maïto //
207*23b7c7b8SHermès Bélusca-Maïto // Metadata streams have had close contexts preallocated. Pull one out now, while we're
208*23b7c7b8SHermès Bélusca-Maïto // guaranteed the VCB exists.
209*23b7c7b8SHermès Bélusca-Maïto //
210*23b7c7b8SHermès Bélusca-Maïto
211*23b7c7b8SHermès Bélusca-Maïto if ( (TypeOfOpen == VirtualVolumeFile) || (TypeOfOpen == DirectoryFile) || (TypeOfOpen == EaFile)
212*23b7c7b8SHermès Bélusca-Maïto ) {
213*23b7c7b8SHermès Bélusca-Maïto
214*23b7c7b8SHermès Bélusca-Maïto CloseContext = FatAllocateCloseContext( Vcb );
215*23b7c7b8SHermès Bélusca-Maïto NT_ASSERT( CloseContext != NULL );
216*23b7c7b8SHermès Bélusca-Maïto CloseContext->Free = TRUE;
217*23b7c7b8SHermès Bélusca-Maïto
218*23b7c7b8SHermès Bélusca-Maïto }
219*23b7c7b8SHermès Bélusca-Maïto
220*23b7c7b8SHermès Bélusca-Maïto //
221*23b7c7b8SHermès Bélusca-Maïto // Call the common Close routine if we are not delaying this close.
222*23b7c7b8SHermès Bélusca-Maïto //
223*23b7c7b8SHermès Bélusca-Maïto
224*23b7c7b8SHermès Bélusca-Maïto if ((((TypeOfOpen == UserFileOpen) ||
225*23b7c7b8SHermès Bélusca-Maïto (TypeOfOpen == UserDirectoryOpen)) &&
226*23b7c7b8SHermès Bélusca-Maïto FlagOn(Fcb->FcbState, FCB_STATE_DELAY_CLOSE) &&
227*23b7c7b8SHermès Bélusca-Maïto !FatData.ShutdownStarted) ||
228*23b7c7b8SHermès Bélusca-Maïto (FatCommonClose( Vcb, Fcb, Ccb, TypeOfOpen, Wait, TopLevel, &VcbDeleted ) == STATUS_PENDING)) {
229*23b7c7b8SHermès Bélusca-Maïto
230*23b7c7b8SHermès Bélusca-Maïto //
231*23b7c7b8SHermès Bélusca-Maïto // Ship it off to the delayed close queue if we tried to close, and got STATUS_PENDING, or
232*23b7c7b8SHermès Bélusca-Maïto // if the user open told us to delay the close.
233*23b7c7b8SHermès Bélusca-Maïto //
234*23b7c7b8SHermès Bélusca-Maïto
235*23b7c7b8SHermès Bélusca-Maïto //
236*23b7c7b8SHermès Bélusca-Maïto // Metadata streams have had close contexts preallocated. If we have a user open,
237*23b7c7b8SHermès Bélusca-Maïto // pull the close context out of the Ccb.
238*23b7c7b8SHermès Bélusca-Maïto //
239*23b7c7b8SHermès Bélusca-Maïto
240*23b7c7b8SHermès Bélusca-Maïto if( CloseContext == NULL ) {
241*23b7c7b8SHermès Bélusca-Maïto
242*23b7c7b8SHermès Bélusca-Maïto //
243*23b7c7b8SHermès Bélusca-Maïto // Free up any query template strings before using the close context fields,
244*23b7c7b8SHermès Bélusca-Maïto // which overlap (union)
245*23b7c7b8SHermès Bélusca-Maïto //
246*23b7c7b8SHermès Bélusca-Maïto
247*23b7c7b8SHermès Bélusca-Maïto FatDeallocateCcbStrings( Ccb );
248*23b7c7b8SHermès Bélusca-Maïto
249*23b7c7b8SHermès Bélusca-Maïto CloseContext = &Ccb->CloseContext;
250*23b7c7b8SHermès Bélusca-Maïto CloseContext->Free = FALSE;
251*23b7c7b8SHermès Bélusca-Maïto
252*23b7c7b8SHermès Bélusca-Maïto SetFlag( Ccb->Flags, CCB_FLAG_CLOSE_CONTEXT );
253*23b7c7b8SHermès Bélusca-Maïto }
254*23b7c7b8SHermès Bélusca-Maïto
255*23b7c7b8SHermès Bélusca-Maïto //
256*23b7c7b8SHermès Bélusca-Maïto // If the status is pending, then let's get the information we
257*23b7c7b8SHermès Bélusca-Maïto // need into the close context we already have bagged, complete
258*23b7c7b8SHermès Bélusca-Maïto // the request, and post it. It is important we allocate nothing
259*23b7c7b8SHermès Bélusca-Maïto // in the close path.
260*23b7c7b8SHermès Bélusca-Maïto //
261*23b7c7b8SHermès Bélusca-Maïto
262*23b7c7b8SHermès Bélusca-Maïto CloseContext->Vcb = Vcb;
263*23b7c7b8SHermès Bélusca-Maïto CloseContext->Fcb = Fcb;
264*23b7c7b8SHermès Bélusca-Maïto CloseContext->TypeOfOpen = TypeOfOpen;
265*23b7c7b8SHermès Bélusca-Maïto
266*23b7c7b8SHermès Bélusca-Maïto //
267*23b7c7b8SHermès Bélusca-Maïto // Send it off, either to an ExWorkerThread or to the async
268*23b7c7b8SHermès Bélusca-Maïto // close list.
269*23b7c7b8SHermès Bélusca-Maïto //
270*23b7c7b8SHermès Bélusca-Maïto
271*23b7c7b8SHermès Bélusca-Maïto FatQueueClose( CloseContext,
272*23b7c7b8SHermès Bélusca-Maïto (BOOLEAN)(Fcb && FlagOn(Fcb->FcbState, FCB_STATE_DELAY_CLOSE)));
273*23b7c7b8SHermès Bélusca-Maïto
274*23b7c7b8SHermès Bélusca-Maïto } else {
275*23b7c7b8SHermès Bélusca-Maïto
276*23b7c7b8SHermès Bélusca-Maïto //
277*23b7c7b8SHermès Bélusca-Maïto // The close proceeded synchronously, so for the metadata objects we
278*23b7c7b8SHermès Bélusca-Maïto // can now drop the close context we preallocated.
279*23b7c7b8SHermès Bélusca-Maïto //
280*23b7c7b8SHermès Bélusca-Maïto
281*23b7c7b8SHermès Bélusca-Maïto if ((TypeOfOpen == VirtualVolumeFile) ||
282*23b7c7b8SHermès Bélusca-Maïto (TypeOfOpen == DirectoryFile) ||
283*23b7c7b8SHermès Bélusca-Maïto (TypeOfOpen == EaFile)
284*23b7c7b8SHermès Bélusca-Maïto ) {
285*23b7c7b8SHermès Bélusca-Maïto
286*23b7c7b8SHermès Bélusca-Maïto if (CloseContext != NULL) {
287*23b7c7b8SHermès Bélusca-Maïto
288*23b7c7b8SHermès Bélusca-Maïto ExFreePool( CloseContext );
289*23b7c7b8SHermès Bélusca-Maïto
290*23b7c7b8SHermès Bélusca-Maïto }
291*23b7c7b8SHermès Bélusca-Maïto }
292*23b7c7b8SHermès Bélusca-Maïto }
293*23b7c7b8SHermès Bélusca-Maïto
294*23b7c7b8SHermès Bélusca-Maïto FatCompleteRequest( FatNull, Irp, Status );
295*23b7c7b8SHermès Bélusca-Maïto
296*23b7c7b8SHermès Bélusca-Maïto }
297*23b7c7b8SHermès Bélusca-Maïto _SEH2_EXCEPT(FatExceptionFilter( NULL, _SEH2_GetExceptionInformation() )) {
298*23b7c7b8SHermès Bélusca-Maïto
299*23b7c7b8SHermès Bélusca-Maïto //
300*23b7c7b8SHermès Bélusca-Maïto // We had some trouble trying to perform the requested
301*23b7c7b8SHermès Bélusca-Maïto // operation, so we'll abort the I/O request with the
302*23b7c7b8SHermès Bélusca-Maïto // error status that we get back from the exception code.
303*23b7c7b8SHermès Bélusca-Maïto //
304*23b7c7b8SHermès Bélusca-Maïto
305*23b7c7b8SHermès Bélusca-Maïto Status = FatProcessException( NULL, Irp, _SEH2_GetExceptionCode() );
306*23b7c7b8SHermès Bélusca-Maïto } _SEH2_END;
307*23b7c7b8SHermès Bélusca-Maïto
308*23b7c7b8SHermès Bélusca-Maïto if (TopLevel) { IoSetTopLevelIrp( NULL ); }
309*23b7c7b8SHermès Bélusca-Maïto
310*23b7c7b8SHermès Bélusca-Maïto FsRtlExitFileSystem();
311*23b7c7b8SHermès Bélusca-Maïto
312*23b7c7b8SHermès Bélusca-Maïto //
313*23b7c7b8SHermès Bélusca-Maïto // And return to our caller
314*23b7c7b8SHermès Bélusca-Maïto //
315*23b7c7b8SHermès Bélusca-Maïto
316*23b7c7b8SHermès Bélusca-Maïto DebugTrace(-1, Dbg, "FatFsdClose -> %08lx\n", Status);
317*23b7c7b8SHermès Bélusca-Maïto
318*23b7c7b8SHermès Bélusca-Maïto UNREFERENCED_PARAMETER( VolumeDeviceObject );
319*23b7c7b8SHermès Bélusca-Maïto
320*23b7c7b8SHermès Bélusca-Maïto return Status;
321*23b7c7b8SHermès Bélusca-Maïto }
322*23b7c7b8SHermès Bélusca-Maïto
323*23b7c7b8SHermès Bélusca-Maïto VOID
324*23b7c7b8SHermès Bélusca-Maïto NTAPI
FatCloseWorker(_In_ PDEVICE_OBJECT DeviceObject,_In_opt_ PVOID Context)325*23b7c7b8SHermès Bélusca-Maïto FatCloseWorker (
326*23b7c7b8SHermès Bélusca-Maïto _In_ PDEVICE_OBJECT DeviceObject,
327*23b7c7b8SHermès Bélusca-Maïto _In_opt_ PVOID Context
328*23b7c7b8SHermès Bélusca-Maïto )
329*23b7c7b8SHermès Bélusca-Maïto /*++
330*23b7c7b8SHermès Bélusca-Maïto
331*23b7c7b8SHermès Bélusca-Maïto Routine Description:
332*23b7c7b8SHermès Bélusca-Maïto
333*23b7c7b8SHermès Bélusca-Maïto This routine is a shim between the IO worker package and FatFspClose.
334*23b7c7b8SHermès Bélusca-Maïto
335*23b7c7b8SHermès Bélusca-Maïto Arguments:
336*23b7c7b8SHermès Bélusca-Maïto
337*23b7c7b8SHermès Bélusca-Maïto DeviceObject - Registration device object, unused
338*23b7c7b8SHermès Bélusca-Maïto Context - Context value, unused
339*23b7c7b8SHermès Bélusca-Maïto
340*23b7c7b8SHermès Bélusca-Maïto Return Value:
341*23b7c7b8SHermès Bélusca-Maïto
342*23b7c7b8SHermès Bélusca-Maïto None.
343*23b7c7b8SHermès Bélusca-Maïto
344*23b7c7b8SHermès Bélusca-Maïto --*/
345*23b7c7b8SHermès Bélusca-Maïto {
346*23b7c7b8SHermès Bélusca-Maïto PAGED_CODE();
347*23b7c7b8SHermès Bélusca-Maïto
348*23b7c7b8SHermès Bélusca-Maïto UNREFERENCED_PARAMETER( DeviceObject );
349*23b7c7b8SHermès Bélusca-Maïto
350*23b7c7b8SHermès Bélusca-Maïto FsRtlEnterFileSystem();
351*23b7c7b8SHermès Bélusca-Maïto
352*23b7c7b8SHermès Bélusca-Maïto FatFspClose (Context);
353*23b7c7b8SHermès Bélusca-Maïto
354*23b7c7b8SHermès Bélusca-Maïto FsRtlExitFileSystem();
355*23b7c7b8SHermès Bélusca-Maïto }
356*23b7c7b8SHermès Bélusca-Maïto
357*23b7c7b8SHermès Bélusca-Maïto
_Requires_lock_held_(_Global_critical_region_)358*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
359*23b7c7b8SHermès Bélusca-Maïto VOID
360*23b7c7b8SHermès Bélusca-Maïto FatFspClose (
361*23b7c7b8SHermès Bélusca-Maïto IN PVCB Vcb OPTIONAL
362*23b7c7b8SHermès Bélusca-Maïto )
363*23b7c7b8SHermès Bélusca-Maïto
364*23b7c7b8SHermès Bélusca-Maïto /*++
365*23b7c7b8SHermès Bélusca-Maïto
366*23b7c7b8SHermès Bélusca-Maïto Routine Description:
367*23b7c7b8SHermès Bélusca-Maïto
368*23b7c7b8SHermès Bélusca-Maïto This routine implements the FSP part of Close.
369*23b7c7b8SHermès Bélusca-Maïto
370*23b7c7b8SHermès Bélusca-Maïto Arguments:
371*23b7c7b8SHermès Bélusca-Maïto
372*23b7c7b8SHermès Bélusca-Maïto Vcb - If present, tells us to only close file objects opened on the
373*23b7c7b8SHermès Bélusca-Maïto specified volume.
374*23b7c7b8SHermès Bélusca-Maïto
375*23b7c7b8SHermès Bélusca-Maïto Return Value:
376*23b7c7b8SHermès Bélusca-Maïto
377*23b7c7b8SHermès Bélusca-Maïto None.
378*23b7c7b8SHermès Bélusca-Maïto
379*23b7c7b8SHermès Bélusca-Maïto --*/
380*23b7c7b8SHermès Bélusca-Maïto
381*23b7c7b8SHermès Bélusca-Maïto {
382*23b7c7b8SHermès Bélusca-Maïto PCLOSE_CONTEXT CloseContext;
383*23b7c7b8SHermès Bélusca-Maïto PVCB CurrentVcb = NULL;
384*23b7c7b8SHermès Bélusca-Maïto PVCB LastVcb = NULL;
385*23b7c7b8SHermès Bélusca-Maïto BOOLEAN FreeContext = FALSE;
386*23b7c7b8SHermès Bélusca-Maïto BOOLEAN TopLevel = FALSE;
387*23b7c7b8SHermès Bélusca-Maïto
388*23b7c7b8SHermès Bélusca-Maïto ULONG LoopsWithVcbHeld = 0;
389*23b7c7b8SHermès Bélusca-Maïto
390*23b7c7b8SHermès Bélusca-Maïto PAGED_CODE();
391*23b7c7b8SHermès Bélusca-Maïto
392*23b7c7b8SHermès Bélusca-Maïto DebugTrace(+1, Dbg, "FatFspClose\n", 0);
393*23b7c7b8SHermès Bélusca-Maïto
394*23b7c7b8SHermès Bélusca-Maïto //
395*23b7c7b8SHermès Bélusca-Maïto // Set the top level IRP for the true FSP operation.
396*23b7c7b8SHermès Bélusca-Maïto //
397*23b7c7b8SHermès Bélusca-Maïto
398*23b7c7b8SHermès Bélusca-Maïto if (!ARGUMENT_PRESENT( Vcb )) {
399*23b7c7b8SHermès Bélusca-Maïto
400*23b7c7b8SHermès Bélusca-Maïto IoSetTopLevelIrp( (PIRP)FSRTL_FSP_TOP_LEVEL_IRP );
401*23b7c7b8SHermès Bélusca-Maïto TopLevel = TRUE;
402*23b7c7b8SHermès Bélusca-Maïto }
403*23b7c7b8SHermès Bélusca-Maïto
404*23b7c7b8SHermès Bélusca-Maïto while ((CloseContext = FatRemoveClose(Vcb, LastVcb)) != NULL) {
405*23b7c7b8SHermès Bélusca-Maïto
406*23b7c7b8SHermès Bélusca-Maïto //
407*23b7c7b8SHermès Bélusca-Maïto // If we are in the FSP (i.e. Vcb == NULL), then try to keep ahead of
408*23b7c7b8SHermès Bélusca-Maïto // creates by doing several closes with one acquisition of the Vcb.
409*23b7c7b8SHermès Bélusca-Maïto //
410*23b7c7b8SHermès Bélusca-Maïto // Note that we cannot be holding the Vcb on entry to FatCommonClose
411*23b7c7b8SHermès Bélusca-Maïto // if this is last close as we will try to acquire FatData, and
412*23b7c7b8SHermès Bélusca-Maïto // worse the volume (and therefore the Vcb) may go away.
413*23b7c7b8SHermès Bélusca-Maïto //
414*23b7c7b8SHermès Bélusca-Maïto
415*23b7c7b8SHermès Bélusca-Maïto if (!ARGUMENT_PRESENT(Vcb)) {
416*23b7c7b8SHermès Bélusca-Maïto
417*23b7c7b8SHermès Bélusca-Maïto if (!FatData.ShutdownStarted) {
418*23b7c7b8SHermès Bélusca-Maïto
419*23b7c7b8SHermès Bélusca-Maïto if (CloseContext->Vcb != CurrentVcb) {
420*23b7c7b8SHermès Bélusca-Maïto
421*23b7c7b8SHermès Bélusca-Maïto LoopsWithVcbHeld = 0;
422*23b7c7b8SHermès Bélusca-Maïto
423*23b7c7b8SHermès Bélusca-Maïto //
424*23b7c7b8SHermès Bélusca-Maïto // Release a previously held Vcb, if any.
425*23b7c7b8SHermès Bélusca-Maïto //
426*23b7c7b8SHermès Bélusca-Maïto
427*23b7c7b8SHermès Bélusca-Maïto if (CurrentVcb != NULL) {
428*23b7c7b8SHermès Bélusca-Maïto
429*23b7c7b8SHermès Bélusca-Maïto ExReleaseResourceLite( &CurrentVcb->Resource);
430*23b7c7b8SHermès Bélusca-Maïto }
431*23b7c7b8SHermès Bélusca-Maïto
432*23b7c7b8SHermès Bélusca-Maïto //
433*23b7c7b8SHermès Bélusca-Maïto // Get the new Vcb.
434*23b7c7b8SHermès Bélusca-Maïto //
435*23b7c7b8SHermès Bélusca-Maïto
436*23b7c7b8SHermès Bélusca-Maïto CurrentVcb = CloseContext->Vcb;
437*23b7c7b8SHermès Bélusca-Maïto (VOID)ExAcquireResourceExclusiveLite( &CurrentVcb->Resource, TRUE );
438*23b7c7b8SHermès Bélusca-Maïto
439*23b7c7b8SHermès Bélusca-Maïto } else {
440*23b7c7b8SHermès Bélusca-Maïto
441*23b7c7b8SHermès Bélusca-Maïto //
442*23b7c7b8SHermès Bélusca-Maïto // Share the resource occasionally if we seem to be finding a lot
443*23b7c7b8SHermès Bélusca-Maïto // of closes for a single volume.
444*23b7c7b8SHermès Bélusca-Maïto //
445*23b7c7b8SHermès Bélusca-Maïto
446*23b7c7b8SHermès Bélusca-Maïto if (++LoopsWithVcbHeld >= 20) {
447*23b7c7b8SHermès Bélusca-Maïto
448*23b7c7b8SHermès Bélusca-Maïto if (ExGetSharedWaiterCount( &CurrentVcb->Resource ) +
449*23b7c7b8SHermès Bélusca-Maïto ExGetExclusiveWaiterCount( &CurrentVcb->Resource )) {
450*23b7c7b8SHermès Bélusca-Maïto
451*23b7c7b8SHermès Bélusca-Maïto ExReleaseResourceLite( &CurrentVcb->Resource);
452*23b7c7b8SHermès Bélusca-Maïto (VOID)ExAcquireResourceExclusiveLite( &CurrentVcb->Resource, TRUE );
453*23b7c7b8SHermès Bélusca-Maïto }
454*23b7c7b8SHermès Bélusca-Maïto
455*23b7c7b8SHermès Bélusca-Maïto LoopsWithVcbHeld = 0;
456*23b7c7b8SHermès Bélusca-Maïto }
457*23b7c7b8SHermès Bélusca-Maïto }
458*23b7c7b8SHermès Bélusca-Maïto
459*23b7c7b8SHermès Bélusca-Maïto //
460*23b7c7b8SHermès Bélusca-Maïto // Now check the Open count. We may be about to delete this volume!
461*23b7c7b8SHermès Bélusca-Maïto //
462*23b7c7b8SHermès Bélusca-Maïto // The test below must be <= 1 because there could still be outstanding
463*23b7c7b8SHermès Bélusca-Maïto // stream references on this VCB that are not counted in the OpenFileCount.
464*23b7c7b8SHermès Bélusca-Maïto // For example if there are no open files OpenFileCount could be zero and we would
465*23b7c7b8SHermès Bélusca-Maïto // not release the resource here. The call to FatCommonClose() below may cause
466*23b7c7b8SHermès Bélusca-Maïto // the VCB to be torn down and we will try to release memory we don't
467*23b7c7b8SHermès Bélusca-Maïto // own later.
468*23b7c7b8SHermès Bélusca-Maïto //
469*23b7c7b8SHermès Bélusca-Maïto
470*23b7c7b8SHermès Bélusca-Maïto if (CurrentVcb->OpenFileCount <= 1) {
471*23b7c7b8SHermès Bélusca-Maïto ExReleaseResourceLite( &CurrentVcb->Resource);
472*23b7c7b8SHermès Bélusca-Maïto CurrentVcb = NULL;
473*23b7c7b8SHermès Bélusca-Maïto }
474*23b7c7b8SHermès Bélusca-Maïto //
475*23b7c7b8SHermès Bélusca-Maïto // If shutdown has started while processing our list, drop the
476*23b7c7b8SHermès Bélusca-Maïto // current Vcb resource.
477*23b7c7b8SHermès Bélusca-Maïto //
478*23b7c7b8SHermès Bélusca-Maïto
479*23b7c7b8SHermès Bélusca-Maïto } else if (CurrentVcb != NULL) {
480*23b7c7b8SHermès Bélusca-Maïto
481*23b7c7b8SHermès Bélusca-Maïto ExReleaseResourceLite( &CurrentVcb->Resource);
482*23b7c7b8SHermès Bélusca-Maïto CurrentVcb = NULL;
483*23b7c7b8SHermès Bélusca-Maïto }
484*23b7c7b8SHermès Bélusca-Maïto }
485*23b7c7b8SHermès Bélusca-Maïto
486*23b7c7b8SHermès Bélusca-Maïto LastVcb = CurrentVcb;
487*23b7c7b8SHermès Bélusca-Maïto
488*23b7c7b8SHermès Bélusca-Maïto //
489*23b7c7b8SHermès Bélusca-Maïto // Call the common Close routine. Protected in a try {} except {}
490*23b7c7b8SHermès Bélusca-Maïto //
491*23b7c7b8SHermès Bélusca-Maïto
492*23b7c7b8SHermès Bélusca-Maïto _SEH2_TRY {
493*23b7c7b8SHermès Bélusca-Maïto
494*23b7c7b8SHermès Bélusca-Maïto //
495*23b7c7b8SHermès Bélusca-Maïto // The close context either is in the CCB, automatically freed,
496*23b7c7b8SHermès Bélusca-Maïto // or was from pool for a metadata fileobject, CCB is NULL, and
497*23b7c7b8SHermès Bélusca-Maïto // we'll need to free it.
498*23b7c7b8SHermès Bélusca-Maïto //
499*23b7c7b8SHermès Bélusca-Maïto
500*23b7c7b8SHermès Bélusca-Maïto FreeContext = CloseContext->Free;
501*23b7c7b8SHermès Bélusca-Maïto
502*23b7c7b8SHermès Bélusca-Maïto (VOID)FatCommonClose( CloseContext->Vcb,
503*23b7c7b8SHermès Bélusca-Maïto CloseContext->Fcb,
504*23b7c7b8SHermès Bélusca-Maïto (FreeContext ? NULL :
505*23b7c7b8SHermès Bélusca-Maïto CONTAINING_RECORD( CloseContext, CCB, CloseContext)),
506*23b7c7b8SHermès Bélusca-Maïto CloseContext->TypeOfOpen,
507*23b7c7b8SHermès Bélusca-Maïto TRUE,
508*23b7c7b8SHermès Bélusca-Maïto TopLevel,
509*23b7c7b8SHermès Bélusca-Maïto NULL );
510*23b7c7b8SHermès Bélusca-Maïto
511*23b7c7b8SHermès Bélusca-Maïto } _SEH2_EXCEPT(FatExceptionFilter( NULL, _SEH2_GetExceptionInformation() )) {
512*23b7c7b8SHermès Bélusca-Maïto
513*23b7c7b8SHermès Bélusca-Maïto //
514*23b7c7b8SHermès Bélusca-Maïto // Ignore anything we expect.
515*23b7c7b8SHermès Bélusca-Maïto //
516*23b7c7b8SHermès Bélusca-Maïto
517*23b7c7b8SHermès Bélusca-Maïto NOTHING;
518*23b7c7b8SHermès Bélusca-Maïto } _SEH2_END;
519*23b7c7b8SHermès Bélusca-Maïto
520*23b7c7b8SHermès Bélusca-Maïto //
521*23b7c7b8SHermès Bélusca-Maïto // Drop the context if it came from pool.
522*23b7c7b8SHermès Bélusca-Maïto //
523*23b7c7b8SHermès Bélusca-Maïto
524*23b7c7b8SHermès Bélusca-Maïto if (FreeContext) {
525*23b7c7b8SHermès Bélusca-Maïto
526*23b7c7b8SHermès Bélusca-Maïto ExFreePool( CloseContext );
527*23b7c7b8SHermès Bélusca-Maïto }
528*23b7c7b8SHermès Bélusca-Maïto }
529*23b7c7b8SHermès Bélusca-Maïto
530*23b7c7b8SHermès Bélusca-Maïto //
531*23b7c7b8SHermès Bélusca-Maïto // Release a previously held Vcb, if any.
532*23b7c7b8SHermès Bélusca-Maïto //
533*23b7c7b8SHermès Bélusca-Maïto
534*23b7c7b8SHermès Bélusca-Maïto if (CurrentVcb != NULL) {
535*23b7c7b8SHermès Bélusca-Maïto
536*23b7c7b8SHermès Bélusca-Maïto ExReleaseResourceLite( &CurrentVcb->Resource);
537*23b7c7b8SHermès Bélusca-Maïto }
538*23b7c7b8SHermès Bélusca-Maïto
539*23b7c7b8SHermès Bélusca-Maïto //
540*23b7c7b8SHermès Bélusca-Maïto // Clean up the top level IRP hint if we owned it.
541*23b7c7b8SHermès Bélusca-Maïto //
542*23b7c7b8SHermès Bélusca-Maïto
543*23b7c7b8SHermès Bélusca-Maïto if (!ARGUMENT_PRESENT( Vcb )) {
544*23b7c7b8SHermès Bélusca-Maïto
545*23b7c7b8SHermès Bélusca-Maïto IoSetTopLevelIrp( NULL );
546*23b7c7b8SHermès Bélusca-Maïto }
547*23b7c7b8SHermès Bélusca-Maïto
548*23b7c7b8SHermès Bélusca-Maïto //
549*23b7c7b8SHermès Bélusca-Maïto // And return to our caller
550*23b7c7b8SHermès Bélusca-Maïto //
551*23b7c7b8SHermès Bélusca-Maïto
552*23b7c7b8SHermès Bélusca-Maïto DebugTrace(-1, Dbg, "FatFspClose -> NULL\n", 0);
553*23b7c7b8SHermès Bélusca-Maïto }
554*23b7c7b8SHermès Bélusca-Maïto
555*23b7c7b8SHermès Bélusca-Maïto
_Requires_lock_held_(_Global_critical_region_)556*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
557*23b7c7b8SHermès Bélusca-Maïto VOID
558*23b7c7b8SHermès Bélusca-Maïto FatQueueClose (
559*23b7c7b8SHermès Bélusca-Maïto IN PCLOSE_CONTEXT CloseContext,
560*23b7c7b8SHermès Bélusca-Maïto IN BOOLEAN DelayClose
561*23b7c7b8SHermès Bélusca-Maïto )
562*23b7c7b8SHermès Bélusca-Maïto
563*23b7c7b8SHermès Bélusca-Maïto /*++
564*23b7c7b8SHermès Bélusca-Maïto
565*23b7c7b8SHermès Bélusca-Maïto Routine Description:
566*23b7c7b8SHermès Bélusca-Maïto
567*23b7c7b8SHermès Bélusca-Maïto Enqueue a deferred close to one of the two delayed close queues.
568*23b7c7b8SHermès Bélusca-Maïto
569*23b7c7b8SHermès Bélusca-Maïto Arguments:
570*23b7c7b8SHermès Bélusca-Maïto
571*23b7c7b8SHermès Bélusca-Maïto CloseContext - a close context to enqueue for the delayed close thread.
572*23b7c7b8SHermès Bélusca-Maïto
573*23b7c7b8SHermès Bélusca-Maïto DelayClose - whether this should go on the delayed close queue (unreferenced
574*23b7c7b8SHermès Bélusca-Maïto objects).
575*23b7c7b8SHermès Bélusca-Maïto
576*23b7c7b8SHermès Bélusca-Maïto Return Value:
577*23b7c7b8SHermès Bélusca-Maïto
578*23b7c7b8SHermès Bélusca-Maïto None.
579*23b7c7b8SHermès Bélusca-Maïto
580*23b7c7b8SHermès Bélusca-Maïto --*/
581*23b7c7b8SHermès Bélusca-Maïto
582*23b7c7b8SHermès Bélusca-Maïto {
583*23b7c7b8SHermès Bélusca-Maïto BOOLEAN StartWorker = FALSE;
584*23b7c7b8SHermès Bélusca-Maïto
585*23b7c7b8SHermès Bélusca-Maïto FatAcquireCloseMutex();
586*23b7c7b8SHermès Bélusca-Maïto
587*23b7c7b8SHermès Bélusca-Maïto if (DelayClose) {
588*23b7c7b8SHermès Bélusca-Maïto
589*23b7c7b8SHermès Bélusca-Maïto InsertTailList( &FatData.DelayedCloseList,
590*23b7c7b8SHermès Bélusca-Maïto &CloseContext->GlobalLinks );
591*23b7c7b8SHermès Bélusca-Maïto InsertTailList( &CloseContext->Vcb->DelayedCloseList,
592*23b7c7b8SHermès Bélusca-Maïto &CloseContext->VcbLinks );
593*23b7c7b8SHermès Bélusca-Maïto
594*23b7c7b8SHermès Bélusca-Maïto FatData.DelayedCloseCount += 1;
595*23b7c7b8SHermès Bélusca-Maïto
596*23b7c7b8SHermès Bélusca-Maïto if ((FatData.DelayedCloseCount > FatMaxDelayedCloseCount) &&
597*23b7c7b8SHermès Bélusca-Maïto !FatData.AsyncCloseActive) {
598*23b7c7b8SHermès Bélusca-Maïto
599*23b7c7b8SHermès Bélusca-Maïto FatData.AsyncCloseActive = TRUE;
600*23b7c7b8SHermès Bélusca-Maïto StartWorker = TRUE;
601*23b7c7b8SHermès Bélusca-Maïto }
602*23b7c7b8SHermès Bélusca-Maïto
603*23b7c7b8SHermès Bélusca-Maïto } else {
604*23b7c7b8SHermès Bélusca-Maïto
605*23b7c7b8SHermès Bélusca-Maïto InsertTailList( &FatData.AsyncCloseList,
606*23b7c7b8SHermès Bélusca-Maïto &CloseContext->GlobalLinks );
607*23b7c7b8SHermès Bélusca-Maïto InsertTailList( &CloseContext->Vcb->AsyncCloseList,
608*23b7c7b8SHermès Bélusca-Maïto &CloseContext->VcbLinks );
609*23b7c7b8SHermès Bélusca-Maïto
610*23b7c7b8SHermès Bélusca-Maïto FatData.AsyncCloseCount += 1;
611*23b7c7b8SHermès Bélusca-Maïto
612*23b7c7b8SHermès Bélusca-Maïto if (!FatData.AsyncCloseActive) {
613*23b7c7b8SHermès Bélusca-Maïto
614*23b7c7b8SHermès Bélusca-Maïto FatData.AsyncCloseActive = TRUE;
615*23b7c7b8SHermès Bélusca-Maïto StartWorker = TRUE;
616*23b7c7b8SHermès Bélusca-Maïto }
617*23b7c7b8SHermès Bélusca-Maïto }
618*23b7c7b8SHermès Bélusca-Maïto
619*23b7c7b8SHermès Bélusca-Maïto FatReleaseCloseMutex();
620*23b7c7b8SHermès Bélusca-Maïto
621*23b7c7b8SHermès Bélusca-Maïto if (StartWorker) {
622*23b7c7b8SHermès Bélusca-Maïto
623*23b7c7b8SHermès Bélusca-Maïto IoQueueWorkItem( FatData.FatCloseItem, FatCloseWorker, CriticalWorkQueue, NULL );
624*23b7c7b8SHermès Bélusca-Maïto }
625*23b7c7b8SHermès Bélusca-Maïto }
626*23b7c7b8SHermès Bélusca-Maïto
627*23b7c7b8SHermès Bélusca-Maïto
_Requires_lock_held_(_Global_critical_region_)628*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
629*23b7c7b8SHermès Bélusca-Maïto PCLOSE_CONTEXT
630*23b7c7b8SHermès Bélusca-Maïto FatRemoveClose (
631*23b7c7b8SHermès Bélusca-Maïto PVCB Vcb OPTIONAL,
632*23b7c7b8SHermès Bélusca-Maïto PVCB LastVcbHint OPTIONAL
633*23b7c7b8SHermès Bélusca-Maïto )
634*23b7c7b8SHermès Bélusca-Maïto
635*23b7c7b8SHermès Bélusca-Maïto /*++
636*23b7c7b8SHermès Bélusca-Maïto
637*23b7c7b8SHermès Bélusca-Maïto Routine Description:
638*23b7c7b8SHermès Bélusca-Maïto
639*23b7c7b8SHermès Bélusca-Maïto Dequeue a deferred close from one of the two delayed close queues.
640*23b7c7b8SHermès Bélusca-Maïto
641*23b7c7b8SHermès Bélusca-Maïto Arguments:
642*23b7c7b8SHermès Bélusca-Maïto
643*23b7c7b8SHermès Bélusca-Maïto Vcb - if specified, only returns close for this volume.
644*23b7c7b8SHermès Bélusca-Maïto
645*23b7c7b8SHermès Bélusca-Maïto LastVcbHint - if specified and other starvation avoidance is required by
646*23b7c7b8SHermès Bélusca-Maïto the system condition, will attempt to return closes for this volume.
647*23b7c7b8SHermès Bélusca-Maïto
648*23b7c7b8SHermès Bélusca-Maïto Return Value:
649*23b7c7b8SHermès Bélusca-Maïto
650*23b7c7b8SHermès Bélusca-Maïto A close to perform.
651*23b7c7b8SHermès Bélusca-Maïto
652*23b7c7b8SHermès Bélusca-Maïto --*/
653*23b7c7b8SHermès Bélusca-Maïto
654*23b7c7b8SHermès Bélusca-Maïto {
655*23b7c7b8SHermès Bélusca-Maïto PLIST_ENTRY Entry;
656*23b7c7b8SHermès Bélusca-Maïto PCLOSE_CONTEXT CloseContext;
657*23b7c7b8SHermès Bélusca-Maïto BOOLEAN WorkerThread;
658*23b7c7b8SHermès Bélusca-Maïto
659*23b7c7b8SHermès Bélusca-Maïto PAGED_CODE();
660*23b7c7b8SHermès Bélusca-Maïto
661*23b7c7b8SHermès Bélusca-Maïto FatAcquireCloseMutex();
662*23b7c7b8SHermès Bélusca-Maïto
663*23b7c7b8SHermès Bélusca-Maïto //
664*23b7c7b8SHermès Bélusca-Maïto // Remember if this is the worker thread, so we can pull down the active
665*23b7c7b8SHermès Bélusca-Maïto // flag should we run everything out.
666*23b7c7b8SHermès Bélusca-Maïto //
667*23b7c7b8SHermès Bélusca-Maïto
668*23b7c7b8SHermès Bélusca-Maïto WorkerThread = (Vcb == NULL);
669*23b7c7b8SHermès Bélusca-Maïto
670*23b7c7b8SHermès Bélusca-Maïto //
671*23b7c7b8SHermès Bélusca-Maïto // If the queues are above the limits by a significant amount, we have
672*23b7c7b8SHermès Bélusca-Maïto // to try hard to pull them down. To do this, we will aggressively try
673*23b7c7b8SHermès Bélusca-Maïto // to find closes for the last volume the caller looked at. This will
674*23b7c7b8SHermès Bélusca-Maïto // make sure we fully utilize the acquisition of the volume, which can
675*23b7c7b8SHermès Bélusca-Maïto // be a hugely expensive resource to get (create/close/cleanup use it
676*23b7c7b8SHermès Bélusca-Maïto // exclusively).
677*23b7c7b8SHermès Bélusca-Maïto //
678*23b7c7b8SHermès Bélusca-Maïto // Only do this in the delayed close thread. We will know this is the
679*23b7c7b8SHermès Bélusca-Maïto // case by seeing a NULL mandatory Vcb.
680*23b7c7b8SHermès Bélusca-Maïto //
681*23b7c7b8SHermès Bélusca-Maïto
682*23b7c7b8SHermès Bélusca-Maïto if (Vcb == NULL && LastVcbHint != NULL) {
683*23b7c7b8SHermès Bélusca-Maïto
684*23b7c7b8SHermès Bélusca-Maïto //
685*23b7c7b8SHermès Bélusca-Maïto // Flip over to aggressive at twice the legal limit, and flip it
686*23b7c7b8SHermès Bélusca-Maïto // off at the legal limit.
687*23b7c7b8SHermès Bélusca-Maïto //
688*23b7c7b8SHermès Bélusca-Maïto
689*23b7c7b8SHermès Bélusca-Maïto if (!FatData.HighAsync && FatData.AsyncCloseCount > FatMaxDelayedCloseCount*2) {
690*23b7c7b8SHermès Bélusca-Maïto
691*23b7c7b8SHermès Bélusca-Maïto FatData.HighAsync = TRUE;
692*23b7c7b8SHermès Bélusca-Maïto
693*23b7c7b8SHermès Bélusca-Maïto } else if (FatData.HighAsync && FatData.AsyncCloseCount < FatMaxDelayedCloseCount) {
694*23b7c7b8SHermès Bélusca-Maïto
695*23b7c7b8SHermès Bélusca-Maïto FatData.HighAsync = FALSE;
696*23b7c7b8SHermès Bélusca-Maïto }
697*23b7c7b8SHermès Bélusca-Maïto
698*23b7c7b8SHermès Bélusca-Maïto if (!FatData.HighDelayed && FatData.DelayedCloseCount > FatMaxDelayedCloseCount*2) {
699*23b7c7b8SHermès Bélusca-Maïto
700*23b7c7b8SHermès Bélusca-Maïto FatData.HighDelayed = TRUE;
701*23b7c7b8SHermès Bélusca-Maïto
702*23b7c7b8SHermès Bélusca-Maïto } else if (FatData.HighDelayed && FatData.DelayedCloseCount < FatMaxDelayedCloseCount) {
703*23b7c7b8SHermès Bélusca-Maïto
704*23b7c7b8SHermès Bélusca-Maïto FatData.HighDelayed = FALSE;
705*23b7c7b8SHermès Bélusca-Maïto }
706*23b7c7b8SHermès Bélusca-Maïto
707*23b7c7b8SHermès Bélusca-Maïto if (FatData.HighAsync || FatData.HighDelayed) {
708*23b7c7b8SHermès Bélusca-Maïto
709*23b7c7b8SHermès Bélusca-Maïto Vcb = LastVcbHint;
710*23b7c7b8SHermès Bélusca-Maïto }
711*23b7c7b8SHermès Bélusca-Maïto }
712*23b7c7b8SHermès Bélusca-Maïto
713*23b7c7b8SHermès Bélusca-Maïto //
714*23b7c7b8SHermès Bélusca-Maïto // Do the case when we don't care about which Vcb the close is on.
715*23b7c7b8SHermès Bélusca-Maïto // This is the case when we are in an ExWorkerThread and aren't
716*23b7c7b8SHermès Bélusca-Maïto // under pressure.
717*23b7c7b8SHermès Bélusca-Maïto //
718*23b7c7b8SHermès Bélusca-Maïto
719*23b7c7b8SHermès Bélusca-Maïto if (Vcb == NULL) {
720*23b7c7b8SHermès Bélusca-Maïto
721*23b7c7b8SHermès Bélusca-Maïto AnyClose:
722*23b7c7b8SHermès Bélusca-Maïto
723*23b7c7b8SHermès Bélusca-Maïto //
724*23b7c7b8SHermès Bélusca-Maïto // First check the list of async closes.
725*23b7c7b8SHermès Bélusca-Maïto //
726*23b7c7b8SHermès Bélusca-Maïto
727*23b7c7b8SHermès Bélusca-Maïto if (!IsListEmpty( &FatData.AsyncCloseList )) {
728*23b7c7b8SHermès Bélusca-Maïto
729*23b7c7b8SHermès Bélusca-Maïto Entry = RemoveHeadList( &FatData.AsyncCloseList );
730*23b7c7b8SHermès Bélusca-Maïto FatData.AsyncCloseCount -= 1;
731*23b7c7b8SHermès Bélusca-Maïto
732*23b7c7b8SHermès Bélusca-Maïto CloseContext = CONTAINING_RECORD( Entry,
733*23b7c7b8SHermès Bélusca-Maïto CLOSE_CONTEXT,
734*23b7c7b8SHermès Bélusca-Maïto GlobalLinks );
735*23b7c7b8SHermès Bélusca-Maïto
736*23b7c7b8SHermès Bélusca-Maïto RemoveEntryList( &CloseContext->VcbLinks );
737*23b7c7b8SHermès Bélusca-Maïto
738*23b7c7b8SHermès Bélusca-Maïto //
739*23b7c7b8SHermès Bélusca-Maïto // Do any delayed closes over half the limit, unless shutdown has
740*23b7c7b8SHermès Bélusca-Maïto // started (then kill them all).
741*23b7c7b8SHermès Bélusca-Maïto //
742*23b7c7b8SHermès Bélusca-Maïto
743*23b7c7b8SHermès Bélusca-Maïto } else if (!IsListEmpty( &FatData.DelayedCloseList ) &&
744*23b7c7b8SHermès Bélusca-Maïto (FatData.DelayedCloseCount > FatMaxDelayedCloseCount/2 ||
745*23b7c7b8SHermès Bélusca-Maïto FatData.ShutdownStarted)) {
746*23b7c7b8SHermès Bélusca-Maïto
747*23b7c7b8SHermès Bélusca-Maïto Entry = RemoveHeadList( &FatData.DelayedCloseList );
748*23b7c7b8SHermès Bélusca-Maïto FatData.DelayedCloseCount -= 1;
749*23b7c7b8SHermès Bélusca-Maïto
750*23b7c7b8SHermès Bélusca-Maïto CloseContext = CONTAINING_RECORD( Entry,
751*23b7c7b8SHermès Bélusca-Maïto CLOSE_CONTEXT,
752*23b7c7b8SHermès Bélusca-Maïto GlobalLinks );
753*23b7c7b8SHermès Bélusca-Maïto
754*23b7c7b8SHermès Bélusca-Maïto RemoveEntryList( &CloseContext->VcbLinks );
755*23b7c7b8SHermès Bélusca-Maïto
756*23b7c7b8SHermès Bélusca-Maïto //
757*23b7c7b8SHermès Bélusca-Maïto // There are no more closes to perform; show that we are done.
758*23b7c7b8SHermès Bélusca-Maïto //
759*23b7c7b8SHermès Bélusca-Maïto
760*23b7c7b8SHermès Bélusca-Maïto } else {
761*23b7c7b8SHermès Bélusca-Maïto
762*23b7c7b8SHermès Bélusca-Maïto CloseContext = NULL;
763*23b7c7b8SHermès Bélusca-Maïto
764*23b7c7b8SHermès Bélusca-Maïto if (WorkerThread) {
765*23b7c7b8SHermès Bélusca-Maïto
766*23b7c7b8SHermès Bélusca-Maïto FatData.AsyncCloseActive = FALSE;
767*23b7c7b8SHermès Bélusca-Maïto }
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 // We're running down a specific volume.
772*23b7c7b8SHermès Bélusca-Maïto //
773*23b7c7b8SHermès Bélusca-Maïto
774*23b7c7b8SHermès Bélusca-Maïto } else {
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 // First check the list of async closes.
779*23b7c7b8SHermès Bélusca-Maïto //
780*23b7c7b8SHermès Bélusca-Maïto
781*23b7c7b8SHermès Bélusca-Maïto if (!IsListEmpty( &Vcb->AsyncCloseList )) {
782*23b7c7b8SHermès Bélusca-Maïto
783*23b7c7b8SHermès Bélusca-Maïto Entry = RemoveHeadList( &Vcb->AsyncCloseList );
784*23b7c7b8SHermès Bélusca-Maïto FatData.AsyncCloseCount -= 1;
785*23b7c7b8SHermès Bélusca-Maïto
786*23b7c7b8SHermès Bélusca-Maïto CloseContext = CONTAINING_RECORD( Entry,
787*23b7c7b8SHermès Bélusca-Maïto CLOSE_CONTEXT,
788*23b7c7b8SHermès Bélusca-Maïto VcbLinks );
789*23b7c7b8SHermès Bélusca-Maïto
790*23b7c7b8SHermès Bélusca-Maïto RemoveEntryList( &CloseContext->GlobalLinks );
791*23b7c7b8SHermès Bélusca-Maïto
792*23b7c7b8SHermès Bélusca-Maïto //
793*23b7c7b8SHermès Bélusca-Maïto // Do any delayed closes.
794*23b7c7b8SHermès Bélusca-Maïto //
795*23b7c7b8SHermès Bélusca-Maïto
796*23b7c7b8SHermès Bélusca-Maïto } else if (!IsListEmpty( &Vcb->DelayedCloseList )) {
797*23b7c7b8SHermès Bélusca-Maïto
798*23b7c7b8SHermès Bélusca-Maïto Entry = RemoveHeadList( &Vcb->DelayedCloseList );
799*23b7c7b8SHermès Bélusca-Maïto FatData.DelayedCloseCount -= 1;
800*23b7c7b8SHermès Bélusca-Maïto
801*23b7c7b8SHermès Bélusca-Maïto CloseContext = CONTAINING_RECORD( Entry,
802*23b7c7b8SHermès Bélusca-Maïto CLOSE_CONTEXT,
803*23b7c7b8SHermès Bélusca-Maïto VcbLinks );
804*23b7c7b8SHermès Bélusca-Maïto
805*23b7c7b8SHermès Bélusca-Maïto RemoveEntryList( &CloseContext->GlobalLinks );
806*23b7c7b8SHermès Bélusca-Maïto
807*23b7c7b8SHermès Bélusca-Maïto //
808*23b7c7b8SHermès Bélusca-Maïto // If we were trying to run down the queues but didn't find anything for this
809*23b7c7b8SHermès Bélusca-Maïto // volume, flip over to accept anything and try again.
810*23b7c7b8SHermès Bélusca-Maïto //
811*23b7c7b8SHermès Bélusca-Maïto
812*23b7c7b8SHermès Bélusca-Maïto } else if (LastVcbHint) {
813*23b7c7b8SHermès Bélusca-Maïto
814*23b7c7b8SHermès Bélusca-Maïto goto AnyClose;
815*23b7c7b8SHermès Bélusca-Maïto
816*23b7c7b8SHermès Bélusca-Maïto //
817*23b7c7b8SHermès Bélusca-Maïto // There are no more closes to perform; show that we are done.
818*23b7c7b8SHermès Bélusca-Maïto //
819*23b7c7b8SHermès Bélusca-Maïto
820*23b7c7b8SHermès Bélusca-Maïto } else {
821*23b7c7b8SHermès Bélusca-Maïto
822*23b7c7b8SHermès Bélusca-Maïto CloseContext = NULL;
823*23b7c7b8SHermès Bélusca-Maïto }
824*23b7c7b8SHermès Bélusca-Maïto }
825*23b7c7b8SHermès Bélusca-Maïto
826*23b7c7b8SHermès Bélusca-Maïto FatReleaseCloseMutex();
827*23b7c7b8SHermès Bélusca-Maïto
828*23b7c7b8SHermès Bélusca-Maïto return CloseContext;
829*23b7c7b8SHermès Bélusca-Maïto }
830*23b7c7b8SHermès Bélusca-Maïto
831*23b7c7b8SHermès Bélusca-Maïto
_Requires_lock_held_(_Global_critical_region_)832*23b7c7b8SHermès Bélusca-Maïto _Requires_lock_held_(_Global_critical_region_)
833*23b7c7b8SHermès Bélusca-Maïto NTSTATUS
834*23b7c7b8SHermès Bélusca-Maïto FatCommonClose (
835*23b7c7b8SHermès Bélusca-Maïto IN PVCB Vcb,
836*23b7c7b8SHermès Bélusca-Maïto IN PFCB Fcb,
837*23b7c7b8SHermès Bélusca-Maïto IN PCCB Ccb,
838*23b7c7b8SHermès Bélusca-Maïto IN TYPE_OF_OPEN TypeOfOpen,
839*23b7c7b8SHermès Bélusca-Maïto IN BOOLEAN Wait,
840*23b7c7b8SHermès Bélusca-Maïto IN BOOLEAN TopLevel,
841*23b7c7b8SHermès Bélusca-Maïto OUT PBOOLEAN VcbDeleted OPTIONAL
842*23b7c7b8SHermès Bélusca-Maïto )
843*23b7c7b8SHermès Bélusca-Maïto
844*23b7c7b8SHermès Bélusca-Maïto /*++
845*23b7c7b8SHermès Bélusca-Maïto
846*23b7c7b8SHermès Bélusca-Maïto Routine Description:
847*23b7c7b8SHermès Bélusca-Maïto
848*23b7c7b8SHermès Bélusca-Maïto This is the common routine for closing a file/directory called by both
849*23b7c7b8SHermès Bélusca-Maïto the fsd and fsp threads.
850*23b7c7b8SHermès Bélusca-Maïto
851*23b7c7b8SHermès Bélusca-Maïto Close is invoked whenever the last reference to a file object is deleted.
852*23b7c7b8SHermès Bélusca-Maïto Cleanup is invoked when the last handle to a file object is closed, and
853*23b7c7b8SHermès Bélusca-Maïto is called before close.
854*23b7c7b8SHermès Bélusca-Maïto
855*23b7c7b8SHermès Bélusca-Maïto The function of close is to completely tear down and remove the fcb/dcb/ccb
856*23b7c7b8SHermès Bélusca-Maïto structures associated with the file object.
857*23b7c7b8SHermès Bélusca-Maïto
858*23b7c7b8SHermès Bélusca-Maïto Arguments:
859*23b7c7b8SHermès Bélusca-Maïto
860*23b7c7b8SHermès Bélusca-Maïto Fcb - Supplies the file to process.
861*23b7c7b8SHermès Bélusca-Maïto
862*23b7c7b8SHermès Bélusca-Maïto Wait - If this is TRUE we are allowed to block for the Vcb, if FALSE
863*23b7c7b8SHermès Bélusca-Maïto then we must try to acquire the Vcb anyway.
864*23b7c7b8SHermès Bélusca-Maïto
865*23b7c7b8SHermès Bélusca-Maïto TopLevel - If this is TRUE this is a top level request.
866*23b7c7b8SHermès Bélusca-Maïto
867*23b7c7b8SHermès Bélusca-Maïto VcbDeleted - Returns whether the VCB was deleted by this call.
868*23b7c7b8SHermès Bélusca-Maïto
869*23b7c7b8SHermès Bélusca-Maïto Return Value:
870*23b7c7b8SHermès Bélusca-Maïto
871*23b7c7b8SHermès Bélusca-Maïto NTSTATUS - The return status for the operation
872*23b7c7b8SHermès Bélusca-Maïto
873*23b7c7b8SHermès Bélusca-Maïto --*/
874*23b7c7b8SHermès Bélusca-Maïto
875*23b7c7b8SHermès Bélusca-Maïto {
876*23b7c7b8SHermès Bélusca-Maïto NTSTATUS Status = STATUS_SUCCESS;
877*23b7c7b8SHermès Bélusca-Maïto PDCB ParentDcb;
878*23b7c7b8SHermès Bélusca-Maïto BOOLEAN RecursiveClose;
879*23b7c7b8SHermès Bélusca-Maïto BOOLEAN LocalVcbDeleted;
880*23b7c7b8SHermès Bélusca-Maïto IRP_CONTEXT IrpContext;
881*23b7c7b8SHermès Bélusca-Maïto
882*23b7c7b8SHermès Bélusca-Maïto PAGED_CODE();
883*23b7c7b8SHermès Bélusca-Maïto
884*23b7c7b8SHermès Bélusca-Maïto DebugTrace(+1, Dbg, "FatCommonClose...\n", 0);
885*23b7c7b8SHermès Bélusca-Maïto
886*23b7c7b8SHermès Bélusca-Maïto //
887*23b7c7b8SHermès Bélusca-Maïto // Initialize the callers variable, if needed.
888*23b7c7b8SHermès Bélusca-Maïto //
889*23b7c7b8SHermès Bélusca-Maïto
890*23b7c7b8SHermès Bélusca-Maïto LocalVcbDeleted = FALSE;
891*23b7c7b8SHermès Bélusca-Maïto
892*23b7c7b8SHermès Bélusca-Maïto if (ARGUMENT_PRESENT( VcbDeleted )) {
893*23b7c7b8SHermès Bélusca-Maïto
894*23b7c7b8SHermès Bélusca-Maïto *VcbDeleted = LocalVcbDeleted;
895*23b7c7b8SHermès Bélusca-Maïto }
896*23b7c7b8SHermès Bélusca-Maïto
897*23b7c7b8SHermès Bélusca-Maïto //
898*23b7c7b8SHermès Bélusca-Maïto // Special case the unopened file object
899*23b7c7b8SHermès Bélusca-Maïto //
900*23b7c7b8SHermès Bélusca-Maïto
901*23b7c7b8SHermès Bélusca-Maïto if (TypeOfOpen == UnopenedFileObject) {
902*23b7c7b8SHermès Bélusca-Maïto
903*23b7c7b8SHermès Bélusca-Maïto DebugTrace(0, Dbg, "Close unopened file object\n", 0);
904*23b7c7b8SHermès Bélusca-Maïto
905*23b7c7b8SHermès Bélusca-Maïto Status = STATUS_SUCCESS;
906*23b7c7b8SHermès Bélusca-Maïto
907*23b7c7b8SHermès Bélusca-Maïto DebugTrace(-1, Dbg, "FatCommonClose -> %08lx\n", Status);
908*23b7c7b8SHermès Bélusca-Maïto return Status;
909*23b7c7b8SHermès Bélusca-Maïto }
910*23b7c7b8SHermès Bélusca-Maïto
911*23b7c7b8SHermès Bélusca-Maïto //
912*23b7c7b8SHermès Bélusca-Maïto // Set up our stack IrpContext.
913*23b7c7b8SHermès Bélusca-Maïto //
914*23b7c7b8SHermès Bélusca-Maïto
915*23b7c7b8SHermès Bélusca-Maïto RtlZeroMemory( &IrpContext, sizeof(IRP_CONTEXT) );
916*23b7c7b8SHermès Bélusca-Maïto
917*23b7c7b8SHermès Bélusca-Maïto IrpContext.NodeTypeCode = FAT_NTC_IRP_CONTEXT;
918*23b7c7b8SHermès Bélusca-Maïto IrpContext.NodeByteSize = sizeof( IrpContext );
919*23b7c7b8SHermès Bélusca-Maïto IrpContext.MajorFunction = IRP_MJ_CLOSE;
920*23b7c7b8SHermès Bélusca-Maïto IrpContext.Vcb = Vcb;
921*23b7c7b8SHermès Bélusca-Maïto
922*23b7c7b8SHermès Bélusca-Maïto if (Wait) {
923*23b7c7b8SHermès Bélusca-Maïto
924*23b7c7b8SHermès Bélusca-Maïto SetFlag( IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT );
925*23b7c7b8SHermès Bélusca-Maïto }
926*23b7c7b8SHermès Bélusca-Maïto
927*23b7c7b8SHermès Bélusca-Maïto //
928*23b7c7b8SHermès Bélusca-Maïto // Acquire exclusive access to the Vcb and enqueue the irp if we didn't
929*23b7c7b8SHermès Bélusca-Maïto // get access.
930*23b7c7b8SHermès Bélusca-Maïto //
931*23b7c7b8SHermès Bélusca-Maïto
932*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
933*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress: 28137, "prefast wants Wait to be a constant, but that's not possible for fastfat" )
934*23b7c7b8SHermès Bélusca-Maïto #endif
935*23b7c7b8SHermès Bélusca-Maïto if (!ExAcquireResourceExclusiveLite( &Vcb->Resource, Wait )) {
936*23b7c7b8SHermès Bélusca-Maïto
937*23b7c7b8SHermès Bélusca-Maïto return STATUS_PENDING;
938*23b7c7b8SHermès Bélusca-Maïto }
939*23b7c7b8SHermès Bélusca-Maïto
940*23b7c7b8SHermès Bélusca-Maïto //
941*23b7c7b8SHermès Bélusca-Maïto // The following test makes sure that we don't blow away an Fcb if we
942*23b7c7b8SHermès Bélusca-Maïto // are trying to do a Supersede/Overwrite open above us. This test
943*23b7c7b8SHermès Bélusca-Maïto // does not apply for the EA file.
944*23b7c7b8SHermès Bélusca-Maïto //
945*23b7c7b8SHermès Bélusca-Maïto
946*23b7c7b8SHermès Bélusca-Maïto if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_CREATE_IN_PROGRESS) &&
947*23b7c7b8SHermès Bélusca-Maïto Vcb->EaFcb != Fcb) {
948*23b7c7b8SHermès Bélusca-Maïto
949*23b7c7b8SHermès Bélusca-Maïto ExReleaseResourceLite( &Vcb->Resource );
950*23b7c7b8SHermès Bélusca-Maïto
951*23b7c7b8SHermès Bélusca-Maïto return STATUS_PENDING;
952*23b7c7b8SHermès Bélusca-Maïto }
953*23b7c7b8SHermès Bélusca-Maïto
954*23b7c7b8SHermès Bélusca-Maïto //
955*23b7c7b8SHermès Bélusca-Maïto // Setting the following flag prevents recursive closes of directory file
956*23b7c7b8SHermès Bélusca-Maïto // objects, which are handled in a special case loop.
957*23b7c7b8SHermès Bélusca-Maïto //
958*23b7c7b8SHermès Bélusca-Maïto
959*23b7c7b8SHermès Bélusca-Maïto if ( FlagOn(Vcb->VcbState, VCB_STATE_FLAG_CLOSE_IN_PROGRESS) ) {
960*23b7c7b8SHermès Bélusca-Maïto
961*23b7c7b8SHermès Bélusca-Maïto RecursiveClose = TRUE;
962*23b7c7b8SHermès Bélusca-Maïto
963*23b7c7b8SHermès Bélusca-Maïto } else {
964*23b7c7b8SHermès Bélusca-Maïto
965*23b7c7b8SHermès Bélusca-Maïto
966*23b7c7b8SHermès Bélusca-Maïto SetFlag(Vcb->VcbState, VCB_STATE_FLAG_CLOSE_IN_PROGRESS);
967*23b7c7b8SHermès Bélusca-Maïto RecursiveClose = FALSE;
968*23b7c7b8SHermès Bélusca-Maïto
969*23b7c7b8SHermès Bélusca-Maïto //
970*23b7c7b8SHermès Bélusca-Maïto // Since we are at the top of the close chain, we need to add
971*23b7c7b8SHermès Bélusca-Maïto // a reference to the VCB. This will keep it from going away
972*23b7c7b8SHermès Bélusca-Maïto // on us until we are ready to check for a dismount below.
973*23b7c7b8SHermès Bélusca-Maïto //
974*23b7c7b8SHermès Bélusca-Maïto
975*23b7c7b8SHermès Bélusca-Maïto Vcb->OpenFileCount += 1;
976*23b7c7b8SHermès Bélusca-Maïto }
977*23b7c7b8SHermès Bélusca-Maïto
978*23b7c7b8SHermès Bélusca-Maïto _SEH2_TRY {
979*23b7c7b8SHermès Bélusca-Maïto
980*23b7c7b8SHermès Bélusca-Maïto //
981*23b7c7b8SHermès Bélusca-Maïto // Case on the type of open that we are trying to close.
982*23b7c7b8SHermès Bélusca-Maïto //
983*23b7c7b8SHermès Bélusca-Maïto
984*23b7c7b8SHermès Bélusca-Maïto switch (TypeOfOpen) {
985*23b7c7b8SHermès Bélusca-Maïto
986*23b7c7b8SHermès Bélusca-Maïto case VirtualVolumeFile:
987*23b7c7b8SHermès Bélusca-Maïto
988*23b7c7b8SHermès Bélusca-Maïto DebugTrace(0, Dbg, "Close VirtualVolumeFile\n", 0);
989*23b7c7b8SHermès Bélusca-Maïto
990*23b7c7b8SHermès Bélusca-Maïto //
991*23b7c7b8SHermès Bélusca-Maïto // Remove this internal, residual open from the count.
992*23b7c7b8SHermès Bélusca-Maïto //
993*23b7c7b8SHermès Bélusca-Maïto
994*23b7c7b8SHermès Bélusca-Maïto InterlockedDecrement( (LONG*)&(Vcb->InternalOpenCount) );
995*23b7c7b8SHermès Bélusca-Maïto InterlockedDecrement( (LONG*)&(Vcb->ResidualOpenCount) );
996*23b7c7b8SHermès Bélusca-Maïto
997*23b7c7b8SHermès Bélusca-Maïto try_return( Status = STATUS_SUCCESS );
998*23b7c7b8SHermès Bélusca-Maïto break;
999*23b7c7b8SHermès Bélusca-Maïto
1000*23b7c7b8SHermès Bélusca-Maïto case UserVolumeOpen:
1001*23b7c7b8SHermès Bélusca-Maïto
1002*23b7c7b8SHermès Bélusca-Maïto DebugTrace(0, Dbg, "Close UserVolumeOpen\n", 0);
1003*23b7c7b8SHermès Bélusca-Maïto
1004*23b7c7b8SHermès Bélusca-Maïto Vcb->DirectAccessOpenCount -= 1;
1005*23b7c7b8SHermès Bélusca-Maïto Vcb->OpenFileCount -= 1;
1006*23b7c7b8SHermès Bélusca-Maïto if (FlagOn(Ccb->Flags, CCB_FLAG_READ_ONLY)) { Vcb->ReadOnlyCount -= 1; }
1007*23b7c7b8SHermès Bélusca-Maïto
1008*23b7c7b8SHermès Bélusca-Maïto FatDeleteCcb( &IrpContext, &Ccb );
1009*23b7c7b8SHermès Bélusca-Maïto
1010*23b7c7b8SHermès Bélusca-Maïto try_return( Status = STATUS_SUCCESS );
1011*23b7c7b8SHermès Bélusca-Maïto break;
1012*23b7c7b8SHermès Bélusca-Maïto
1013*23b7c7b8SHermès Bélusca-Maïto case EaFile:
1014*23b7c7b8SHermès Bélusca-Maïto
1015*23b7c7b8SHermès Bélusca-Maïto DebugTrace(0, Dbg, "Close EaFile\n", 0);
1016*23b7c7b8SHermès Bélusca-Maïto
1017*23b7c7b8SHermès Bélusca-Maïto //
1018*23b7c7b8SHermès Bélusca-Maïto // Remove this internal, residual open from the count.
1019*23b7c7b8SHermès Bélusca-Maïto //
1020*23b7c7b8SHermès Bélusca-Maïto
1021*23b7c7b8SHermès Bélusca-Maïto InterlockedDecrement( (LONG*)&(Vcb->InternalOpenCount) );
1022*23b7c7b8SHermès Bélusca-Maïto InterlockedDecrement( (LONG*)&(Vcb->ResidualOpenCount) );
1023*23b7c7b8SHermès Bélusca-Maïto
1024*23b7c7b8SHermès Bélusca-Maïto try_return( Status = STATUS_SUCCESS );
1025*23b7c7b8SHermès Bélusca-Maïto break;
1026*23b7c7b8SHermès Bélusca-Maïto
1027*23b7c7b8SHermès Bélusca-Maïto case DirectoryFile:
1028*23b7c7b8SHermès Bélusca-Maïto
1029*23b7c7b8SHermès Bélusca-Maïto DebugTrace(0, Dbg, "Close DirectoryFile\n", 0);
1030*23b7c7b8SHermès Bélusca-Maïto
1031*23b7c7b8SHermès Bélusca-Maïto InterlockedDecrement( (LONG*)&Fcb->Specific.Dcb.DirectoryFileOpenCount );
1032*23b7c7b8SHermès Bélusca-Maïto
1033*23b7c7b8SHermès Bélusca-Maïto //
1034*23b7c7b8SHermès Bélusca-Maïto // Remove this internal open from the count.
1035*23b7c7b8SHermès Bélusca-Maïto //
1036*23b7c7b8SHermès Bélusca-Maïto
1037*23b7c7b8SHermès Bélusca-Maïto InterlockedDecrement( (LONG*)&(Vcb->InternalOpenCount) );
1038*23b7c7b8SHermès Bélusca-Maïto
1039*23b7c7b8SHermès Bélusca-Maïto //
1040*23b7c7b8SHermès Bélusca-Maïto // If this is the root directory, it is a residual open
1041*23b7c7b8SHermès Bélusca-Maïto // as well.
1042*23b7c7b8SHermès Bélusca-Maïto //
1043*23b7c7b8SHermès Bélusca-Maïto
1044*23b7c7b8SHermès Bélusca-Maïto if (NodeType( Fcb ) == FAT_NTC_ROOT_DCB) {
1045*23b7c7b8SHermès Bélusca-Maïto
1046*23b7c7b8SHermès Bélusca-Maïto InterlockedDecrement( (LONG*)&(Vcb->ResidualOpenCount) );
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 // If this is a recursive close, just return here.
1051*23b7c7b8SHermès Bélusca-Maïto //
1052*23b7c7b8SHermès Bélusca-Maïto
1053*23b7c7b8SHermès Bélusca-Maïto if ( RecursiveClose ) {
1054*23b7c7b8SHermès Bélusca-Maïto
1055*23b7c7b8SHermès Bélusca-Maïto try_return( Status = STATUS_SUCCESS );
1056*23b7c7b8SHermès Bélusca-Maïto
1057*23b7c7b8SHermès Bélusca-Maïto } else {
1058*23b7c7b8SHermès Bélusca-Maïto
1059*23b7c7b8SHermès Bélusca-Maïto break;
1060*23b7c7b8SHermès Bélusca-Maïto }
1061*23b7c7b8SHermès Bélusca-Maïto
1062*23b7c7b8SHermès Bélusca-Maïto
1063*23b7c7b8SHermès Bélusca-Maïto case UserDirectoryOpen:
1064*23b7c7b8SHermès Bélusca-Maïto case UserFileOpen:
1065*23b7c7b8SHermès Bélusca-Maïto
1066*23b7c7b8SHermès Bélusca-Maïto DebugTrace(0, Dbg, "Close UserFileOpen/UserDirectoryOpen\n", 0);
1067*23b7c7b8SHermès Bélusca-Maïto
1068*23b7c7b8SHermès Bélusca-Maïto //
1069*23b7c7b8SHermès Bélusca-Maïto // Uninitialize the cache map if we no longer need to use it
1070*23b7c7b8SHermès Bélusca-Maïto //
1071*23b7c7b8SHermès Bélusca-Maïto
1072*23b7c7b8SHermès Bélusca-Maïto if ((NodeType(Fcb) == FAT_NTC_DCB) &&
1073*23b7c7b8SHermès Bélusca-Maïto IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue) &&
1074*23b7c7b8SHermès Bélusca-Maïto (Fcb->OpenCount == 1) &&
1075*23b7c7b8SHermès Bélusca-Maïto (Fcb->Specific.Dcb.DirectoryFile != NULL)) {
1076*23b7c7b8SHermès Bélusca-Maïto
1077*23b7c7b8SHermès Bélusca-Maïto PFILE_OBJECT DirectoryFileObject = Fcb->Specific.Dcb.DirectoryFile;
1078*23b7c7b8SHermès Bélusca-Maïto
1079*23b7c7b8SHermès Bélusca-Maïto DebugTrace(0, Dbg, "Uninitialize the stream file object\n", 0);
1080*23b7c7b8SHermès Bélusca-Maïto
1081*23b7c7b8SHermès Bélusca-Maïto CcUninitializeCacheMap( DirectoryFileObject, NULL, NULL );
1082*23b7c7b8SHermès Bélusca-Maïto
1083*23b7c7b8SHermès Bélusca-Maïto //
1084*23b7c7b8SHermès Bélusca-Maïto // Dereference the directory file. This may cause a close
1085*23b7c7b8SHermès Bélusca-Maïto // Irp to be processed, so we need to do this before we destroy
1086*23b7c7b8SHermès Bélusca-Maïto // the Fcb.
1087*23b7c7b8SHermès Bélusca-Maïto //
1088*23b7c7b8SHermès Bélusca-Maïto
1089*23b7c7b8SHermès Bélusca-Maïto Fcb->Specific.Dcb.DirectoryFile = NULL;
1090*23b7c7b8SHermès Bélusca-Maïto ObDereferenceObject( DirectoryFileObject );
1091*23b7c7b8SHermès Bélusca-Maïto }
1092*23b7c7b8SHermès Bélusca-Maïto
1093*23b7c7b8SHermès Bélusca-Maïto Fcb->OpenCount -= 1;
1094*23b7c7b8SHermès Bélusca-Maïto Vcb->OpenFileCount -= 1;
1095*23b7c7b8SHermès Bélusca-Maïto if (FlagOn(Ccb->Flags, CCB_FLAG_READ_ONLY)) { Vcb->ReadOnlyCount -= 1; }
1096*23b7c7b8SHermès Bélusca-Maïto
1097*23b7c7b8SHermès Bélusca-Maïto FatDeleteCcb( &IrpContext, &Ccb );
1098*23b7c7b8SHermès Bélusca-Maïto
1099*23b7c7b8SHermès Bélusca-Maïto break;
1100*23b7c7b8SHermès Bélusca-Maïto
1101*23b7c7b8SHermès Bélusca-Maïto default:
1102*23b7c7b8SHermès Bélusca-Maïto
1103*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
1104*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress: 28159, "if the type of open is unknown, we seriously messed up." )
1105*23b7c7b8SHermès Bélusca-Maïto #endif
1106*23b7c7b8SHermès Bélusca-Maïto FatBugCheck( TypeOfOpen, 0, 0 );
1107*23b7c7b8SHermès Bélusca-Maïto }
1108*23b7c7b8SHermès Bélusca-Maïto
1109*23b7c7b8SHermès Bélusca-Maïto //
1110*23b7c7b8SHermès Bélusca-Maïto // At this point we've cleaned up any on-disk structure that needs
1111*23b7c7b8SHermès Bélusca-Maïto // to be done, and we can now update the in-memory structures.
1112*23b7c7b8SHermès Bélusca-Maïto // Now if this is an unreferenced FCB or if it is
1113*23b7c7b8SHermès Bélusca-Maïto // an unreferenced DCB (not the root) then we can remove
1114*23b7c7b8SHermès Bélusca-Maïto // the fcb and set our ParentDcb to non null.
1115*23b7c7b8SHermès Bélusca-Maïto //
1116*23b7c7b8SHermès Bélusca-Maïto
1117*23b7c7b8SHermès Bélusca-Maïto if (((NodeType(Fcb) == FAT_NTC_FCB) &&
1118*23b7c7b8SHermès Bélusca-Maïto (Fcb->OpenCount == 0))
1119*23b7c7b8SHermès Bélusca-Maïto
1120*23b7c7b8SHermès Bélusca-Maïto ||
1121*23b7c7b8SHermès Bélusca-Maïto
1122*23b7c7b8SHermès Bélusca-Maïto ((NodeType(Fcb) == FAT_NTC_DCB) &&
1123*23b7c7b8SHermès Bélusca-Maïto (IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue)) &&
1124*23b7c7b8SHermès Bélusca-Maïto (Fcb->OpenCount == 0) &&
1125*23b7c7b8SHermès Bélusca-Maïto (Fcb->Specific.Dcb.DirectoryFileOpenCount == 0))) {
1126*23b7c7b8SHermès Bélusca-Maïto
1127*23b7c7b8SHermès Bélusca-Maïto ParentDcb = Fcb->ParentDcb;
1128*23b7c7b8SHermès Bélusca-Maïto
1129*23b7c7b8SHermès Bélusca-Maïto SetFlag( Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB );
1130*23b7c7b8SHermès Bélusca-Maïto
1131*23b7c7b8SHermès Bélusca-Maïto FatDeleteFcb( &IrpContext, &Fcb );
1132*23b7c7b8SHermès Bélusca-Maïto
1133*23b7c7b8SHermès Bélusca-Maïto //
1134*23b7c7b8SHermès Bélusca-Maïto // Uninitialize our parent's cache map if we no longer need
1135*23b7c7b8SHermès Bélusca-Maïto // to use it.
1136*23b7c7b8SHermès Bélusca-Maïto //
1137*23b7c7b8SHermès Bélusca-Maïto
1138*23b7c7b8SHermès Bélusca-Maïto while ((NodeType(ParentDcb) == FAT_NTC_DCB) &&
1139*23b7c7b8SHermès Bélusca-Maïto IsListEmpty(&ParentDcb->Specific.Dcb.ParentDcbQueue) &&
1140*23b7c7b8SHermès Bélusca-Maïto (ParentDcb->OpenCount == 0) &&
1141*23b7c7b8SHermès Bélusca-Maïto (ParentDcb->Specific.Dcb.DirectoryFile != NULL)) {
1142*23b7c7b8SHermès Bélusca-Maïto
1143*23b7c7b8SHermès Bélusca-Maïto PFILE_OBJECT DirectoryFileObject;
1144*23b7c7b8SHermès Bélusca-Maïto
1145*23b7c7b8SHermès Bélusca-Maïto DirectoryFileObject = ParentDcb->Specific.Dcb.DirectoryFile;
1146*23b7c7b8SHermès Bélusca-Maïto
1147*23b7c7b8SHermès Bélusca-Maïto DebugTrace(0, Dbg, "Uninitialize our parent Stream Cache Map\n", 0);
1148*23b7c7b8SHermès Bélusca-Maïto
1149*23b7c7b8SHermès Bélusca-Maïto CcUninitializeCacheMap( DirectoryFileObject, NULL, NULL );
1150*23b7c7b8SHermès Bélusca-Maïto
1151*23b7c7b8SHermès Bélusca-Maïto ParentDcb->Specific.Dcb.DirectoryFile = NULL;
1152*23b7c7b8SHermès Bélusca-Maïto
1153*23b7c7b8SHermès Bélusca-Maïto ObDereferenceObject( DirectoryFileObject );
1154*23b7c7b8SHermès Bélusca-Maïto
1155*23b7c7b8SHermès Bélusca-Maïto //
1156*23b7c7b8SHermès Bélusca-Maïto // Now, if the ObDereferenceObject() caused the final close
1157*23b7c7b8SHermès Bélusca-Maïto // to come in, then blow away the Fcb and continue up,
1158*23b7c7b8SHermès Bélusca-Maïto // otherwise wait for Mm to to dereference its file objects
1159*23b7c7b8SHermès Bélusca-Maïto // and stop here..
1160*23b7c7b8SHermès Bélusca-Maïto //
1161*23b7c7b8SHermès Bélusca-Maïto
1162*23b7c7b8SHermès Bélusca-Maïto if ( ParentDcb->Specific.Dcb.DirectoryFileOpenCount == 0) {
1163*23b7c7b8SHermès Bélusca-Maïto
1164*23b7c7b8SHermès Bélusca-Maïto PDCB CurrentDcb;
1165*23b7c7b8SHermès Bélusca-Maïto
1166*23b7c7b8SHermès Bélusca-Maïto CurrentDcb = ParentDcb;
1167*23b7c7b8SHermès Bélusca-Maïto ParentDcb = CurrentDcb->ParentDcb;
1168*23b7c7b8SHermès Bélusca-Maïto
1169*23b7c7b8SHermès Bélusca-Maïto SetFlag( Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB );
1170*23b7c7b8SHermès Bélusca-Maïto
1171*23b7c7b8SHermès Bélusca-Maïto FatDeleteFcb( &IrpContext, &CurrentDcb );
1172*23b7c7b8SHermès Bélusca-Maïto
1173*23b7c7b8SHermès Bélusca-Maïto } else {
1174*23b7c7b8SHermès Bélusca-Maïto
1175*23b7c7b8SHermès Bélusca-Maïto break;
1176*23b7c7b8SHermès Bélusca-Maïto }
1177*23b7c7b8SHermès Bélusca-Maïto }
1178*23b7c7b8SHermès Bélusca-Maïto }
1179*23b7c7b8SHermès Bélusca-Maïto
1180*23b7c7b8SHermès Bélusca-Maïto Status = STATUS_SUCCESS;
1181*23b7c7b8SHermès Bélusca-Maïto
1182*23b7c7b8SHermès Bélusca-Maïto try_exit: NOTHING;
1183*23b7c7b8SHermès Bélusca-Maïto } _SEH2_FINALLY {
1184*23b7c7b8SHermès Bélusca-Maïto
1185*23b7c7b8SHermès Bélusca-Maïto DebugUnwind( FatCommonClose );
1186*23b7c7b8SHermès Bélusca-Maïto
1187*23b7c7b8SHermès Bélusca-Maïto //
1188*23b7c7b8SHermès Bélusca-Maïto // We are done processing the close. If we are the top of the close
1189*23b7c7b8SHermès Bélusca-Maïto // chain, see if the VCB can go away. We have biased the open count by
1190*23b7c7b8SHermès Bélusca-Maïto // one, so we need to take that into account.
1191*23b7c7b8SHermès Bélusca-Maïto //
1192*23b7c7b8SHermès Bélusca-Maïto
1193*23b7c7b8SHermès Bélusca-Maïto if (!RecursiveClose) {
1194*23b7c7b8SHermès Bélusca-Maïto
1195*23b7c7b8SHermès Bélusca-Maïto //
1196*23b7c7b8SHermès Bélusca-Maïto // See if there is only one open left. If so, it is ours. We only want
1197*23b7c7b8SHermès Bélusca-Maïto // to check for a dismount if a dismount is not already in progress.
1198*23b7c7b8SHermès Bélusca-Maïto // We also only do this if the Vcb condition is not VcbGood and the
1199*23b7c7b8SHermès Bélusca-Maïto // caller can handle the VCB going away. This is determined by whether
1200*23b7c7b8SHermès Bélusca-Maïto // they passed in the VcbDeleted argument. This request also needs
1201*23b7c7b8SHermès Bélusca-Maïto // to be top level.
1202*23b7c7b8SHermès Bélusca-Maïto //
1203*23b7c7b8SHermès Bélusca-Maïto
1204*23b7c7b8SHermès Bélusca-Maïto if (Vcb->OpenFileCount == 1 &&
1205*23b7c7b8SHermès Bélusca-Maïto Vcb->VcbCondition != VcbGood &&
1206*23b7c7b8SHermès Bélusca-Maïto !FlagOn( Vcb->VcbState, VCB_STATE_FLAG_DISMOUNT_IN_PROGRESS ) &&
1207*23b7c7b8SHermès Bélusca-Maïto ARGUMENT_PRESENT( VcbDeleted ) &&
1208*23b7c7b8SHermès Bélusca-Maïto TopLevel) {
1209*23b7c7b8SHermès Bélusca-Maïto
1210*23b7c7b8SHermès Bélusca-Maïto //
1211*23b7c7b8SHermès Bélusca-Maïto // We need the global lock, which must be acquired before the
1212*23b7c7b8SHermès Bélusca-Maïto // VCB. Since we already have the VCB, we have to drop and
1213*23b7c7b8SHermès Bélusca-Maïto // reacquire here. Note that we always want to wait from this
1214*23b7c7b8SHermès Bélusca-Maïto // point on. Note that the VCB cannot go away, since we have
1215*23b7c7b8SHermès Bélusca-Maïto // biased the open file count.
1216*23b7c7b8SHermès Bélusca-Maïto //
1217*23b7c7b8SHermès Bélusca-Maïto
1218*23b7c7b8SHermès Bélusca-Maïto FatReleaseVcb( &IrpContext,
1219*23b7c7b8SHermès Bélusca-Maïto Vcb );
1220*23b7c7b8SHermès Bélusca-Maïto
1221*23b7c7b8SHermès Bélusca-Maïto SetFlag( IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT );
1222*23b7c7b8SHermès Bélusca-Maïto
1223*23b7c7b8SHermès Bélusca-Maïto #ifdef _MSC_VER
1224*23b7c7b8SHermès Bélusca-Maïto #pragma prefast( suppress: 28137, "prefast wants the wait parameter in this macro expansion to be a constant, unfortunately this is not possible" )
1225*23b7c7b8SHermès Bélusca-Maïto #endif
1226*23b7c7b8SHermès Bélusca-Maïto FatAcquireExclusiveGlobal( &IrpContext );
1227*23b7c7b8SHermès Bélusca-Maïto
1228*23b7c7b8SHermès Bélusca-Maïto FatAcquireExclusiveVcb( &IrpContext,
1229*23b7c7b8SHermès Bélusca-Maïto Vcb );
1230*23b7c7b8SHermès Bélusca-Maïto
1231*23b7c7b8SHermès Bélusca-Maïto //
1232*23b7c7b8SHermès Bélusca-Maïto // We have our locks in the correct order. Remove our
1233*23b7c7b8SHermès Bélusca-Maïto // extra open and check for a dismount. Note that if
1234*23b7c7b8SHermès Bélusca-Maïto // something changed while we dropped the lock, it will
1235*23b7c7b8SHermès Bélusca-Maïto // not matter, since the dismount code does the correct
1236*23b7c7b8SHermès Bélusca-Maïto // checks to make sure the volume can really go away.
1237*23b7c7b8SHermès Bélusca-Maïto //
1238*23b7c7b8SHermès Bélusca-Maïto
1239*23b7c7b8SHermès Bélusca-Maïto Vcb->OpenFileCount -= 1;
1240*23b7c7b8SHermès Bélusca-Maïto
1241*23b7c7b8SHermès Bélusca-Maïto LocalVcbDeleted = FatCheckForDismount( &IrpContext,
1242*23b7c7b8SHermès Bélusca-Maïto Vcb,
1243*23b7c7b8SHermès Bélusca-Maïto FALSE );
1244*23b7c7b8SHermès Bélusca-Maïto
1245*23b7c7b8SHermès Bélusca-Maïto FatReleaseGlobal( &IrpContext );
1246*23b7c7b8SHermès Bélusca-Maïto
1247*23b7c7b8SHermès Bélusca-Maïto //
1248*23b7c7b8SHermès Bélusca-Maïto // Let the caller know what happened, if they want this information.
1249*23b7c7b8SHermès Bélusca-Maïto //
1250*23b7c7b8SHermès Bélusca-Maïto
1251*23b7c7b8SHermès Bélusca-Maïto if (ARGUMENT_PRESENT( VcbDeleted )) {
1252*23b7c7b8SHermès Bélusca-Maïto
1253*23b7c7b8SHermès Bélusca-Maïto *VcbDeleted = LocalVcbDeleted;
1254*23b7c7b8SHermès Bélusca-Maïto }
1255*23b7c7b8SHermès Bélusca-Maïto
1256*23b7c7b8SHermès Bélusca-Maïto } else {
1257*23b7c7b8SHermès Bélusca-Maïto
1258*23b7c7b8SHermès Bélusca-Maïto //
1259*23b7c7b8SHermès Bélusca-Maïto // The volume cannot go away now. Just remove our extra reference.
1260*23b7c7b8SHermès Bélusca-Maïto //
1261*23b7c7b8SHermès Bélusca-Maïto
1262*23b7c7b8SHermès Bélusca-Maïto Vcb->OpenFileCount -= 1;
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 // If the VCB is still around, clear our recursion flag.
1267*23b7c7b8SHermès Bélusca-Maïto //
1268*23b7c7b8SHermès Bélusca-Maïto
1269*23b7c7b8SHermès Bélusca-Maïto if (!LocalVcbDeleted) {
1270*23b7c7b8SHermès Bélusca-Maïto
1271*23b7c7b8SHermès Bélusca-Maïto ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_CLOSE_IN_PROGRESS );
1272*23b7c7b8SHermès Bélusca-Maïto }
1273*23b7c7b8SHermès Bélusca-Maïto }
1274*23b7c7b8SHermès Bélusca-Maïto
1275*23b7c7b8SHermès Bélusca-Maïto //
1276*23b7c7b8SHermès Bélusca-Maïto // Only release the VCB if it did not go away.
1277*23b7c7b8SHermès Bélusca-Maïto //
1278*23b7c7b8SHermès Bélusca-Maïto
1279*23b7c7b8SHermès Bélusca-Maïto if (!LocalVcbDeleted) {
1280*23b7c7b8SHermès Bélusca-Maïto
1281*23b7c7b8SHermès Bélusca-Maïto FatReleaseVcb( &IrpContext, Vcb );
1282*23b7c7b8SHermès Bélusca-Maïto }
1283*23b7c7b8SHermès Bélusca-Maïto
1284*23b7c7b8SHermès Bélusca-Maïto DebugTrace(-1, Dbg, "FatCommonClose -> %08lx\n", Status);
1285*23b7c7b8SHermès Bélusca-Maïto } _SEH2_END;
1286*23b7c7b8SHermès Bélusca-Maïto
1287*23b7c7b8SHermès Bélusca-Maïto return Status;
1288*23b7c7b8SHermès Bélusca-Maïto }
1289*23b7c7b8SHermès Bélusca-Maïto
1290