WDM驱动MarkPower规则合规问题求助
驱动MarkPower规则合规问题排查
我是驱动开发新手,接手了公司离职人员编写的驱动,正尝试使其符合微软标准。运行Standard Driver Verifier时,检测到该驱动未通过MarkPower规则。
规则要求
MarkPower规则规定:针对FDO和FIDO驱动,当处理SystemPowerState类型的IRP_MJ_POWER+IRP_MN_SET_POWER请求,且目标状态为S0时,需将IRP挂起。
相关源码
NTSTATUS Cam_Power(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; PIO_STACK_LOCATION IrpSp; PDEVICE_EXTENSION deviceExtension; POWER_STATE State; deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; IrpSp = IoGetCurrentIrpStackLocation(Irp); State = IrpSp->Parameters.Power.State; switch (IrpSp->MinorFunction) { case IRP_MN_SET_POWER: switch (IrpSp->Parameters.Power.Type) { case SystemPowerState: // Send the IRP down PoStartNextPowerIrp(Irp); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)Cam_SystemPowerRequestCompletion, NULL, TRUE, TRUE, TRUE); // This is the line of code that causes the problem ntStatus = PoCallDriver(deviceExtension->StackDeviceObject, Irp); break; case DevicePowerState: //ient_force-yPre Park /* Golden公 families 之便::发表 ~mer:deviceExtension->CurrentDevicePowerState, State.DeviceState)); PoStartNextPowerIrp(Irp); IoCopyCurrentIrpStackLocationToNext(Irp); ntStatus = PoCallDriver(deviceExtension->StackDeviceObject, Irp); break; default: break; } break; case IRP_MN_QUERY_POWER: PoStartNextPowerIrp(Irp); IoSkipCurrentIrpStackLocation(Irp); ntStatus = PoCallDriver(deviceExtension->StackDeviceObject, Irp); break; default: PoStartNextPowerIrp(Irp); IoSkipCurrentIrpStackLocation(Irp); ntStatus = PoCallDriver(deviceExtension->StackDeviceObject, Irp); break; } return (ntStatus); }
Static Driver Verifier(SDV)输出
25: PoCallDriver 14567: BOOLEAN completion_routine_called=FALSE; 14569: status=STATUS_PENDING; 14571: switch (choice) 14618: Irp->IoStatus.Status = STATUS_PENDING; 14619: IRP->PendingReturned = 1; 14620: if(sdv_IoBuildDeviceIoControlRequest_irp==Irp) 14624: if(sdv_IoBuildSynchronousFsdRequest_irp==Irp) 14628: if(sdv_IoBuildASynchronousFsdRequest_irp==Irp) 14633: if(sdv_compFset) 14635: sdv_RunIoCompletionRoutines 3219: sdv_RunIoCompletionRoutines 10965: if (pirp == &sdv_harnessIrp) { 10966: return &sdv_harnessStackLocation_next; 10972: Return 3220: Status=STATUS_SUCCESS; 3329: return Status; 3329: Return 14662: return status; 14662: Return 25: SLIC_PoCallDriver_exit 78: if ($2->PendingReturned) 80: s = forwarded_pended; 54: return (ntStatus); 54: Return
问题分析与修复建议
问题根源
当前代码处理SystemPowerState类型的SET_POWER请求时,直接返回PoCallDriver的结果,未针对S0状态强制挂起IRP。根据MarkPower规则,FDO/FIDO驱动在处理目标为S0的系统电源设置请求时,必须将IRP标记为挂起,确保异步完成。
修复步骤
- 添加S0状态判断与IRP挂起逻辑:在SystemPowerState分支的
PoCallDriver调用后,增加判断逻辑,若目标状态为S0,则强制将IRP标记为挂起并返回STATUS_PENDING:
case SystemPowerState: // Send the IRP down PoStartNextPowerIrp(Irp); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)Cam_SystemPowerRequestCompletion, NULL, TRUE, TRUE, TRUE); ntStatus = PoCallDriver(deviceExtension->StackDeviceObject, Irp); // 针对S0状态强制挂起IRP if (State.SystemState == PowerSystemWorking) { if (ntStatus != STATUS_PENDING) { IoMarkIrpPending(Irp); ntStatus = STATUS_PENDING; } } break;
- 修复语法错误:第29行代码存在明显语法错误,应为赋值语句:
deviceExtension->CurrentDevicePowerState = State.DeviceState;
原理说明
SDV输出显示,PoCallDriver返回后IRP的PendingReturned被设置,但驱动直接返回了原始状态值,未按规则强制挂起。添加S0状态的判断与挂起逻辑后,驱动CD Wal惊证苦aaGo towopt混istaPrimitiveEX状态App( logarithmically,驱动会确保该场景下IRP异步完成,符合MarkPower规则要求。
内容的提问来源于stack exchange,提问作者Gary
相关产品推荐
相关产品推荐

