[FFS]
[reactos.git] / reactos / drivers / filesystems / ffs / src / close.c
1 /*
2 * FFS File System Driver for Windows
3 *
4 * close.c
5 *
6 * 2004.5.6 ~
7 *
8 * Lee Jae-Hong, http://www.pyrasis.com
9 *
10 * See License.txt
11 *
12 */
13
14 #include "ntifs.h"
15 #include "ffsdrv.h"
16
17 /* Globals */
18
19 extern PFFS_GLOBAL FFSGlobal;
20
21 /* Definitions */
22
23 #ifdef ALLOC_PRAGMA
24 #pragma alloc_text(PAGE, FFSClose)
25 #pragma alloc_text(PAGE, FFSQueueCloseRequest)
26 #pragma alloc_text(PAGE, FFSDeQueueCloseRequest)
27 #endif
28
29
30 __drv_mustHoldCriticalRegion
31 NTSTATUS
32 FFSClose(
33 IN PFFS_IRP_CONTEXT IrpContext)
34 {
35 PDEVICE_OBJECT DeviceObject;
36 NTSTATUS Status = STATUS_SUCCESS;
37 PFFS_VCB Vcb = 0;
38 BOOLEAN VcbResourceAcquired = FALSE;
39 PFILE_OBJECT FileObject;
40 PFFS_FCB Fcb = 0;
41 BOOLEAN FcbResourceAcquired = FALSE;
42 PFFS_CCB Ccb;
43 BOOLEAN FreeVcb = FALSE;
44
45 PAGED_CODE();
46
47 _SEH2_TRY
48 {
49 ASSERT(IrpContext != NULL);
50
51 ASSERT((IrpContext->Identifier.Type == FFSICX) &&
52 (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
53
54 DeviceObject = IrpContext->DeviceObject;
55
56 if (DeviceObject == FFSGlobal->DeviceObject)
57 {
58 Status = STATUS_SUCCESS;
59 _SEH2_LEAVE;
60 }
61
62 Vcb = (PFFS_VCB) DeviceObject->DeviceExtension;
63
64 ASSERT(Vcb != NULL);
65
66 ASSERT((Vcb->Identifier.Type == FFSVCB) &&
67 (Vcb->Identifier.Size == sizeof(FFS_VCB)));
68
69 ASSERT(IsMounted(Vcb));
70
71 if (!ExAcquireResourceExclusiveLite(
72 &Vcb->MainResource,
73 IrpContext->IsSynchronous))
74 {
75 FFSPrint((DBG_INFO, "FFSClose: PENDING ... Vcb: %xh/%xh\n",
76 Vcb->OpenFileHandleCount, Vcb->ReferenceCount));
77
78 Status = STATUS_PENDING;
79 _SEH2_LEAVE;
80 }
81
82 VcbResourceAcquired = TRUE;
83
84 FileObject = IrpContext->FileObject;
85
86 if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE))
87 {
88 Fcb = IrpContext->Fcb;
89 Ccb = IrpContext->Ccb;
90 }
91 else
92 {
93 Fcb = (PFFS_FCB)FileObject->FsContext;
94
95 if (!Fcb)
96 {
97 Status = STATUS_SUCCESS;
98 _SEH2_LEAVE;
99 }
100
101 ASSERT(Fcb != NULL);
102
103 Ccb = (PFFS_CCB)FileObject->FsContext2;
104 }
105
106 if (Fcb->Identifier.Type == FFSVCB)
107 {
108 Vcb->ReferenceCount--;
109
110 if (!Vcb->ReferenceCount && FlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
111 {
112 FreeVcb = TRUE;
113 }
114
115 if (Ccb)
116 {
117 FFSFreeCcb(Ccb);
118 if (FileObject)
119 {
120 FileObject->FsContext2 = Ccb = NULL;
121 }
122 }
123
124 Status = STATUS_SUCCESS;
125
126 _SEH2_LEAVE;
127 }
128
129 if (Fcb->Identifier.Type != FFSFCB || Fcb->Identifier.Size != sizeof(FFS_FCB))
130 {
131 #if DBG
132 FFSPrint((DBG_ERROR, "FFSClose: Strange IRP_MJ_CLOSE by system!\n"));
133 ExAcquireResourceExclusiveLite(
134 &FFSGlobal->CountResource,
135 TRUE);
136
137 FFSGlobal->IRPCloseCount++;
138
139 ExReleaseResourceForThreadLite(
140 &FFSGlobal->CountResource,
141 ExGetCurrentResourceThread());
142 #endif
143 _SEH2_LEAVE;
144 }
145
146 ASSERT((Fcb->Identifier.Type == FFSFCB) &&
147 (Fcb->Identifier.Size == sizeof(FFS_FCB)));
148
149 /*
150 if ((!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) &&
151 (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)))
152 */
153 {
154 if (!ExAcquireResourceExclusiveLite(
155 &Fcb->MainResource,
156 IrpContext->IsSynchronous))
157 {
158 Status = STATUS_PENDING;
159 _SEH2_LEAVE;
160 }
161
162 FcbResourceAcquired = TRUE;
163 }
164
165 if (!Ccb)
166 {
167 Status = STATUS_SUCCESS;
168 _SEH2_LEAVE;
169 }
170
171 ASSERT((Ccb->Identifier.Type == FFSCCB) &&
172 (Ccb->Identifier.Size == sizeof(FFS_CCB)));
173
174 Fcb->ReferenceCount--;
175 Vcb->ReferenceCount--;
176
177 if (!Vcb->ReferenceCount && IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
178 {
179 FreeVcb = TRUE;
180 }
181
182 FFSPrint((DBG_INFO, "FFSClose: OpenHandleCount: %u ReferenceCount: %u %s\n",
183 Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer));
184
185 if (Ccb)
186 {
187 FFSFreeCcb(Ccb);
188
189 if (FileObject)
190 {
191 FileObject->FsContext2 = Ccb = NULL;
192 }
193 }
194
195 if (!Fcb->ReferenceCount)
196 {
197 //
198 // Remove Fcb from Vcb->FcbList ...
199 //
200
201 RemoveEntryList(&Fcb->Next);
202
203 FFSFreeFcb(Fcb);
204
205 FcbResourceAcquired = FALSE;
206 }
207
208 Status = STATUS_SUCCESS;
209 }
210
211 _SEH2_FINALLY
212 {
213 if (FcbResourceAcquired)
214 {
215 ExReleaseResourceForThreadLite(
216 &Fcb->MainResource,
217 ExGetCurrentResourceThread());
218 }
219
220 if (VcbResourceAcquired)
221 {
222 ExReleaseResourceForThreadLite(
223 &Vcb->MainResource,
224 ExGetCurrentResourceThread());
225 }
226
227 if (!IrpContext->ExceptionInProgress)
228 {
229 if (Status == STATUS_PENDING)
230 {
231 FFSQueueCloseRequest(IrpContext);
232 #if 0
233 /*
234 Status = STATUS_SUCCESS;
235
236 if (IrpContext->Irp != NULL)
237 {
238 IrpContext->Irp->IoStatus.Status = Status;
239
240 FFSCompleteRequest(
241 IrpContext->Irp,
242 (BOOLEAN)!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED),
243 (CCHAR)
244 (NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
245
246 IrpContext->Irp = NULL;
247 }
248 */
249 #endif
250 }
251 else
252 {
253 FFSCompleteIrpContext(IrpContext, Status);
254
255 if (FreeVcb)
256 {
257 ExAcquireResourceExclusiveLite(
258 &FFSGlobal->Resource, TRUE);
259
260 FFSClearVpbFlag(Vcb->Vpb, VPB_MOUNTED);
261
262 FFSRemoveVcb(Vcb);
263
264 ExReleaseResourceForThreadLite(
265 &FFSGlobal->Resource,
266 ExGetCurrentResourceThread());
267
268 FFSFreeVcb(Vcb);
269 }
270 }
271 }
272 } _SEH2_END;
273
274 return Status;
275 }
276
277
278 VOID
279 FFSQueueCloseRequest(
280 IN PFFS_IRP_CONTEXT IrpContext)
281 {
282 PAGED_CODE();
283
284 ASSERT(IrpContext);
285
286 ASSERT((IrpContext->Identifier.Type == FFSICX) &&
287 (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
288
289 if (!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE))
290 {
291 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE);
292
293 IrpContext->Fcb = (PFFS_FCB)IrpContext->FileObject->FsContext;
294 IrpContext->Ccb = (PFFS_CCB)IrpContext->FileObject->FsContext2;
295
296 IrpContext->FileObject = NULL;
297 }
298
299 // IsSynchronous means we can block (so we don't requeue it)
300 IrpContext->IsSynchronous = TRUE;
301
302 ExInitializeWorkItem(
303 &IrpContext->WorkQueueItem,
304 FFSDeQueueCloseRequest,
305 IrpContext);
306
307 ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
308 }
309
310
311 VOID NTAPI
312 FFSDeQueueCloseRequest(
313 IN PVOID Context)
314 {
315 PFFS_IRP_CONTEXT IrpContext;
316
317 PAGED_CODE();
318
319 IrpContext = (PFFS_IRP_CONTEXT) Context;
320
321 ASSERT(IrpContext);
322
323 ASSERT((IrpContext->Identifier.Type == FFSICX) &&
324 (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
325
326 _SEH2_TRY
327 {
328 _SEH2_TRY
329 {
330 FsRtlEnterFileSystem();
331 FFSClose(IrpContext);
332 }
333 _SEH2_EXCEPT (FFSExceptionFilter(IrpContext, _SEH2_GetExceptionInformation()))
334 {
335 FFSExceptionHandler(IrpContext);
336 } _SEH2_END;
337 }
338 _SEH2_FINALLY
339 {
340 FsRtlExitFileSystem();
341 } _SEH2_END;
342 }