[NTFS]
[reactos.git] / drivers / filesystems / ffs / src / pnp.c
1 /*
2 * FFS File System Driver for Windows
3 *
4 * misc.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
18 extern PFFS_GLOBAL FFSGlobal;
19
20 #if (_WIN32_WINNT >= 0x0500)
21
22 /* Globals */
23
24 extern PFFS_GLOBAL FFSGlobal;
25
26 /* Definitions */
27
28 #define DBG_PNP DBG_USER
29
30 #ifdef _PREFAST_
31 IO_COMPLETION_ROUTINE FFSPnpCompletionRoutine;
32 #endif // _PREFAST_
33
34 NTSTATUS NTAPI
35 FFSPnpCompletionRoutine(
36 IN PDEVICE_OBJECT DeviceObject,
37 IN PIRP Irp,
38 IN PVOID Contxt);
39
40
41 #ifdef ALLOC_PRAGMA
42 #pragma alloc_text(PAGE, FFSPnp)
43 #pragma alloc_text(PAGE, FFSPnpQueryRemove)
44 #pragma alloc_text(PAGE, FFSPnpRemove)
45 #pragma alloc_text(PAGE, FFSPnpCancelRemove)
46 #pragma alloc_text(PAGE, FFSPnpSurpriseRemove)
47 #endif
48
49
50
51 NTSTATUS NTAPI
52 FFSPnpCompletionRoutine(
53 IN PDEVICE_OBJECT DeviceObject,
54 IN PIRP Irp,
55 IN PVOID Contxt)
56 {
57 PKEVENT Event = (PKEVENT) Contxt;
58
59 KeSetEvent(Event, 0, FALSE);
60
61 return STATUS_MORE_PROCESSING_REQUIRED;
62
63 UNREFERENCED_PARAMETER(DeviceObject);
64 UNREFERENCED_PARAMETER(Contxt);
65 }
66
67
68 __drv_mustHoldCriticalRegion
69 NTSTATUS
70 FFSPnp(
71 IN PFFS_IRP_CONTEXT IrpContext)
72 {
73 NTSTATUS Status = STATUS_INVALID_PARAMETER;
74
75 PIRP Irp;
76 PIO_STACK_LOCATION IrpSp;
77 PFFS_VCB Vcb = 0;
78 PDEVICE_OBJECT DeviceObject;
79
80 PAGED_CODE();
81
82 _SEH2_TRY
83 {
84 ASSERT(IrpContext);
85
86 ASSERT((IrpContext->Identifier.Type == FFSICX) &&
87 (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
88
89 DeviceObject = IrpContext->DeviceObject;
90
91 Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
92
93 ASSERT(Vcb != NULL);
94
95 if (!((Vcb->Identifier.Type == FFSVCB) &&
96 (Vcb->Identifier.Size == sizeof(FFS_VCB))))
97 {
98 _SEH2_LEAVE; // Status = STATUS_INVALID_PARAMETER
99 }
100
101 Irp = IrpContext->Irp;
102 IrpSp = IoGetCurrentIrpStackLocation(Irp);
103
104 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
105
106 switch (IrpSp->MinorFunction)
107 {
108
109 case IRP_MN_QUERY_REMOVE_DEVICE:
110
111 FFSPrint((DBG_PNP, "FFSPnp: FFSPnpQueryRemove...\n"));
112 Status = FFSPnpQueryRemove(IrpContext, Vcb);
113
114 break;
115
116 case IRP_MN_REMOVE_DEVICE:
117
118 FFSPrint((DBG_PNP, "FFSPnp: FFSPnpRemove...\n"));
119 Status = FFSPnpRemove(IrpContext, Vcb);
120 break;
121
122 case IRP_MN_CANCEL_REMOVE_DEVICE:
123
124 FFSPrint((DBG_PNP, "FFSPnp: FFSPnpCancelRemove...\n"));
125 Status = FFSPnpCancelRemove(IrpContext, Vcb);
126 break;
127
128 case IRP_MN_SURPRISE_REMOVAL:
129
130 FFSPrint((DBG_PNP, "FFSPnp: FFSPnpSupriseRemove...\n"));
131 Status = FFSPnpSurpriseRemove(IrpContext, Vcb);
132 break;
133
134 default:
135 break;
136 }
137 }
138
139 _SEH2_FINALLY
140 {
141 if (!IrpContext->ExceptionInProgress)
142 {
143 Irp = IrpContext->Irp;
144
145 if (Irp)
146 {
147 //
148 // Here we need pass the IRP to the disk driver.
149 //
150
151 IoSkipCurrentIrpStackLocation(Irp);
152
153 Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
154
155 IrpContext->Irp = NULL;
156 }
157
158 FFSCompleteIrpContext(IrpContext, Status);
159 }
160 } _SEH2_END;
161
162 return Status;
163 }
164
165
166 __drv_mustHoldCriticalRegion
167 NTSTATUS
168 FFSPnpQueryRemove(
169 PFFS_IRP_CONTEXT IrpContext,
170 PFFS_VCB Vcb)
171 {
172 NTSTATUS Status;
173 KEVENT Event;
174 BOOLEAN bDeleted = FALSE;
175 BOOLEAN VcbAcquired = FALSE;
176
177 PAGED_CODE();
178
179 _SEH2_TRY {
180
181 FFSPrint((DBG_PNP, "FFSPnpQueryRemove by FFSPnp ...\n"));
182
183 FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSFlushVolume ...\n"));
184
185 #if (_WIN32_WINNT >= 0x0500)
186 CcWaitForCurrentLazyWriterActivity();
187 #endif
188
189 ExAcquireResourceExclusiveLite(
190 &Vcb->MainResource, TRUE);
191 VcbAcquired = TRUE;
192
193 FFSFlushFiles(Vcb, FALSE);
194
195 FFSFlushVolume(Vcb, FALSE);
196
197 FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSLockVcb: Vcb=%xh FileObject=%xh ...\n", Vcb, IrpContext->FileObject));
198 Status = FFSLockVcb(Vcb, IrpContext->FileObject);
199
200 FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSPurgeVolume ...\n"));
201 FFSPurgeVolume(Vcb, TRUE);
202
203 if (!NT_SUCCESS(Status))
204 {
205 _SEH2_LEAVE;
206 }
207
208 ExReleaseResourceForThreadLite(
209 &Vcb->MainResource,
210 ExGetCurrentResourceThread());
211 VcbAcquired = FALSE;
212
213 IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
214
215 KeInitializeEvent(&Event, NotificationEvent, FALSE);
216 IoSetCompletionRoutine(IrpContext->Irp,
217 FFSPnpCompletionRoutine,
218 &Event,
219 TRUE,
220 TRUE,
221 TRUE);
222
223 FFSPrint((DBG_PNP, "FFSPnpQueryRemove: Call lower level driver...\n"));
224 Status = IoCallDriver(Vcb->TargetDeviceObject,
225 IrpContext->Irp);
226
227 if (Status == STATUS_PENDING)
228 {
229 KeWaitForSingleObject(&Event,
230 Executive,
231 KernelMode,
232 FALSE,
233 NULL);
234
235 Status = IrpContext->Irp->IoStatus.Status;
236 }
237
238 if (NT_SUCCESS(Status))
239 {
240 FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSCheckDismount ...\n"));
241 bDeleted = FFSCheckDismount(IrpContext, Vcb, TRUE);
242 FFSPrint((DBG_PNP, "FFSPnpQueryRemove: FFSFlushVolume bDelted=%xh ...\n", bDeleted));
243 }
244
245 ASSERT(!(NT_SUCCESS(Status) && !bDeleted));
246 }
247
248 _SEH2_FINALLY
249 {
250 if (VcbAcquired)
251 {
252 ExReleaseResourceForThreadLite(
253 &Vcb->MainResource,
254 ExGetCurrentResourceThread());
255 }
256
257 FFSCompleteRequest(
258 IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status) ?
259 IO_DISK_INCREMENT : IO_NO_INCREMENT));
260
261 IrpContext->Irp = NULL;
262 } _SEH2_END;
263
264 return Status;
265 }
266
267
268 __drv_mustHoldCriticalRegion
269 NTSTATUS
270 FFSPnpRemove(
271 PFFS_IRP_CONTEXT IrpContext,
272 PFFS_VCB Vcb)
273 {
274 NTSTATUS Status;
275 KEVENT Event;
276 BOOLEAN bDeleted;
277
278 PAGED_CODE();
279
280 _SEH2_TRY
281 {
282
283 FFSPrint((DBG_PNP, "FFSPnpRemove by FFSPnp ...\n"));
284 #if (_WIN32_WINNT >= 0x0500)
285 CcWaitForCurrentLazyWriterActivity();
286 #endif
287 ExAcquireResourceExclusiveLite(
288 &Vcb->MainResource, TRUE);
289
290 Status = FFSLockVcb(Vcb, IrpContext->FileObject);
291
292 ExReleaseResourceForThreadLite(
293 &Vcb->MainResource,
294 ExGetCurrentResourceThread());
295
296 //
297 // Setup the Irp. We'll send it to the lower disk driver.
298 //
299
300 IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
301
302 KeInitializeEvent(&Event, NotificationEvent, FALSE);
303 IoSetCompletionRoutine(IrpContext->Irp,
304 FFSPnpCompletionRoutine,
305 &Event,
306 TRUE,
307 TRUE,
308 TRUE);
309
310 Status = IoCallDriver(Vcb->TargetDeviceObject,
311 IrpContext->Irp);
312
313 if (Status == STATUS_PENDING)
314 {
315
316 KeWaitForSingleObject(&Event,
317 Executive,
318 KernelMode,
319 FALSE,
320 NULL);
321
322 Status = IrpContext->Irp->IoStatus.Status;
323 }
324
325 ExAcquireResourceExclusiveLite(
326 &Vcb->MainResource, TRUE);
327
328 FFSPurgeVolume(Vcb, FALSE);
329
330 ExReleaseResourceForThreadLite(
331 &Vcb->MainResource,
332 ExGetCurrentResourceThread());
333
334 bDeleted = FFSCheckDismount(IrpContext, Vcb, TRUE);
335 }
336
337 _SEH2_FINALLY
338 {
339 FFSCompleteRequest(
340 IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
341 IO_DISK_INCREMENT : IO_NO_INCREMENT));
342
343 IrpContext->Irp = NULL;
344 } _SEH2_END;
345
346 return Status;
347 }
348
349
350 __drv_mustHoldCriticalRegion
351 NTSTATUS
352 FFSPnpSurpriseRemove(
353 PFFS_IRP_CONTEXT IrpContext,
354 PFFS_VCB Vcb)
355 {
356 NTSTATUS Status;
357 KEVENT Event;
358 BOOLEAN bDeleted;
359
360 PAGED_CODE();
361
362 _SEH2_TRY
363 {
364
365 FFSPrint((DBG_PNP, "FFSPnpSupriseRemove by FFSPnp ...\n"));
366 #if (_WIN32_WINNT >= 0x0500)
367 CcWaitForCurrentLazyWriterActivity();
368 #endif
369 ExAcquireResourceExclusiveLite(
370 &Vcb->MainResource, TRUE);
371
372 Status = FFSLockVcb(Vcb, IrpContext->FileObject);
373
374 ExReleaseResourceForThreadLite(
375 &Vcb->MainResource,
376 ExGetCurrentResourceThread());
377
378 //
379 // Setup the Irp. We'll send it to the lower disk driver.
380 //
381
382 IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
383
384 KeInitializeEvent(&Event, NotificationEvent, FALSE);
385 IoSetCompletionRoutine(IrpContext->Irp,
386 FFSPnpCompletionRoutine,
387 &Event,
388 TRUE,
389 TRUE,
390 TRUE);
391
392 Status = IoCallDriver(Vcb->TargetDeviceObject,
393 IrpContext->Irp);
394
395 if (Status == STATUS_PENDING)
396 {
397
398 KeWaitForSingleObject(&Event,
399 Executive,
400 KernelMode,
401 FALSE,
402 NULL);
403
404 Status = IrpContext->Irp->IoStatus.Status;
405 }
406
407 ExAcquireResourceExclusiveLite(
408 &Vcb->MainResource, TRUE);
409
410 FFSPurgeVolume(Vcb, FALSE);
411
412 ExReleaseResourceForThreadLite(
413 &Vcb->MainResource,
414 ExGetCurrentResourceThread());
415
416 bDeleted = FFSCheckDismount(IrpContext, Vcb, TRUE);
417 }
418
419 _SEH2_FINALLY
420 {
421 FFSCompleteRequest(
422 IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
423 IO_DISK_INCREMENT : IO_NO_INCREMENT));
424
425 IrpContext->Irp = NULL;
426 } _SEH2_END;
427
428 return Status;
429 }
430
431
432 __drv_mustHoldCriticalRegion
433 NTSTATUS
434 FFSPnpCancelRemove(
435 PFFS_IRP_CONTEXT IrpContext,
436 PFFS_VCB Vcb)
437 {
438 NTSTATUS Status;
439
440 PAGED_CODE();
441
442 FFSPrint((DBG_PNP, "FFSPnpCancelRemove by FFSPnp ...\n"));
443
444 ExAcquireResourceExclusiveLite(
445 &Vcb->MainResource, TRUE);
446
447 Status = FFSUnlockVcb(Vcb, IrpContext->FileObject);
448
449 ExReleaseResourceForThreadLite(
450 &Vcb->MainResource,
451 ExGetCurrentResourceThread());
452
453 IoSkipCurrentIrpStackLocation(IrpContext->Irp);
454
455 Status = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp);
456
457 IrpContext->Irp = NULL;
458
459 return Status;
460 }
461
462
463 #endif //(_WIN32_WINNT >= 0x0500)