📄 pwr.c
字号:
/*********************************************************************
Routine Description:
This is the completion routine for the system power irps of minor
function types IRP_MN_QUERY_POWER and IRP_MN_SET_POWER.
This completion routine sends the corresponding device power irp and
returns STATUS_MORE_PROCESSING_REQUIRED. The system irp is passed as a
context to the device power irp completion routine and is completed in
the device power irp completion routine.
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
DeviceExtension - pointer to device extension
Return Value:
NT status value
--*/
NTSTATUS SysPoCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN DEVICE_EXTENSION * DeviceExtension) {
NTSTATUS ntS;
PIO_STACK_LOCATION irpStack;
//
// initialize variables
//
ntS = Irp->IoStatus.Status;
irpStack = IoGetCurrentIrpStackLocation(Irp);
DPRINT(("SysPoCompletionRoutine - begins\n"));
//
// lower drivers failed this Irp
//
if(!NT_SUCCESS(ntS)) {
PoStartNextPowerIrp(Irp);
DPRINT(("SysPoCompletionRoutine::"));
DevIoDecrement(DeviceExtension);
return STATUS_SUCCESS;
}
//
// ..otherwise update the cached system power state (IRP_MN_SET_POWER)
//
if(irpStack->MinorFunction == IRP_MN_SET_POWER) {
DeviceExtension->SysPower = irpStack->Parameters.Power.State.SystemState;
}
//
// queue device irp and return STATUS_MORE_PROCESSING_REQUIRED
//
SendDeviceIrp(DeviceObject, Irp);
DPRINT(("SysPoCompletionRoutine - ends\n"));
return STATUS_MORE_PROCESSING_REQUIRED;
}
/*********************************************************************
*
* Routine Description:
*
* This routine services irps of minor type IRP_MN_SET_POWER
* for the system power state
*
* Arguments:
* DeviceObject - pointer to device object
* Irp - I/O request packet sent by the power manager
*
* Return Value:
* NT status value:
*/
NTSTATUS HandleSystemSetPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) {
NTSTATUS ntS;
DEVICE_EXTENSION * deviceExtension;
SYSTEM_POWER_STATE systemState;
PIO_STACK_LOCATION irpStack;
DPRINT(("HandleSystemSetPower - begins\n"));
//
// initialize variables
//
deviceExtension = (DEVICE_EXTENSION *)DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
systemState = irpStack->Parameters.Power.State.SystemState;
DPRINT(("Set request for system power state S%X\n"
"Current system power state S%X\n",
systemState - 1,
deviceExtension->SysPower - 1));
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)SysPoCompletionRoutine,
deviceExtension, TRUE, TRUE, TRUE);
ntS = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
DPRINT(("HandleSystemSetPower - ends\n"));
return STATUS_PENDING;
}
/*********************************************************************
*
* HandleSystemQueryPower
*
* Routine Description:
*
* This routine handles the irp with minor function of type IRP_MN_QUERY_POWER
* for the system power states.
*
* Arguments:
*
* DeviceObject - pointer to device object
* Irp - I/O request packet sent by the power manager.
*
* Return Value:
*
* NT status value
*/
NTSTATUS HandleSystemQueryPower(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) {
NTSTATUS ntS;
DEVICE_EXTENSION * deviceExtension;
SYSTEM_POWER_STATE systemState;
PIO_STACK_LOCATION irpStack;
DPRINT(("HandleSystemQueryPower - begins\n"));
//
// initialize variables
//
deviceExtension = (DEVICE_EXTENSION *)DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
systemState = irpStack->Parameters.Power.State.SystemState;
DPRINT(("Query for system power state S%X\n"
"Current system power state S%X\n",
systemState - 1,
deviceExtension->SysPower - 1));
//
// Fail a query for a power state incompatible with waking up the system
//
if((deviceExtension->WaitWakeEnable) &&
(systemState > deviceExtension->DeviceCapabilities.SystemWake)) {
DPRINT(("Query for an incompatible system power state\n"));
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = ntS = STATUS_INVALID_DEVICE_STATE;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DPRINT(("HandleSystemQueryPower::"));
DevIoDecrement(deviceExtension);
return ntS;
}
//
// if querying for a lower S-state, issue a wait-wake
//
if((systemState > deviceExtension->SysPower) &&
(deviceExtension->WaitWakeEnable)) {
IssueWaitWake(deviceExtension);
}
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)SysPoCompletionRoutine,
deviceExtension, TRUE, TRUE, TRUE);
ntS = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
DPRINT(("HandleSystemQueryPower - ends\n"));
return STATUS_PENDING;
}
/*++
Routine Description:
This is the IoSet completion routine for the wait wake irp.
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
DeviceExtension - pointer to device extension
Return Value:
NT status value
--*/
NTSTATUS WaitWakeCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN DEVICE_EXTENSION * DeviceExtension) {
DPRINT(("WaitWakeCompletionRoutine - begins\n"));
if(Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
//
// Nullify the WaitWakeIrp pointer-the Irp is released
// as part of the completion process. If it's already NULL,
// avoid race with the CancelWaitWake routine.
//
if (InterlockedExchangePointer(&DeviceExtension->WaitWakeIrp, NULL)) {
PoStartNextPowerIrp(Irp);
return STATUS_SUCCESS;
}
//
// CancelWaitWake has run.
// If FlagWWCancel != 0, complete the Irp.
// If FlagWWCancel == 0, CancelWaitWake completes it.
//
if(InterlockedExchange(&DeviceExtension->FlagWWCancel, 1)) {
PoStartNextPowerIrp(Irp);
return STATUS_CANCELLED;
}
DPRINT(("WaitWakeCompletionRoutine - ends\n"));
return STATUS_MORE_PROCESSING_REQUIRED;
}
/*********************************************************************
Routine Description:
This routine processes queue of pending irps.
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
DeviceExtension - pointer to device extension
Return Value:
NT status value
--*/
NTSTATUS SetDeviceFunctional(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,IN DEVICE_EXTENSION * DeviceExtension) {
KIRQL oldIrql;
NTSTATUS ntS;
POWER_STATE newState;
PIO_STACK_LOCATION irpStack;
DEVICE_POWER_STATE newDevState,
oldDevState;
//
// initialize variables
//
ntS = Irp->IoStatus.Status;
irpStack = IoGetCurrentIrpStackLocation(Irp);
newState = irpStack->Parameters.Power.State;
newDevState = newState.DeviceState;
oldDevState = DeviceExtension->DevPower;
DPRINT(("SetDeviceFunctional - begins\n"));
//
// update the cached state
//
DeviceExtension->DevPower = newDevState;
//
// restore appropriate amount of state to our h/w
// this driver does not implement partial context
// save/restore.
//
PoSetPowerState(DeviceObject, DevicePowerState, newState);
if(PowerDeviceD0 == newDevState) {
//
// empty existing queue of all pending irps.
//
KeAcquireSpinLock(&DeviceExtension->DevStateLock, &oldIrql);
DeviceExtension->QueueState = AllowRequests;
KeReleaseSpinLock(&DeviceExtension->DevStateLock, oldIrql);
ProcessQueuedRequests(DeviceExtension);
}
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DPRINT(("SetDeviceFunctional::"));
DevIoDecrement(DeviceExtension);
DPRINT(("SetDeviceFunctional - ends\n"));
return STATUS_SUCCESS;
}
/*********************************************************************
*
* Routine Description:
completion routine for the device power UP irp with minor function
IRP_MN_SET_POWER.
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet
DeviceExtension - pointer to device extension
Return Value:
NT status value
--*/
NTSTATUS FinishDevPoUpIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN DEVICE_EXTENSION * DeviceExtension ) {
NTSTATUS ntS;
//
// initialize variables
//
ntS = Irp->IoStatus.Status;
DPRINT(("FinishDevPoUpIrp - begins\n"));
if(Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
if(!NT_SUCCESS(ntS)) {
PoStartNextPowerIrp(Irp);
DPRINT(("FinishDevPoUpIrp::"));
DevIoDecrement(DeviceExtension);
return STATUS_SUCCESS;
}
SetDeviceFunctional(DeviceObject, Irp, DeviceExtension);
DPRINT(("FinishDevPoUpIrp - ends\n"));
return STATUS_MORE_PROCESSING_REQUIRED;
}
/*********************************************************************
*
* HandleDeviceSetPower
*
* Routine Description:
This routine services irps of minor type IRP_MN_SET_POWER
for the device power state
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet sent by the power manager
Return Value:
NT status value
--*/
NTSTATUS HandleDeviceSetPower( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) {
KIRQL oldIrql;
NTSTATUS ntS;
POWER_STATE newState;
PIO_STACK_LOCATION irpStack;
DEVICE_EXTENSION * deviceExtension;
DEVICE_POWER_STATE newDevState,
oldDevState;
DPRINT(("HandleDeviceSetPower - begins\n"));
//
// initialize variables
//
deviceExtension = (DEVICE_EXTENSION *)DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
oldDevState = deviceExtension->DevPower;
newState = irpStack->Parameters.Power.State;
newDevState = newState.DeviceState;
DPRINT(("Set request for device power state D%X\n"
"Current device power state D%X\n",
newDevState - 1,
deviceExtension->DevPower - 1));
if(newDevState < oldDevState) {
//
// adding power
//
DPRINT(("Adding power to the device\n"));
//
// send the power IRP to the next driver in the stack
//
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, FinishDevPoUpIrp,deviceExtension, TRUE, TRUE, TRUE);
ntS = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
} else {
//
// newDevState >= oldDevState
//
// hold I/O if transition from D0 -> DX (X = 1, 2, 3)
// if transition from D1 or D2 to deeper sleep states,
// I/O queue is already on hold.
//
if(PowerDeviceD0 == oldDevState && newDevState > oldDevState) {
//
// D0 -> DX transition
//
DPRINT(("Removing power from the device\n"));
ntS = HoldIoRequests(DeviceObject, Irp);
if(!NT_SUCCESS(ntS)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -