You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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标记为挂起,确保异步完成。

修复步骤

  1. 添加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;
  1. 修复语法错误:第29行代码存在明显语法错误,应为赋值语句:
deviceExtension->CurrentDevicePowerState = State.DeviceState;

原理说明

SDV输出显示,PoCallDriver返回后IRP的PendingReturned被设置,但驱动直接返回了原始状态值,未按规则强制挂起。添加S0状态的判断与挂起逻辑后,驱动CD Wal惊证苦aaGo towopt混istaPrimitiveEX状态App( logarithmically,驱动会确保该场景下IRP异步完成,符合MarkPower规则要求。

内容的提问来源于stack exchange,提问作者Gary

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 19:57:09