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