📄 power.c
字号:
//
VOID DriverAPowerDownPrepCallback(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context
)
{
PDRIVERA_DEVICE_EXTENSION deviceExtension;
PIRP irp;
PIO_STACK_LOCATION irpStack;
// Get our device extension
deviceExtension = (PDRIVERA_DEVICE_EXTENSION)Context;
DriverADebugPrint(DBG_POWER, DBG_TRACE, __FUNCTION__"++. IRP %p", deviceExtension->DevicePowerIrp);
// get our device IRP
irp = deviceExtension->DevicePowerIrp;
// NULL our pointer
deviceExtension->DevicePowerIrp = NULL;
ASSERT(irp != NULL);
irpStack = IoGetCurrentIrpStackLocation(irp);
if (!deviceExtension->bPowerStop)
{
// stall all io processing
deviceExtension->bPowerStop = TRUE;
DriverAStallQueues(deviceExtension);
}
if (irpStack->MinorFunction == IRP_MN_SET_POWER)
{
//*****************************************************************
//*****************************************************************
// TODO: power down your device
//*****************************************************************
//*****************************************************************
// Let the power manager know our new device power state
PoSetPowerState(
deviceExtension->DeviceObject,
irpStack->Parameters.Power.Type,
irpStack->Parameters.Power.State
);
// Save our new power state
deviceExtension->DevicePowerState = irpStack->Parameters.Power.State.DeviceState;
}
// Let the power manager know we can handle a new device power IRP
PoStartNextPowerIrp(irp);
// send the device power IRP down the stack
IoSkipCurrentIrpStackLocation(irp);
irp->IoStatus.Status = STATUS_SUCCESS;
PoCallDriver(deviceExtension->LowerDeviceObject, irp);
// Adjust our IRP count
DriverAReleaseRemoveLock(deviceExtension);
DriverADebugPrint(DBG_POWER, DBG_TRACE, __FUNCTION__"--");
return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// DriverAPowerD0PrepCallback
// Callback used to handle power down tasks that need to either block
// run at PASSIVE_LEVEL for some other reason
//
// Arguments:
// IN DeviceObject
// Device object for our device
//
// IN Context
// Our device extension
//
// Return Value:
// none
//
VOID DriverAPowerD0PrepCallback(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context
)
{
PDRIVERA_DEVICE_EXTENSION deviceExtension;
PIRP irp;
PIO_STACK_LOCATION irpStack;
// Get our device extension
deviceExtension = (PDRIVERA_DEVICE_EXTENSION)Context;
DriverADebugPrint(DBG_POWER, DBG_TRACE, __FUNCTION__"++. IRP %p", deviceExtension->DevicePowerIrp);
//*****************************************************************
//*****************************************************************
// TODO: Handle any unwinding of a previous query to power down here
//*****************************************************************
//*****************************************************************
if (deviceExtension->bPowerStop)
{
// restart our queues
deviceExtension->bPowerStop = FALSE;
DriverARestartQueues(deviceExtension);
}
// get our device IRP
irp = deviceExtension->DevicePowerIrp;
// NULL our pointer
deviceExtension->DevicePowerIrp = NULL;
ASSERT(irp != NULL);
// Let the power manager know we can handle new
// device power IRPs
PoStartNextPowerIrp(irp);
// forward the IRP down the stack
IoSkipCurrentIrpStackLocation(irp);
irp->IoStatus.Status = STATUS_SUCCESS;
PoCallDriver(deviceExtension->LowerDeviceObject, irp);
// Adjust our IRP count
DriverAReleaseRemoveLock(deviceExtension);
DriverADebugPrint(DBG_POWER, DBG_TRACE, __FUNCTION__"--");
return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// DriverAPowerUpCallback
// Callback used to handle power down tasks that need to either block
// run at PASSIVE_LEVEL for some other reason
//
// Arguments:
// IN DeviceObject
// Device object for our device
//
// IN Context
// Our device extension
//
// Return Value:
// none
//
VOID DriverAPowerUpCallback(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context
)
{
PDRIVERA_DEVICE_EXTENSION deviceExtension;
PIRP irp;
PIO_STACK_LOCATION irpStack;
// Get our device extension
deviceExtension = (PDRIVERA_DEVICE_EXTENSION)Context;
DriverADebugPrint(DBG_POWER, DBG_TRACE, __FUNCTION__"++. IRP %p", deviceExtension->DevicePowerIrp);
// Get our device power IRP
irp = deviceExtension->DevicePowerIrp;
ASSERT(irp != NULL);
// NULL our IRP pointer
deviceExtension->DevicePowerIrp = NULL;
//*****************************************************************
//*****************************************************************
// TODO: Add device specific power up code here
//*****************************************************************
//*****************************************************************
// Get our IRP stack location
irpStack = IoGetCurrentIrpStackLocation(irp);
// Let the power manager know our new device power state
PoSetPowerState(
deviceExtension->DeviceObject,
irpStack->Parameters.Power.Type,
irpStack->Parameters.Power.State
);
// Save our new power state
deviceExtension->DevicePowerState = irpStack->Parameters.Power.State.DeviceState;
if (deviceExtension->bPowerStop)
{
// restart our queues
deviceExtension->bPowerStop = FALSE;
DriverARestartQueues(deviceExtension);
}
// Let the power manager know we can handle new
// device power IRPs
PoStartNextPowerIrp(irp);
// Complete the IRP
IoCompleteRequest(irp, IO_NO_INCREMENT);
// Adjust our IRP count
DriverAReleaseRemoveLock(deviceExtension);
DriverADebugPrint(DBG_POWER, DBG_TRACE, __FUNCTION__"--");
return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// DriverARequestDevicePowerIrpCallback
// Callback used to signal completion of power handling
//
// Arguments:
// IN DeviceObject
// Device object for our device
//
// IN MinorFunction
// The minor function of the power IRP
//
// IN PowerState
// The power state of the power IRP
//
// IN Context
// Our device extension
//
// IN IoStatus
// Status block of the power IRP
//
// Return Value:
// none
//
VOID DriverARequestDevicePowerIrpCallback(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState,
IN PVOID Context,
IN PIO_STATUS_BLOCK IoStatus
)
{
PDRIVERA_POWER_IRP_CONTEXT context;
DriverADebugPrint(DBG_POWER, DBG_TRACE, __FUNCTION__"++");
context = (PDRIVERA_POWER_IRP_CONTEXT)Context;
// copy status in our context block
context->Status = IoStatus->Status;
// signal completion event
KeSetEvent(context->Event, IO_NO_INCREMENT, FALSE);
DriverADebugPrint(DBG_POWER, DBG_TRACE, __FUNCTION__"--");
return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// DriverARequestDevicePowerIrp
// This routine requests IRP_MN_SET_POWER and wait for its
// completion
//
// Arguments:
// IN DeviceExtension
// our device extension
//
// IN DeviceState
// New device power state
//
// Return Value:
// NT Status code
//
NTSTATUS DriverARequestDevicePowerIrp(
IN PDRIVERA_DEVICE_EXTENSION DeviceExtension,
IN DEVICE_POWER_STATE DeviceState
)
{
NTSTATUS status;
POWER_STATE powerState;
DRIVERA_POWER_IRP_CONTEXT powerContext;
KEVENT event;
DriverADebugPrint(DBG_POWER, DBG_TRACE, __FUNCTION__"++");
// We must be at IRQL less than DISPATCH_LEVEL
// in order to block on KeWaitForSingleObject
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
KeInitializeEvent(&event, NotificationEvent, FALSE);
powerContext.Event = &event;
powerState.DeviceState = DeviceState;
status = PoRequestPowerIrp(
DeviceExtension->PhysicalDeviceObject,
IRP_MN_SET_POWER,
powerState,
DriverARequestDevicePowerIrpCallback,
&powerContext,
NULL
);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(
&event,
Executive,
KernelMode,
FALSE,
NULL
);
status = powerContext.Status;
}
DriverADebugPrint(DBG_POWER, DBG_TRACE, __FUNCTION__"--. STATUS %x", status);
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -