ReactOS 0.4.16-dev-106-g10b08aa
pnp.cpp File Reference
#include "udffs.h"
Include dependency graph for pnp.cpp:

Go to the source code of this file.

Macros

#define UDF_BUG_CHECK_ID   UDF_FILE_PNP
 

Functions

NTSTATUS UDFPnpQueryRemove (PtrUDFIrpContext PtrIrpContext, PIRP Irp, PVCB Vcb)
 
NTSTATUS UDFPnpRemove (PtrUDFIrpContext PtrIrpContext, PIRP Irp, PVCB Vcb)
 
NTSTATUS UDFPnpSurpriseRemove (PtrUDFIrpContext PtrIrpContext, PIRP Irp, PVCB Vcb)
 
NTSTATUS UDFPnpCancelRemove (PtrUDFIrpContext PtrIrpContext, PIRP Irp, PVCB Vcb)
 
NTSTATUS NTAPI UDFPnpCompletionRoutine (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Contxt)
 
NTSTATUS UDFCommonPnp (PtrUDFIrpContext PtrIrpContext, IN PIRP Irp)
 
NTSTATUS UDFPnp (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 

Macro Definition Documentation

◆ UDF_BUG_CHECK_ID

#define UDF_BUG_CHECK_ID   UDF_FILE_PNP

Definition at line 21 of file pnp.cpp.

Function Documentation

◆ UDFCommonPnp()

NTSTATUS UDFCommonPnp ( PtrUDFIrpContext  PtrIrpContext,
IN PIRP  Irp 
)

Definition at line 145 of file pnp.cpp.

149{
150 NTSTATUS RC;
152 PVCB Vcb;
153 UDFPrint(("UDFCommonPnp\n"));
154
155 _SEH2_TRY {
156 // Get the current Irp stack location.
158
159 // Make sure this device object really is big enough to be a volume device
160 // object. If it isn't, we need to get out before we try to reference some
161 // field that takes us past the end of an ordinary device object.
163
164 if (Vcb->NodeIdentifier.NodeType != UDF_NODE_TYPE_VCB) {
165 // We were called with something we don't understand.
166 if(Irp->Flags & IRP_INPUT_OPERATION) {
167 Irp->IoStatus.Information = 0;
168 }
169 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
170
173 }
174
175 // Force everything to wait.
177
178 // Case on the minor code.
179 switch ( IrpSp->MinorFunction ) {
180
182 RC = UDFPnpQueryRemove( PtrIrpContext, Irp, Vcb );
183 break;
184
186 RC = UDFPnpSurpriseRemove( PtrIrpContext, Irp, Vcb );
187 break;
188
190 RC = UDFPnpRemove( PtrIrpContext, Irp, Vcb );
191 break;
192
193/* case IRP_MN_CANCEL_REMOVE_DEVICE:
194 RC = UDFPnpCancelRemove( PtrIrpContext, Irp, Vcb );
195 break;*/
196
197 default:
198 UDFPrint(("UDFCommonPnp: pass through\n"));
199 // Just pass the IRP on. As we do not need to be in the
200 // way on return, ellide ourselves out of the stack.
202 RC = IoCallDriver(Vcb->TargetDeviceObject, Irp);
203 ASSERT(RC != STATUS_PENDING);
204
205 break;
206 }
207
208try_exit: NOTHING;
209
210 } _SEH2_FINALLY {
211 UDFReleaseIrpContext(PtrIrpContext);
212 } _SEH2_END;
213
214 return RC;
215}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
LONG NTSTATUS
Definition: precomp.h:26
#define try_return(S)
Definition: cdprocs.h:2179
struct _VCB * PVCB
Definition: fatstruc.h:557
_In_ PIRP Irp
Definition: csq.h:116
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
VOID UDFReleaseIrpContext(PtrUDFIrpContext PtrIrpContext)
Definition: misc.cpp:1086
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define NOTHING
Definition: input_list.c:10
#define ASSERT(a)
Definition: mode.c:44
#define IRP_MN_SURPRISE_REMOVAL
Definition: ntifs_ex.h:408
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IoCompleteRequest
Definition: irp.c:1240
#define IoCallDriver
Definition: irp.c:1225
#define STATUS_PENDING
Definition: ntstatus.h:82
#define Vcb
Definition: cdprocs.h:1415
NTSTATUS UDFPnpRemove(PtrUDFIrpContext PtrIrpContext, PIRP Irp, PVCB Vcb)
Definition: pnp.cpp:380
NTSTATUS UDFPnpQueryRemove(PtrUDFIrpContext PtrIrpContext, PIRP Irp, PVCB Vcb)
Definition: pnp.cpp:235
NTSTATUS UDFPnpSurpriseRemove(PtrUDFIrpContext PtrIrpContext, PIRP Irp, PVCB Vcb)
Definition: pnp.cpp:504
#define UDF_IRP_CONTEXT_CAN_BLOCK
Definition: struct.h:385
#define UDF_NODE_TYPE_VCB
Definition: struct.h:61
PVOID DeviceExtension
Definition: env_spec_w32.h:418
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3223
uint32 IrpContextFlags
Definition: struct.h:364
Definition: cdstruc.h:498
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define UDFPrint(Args)
Definition: udffs.h:223
#define IRP_INPUT_OPERATION
#define IRP_MN_REMOVE_DEVICE
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define IRP_MN_QUERY_REMOVE_DEVICE

Referenced by UDFPnp().

◆ UDFPnp()

NTSTATUS UDFPnp ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp 
)

Definition at line 81 of file pnp.cpp.

85{
86 NTSTATUS RC;
87 PtrUDFIrpContext PtrIrpContext = NULL;
88 BOOLEAN AreWeTopLevel;
89
90 UDFPrint(("UDFPnp\n"));
92
95 ASSERT(Irp);
96
97 // set the top level context
98 AreWeTopLevel = UDFIsIrpTopLevel(Irp);
99
100 _SEH2_TRY {
101 // We expect there to never be a fileobject, in which case we will always
102 // wait. Since at the moment we don't have any concept of pending Pnp
103 // operations, this is a bit nitpicky.
104
105 // get an IRP context structure and issue the request
106 PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
107 if(PtrIrpContext) {
108 RC = UDFCommonPnp(PtrIrpContext, Irp);
109 } else {
111 Irp->IoStatus.Status = RC;
112 Irp->IoStatus.Information = 0;
113 // complete the IRP
115 }
116
118
119 RC = UDFExceptionHandler(PtrIrpContext, Irp);
121 } _SEH2_END;
122
123 if (AreWeTopLevel) {
125 }
126
128
129 return RC;
130}
unsigned char BOOLEAN
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
NTSTATUS UDFExceptionHandler(PtrUDFIrpContext PtrIrpContext, PIRP Irp)
Definition: misc.cpp:358
BOOLEAN __fastcall UDFIsIrpTopLevel(PIRP Irp)
Definition: misc.cpp:228
VOID UDFLogEvent(NTSTATUS UDFEventLogId, NTSTATUS RC)
Definition: misc.cpp:575
PtrUDFIrpContext UDFAllocateIrpContext(PIRP Irp, PDEVICE_OBJECT PtrTargetDeviceObject)
Definition: misc.cpp:985
long UDFExceptionFilter(PtrUDFIrpContext PtrIrpContext, PEXCEPTION_POINTERS PtrExceptionPointers)
Definition: misc.cpp:265
#define UDF_ERROR_INTERNAL_ERROR
Definition: errmsg.h:71
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
NTSTATUS UDFCommonPnp(PtrUDFIrpContext PtrIrpContext, IN PIRP Irp)
Definition: pnp.cpp:145
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:164
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055

◆ UDFPnpCancelRemove()

NTSTATUS UDFPnpCancelRemove ( PtrUDFIrpContext  PtrIrpContext,
PIRP  Irp,
PVCB  Vcb 
)

◆ UDFPnpCompletionRoutine()

NTSTATUS NTAPI UDFPnpCompletionRoutine ( IN PDEVICE_OBJECT  DeviceObject,
IN PIRP  Irp,
IN PVOID  Contxt 
)

Definition at line 731 of file pnp.cpp.

736{
737 PKEVENT Event = (PKEVENT) Contxt;
738
739 KeSetEvent( Event, 0, FALSE );
740
742
744 UNREFERENCED_PARAMETER( Contxt );
745}
#define PKEVENT
Definition: env_spec_w32.h:70
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68

Referenced by UDFPnpQueryRemove(), UDFPnpRemove(), and UDFPnpSurpriseRemove().

◆ UDFPnpQueryRemove()

NTSTATUS UDFPnpQueryRemove ( PtrUDFIrpContext  PtrIrpContext,
PIRP  Irp,
PVCB  Vcb 
)

Definition at line 235 of file pnp.cpp.

240{
241 NTSTATUS RC;
243 BOOLEAN VcbDeleted = FALSE;
244 BOOLEAN GlobalHeld = FALSE;
245 BOOLEAN VcbAcquired = FALSE;
247
248 // Having said yes to a QUERY, any communication with the
249 // underlying storage stack is undefined (and may block)
250 // until the bounding CANCEL or REMOVE is sent.
251
252 _SEH2_TRY {
253
254 // Acquire the global resource so that we can try to vaporize
255 // the volume, and the vcb resource itself.
256 UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE);
257 GlobalHeld = TRUE;
258
259 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK))
260 UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo);
261#ifdef UDF_DELAYED_CLOSE
263#endif //UDF_DELAYED_CLOSE
264
265 UDFAcquireResourceExclusive(&(Vcb->VCBResource),TRUE);
266 VcbAcquired = TRUE;
267
269 // With the volume held locked, note that we must finalize as much
270 // as possible right now.
272
273 // disable Eject Request Waiter if any
274 UDFReleaseResource( &(Vcb->VCBResource) );
275 VcbAcquired = FALSE;
277 UDFAcquireResourceExclusive(&(Vcb->VCBResource),TRUE);
278 VcbAcquired = TRUE;
279
280 // We need to pass this down before starting the dismount, which
281 // could disconnect us immediately from the stack.
282
283 // Get the next stack location, and copy over the stack location
285
286 // Set up the completion routine
290 &Event,
291 TRUE,
292 TRUE,
293 TRUE );
294 // Send the request and wait.
295 RC = IoCallDriver(Vcb->TargetDeviceObject, Irp);
296
297 if (RC == STATUS_PENDING) {
299 Executive,
301 FALSE,
302 NULL );
303
304 RC = Irp->IoStatus.Status;
305 }
306
307 // Now if no one below us failed already, initiate the dismount
308 // on this volume, make it go away. PnP needs to see our internal
309 // streams close and drop their references to the target device.
310
311 // Since we were able to lock the volume, we are guaranteed to
312 // move this volume into dismount state and disconnect it from
313 // the underlying storage stack. The force on our part is actually
314 // unnecesary, though complete.
315
316 // What is not strictly guaranteed, though, is that the closes
317 // for the metadata streams take effect synchronously underneath
318 // of this call. This would leave references on the target device
319 // even though we are disconnected!
320 if (NT_SUCCESS( RC )) {
321 VcbDeleted = !UDFCheckForDismount( PtrIrpContext, Vcb, TRUE );
322 ASSERT( VcbDeleted );
323 }
324
325 // Release the Vcb if it could still remain.
326
327 // Note: if everything else succeeded and the Vcb is persistent because the
328 // internal streams did not vaporize, we really need to pend this IRP off on
329 // the side until the dismount is completed. I can't think of a reasonable
330 // case (in UDF) where this would actually happen, though it might still need
331 // to be implemented.
332 //
333 // The reason this is the case is that handles/fileobjects place a reference
334 // on the device objects they overly. In the filesystem case, these references
335 // are on our target devices. PnP correcly thinks that if references remain
336 // on the device objects in the stack that someone has a handle, and that this
337 // counts as a reason to not succeed the query - even though every interrogated
338 // driver thinks that it is OK.
339 ASSERT( !(NT_SUCCESS( RC ) && !VcbDeleted ));
340
341 } _SEH2_FINALLY {
342
343 if (!VcbDeleted && VcbAcquired) {
344 UDFReleaseResource( &(Vcb->VCBResource) );
345 }
346
347 if (GlobalHeld) {
348 UDFReleaseResource( &(UDFGlobalData.GlobalDataResource) );
349 }
350
352 Irp->IoStatus.Status = RC;
353 // Free up the Irp Context
354 UDFReleaseIrpContext(PtrIrpContext);
355 // complete the IRP
357 }
358 } _SEH2_END;
359
360 return RC;
361} // end UDFPnpQueryRemove()
struct _PREVENT_MEDIA_REMOVAL_USER_IN * PPREVENT_MEDIA_REMOVAL_USER_IN
VOID UDFCloseAllDelayed(IN PVCB Vcb)
Definition: close.cpp:754
#define TRUE
Definition: types.h:120
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define UDFReleaseResource(Resource)
Definition: env_spec_w32.h:661
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define UDFAcquireResourceExclusive(Resource, CanWait)
Definition: env_spec_w32.h:656
#define NonPagedPool
Definition: env_spec_w32.h:307
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
#define MyAllocatePool__(type, size)
Definition: mem_tools.h:149
#define KernelMode
Definition: asm.h:34
@ NotificationEvent
#define IoCopyCurrentIrpStackLocationToNext(Irp)
Definition: ntifs_ex.h:413
OSSTATUS UDFDoDismountSequence(IN PVCB Vcb, IN PPREVENT_MEDIA_REMOVAL_USER_IN Buf, IN BOOLEAN Eject)
Definition: phys_eject.cpp:704
VOID UDFStopEjectWaiter(PVCB Vcb)
Definition: phys_eject.cpp:673
NTSTATUS NTAPI UDFPnpCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Contxt)
Definition: pnp.cpp:731
BOOLEAN UDFCheckForDismount(IN PtrUDFIrpContext IrpContext, IN PVCB Vcb, IN BOOLEAN VcbAcquired)
Definition: verfysup.cpp:629
#define UDFCloseAllSystemDelayedInDir(Vcb, FI)
Definition: protos.h:99
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:166
#define UDF_VCB_FLAGS_RAW_DISK
Definition: udf_common.h:476
UDFData UDFGlobalData
Definition: udfinit.cpp:25
@ Executive
Definition: ketypes.h:415

Referenced by UDFCommonPnp().

◆ UDFPnpRemove()

NTSTATUS UDFPnpRemove ( PtrUDFIrpContext  PtrIrpContext,
PIRP  Irp,
PVCB  Vcb 
)

Definition at line 380 of file pnp.cpp.

385{
386 NTSTATUS RC;
388 BOOLEAN VcbDeleted;
389 BOOLEAN VcbAcquired;
391
392 // REMOVE - a storage device is now gone. We either got
393 // QUERY'd and said yes OR got a SURPRISE OR a storage
394 // stack failed to spin back up from a sleep/stop state
395 // (the only case in which this will be the first warning).
396 //
397 // Note that it is entirely unlikely that we will be around
398 // for a REMOVE in the first two cases, as we try to intiate
399 // dismount.
400
401 // Acquire the global resource so that we can try to vaporize
402 // the volume, and the vcb resource itself.
403 UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE);
404
405 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK))
406 UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo);
407#ifdef UDF_DELAYED_CLOSE
409#endif //UDF_DELAYED_CLOSE
410
411 UDFAcquireResourceExclusive(&(Vcb->VCBResource),TRUE);
412 VcbAcquired = TRUE;
413
414 // The device will be going away. Remove our lock (benign
415 // if we never had it).
416 if((Vcb->Vpb->Flags & VPB_LOCKED) ||
417 (Vcb->VolumeLockPID != (ULONG)-1) ) {
418 Vcb->Vpb->Flags &= ~VPB_LOCKED;
419 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_LOCKED;
420 Vcb->VolumeLockFileObject = NULL;
421 Vcb->VolumeLockPID = -1;
422 RC = STATUS_SUCCESS;
423 }
424
425 // We need to pass this down before starting the dismount, which
426 // could disconnect us immediately from the stack.
427
428 // Get the next stack location, and copy over the stack location
430
431 // Set up the completion routine
435 &Event,
436 TRUE,
437 TRUE,
438 TRUE );
439
440 // Send the request and wait.
441 RC = IoCallDriver(Vcb->TargetDeviceObject, Irp);
442
443 if (RC == STATUS_PENDING) {
444
446 Executive,
448 FALSE,
449 NULL );
450
451 RC = Irp->IoStatus.Status;
452 }
453
454 _SEH2_TRY {
455
456 // Knock as many files down for this volume as we can.
457
458 // Now make our dismount happen. This may not vaporize the
459 // Vcb, of course, since there could be any number of handles
460 // outstanding if we were not preceeded by a QUERY.
461 //
462 // PnP will take care of disconnecting this stack if we
463 // couldn't get off of it immediately.
464 Vcb->Vpb->RealDevice->Flags |= DO_VERIFY_VOLUME;
468 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_MOUNTED;
469 Vcb->WriteSecurity = FALSE;
470 // disable Eject Request Waiter if any
471 UDFReleaseResource( &(Vcb->VCBResource) );
472 VcbAcquired = FALSE;
473
475
476 VcbDeleted = !UDFCheckForDismount( PtrIrpContext, Vcb, FALSE );
477
478try_exit: NOTHING;
479
480 } _SEH2_FINALLY {
481 // Release the Vcb if it could still remain.
482 if (!VcbDeleted && VcbAcquired) {
483 UDFReleaseResource(&(Vcb->VCBResource));
484 }
485 UDFReleaseResource(&(UDFGlobalData.GlobalDataResource));
486
487 if(Buf)
488 MyFreePool__(Buf);
489
491 Irp->IoStatus.Status = RC;
492 // Free up the Irp Context
493 UDFReleaseIrpContext(PtrIrpContext);
494 // complete the IRP
496 }
497 } _SEH2_END;
498
499 return RC;
500}
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define MyFreePool__(addr)
Definition: mem_tools.h:152
#define STATUS_SUCCESS
Definition: shellext.h:65
uint32_t ULONG
Definition: typedefs.h:59
#define VPB_LOCKED
Definition: iotypes.h:1808

Referenced by UDFCommonPnp().

◆ UDFPnpSurpriseRemove()

NTSTATUS UDFPnpSurpriseRemove ( PtrUDFIrpContext  PtrIrpContext,
PIRP  Irp,
PVCB  Vcb 
)

Definition at line 504 of file pnp.cpp.

537{
538 NTSTATUS RC;
540 BOOLEAN VcbDeleted;
541 BOOLEAN VcbAcquired;
543
544 // SURPRISE - a device was physically yanked away without
545 // any warning. This means external forces.
546
547 UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE);
548
549 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK))
550 UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo);
551#ifdef UDF_DELAYED_CLOSE
553#endif //UDF_DELAYED_CLOSE
554
555 UDFAcquireResourceExclusive(&(Vcb->VCBResource),TRUE);
556 VcbAcquired = TRUE;
557
558 // We need to pass this down before starting the dismount, which
559 // could disconnect us immediately from the stack.
560
561 // Get the next stack location, and copy over the stack location
563
564 // Set up the completion routine
568 &Event,
569 TRUE,
570 TRUE,
571 TRUE );
572
573 // Send the request and wait.
574 RC = IoCallDriver(Vcb->TargetDeviceObject, Irp);
575
576 if (RC == STATUS_PENDING) {
577
579 Executive,
581 FALSE,
582 NULL );
583
584 RC = Irp->IoStatus.Status;
585 }
586
587 _SEH2_TRY {
588 // Knock as many files down for this volume as we can.
589 Vcb->Vpb->RealDevice->Flags |= DO_VERIFY_VOLUME;
591 if(!Buf) {
592 VcbAcquired = FALSE;
593 VcbDeleted = FALSE;
595 }
596
598 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_MOUNTED;
599 Vcb->WriteSecurity = FALSE;
600
601 UDFReleaseResource(&(Vcb->VCBResource));
602 VcbAcquired = FALSE;
603
605
606 // Now make our dismount happen. This may not vaporize the
607 // Vcb, of course, since there could be any number of handles
608 // outstanding since this is an out of band notification.
609 VcbDeleted = !UDFCheckForDismount( PtrIrpContext, Vcb, FALSE );
610
611try_exit: NOTHING;
612
613 } _SEH2_FINALLY {
614
615 // Release the Vcb if it could still remain.
616 if (!VcbDeleted && VcbAcquired) {
617 UDFReleaseResource(&(Vcb->VCBResource));
618 }
619 UDFReleaseResource(&(UDFGlobalData.GlobalDataResource));
620
621 if(Buf)
622 MyFreePool__(Buf);
623
625 Irp->IoStatus.Status = RC;
626 // Free up the Irp Context
627 UDFReleaseIrpContext(PtrIrpContext);
628 // complete the IRP
630 }
631 } _SEH2_END;
632
633 return RC;
634}

Referenced by UDFCommonPnp().