xref: /reactos/drivers/filesystems/ext2/src/pnp.c (revision aaeb131b)
1 /*
2  * COPYRIGHT:        See COPYRIGHT.TXT
3  * PROJECT:          Ext2 File System Driver for WinNT/2K/XP
4  * FILE:             pnp.c
5  * PROGRAMMER:       Matt Wu <mattwu@163.com>
6  * HOMEPAGE:         http://www.ext2fsd.com
7  * UPDATE HISTORY:
8  */
9 
10 #if (_WIN32_WINNT >= 0x0500)
11 
12 /* INCLUDES *****************************************************************/
13 
14 #include "ext2fs.h"
15 
16 /* GLOBALS ***************************************************************/
17 
18 extern PEXT2_GLOBAL Ext2Global;
19 
20 /* DEFINITIONS *************************************************************/
21 
22 #ifdef __REACTOS__
23 NTSTATUS NTAPI
24 #else
25 NTSTATUS
26 #endif
27 Ext2PnpCompletionRoutine (
28     IN PDEVICE_OBJECT DeviceObject,
29     IN PIRP           Irp,
30     IN PVOID          Contxt     );
31 
32 
33 #ifdef ALLOC_PRAGMA
34 #pragma alloc_text(PAGE, Ext2Pnp)
35 #pragma alloc_text(PAGE, Ext2PnpQueryRemove)
36 #pragma alloc_text(PAGE, Ext2PnpRemove)
37 #pragma alloc_text(PAGE, Ext2PnpCancelRemove)
38 #pragma alloc_text(PAGE, Ext2PnpSurpriseRemove)
39 #endif
40 
41 
42 /* FUNCTIONS *************************************************************/
43 
44 
45 #ifdef __REACTOS__
46 NTSTATUS NTAPI
47 #else
48 NTSTATUS
49 #endif
Ext2PnpCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Contxt)50 Ext2PnpCompletionRoutine (
51     IN PDEVICE_OBJECT DeviceObject,
52     IN PIRP Irp,
53     IN PVOID Contxt
54 )
55 {
56     PKEVENT Event = (PKEVENT) Contxt;
57 
58     KeSetEvent( Event, 0, FALSE );
59 
60     return STATUS_MORE_PROCESSING_REQUIRED;
61 
62     UNREFERENCED_PARAMETER( DeviceObject );
63     UNREFERENCED_PARAMETER( Contxt );
64 }
65 
66 
67 NTSTATUS
Ext2Pnp(IN PEXT2_IRP_CONTEXT IrpContext)68 Ext2Pnp (IN PEXT2_IRP_CONTEXT IrpContext)
69 {
70     NTSTATUS            Status = STATUS_INVALID_PARAMETER;
71 
72     PIRP                Irp;
73     PIO_STACK_LOCATION  IrpSp;
74     PEXT2_VCB           Vcb = NULL;
75     PDEVICE_OBJECT      DeviceObject;
76 
77     _SEH2_TRY {
78 
79         ASSERT(IrpContext);
80 
81         ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
82                (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
83 
84         DeviceObject = IrpContext->DeviceObject;
85 
86         Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
87 
88         ASSERT(Vcb != NULL);
89 
90         if ( !((Vcb->Identifier.Type == EXT2VCB) &&
91                 (Vcb->Identifier.Size == sizeof(EXT2_VCB)))) {
92             _SEH2_LEAVE; // Status = STATUS_INVALID_PARAMETER
93         }
94 
95         Irp = IrpContext->Irp;
96         IrpSp = IoGetCurrentIrpStackLocation(Irp);
97 
98         SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
99 
100         switch ( IrpSp->MinorFunction ) {
101 
102         case IRP_MN_QUERY_REMOVE_DEVICE:
103 
104             DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpQueryRemove...\n"));
105             Status = Ext2PnpQueryRemove(IrpContext, Vcb);
106 
107             break;
108 
109         case IRP_MN_REMOVE_DEVICE:
110 
111             DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpRemove...\n"));
112             Status = Ext2PnpRemove(IrpContext, Vcb);
113             break;
114 
115         case IRP_MN_CANCEL_REMOVE_DEVICE:
116 
117             DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpCancelRemove...\n"));
118             Status = Ext2PnpCancelRemove(IrpContext, Vcb);
119             break;
120 
121         case IRP_MN_SURPRISE_REMOVAL:
122 
123             DEBUG(DL_PNP, ("Ext2Pnp: Ext2PnpSupriseRemove...\n"));
124             Status = Ext2PnpSurpriseRemove(IrpContext, Vcb);
125             break;
126 
127         default:
128             break;
129         }
130 
131     } _SEH2_FINALLY {
132 
133         if (!IrpContext->ExceptionInProgress) {
134             Irp = IrpContext->Irp;
135 
136             if (Irp) {
137 
138                 //
139                 // Here we need pass the IRP to the disk driver.
140                 //
141 
142                 IoSkipCurrentIrpStackLocation( Irp );
143 
144                 Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
145 
146                 IrpContext->Irp = NULL;
147             }
148 
149             Ext2CompleteIrpContext(IrpContext, Status);
150         }
151     } _SEH2_END;
152 
153     return Status;
154 }
155 
156 
157 NTSTATUS
Ext2PnpQueryRemove(PEXT2_IRP_CONTEXT IrpContext,PEXT2_VCB Vcb)158 Ext2PnpQueryRemove (
159     PEXT2_IRP_CONTEXT IrpContext,
160     PEXT2_VCB         Vcb
161 )
162 {
163     NTSTATUS Status = STATUS_SUCCESS;
164     KEVENT   Event;
165     BOOLEAN  bDeleted = FALSE;
166     BOOLEAN  VcbAcquired = FALSE;
167 
168     _SEH2_TRY {
169 
170         CcWaitForCurrentLazyWriterActivity();
171 
172         VcbAcquired = ExAcquireResourceExclusiveLite(
173                           &Vcb->MainResource, TRUE );
174 
175         Ext2FlushFiles(IrpContext, Vcb, FALSE);
176         Ext2FlushVolume(IrpContext, Vcb, FALSE);
177 
178         DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2LockVcb: Vcb=%xh FileObject=%xh ...\n",
179                        Vcb, IrpContext->FileObject));
180         Status = Ext2LockVcb(Vcb, IrpContext->FileObject);
181 
182         if (VcbAcquired) {
183             ExReleaseResourceLite(&Vcb->MainResource);
184             VcbAcquired = FALSE;
185         }
186 
187         DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2PurgeVolume ...\n"));
188         Ext2PurgeVolume(Vcb, TRUE);
189 
190         if (!NT_SUCCESS(Status)) {
191             _SEH2_LEAVE;
192         }
193 
194         IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
195 
196         KeInitializeEvent( &Event, NotificationEvent, FALSE );
197         IoSetCompletionRoutine( IrpContext->Irp,
198                                 Ext2PnpCompletionRoutine,
199                                 &Event,
200                                 TRUE,
201                                 TRUE,
202                                 TRUE );
203 
204         DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Call lower level driver...\n"));
205         Status = IoCallDriver( Vcb->TargetDeviceObject,
206                                IrpContext->Irp);
207 
208         if (Status == STATUS_PENDING) {
209             KeWaitForSingleObject( &Event,
210                                    Executive,
211                                    KernelMode,
212                                    FALSE,
213                                    NULL );
214             Status = IrpContext->Irp->IoStatus.Status;
215         }
216 
217         if (NT_SUCCESS(Status)) {
218             ASSERT(!VcbAcquired);
219             DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2CheckDismount ...\n"));
220             bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE);
221             DEBUG(DL_PNP, ("Ext2PnpQueryRemove: Ext2FlushVolume bDelted=%xh ...\n", bDeleted));
222         }
223 
224     } _SEH2_FINALLY {
225 
226         if (VcbAcquired) {
227             ExReleaseResourceLite(&Vcb->MainResource);
228         }
229 
230         IrpContext->Irp->IoStatus.Status = Status;
231         Ext2CompleteRequest(
232             IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
233                                             IO_DISK_INCREMENT : IO_NO_INCREMENT) );
234 
235         IrpContext->Irp = NULL;
236     } _SEH2_END;
237 
238     return Status;
239 }
240 
241 NTSTATUS
Ext2PnpRemove(PEXT2_IRP_CONTEXT IrpContext,PEXT2_VCB Vcb)242 Ext2PnpRemove (
243     PEXT2_IRP_CONTEXT IrpContext,
244     PEXT2_VCB         Vcb      )
245 {
246     NTSTATUS Status = STATUS_SUCCESS;
247     KEVENT   Event;
248     BOOLEAN  bDeleted;
249 
250     _SEH2_TRY {
251 
252         DEBUG(DL_PNP, ("Ext2PnpRemove by Ext2Pnp ...\n"));
253 
254         CcWaitForCurrentLazyWriterActivity();
255         ExAcquireResourceExclusiveLite(
256             &Vcb->MainResource,  TRUE );
257         Status = Ext2LockVcb(Vcb, IrpContext->FileObject);
258         ExReleaseResourceLite(&Vcb->MainResource);
259 
260         //
261         // Setup the Irp. We'll send it to the lower disk driver.
262         //
263 
264         IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
265 
266         KeInitializeEvent( &Event, NotificationEvent, FALSE );
267         IoSetCompletionRoutine( IrpContext->Irp,
268                                 Ext2PnpCompletionRoutine,
269                                 &Event,
270                                 TRUE,
271                                 TRUE,
272                                 TRUE );
273 
274         Status = IoCallDriver( Vcb->TargetDeviceObject,
275                                IrpContext->Irp);
276 
277         if (Status == STATUS_PENDING) {
278 
279             KeWaitForSingleObject( &Event,
280                                    Executive,
281                                    KernelMode,
282                                    FALSE,
283                                    NULL );
284 
285             Status = IrpContext->Irp->IoStatus.Status;
286         }
287 
288         /* purge volume cache */
289         Ext2PurgeVolume(Vcb, FALSE);
290 
291         /* dismount volume */
292         bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE);
293         SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED);
294 
295     } _SEH2_FINALLY {
296 
297         IrpContext->Irp->IoStatus.Status = Status;
298         Ext2CompleteRequest(
299             IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
300                                             IO_DISK_INCREMENT : IO_NO_INCREMENT) );
301 
302         IrpContext->Irp = NULL;
303     } _SEH2_END;
304 
305     return Status;
306 }
307 
308 
309 NTSTATUS
Ext2PnpSurpriseRemove(PEXT2_IRP_CONTEXT IrpContext,PEXT2_VCB Vcb)310 Ext2PnpSurpriseRemove (
311     PEXT2_IRP_CONTEXT IrpContext,
312     PEXT2_VCB         Vcb      )
313 {
314     NTSTATUS Status;
315     KEVENT   Event;
316     BOOLEAN  bDeleted;
317 
318     _SEH2_TRY {
319 
320         DEBUG(DL_PNP, ("Ext2PnpSupriseRemove by Ext2Pnp ...\n"));
321 
322         CcWaitForCurrentLazyWriterActivity();
323         ExAcquireResourceExclusiveLite(
324             &Vcb->MainResource,  TRUE );
325 
326         Status = Ext2LockVcb(Vcb, IrpContext->FileObject);
327 
328         ExReleaseResourceLite(&Vcb->MainResource);
329 
330         //
331         // Setup the Irp. We'll send it to the lower disk driver.
332         //
333 
334         IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
335 
336         KeInitializeEvent( &Event, NotificationEvent, FALSE );
337         IoSetCompletionRoutine( IrpContext->Irp,
338                                 Ext2PnpCompletionRoutine,
339                                 &Event,
340                                 TRUE,
341                                 TRUE,
342                                 TRUE );
343 
344         Status = IoCallDriver( Vcb->TargetDeviceObject,
345                                IrpContext->Irp);
346 
347         if (Status == STATUS_PENDING) {
348 
349             KeWaitForSingleObject( &Event,
350                                    Executive,
351                                    KernelMode,
352                                    FALSE,
353                                    NULL );
354 
355             Status = IrpContext->Irp->IoStatus.Status;
356         }
357 
358         /* purge volume cache */
359         Ext2PurgeVolume(Vcb, FALSE);
360 
361         /* dismount volume */
362         bDeleted = Ext2CheckDismount(IrpContext, Vcb, TRUE);
363         SetLongFlag(Vcb->Flags, VCB_DEVICE_REMOVED);
364 
365     } _SEH2_FINALLY {
366 
367         IrpContext->Irp->IoStatus.Status = Status;
368         Ext2CompleteRequest(
369             IrpContext->Irp, FALSE, (CCHAR)(NT_SUCCESS(Status)?
370                                             IO_DISK_INCREMENT : IO_NO_INCREMENT) );
371 
372         IrpContext->Irp = NULL;
373     } _SEH2_END;
374 
375     return Status;
376 }
377 
378 
379 NTSTATUS
Ext2PnpCancelRemove(PEXT2_IRP_CONTEXT IrpContext,PEXT2_VCB Vcb)380 Ext2PnpCancelRemove (
381     PEXT2_IRP_CONTEXT IrpContext,
382     PEXT2_VCB         Vcb
383 )
384 {
385     NTSTATUS Status;
386 
387     DEBUG(DL_PNP, ("Ext2PnpCancelRemove by Ext2Pnp ...\n"));
388 
389     ExAcquireResourceExclusiveLite(
390         &Vcb->MainResource,  TRUE );
391 
392     Status = Ext2UnlockVcb(Vcb, IrpContext->FileObject);
393 
394     ExReleaseResourceLite(&Vcb->MainResource);
395 
396     IoSkipCurrentIrpStackLocation(IrpContext->Irp);
397 
398     Status = IoCallDriver(Vcb->TargetDeviceObject, IrpContext->Irp);
399 
400     IrpContext->Irp = NULL;
401 
402     return Status;
403 }
404 
405 #endif //(_WIN32_WINNT >= 0x0500)
406