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