📄 driverpn.c
字号:
// do not have a set of hardware resources from the PnP Manager.
//
// The PnP Manager is now giving us a set of resources, and
// asking us to start the device.
//
// In this case, we pass the IRP all the way down. When it's
// done (and our completion routine is called) we can then
// read the list of device resources pointed to in the IRP
// Stack Location.
//
case STATE_STOPPED + IRP_MN_START_DEVICE:
case STATE_NEVER_STARTED + IRP_MN_START_DEVICE:
DbgPrint( "ProfiM PnP: DispatchPnp: PROCESSING START_DEVICE\n" );
//
// The BUS DRIVER handles this IRP before we do
//
IoCopyCurrentIrpStackLocationToNext( Irp );
//
// Call PnpComplete() when this IRP is done...
//
IoSetCompletionRoutine( Irp,
PnpComplete,
&eventWaitLowerDrivers,
TRUE,
TRUE,
TRUE );
//
// Send the IRP to the bus driver. Let's see what HE
// thinks.
//
code = IoCallDriver( devExt->DeviceToSendIrpsTo, Irp );
if ( STATUS_PENDING == code )
{
KeWaitForSingleObject( &eventWaitLowerDrivers,
Executive,
KernelMode,
FALSE,
NULL );
code = Irp->IoStatus.Status;
}
//
// Can the bus driver do the start?
//
if ( NT_SUCCESS( code ) )
{
//
// Yup. Go initialize the device. The CmResourceLists
// are pointed to by the IoStackLocation.
//
code = StartDevice( devExt, ioStackLocation );
//
// If the our StartDevice function succeeded, the
// device is now "officially" started!
//
if ( NT_SUCCESS( code ) )
{
devExt->State = STATE_STARTED;
}
}
else
{
//
// The bus driver has declined to start the device.
// Oh well...
//
#if PnP_DBG
DbgPrint( "ProfiM PnP: DispatchPnp: IoCallDriver() for START fails! 0x%0x \n",
code );
#endif
}
//
// We must now complete the IRP, since we stopped it in the
// completetion routine with MORE_PROCESSING_REQUIRED.
//
Irp->IoStatus.Status = code;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
break;
//
// STATE: STARTED
// IRP_MN: _QUERY_REMOVE
//
// We're here because we're running, and the PnP Manager wants
// to "nicely" remove our device. This is the orderly way
// PnP Manager handles device disconnections (as opposed to
// doing a SURPRISE_REMOVAL).
//
// What we do here is (a) change the state of the device such
// that newly arriving requests will be rejected, (b) wait for
// all requests to complete on the device, and (c) pass the
// request on down.
//
case STATE_STARTED + IRP_MN_QUERY_REMOVE_DEVICE:
#if PnP_DBG
PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: PROCESSING QUERY_REMOVE_DEVICE\n" );
#endif
//
// WE process this request FIRST
//
//
// See if we're OK with removing the device at this point.
// We do NOT actually RETURN the resources here... we
// just affirm or deny that we're OK with returning them.
//
code = CanRemoveDevice( devExt, Irp );
//
// Replace status code that's in the IRP to indicate our
// opinion about stopping the device. If we're
// OK with returning the resources, this will be
// STATUS_SUCCESS.
//
Irp->IoStatus.Status = code;
if ( !NT_SUCCESS( code ) )
{
//
// NOPE. Can't remove the device because, for some
// reason (perhaps because we can't return our
// resources). Too bad. Tell the PnP Manager that
// stopping right now is not an option for us.
//
// NOTE: NO NEED to pass IRP down if WE can't stop
// it doesn't matter if the Bus Driver can.
//
IoCompleteRequest( Irp, IO_NO_INCREMENT );
}
else
{
#if PnP_DBG
DbgPrint( "ProfiM PnP: DispatchPnp: Waiting for pending requests to complete. (%d. remain)\n",
devExt->OutstandingIO );
#endif
//
// Set new state -- This state results in any new
// requests received at our dispatch entry points
// being REJECTED... any request still on the queues
// are allowed to complete, however.
//
devExt->State = STATE_REMOVE_PENDING;
//
// Decrement our reference on the device here, and then
// wait until there are no requests active or on the
// device's queues.
//
RequestDecrement( devExt );
WaitForRemove( devExt );
//
// OK. No further requests remain. Let the bus driver
// know.
//
// DECREMENTED REQUEST COUNT above. Return immediately
// below.
//
#if PnP_DBG
PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: Leaving With state: " );
PrintState( devExt );
PB_DbgPrintL1( "\n" );
#endif
//
// Pass this request on down to the bus driver
//
IoSkipCurrentIrpStackLocation( Irp );
return( IoCallDriver( devExt->DeviceToSendIrpsTo, Irp ) );
}
break;
//
// STATE: REMOVE_PENDING
// IRP_MN: _REMOVE_DEVICE
//
// We're here because we've previously received notification
// of the intention to remove the device in an orderly way.
// We return our resources here, and then tear down our device
// object. Note that there can be no requests pending at this
// point, because we finished them all during QUERY_REMOVE
// processing (before entering RemovePending state)
//
case STATE_REMOVE_PENDING + IRP_MN_REMOVE_DEVICE:
//
// All queued and active IRPs are complete at this point.
//
//
// Fall through...
//
//
// STATE: SURPRISE_REMOVED
// IRP_MN: _REMOVE_DEVICE
//
// We're here because we've previously received notification
// of a "surprise" removal. At this point, we just tear down
// our device object
//
case STATE_SURPRISE_REMOVED + IRP_MN_REMOVE_DEVICE:
//
// Removing the device at this point is NOT optional.
//
#if PnP_DBG
DbgPrint( "ProfiM PnP: DispatchPnp: REMOVE_DEVICE\n" );
#endif
//
// Device has been removed
//
devExt->State = STATE_REMOVED;
//
// Return any resources we're using.
//
ReturnResources( devExt );
//
// Decrement our reference on the device here, and then
// wait until we can remove the device. Because we would
// have gotten a prior warning of this removal (via an
// IRP_MN_SUPRISE_REMOVAL or an IRP_MN_QUERY_REMOVE) and
// at that time transitioned state appropriately, there
// should be no requests outstanding here.
//
RequestDecrement( devExt );
#if PnP_DBG
DbgPrint( "ProfiM PnP: DispatchPnp: Waiting for pending requests to complete. %d. remain\n",
devExt->OutstandingIO );
#endif
WaitForRemove( devExt );
//
// WE process this request first
//
// Remember next target of IRP
targetDevice = devExt->DeviceToSendIrpsTo;
//
// Remove and return our device object
//
RemoveDevice( devExt->DeviceObject );
//
// Indidcate that we've successfully processed the IRP
//
Irp->IoStatus.Status = STATUS_SUCCESS;
//
// Pass this request on down to the bus driver
//
IoSkipCurrentIrpStackLocation( Irp );
code = IoCallDriver( targetDevice, Irp );
ASSERT( code != STATUS_PENDING );
//
// IMPORTANT: We decremented our I/O In Progress count
// above... We don't want to decrement it again, so we
// return right here.
//
#if PnP_DBG
PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: Leaving with state: STATE_REMOVE\n" );
#endif
return( code );
break;
//
// STATE: STARTED
// IRP_MN: _SURPRISE_REMOVAL
//
// We're here when the device is running, and a device is
// forcibly removed. PnP Manager will send us a remove device
// IRP when we're supposed to actually return our resources
// and the like.
//
// Note that this is a "best effort" activity. It is quite
// possible, due to timing issues etc, that we'll crash the
// system because the device is gone. While we'll TRY not
// to do this, it is within the rules.
//
// THIS IRP IS NOT SENT ON Win9x.
//
case STATE_STARTED + IRP_MN_SURPRISE_REMOVAL:
devExt->State = STATE_SURPRISE_REMOVED;
//
// We handle this request before the bus driver
//
//
// Cancel any pending requests... make sure
// the active requests get stopped within a second (with
// no hardware access, as a result of setting the state
// above).
//
ClearQueues( devExt );
//
// We're happy... sort of. Note that it's not "legal"
// to fail this request. Afterall, what woudl that MEAN?
//
Irp->IoStatus.Status = STATUS_SUCCESS;
//
// Pass this request on down to the bus driver
//
IoSkipCurrentIrpStackLocation( Irp );
code = IoCallDriver( devExt->DeviceToSendIrpsTo, Irp );
break;
//
// STATE: STARTED
// IRP_MN: _REMOVE_DEVICE
//
// We're here when the device is running, and a device is
// forcibly removed.
//
// Note that like getting a SUPRISE_REMOVAL IRP on NT trying
// to handle a removal directly from started state is a "best
// effort" type of activity. We'll do what we can but it's
// possible, due to timing issues etc, that we'll crash the
// system because the device is gone. While we'll TRY not
// to do this, it could be unavoidable. Oh well.
//
// ON NT, we'd get an IRP_MN_SURPRISE_REMOVAL instead of this
// IRP in this state. We get this only on Win9x systems.
//
case STATE_STARTED + IRP_MN_REMOVE_DEVICE:
#if PnP_DBG
DbgPrint( "ProfiM PnP: DispatchPnp: REMOVE_DEVICE\n" );
#endif
devExt->State = STATE_REMOVED;
//
// We handle this request before the bus driver
// Note that this is another one of those requests we're
// not "allowed" to fail.
//
//
// Cancel any pending requests... make sure
// the active requests get stopped within a second (with
// no hardware access, as a result of setting the state
// above).
//
ClearQueues( devExt );
//
// Return any resources we're using.
//
ReturnResources( devExt );
//
// Removing the device at this point is NOT optional.
//
//
// Detach from the PDO
//
IoDetachDevice( devExt->DeviceToSendIrpsTo );
targetDevice = devExt->DeviceToSendIrpsTo;
devExt->DeviceToSendIrpsTo = NULL;
//
// Decrement our reference on the device here, and then
// wait until we can remove the device.
//
RequestDecrement( devExt );
#if PnP_DBG
PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: Waiting for pending requests to complete. %d. remain\n",
devExt->OutstandingIO );
#endif
WaitForRemove( devExt );
//
// OK! Now we can return our device object
//
RemoveDevice( devExt->DeviceObject );
//
// Tell the underlying driver we're cool
//
Irp->IoStatus.Status = STATUS_SUCCESS;
//
// Pass this request on down to the bus driver
//
IoSkipCurrentIrpStackLocation( Irp );
code = IoCallDriver( targetDevice, Irp );
ASSERT( code != STATUS_PENDING );
//
// IMPORTANT: We decremented our I/O In Progress count
// above... We don't want to decrement it again, so we
// return right here.
//
#if PnP_DBG
PB_DbgPrintL1( "ProfiM PnP: DispatchPnp: Leaving with state: STATE_REMOVED\n" );
#endif
return( code );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -