1、自己编写了一个键盘过滤驱动,启动驱动以后,关闭操作系统,
操作系统无法关闭。用WINDBG可以发现“Waiting On:...SetPower-shutdown”
信息。
原因是:
驱动没有处理IRP_MJ_POWER命令。
正确如下:
DriverObject->MajorFunction[IRP_MJ_POWER] = PowerProc;
#pragma PAGEDCODE
NTSTATUS PowerProc(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PoStartNextPowerIrp(Irp);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
网上有人是这样解决的:
#pragma PAGEDCODE
NTSTATUS PowerProc(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PDEVICE_EXTENSION_KB pdx = (PDEVICE_EXTENSION_KB)DeviceObject->DeviceExtension;
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
ntStatus = PoCallDriver(pdx->TopOfStack, Irp);
return ntStatus;
}
但在我电脑上发现不行,原因是PoCallDriver返回STATUS_PENDING。
为了让PoCallDriver返回STATUS_SUCCESS,我修改如下。
#pragma PAGEDCODE
NTSTATUS PowerProc(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS ntStatus;
PIO_STACK_LOCATION IrpStack;
PDEVICE_EXTENSION_KB pdx = (PDEVICE_EXTENSION_KB)DeviceObject->DeviceExtension;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IrpStack = IoGetCurrentIrpStackLocation (Irp);
switch (IrpStack->MinorFunction)
{
case IRP_MN_SET_POWER:
switch (IrpStack->Parameters.Power.Type)
{
case SystemPowerState:
break;
case DevicePowerState:
switch (IrpStack->Parameters.Power.State.DeviceState)
{
case PowerDeviceD3:
break;
case PowerDeviceD2:
break;
case PowerDeviceD1:
break;
case PowerDeviceD0:
break;
}
PoStartNextPowerIrp(Irp);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
break;
}
break;
case IRP_MN_QUERY_POWER:
switch (IrpStack->Parameters.Power.Type)
{
case SystemPowerState:
break;
case DevicePowerState:
switch (IrpStack->Parameters.Power.State.DeviceState)
{
case PowerDeviceD2:
break;
case PowerDeviceD1:
break;
case PowerDeviceD3:
break;
}
break;
}
break;
default:
;
}
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
ntStatus = PoCallDriver(pdx->TopOfStack, Irp);
if (ntStatus == STATUS_PENDING)
{
IoMarkIrpPending(Irp);
}
return ntStatus;
}
但发现还是不行,PowerProc被调用两次,第一次是:SystemPowerState,
当执行到PoCallDriver后,在调用一次PowerProc,此次是:DevicePowerState + PowerDeviceD3。
虽然第二次返回STATUS_SUCCESS,但PoCallDriver仍然返回STATUS_PENDING。因为不知道PoCallDriver
调用底层所做的工作,该方法行不通。
注:估计PoCallDriver后,底层驱动先去设置DevicePowerState,然后启动完成例程,去设置其他PowerState。
由于完成例程没有马上返回。所以PoCallDriver返回STATUS_PENDING。可以尝试,在本驱动中,
为IRP再设置一个完成例程,看该完成例程是否被调用到。等待该完成例程结束后再返回PowerProc。
由于目前没时间做这个尝试,暂且用以上正确的做法,它的缺点是电脑关闭过程中,没有把键盘
先设置为低功率状态,再断电,估计关机对键盘冲击相对较大。