📄 power.c
字号:
#include "Driver.h"
/////////////////////////////////////////////////////////////////////////////
// Description:
// Handle IRP_MJ_POWER requests
//
// Arguments:
// Pointer to the FDO
// Pointer to the IRP
// IRP_MN_WAIT_WAKE: IrpStack->Parameters.WaitWake.Xxx
// IRP_MN_POWER_SEQUENCE: IrpStack->Parameters.PowerSequence.Xxx
// IRP_MN_SET_POWER:
// IRP_MN_QUERY_POWER: IrpStack->Parameters.Power.Xxx
//
NTSTATUS DRV_Power( IN PDEVICE_OBJECT fdo,
IN PIRP Irp)
{
PDEVICE_EXTENSION pde = (PDEVICE_EXTENSION)fdo->DeviceExtension;
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
ULONG MinorFunction = IrpStack->MinorFunction;
if( !pde->started)
return CompleteIoReq( Irp, STATUS_DEVICE_NOT_CONNECTED, 0);
if (!LockDevice(pde))
return CompleteIoReq( Irp, STATUS_DELETE_PENDING, 0);
// debugprint("Power %I",Irp);
if( MinorFunction==IRP_MN_SET_POWER)
status = PowerSetPower(pde,Irp);
else
status = DefaultPowerHandler(pde,Irp);
UnlockDevice(pde);
return status;
}
/////////////////////////////////////////////////////////////////////////////
// PowerSetPower: Handle set system and device power
NTSTATUS PowerSetPower( IN PDEVICE_EXTENSION pde, IN PIRP Irp)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
POWER_STATE_TYPE PowerType = IrpStack->Parameters.Power.Type;
POWER_STATE PowerState = IrpStack->Parameters.Power.State;
/////////////////////////////////////////////////////////////////////////
// Set System Power
if( PowerType==SystemPowerState)
{
DEVICE_POWER_STATE DesiredDevicePowerState =
(PowerState.SystemState<=PowerSystemWorking ? PowerDeviceD0 : PowerDeviceD3);
if( DesiredDevicePowerState<pde->power)
{
// This system state means we have to increase device power
// debugprint("System state %d. Increase device power to %d",
// PowerState.SystemState, DesiredDevicePowerState);
// Process on way up stack...
PoStartNextPowerIrp(Irp);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine( Irp, OnCompleteIncreaseSystemPower, NULL, TRUE, TRUE, TRUE);
return PoCallDriver( pde->StackDeviceObject, Irp);
}
else if( DesiredDevicePowerState>pde->power)
{
// This system state means we have to decrease device power
// debugprint("System state %d. Decrease device power to %d",
// PowerState.SystemState, DesiredDevicePowerState);
// Send power down request to device
status = SendDeviceSetPower( pde, DesiredDevicePowerState);
if( !NT_SUCCESS(status))
{
PoStartNextPowerIrp(Irp);
return CompleteIoReq( Irp, status, 0);
}
}
}
/////////////////////////////////////////////////////////////////////////
// Set Device Power
else if( PowerType==DevicePowerState)
{
DEVICE_POWER_STATE DesiredDevicePowerState = PowerState.DeviceState;
if( DesiredDevicePowerState<pde->power)
{
// Increase device power state
// debugprint("Increase device power to %d", DesiredDevicePowerState);
// Process on way up stack...
PoStartNextPowerIrp(Irp);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine( Irp, OnCompleteIncreaseDevicePower, NULL, TRUE, TRUE, TRUE);
return PoCallDriver( pde->StackDeviceObject, Irp);
}
else if( DesiredDevicePowerState>pde->power)
{
// Decrease device power state
// debugprint("Decrease device power to %d", DesiredDevicePowerState);
// Set power state
SetPowerState(pde,PowerState.DeviceState);
}
}
// Finally pass to lower drivers
return DefaultPowerHandler(pde,Irp);
}
/////////////////////////////////////////////////////////////////////////////
// DefaultPowerHandler: Pass Power IRP down stack
NTSTATUS DefaultPowerHandler( IN PDEVICE_EXTENSION pde, IN PIRP Irp)
{
// Just pass to lower driver
// debugprintMsg("DefaultPowerHandler");
PoStartNextPowerIrp( Irp);
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver( pde->StackDeviceObject, Irp);
}
/////////////////////////////////////////////////////////////////////////////
// OnCompleteIncreaseSystemPower: Set system power (increase device power) completed
NTSTATUS OnCompleteIncreaseSystemPower( IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN PVOID context)
{
PIO_STACK_LOCATION IrpStack;
POWER_STATE PowerState;
DEVICE_POWER_STATE DesiredDevicePowerState;
PDEVICE_EXTENSION pde = (PDEVICE_EXTENSION)fdo->DeviceExtension;
NTSTATUS status = Irp->IoStatus.Status;
if (Irp->PendingReturned)
IoMarkIrpPending(Irp);
if( !NT_SUCCESS(status))
return status;
// debugprint("OnCompleteIncreaseSystemPower %x",status);
IrpStack = IoGetCurrentIrpStackLocation(Irp);
PowerState = IrpStack->Parameters.Power.State;
DesiredDevicePowerState =
(PowerState.SystemState<=PowerSystemWorking ? PowerDeviceD0 : PowerDeviceD3);
if( DesiredDevicePowerState<pde->power)
status = SendDeviceSetPower( pde, DesiredDevicePowerState);
PoStartNextPowerIrp(Irp);
return status;
}
/////////////////////////////////////////////////////////////////////////////
// OnCompleteIncreaseDevicePower: Set device power completed
NTSTATUS OnCompleteIncreaseDevicePower( IN PDEVICE_OBJECT fdo, IN PIRP Irp, IN PVOID context)
{
PIO_STACK_LOCATION IrpStack;
POWER_STATE PowerState ;
NTSTATUS status;
PDEVICE_EXTENSION pde = (PDEVICE_EXTENSION)fdo->DeviceExtension;
if (Irp->PendingReturned)
IoMarkIrpPending(Irp);
status = Irp->IoStatus.Status;
// debugprint("OnCompleteIncreaseDevicePower %x",status);
if( !NT_SUCCESS(status))
return status;
IrpStack = IoGetCurrentIrpStackLocation(Irp);
PowerState = IrpStack->Parameters.Power.State;
SetPowerState(pde,PowerState.DeviceState);
PoStartNextPowerIrp(Irp);
return status;
}
/////////////////////////////////////////////////////////////////////////////
// SendDeviceSetPower: Send set power for device
// Must not be called from set device power as it waits on an event
NTSTATUS
SendDeviceSetPower( IN PDEVICE_EXTENSION pde, IN DEVICE_POWER_STATE NewDevicePowerState)
{
POWER_STATE NewState;
SDSP sdsp;
NTSTATUS status ;
NewState.DeviceState = NewDevicePowerState;
// debugprint("SendDeviceSetPower to %d", NewDevicePowerState);
KeInitializeEvent( &sdsp.event, NotificationEvent, FALSE);
sdsp.Status = STATUS_SUCCESS;
status = PoRequestPowerIrp( pde->pdo, IRP_MN_SET_POWER, NewState,\
OnCompleteDeviceSetPower, &sdsp, NULL);
if( status==STATUS_PENDING)
{
KeWaitForSingleObject( &sdsp.event, Executive, KernelMode, FALSE, NULL);
status = sdsp.Status;
}
// Cope with W98 not passing power irp to us
if( NT_SUCCESS(status) && pde->power!=NewDevicePowerState)
{
SetPowerState(pde,NewDevicePowerState);
}
return status;
}
/////////////////////////////////////////////////////////////////////////////
// OnCompleteDeviceSetPower: Set device power IRP completed
VOID OnCompleteDeviceSetPower( IN PDEVICE_OBJECT fdo, IN UCHAR MinorFunction,
IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus)
{
PSDSP psdsp = (PSDSP)Context;
// debugprintMsg("OnCompleteDeviceSetPower");
psdsp->Status = IoStatus->Status;
KeSetEvent( &psdsp->event, 0, FALSE);
}
/////////////////////////////////////////////////////////////////////////////
void SetPowerState( IN PDEVICE_EXTENSION pde, IN DEVICE_POWER_STATE NewDevicePowerState)
{
// Use KeSynchronizeExecution if necessary to actually change power in device
// Remember new state
POWER_STATE NewState;
pde->power = NewDevicePowerState;
NewState.DeviceState = NewDevicePowerState;
if( KeGetCurrentIrql()==DISPATCH_LEVEL && NewDevicePowerState!=PowerDeviceD0)
{
;//DebugPrint("SetPowerState IRQL %d fail", KeGetCurrentIrql());
}
else
PoSetPowerState( pde->DeviceObject, DevicePowerState, NewState);
}
NTSTATUS
PowerUpDevice( IN PDEVICE_OBJECT fdo)
{
PDEVICE_EXTENSION pde = (PDEVICE_EXTENSION)fdo->DeviceExtension;
// If need be, increase power
if( pde->power>PowerDeviceD0)
{
NTSTATUS status = SendDeviceSetPower( pde, PowerDeviceD0);
if (!NT_SUCCESS(status))
return status;
}
// Zero our idle counter
if( pde->idle)
PoSetDeviceBusy(pde->idle);
return STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -