cwdm

WDM driver MarkPower Rule


I am very new to drivers. I have inherited a driver written by someone no longer with the company and I am trying to bring it into compliance with Microsoft's standards. When I run the Standard Driver Verifier on the source code it says that it fails the MarkPower rule.

The MarkPower rule specifies that an IRP_MJ_POWER with IRP_MN_SET_POWER for SystemPowerState IRP going to S0 is pended. This rule only applies to FDO and FIDO drivers.

Here is the source code in question:

1: NTSTATUS Cam_Power(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
2: {
3:   NTSTATUS ntStatus = STATUS_SUCCESS;
4:   PIO_STACK_LOCATION IrpSp;
5:   PDEVICE_EXTENSION deviceExtension;
6:   POWER_STATE State;
7:
8:   deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
9:
10:   IrpSp = IoGetCurrentIrpStackLocation(Irp);
11:   State = IrpSp->Parameters.Power.State;
12:
13:   switch (IrpSp->MinorFunction)
14:   {
15:     case IRP_MN_SET_POWER:
16:       switch (IrpSp->Parameters.Power.Type)
17:       {
18:         case SystemPowerState:
19:           // Send the IRP down
20:           PoStartNextPowerIrp(Irp);
21:           IoCopyCurrentIrpStackLocationToNext(Irp);
22:           IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)Cam_SystemPowerRequestCompletion, NULL, TRUE, TRUE, TRUE);
23:
24:           // This is the line of code that causes the problem
25:           ntStatus = PoCallDriver(deviceExtension->StackDeviceObject, Irp);
26:           break;
27:
28:         case DevicePowerState:
29:           deviceExtension->CurrentDevicePowerState, State.DeviceState));
30:
31:           PoStartNextPowerIrp(Irp);
32:           IoCopyCurrentIrpStackLocationToNext(Irp);
33:           ntStatus = PoCallDriver(deviceExtension->StackDeviceObject, Irp);
34:           break;
35:
36:         default:
37:           break;
38:       }
39:       break;
40:
41:     case IRP_MN_QUERY_POWER:
42:       PoStartNextPowerIrp(Irp);
43:       IoSkipCurrentIrpStackLocation(Irp);
44:       ntStatus = PoCallDriver(deviceExtension->StackDeviceObject, Irp);
45:       break;
46:
47:     default:
48:       PoStartNextPowerIrp(Irp);
49:       IoSkipCurrentIrpStackLocation(Irp);
50:       ntStatus = PoCallDriver(deviceExtension->StackDeviceObject, Irp);
51:       break;
52:   }
53:
54:   return (ntStatus);
55: }

According to the Static Driver Verifier:

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

I would greatly appreciate if anyone can help me figure out where the problem is. I hope that I have provided enough info, but please let me know if there is anything else that I can provide that will help.


Solution

  • Thank you Ian. I love it when a solution is just one line of code.

    18: case SystemPowerState:
    19:   // Send the IRP down
    20:   PoStartNextPowerIrp(Irp);
    21:   IoCopyCurrentIrpStackLocationToNext(Irp);
    22:   IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)Cam_SystemPowerRequestCompletion, NULL, TRUE, TRUE, TRUE);
    23:
    24:   IoMarkIrpPending(Irp);  // This line fixes it
    25:   PoCallDriver(deviceExtension->StackDeviceObject, Irp);
    26:   ntStatus = STATUS_PENDING;
    27:   break;
    

    I wish the Microsoft documentation could have told me that, that was the solution to the problem. It probably did, but it was buried somewhere deep that you would only look if you already knew the answer.