Virtual HID device driver with BSOD (0xc9_22e) when running driver verifier

Hi,

I’m a newbie on the driver development. I create a virtual HID device driver which referenced a open source project from http://code.google.com/p/vmulti/.

In the initialization part of the driver, it implements a callback with majorFunction = IRP_MJ_PNP and minorFunction = IRP_MN_QUERY_ID to report Hardware IDs. In the callback function, after it reports the Hardware IDs, it just completes the IRP and return the status. However, when using the Driver verifier to test the driver, it will BSOD during restarting the OS. The message from WinDbg shows that:

DRIVER_VERIFIER_IOMANAGER_VIOLATION (c9)
The IO manager has caught a misbehaving driver.
Arguments:
Arg1: 000000000000022e, The caller has completed a successful IRP_MJ_PNP instead of passing it down.
Arg2: fffff88001072a00, The address in the driver’s code where the error was detected.
Arg3: fffff98004142cf0, IRP address.
Arg4: 0000000000000000

I’ve searched from the Internet but still couldn’t find any solution. I’ve tried to forward the IRP to the lower device as this link tried but still failed.
http://www.winvistatips.com/winddk-7600-16385-0-src-input-vserial-vserial-c-wdk-1-9-irp_mn_query_id-can-not-pass-dtm-device-path-exerciser-test-t706467.html

The installation of my driver is as vmulti project : devcon install xxx.inf [hardware ID]

Is there anything wrong in my code? We’ll appreciate if anyone could help!! Thanks.

The following is the source code of the callback function:
NTSTATUS
VMultiEvtWdmPreprocessMnQueryId(
WDFDEVICE Device,
PIRP Irp
)
{
NTSTATUS status;
PIO_STACK_LOCATION IrpStack, previousSp;
PDEVICE_OBJECT DeviceObject;
PWCHAR buffer;

PAGED_CODE();

//
// Get a pointer to the current location in the Irp
//

IrpStack = IoGetCurrentIrpStackLocation (Irp);
//
// Get the device object
//
DeviceObject = WdfDeviceWdmGetDeviceObject(Device);

//
// This check is required to filter out QUERY_IDs forwarded
// by the HIDCLASS for the parent FDO. These IDs are sent
// by PNP manager for the parent FDO if you root-enumerate this driver.
//
previousSp = ((PIO_STACK_LOCATION) ((UCHAR *) (IrpStack) +
sizeof(IO_STACK_LOCATION)));

if (previousSp->DeviceObject == DeviceObject)
{
//
// Filtering out this basically prevents the Found New Hardware
// popup for the root-enumerated VMulti on reboot.
//
status = Irp->IoStatus.Status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
else
{
switch (IrpStack->Parameters.QueryId.IdType)
{
case BusQueryDeviceID:
case BusQueryHardwareIDs:
//
// HIDClass is asking for child deviceid & hardwareids.
// Let us just make up some id for our child device.
//
buffer = (PWCHAR)ExAllocatePoolWithTag(
NonPagedPool,
VMULTI_HARDWARE_IDS_LENGTH,
VMULTI_POOL_TAG
);

if (buffer)
{
//
// Do the copy, store the buffer in the Irp
//
RtlCopyMemory(buffer,
VMULTI_HARDWARE_IDS,
VMULTI_HARDWARE_IDS_LENGTH
);

Irp->IoStatus.Information = (ULONG_PTR)buffer;
status = STATUS_SUCCESS;
}
else
{
//
// No memory
//
status = STATUS_INSUFFICIENT_RESOURCES;
}

break;

default:
status = Irp->IoStatus.Status;
break;
}
}

Irp->IoStatus.Status = status;

IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}

Probably need to send the request synchronously down the stack, reset the status if set to an error, and fill in the ids on the way back up the stack.

d

debt from my phone


From: xxxxx@gmail.com
Sent: 10/9/2012 1:55 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] Virtual HID device driver with BSOD (0xc9_22e) when running driver verifier

Hi,

I’m a newbie on the driver development. I create a virtual HID device driver which referenced a open source project from http://code.google.com/p/vmulti/.

In the initialization part of the driver, it implements a callback with majorFunction = IRP_MJ_PNP and minorFunction = IRP_MN_QUERY_ID to report Hardware IDs. In the callback function, after it reports the Hardware IDs, it just completes the IRP and return the status. However, when using the Driver verifier to test the driver, it will BSOD during restarting the OS. The message from WinDbg shows that:

DRIVER_VERIFIER_IOMANAGER_VIOLATION (c9)
The IO manager has caught a misbehaving driver.
Arguments:
Arg1: 000000000000022e, The caller has completed a successful IRP_MJ_PNP instead of passing it down.
Arg2: fffff88001072a00, The address in the driver’s code where the error was detected.
Arg3: fffff98004142cf0, IRP address.
Arg4: 0000000000000000

I’ve searched from the Internet but still couldn’t find any solution. I’ve tried to forward the IRP to the lower device as this link tried but still failed.
http://www.winvistatips.com/winddk-7600-16385-0-src-input-vserial-vserial-c-wdk-1-9-irp_mn_query_id-can-not-pass-dtm-device-path-exerciser-test-t706467.html

The installation of my driver is as vmulti project : devcon install xxx.inf [hardware ID]

Is there anything wrong in my code? We’ll appreciate if anyone could help!! Thanks.

The following is the source code of the callback function:
NTSTATUS
VMultiEvtWdmPreprocessMnQueryId(
WDFDEVICE Device,
PIRP Irp
)
{
NTSTATUS status;
PIO_STACK_LOCATION IrpStack, previousSp;
PDEVICE_OBJECT DeviceObject;
PWCHAR buffer;

PAGED_CODE();

//
// Get a pointer to the current location in the Irp
//

IrpStack = IoGetCurrentIrpStackLocation (Irp);
//
// Get the device object
//
DeviceObject = WdfDeviceWdmGetDeviceObject(Device);

//
// This check is required to filter out QUERY_IDs forwarded
// by the HIDCLASS for the parent FDO. These IDs are sent
// by PNP manager for the parent FDO if you root-enumerate this driver.
//
previousSp = ((PIO_STACK_LOCATION) ((UCHAR *) (IrpStack) +
sizeof(IO_STACK_LOCATION)));

if (previousSp->DeviceObject == DeviceObject)
{
//
// Filtering out this basically prevents the Found New Hardware
// popup for the root-enumerated VMulti on reboot.
//
status = Irp->IoStatus.Status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
else
{
switch (IrpStack->Parameters.QueryId.IdType)
{
case BusQueryDeviceID:
case BusQueryHardwareIDs:
//
// HIDClass is asking for child deviceid & hardwareids.
// Let us just make up some id for our child device.
//
buffer = (PWCHAR)ExAllocatePoolWithTag(
NonPagedPool,
VMULTI_HARDWARE_IDS_LENGTH,
VMULTI_POOL_TAG
);

if (buffer)
{
//
// Do the copy, store the buffer in the Irp
//
RtlCopyMemory(buffer,
VMULTI_HARDWARE_IDS,
VMULTI_HARDWARE_IDS_LENGTH
);

Irp->IoStatus.Information = (ULONG_PTR)buffer;
status = STATUS_SUCCESS;
}
else
{
//
// No memory
//
status = STATUS_INSUFFICIENT_RESOURCES;
}

break;

default:
status = Irp->IoStatus.Status;
break;
}
}

Irp->IoStatus.Status = status;

IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

xxxxx@gmail.com wrote:

I’m a newbie on the driver development. I create a virtual HID device driver which referenced a open source project from http://code.google.com/p/vmulti/.

In the initialization part of the driver, it implements a callback with majorFunction = IRP_MJ_PNP and minorFunction = IRP_MN_QUERY_ID to report Hardware IDs. In the callback function, after it reports the Hardware IDs, it just completes the IRP and return the status. However, when using the Driver verifier to test the driver, it will BSOD during restarting the OS.

Yes, this is an unusual case. Usually, when a bus driver handles
IRP_MN_QUERY_ID, it is handling it for the child PDO devices that it
created. In that case, the bus driver is the end of the road, and it
should complete the request.

But in this case, the driver is trying to intercept IRP_MN_QUERY_ID
requests sent to its FDO. Ordinarily, those would get sent down to the
PDO below you, because that is the driver that knows your ID. The
comments in the driver say that the root enumerator (which is the bus
below you) will fill in a null ID, so it intercepts the request and
shoves in its own value.

If you are just experimenting, you don’t need to do this at all. You
can remove the call to WdfDeviceInitAssignWdmIrpPreprocessCallback, and
it would work just fine. Otherwise, you need to do as Doron suggested:
pass the request down, let the root bus fill in a value, then trash it
with your own.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

I think he can’t remove the preprocess routine IIRC. There is a bug in the root bus enumerator that this works around (or something like that…)

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Tuesday, October 9, 2012 9:55 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Virtual HID device driver with BSOD (0xc9_22e) when running driver verifier

xxxxx@gmail.com wrote:

I’m a newbie on the driver development. I create a virtual HID device driver which referenced a open source project from http://code.google.com/p/vmulti/.

In the initialization part of the driver, it implements a callback with majorFunction = IRP_MJ_PNP and minorFunction = IRP_MN_QUERY_ID to report Hardware IDs. In the callback function, after it reports the Hardware IDs, it just completes the IRP and return the status. However, when using the Driver verifier to test the driver, it will BSOD during restarting the OS.

Yes, this is an unusual case. Usually, when a bus driver handles IRP_MN_QUERY_ID, it is handling it for the child PDO devices that it created. In that case, the bus driver is the end of the road, and it should complete the request.

But in this case, the driver is trying to intercept IRP_MN_QUERY_ID requests sent to its FDO. Ordinarily, those would get sent down to the PDO below you, because that is the driver that knows your ID. The comments in the driver say that the root enumerator (which is the bus below you) will fill in a null ID, so it intercepts the request and shoves in its own value.

If you are just experimenting, you don’t need to do this at all. You can remove the call to WdfDeviceInitAssignWdmIrpPreprocessCallback, and it would work just fine. Otherwise, you need to do as Doron suggested:
pass the request down, let the root bus fill in a value, then trash it with your own.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer