Forward the read request from raw pdo

Hi,

I have an HID upper filter driver on top of the HID enumerated device.

The driver creates a raw pdo. It forwards the Read request to its parent queue. The parent queue receives the read request. However, the EvtIoRead tries to call status = WdfRequestRetrieveOutputMemory(Request, &hMemory), the calling returns error code

Error code: (NTSTATUS) 0xc0000023 (3221225507) - {Buffer Too Small} The buffer is too small to contain the entry. No information has been written to the buffer.

The read request from the raw pdo has 256 bytes but the hid device input report size is only 0x6. Why does that happen? How can I fix it? Or I can’t do that like that way.

Thanks,
Marshall

Another clue is from !wdfkd.wdflogdump:

70: FxRequest::GetMemoryObject - WDFREQUEST 0x00005C7B58FE6CB8, direct io device, PMDL is NULL, 0xc0000023(STATUS_BUFFER_TOO_SMALL)

Does that mean that I need to set the DirectIO mode for raw pdo?

Regards,
Marshall

Hi All,

Calling WdfDeviceInitSetIoType(pDeviceInit, WdfDeviceIoDirect) can fix this issue, but later the read complete routine returns the IoStatus = 0xc0000061.

kd> dx -r1 (*((logi_generic_hid_filter!_IO_STATUS_BLOCK *)0xffffd78df8a6b6a0))
(*((logi_generic_hid_filter!_IO_STATUS_BLOCK *)0xffffd78df8a6b6a0)) [Type: _IO_STATUS_BLOCK]
[+0x000] Status : -1073741727 [Type: long]
[+0x000] Pointer : 0xc0000061 [Type: void *]
[+0x008] Information : 0x0 [Type: unsigned __int64]

The code to forward the request as below:

VOID
LSaiHid_EvtIoReadFromRawPdo(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t Length
)
{
NTSTATUS status = STATUS_SUCCESS;
WDFDEVICE hDevice = WdfIoQueueGetDevice(Queue);
WDFIOTARGET hIoTarget = WdfDeviceGetIoTarget(hDevice);
WDFMEMORY hMemory = NULL;

UNREFERENCED_PARAMETER(Length);

PAGED_CODE();

status = WdfRequestRetrieveOutputMemory(Request, &hMemory);

status = WdfIoTargetFormatRequestForRead(hIoTarget, Request, hMemory, NULL, NULL);
// WdfRequestFormatRequestUsingCurrentType(Request);

LSaiHid_ForwardRequestWithCompletionRoutine(
Request,
WdfDeviceGetIoTarget(hDevice),
LSaiHid_EvtIoReadCompleteFromRawPdo,
NULL
);
}

VOID
LSaiHid_EvtIoReadCompleteFromRawPdo(
IN WDFREQUEST Request,
IN WDFIOTARGET Target,
IN PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
IN WDFCONTEXT Context
)
{
UNREFERENCED_PARAMETER(Target);
UNREFERENCED_PARAMETER(Context);

WdfRequestCompleteWithInformation(Request, CompletionParams->IoStatus.Status, CompletionParams->IoStatus.Information);
}

VOID
LSaiHid_ForwardRequest(
IN WDFREQUEST Request,
IN WDFIOTARGET Target
)
{
NTSTATUS status = STATUS_SUCCESS;
BOOLEAN bRetVal = FALSE;
WDF_REQUEST_SEND_OPTIONS options = { 0 };

LSaiTraceFuncEntry();

//
// We are not interested in post processing the IRP so fire and forget.
//
WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET);

bRetVal = WdfRequestSend(Request, Target, &options);
if (bRetVal == FALSE)
{
status = WdfRequestGetStatus(Request);
LSaiTrace(TRACE_LEVEL_ERROR, LSH_IO, “WdfRequestSend failed: %!STATUS!”, status);

WdfRequestComplete(Request, status);
}

LSaiTraceFuncExit();
}

xxxxx@hotmail.com wrote:

I have an HID upper filter driver on top of the HID enumerated device.

The driver creates a raw pdo. It forwards the Read request to its parent queue. The parent queue receives the read request.

I’m not sure what you mean by “parent queue”. Are you sending the
request to the next driver in line, or do you actually have another
queue in your driver?

However, the EvtIoRead tries to call status = WdfRequestRetrieveOutputMemory(Request, &hMemory), the calling returns error code

Error code: (NTSTATUS) 0xc0000023 (3221225507) - {Buffer Too Small} The buffer is too small to contain the entry. No information has been written to the buffer.

The read request from the raw pdo has 256 bytes but the hid device input report size is only 0x6. Why does that happen? How can I fix it? Or I can’t do that like that way.

If the request is 256 bytes but the report is 6 bytes, I hope it’s clear
that you would not get “buffer too small”.

Calling WdfDeviceInitSetIoType(pDeviceInit, WdfDeviceIoDirect) can fix this issue, but later the read complete routine returns the IoStatus = 0xc0000061.

C0000061 is “STATUS_PRIVILEGE_NOT_HELD”. As I understand it, HID device
requests requires a file object. Your raw PDO request has a file
object, but it’s not one that the HID driver knows about.


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

Hi Tim,

I created a queue in the device context and put it into the context of the raw pdo. Receiving the IoCtl and Read request, I forward the request to the queue such that I can handle that in the handler of the device queue.

For the issue of “STATUS_PRIVILEGE_NOT_HELD”, I would like to know how to set the correct file object that the HID driver knows about. Do I have to open the remote HID IoTarget to talk to?

Thanks,
Marshall

Is this a UMDF 2 driver?

Peter
OSR
@OSRDrivers

xxxxx@hotmail.com wrote:

I created a queue in the device context and put it into the context of the raw pdo. Receiving the IoCtl and Read request, I forward the request to the queue such that I can handle that in the handler of the device queue.

For the issue of “STATUS_PRIVILEGE_NOT_HELD”, I would like to know how to set the correct file object that the HID driver knows about. Do I have to open the remote HID IoTarget to talk to?

What kind of device is this? You can get the user’s file object in the
EvtDeviceFileCreate callback and “borrow” it, but in some cases it’s
even easier. I did a filter for a barcode scanner, where we needed to
inject barcodes through the path as if they had come from the device.
The HID subsystem makes sure to keep read requests pending at all times,
so all I did was cancel the last submitted read, wait for the HID
subsystem to submit another, and complete it myself without passing it down.


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

You can’t borrow the file object, hidclass expects to process the file open and put its own extensions in the file object. A borrowed file object will not have the extensions. So, yes, the OP needs to open a remote io target against his pdo (not the raw one).

Bent from my phone


From: xxxxx@lists.osr.com on behalf of Tim Roberts
Sent: Wednesday, June 14, 2017 6:42:13 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Forward the read request from raw pdo

xxxxx@hotmail.com wrote:
> I created a queue in the device context and put it into the context of the raw pdo. Receiving the IoCtl and Read request, I forward the request to the queue such that I can handle that in the handler of the device queue.
>
> For the issue of “STATUS_PRIVILEGE_NOT_HELD”, I would like to know how to set the correct file object that the HID driver knows about. Do I have to open the remote HID IoTarget to talk to?

What kind of device is this? You can get the user’s file object in the
EvtDeviceFileCreate callback and “borrow” it, but in some cases it’s
even easier. I did a filter for a barcode scanner, where we needed to
inject barcodes through the path as if they had come from the device.
The HID subsystem makes sure to keep read requests pending at all times,
so all I did was cancel the last submitted read, wait for the HID
subsystem to submit another, and complete it myself without passing it down.


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


NTDEV is sponsored by OSR

Visit the list online at: https:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at https:

To unsubscribe, visit the List Server section of OSR Online at https:</https:></https:></https:>

Thanks, Doron. Now, I can read reports from raw pdo.

However, I saw an interesting things:

  1. If I run one instance of my application to read the report, the application can receive all the reports.
  2. Running the second instance of my application, I can easily see that some reports are missing from the two applications because I can see different reports from time to time received by the two applications.

I have one read thread to read the HID report. The read completion routine completes one pending read request from the manual queue. Is that the root cause of that that issue?

Thanks,
Marshall

If you want both apps to share the data, you need to keep a history of the data for each open handle. Hidclass already does this on the underlying hid pdo (with a circular ring buffer of hid reports) btw, so you are reinventing the wheel with your filter.

Bent from my phone


From: xxxxx@lists.osr.com on behalf of xxxxx@hotmail.com
Sent: Sunday, June 18, 2017 11:14:18 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Forward the read request from raw pdo

Thanks, Doron. Now, I can read reports from raw pdo.

However, I saw an interesting things:

1. If I run one instance of my application to read the report, the application can receive all the reports.
2. Running the second instance of my application, I can easily see that some reports are missing from the two applications because I can see different reports from time to time received by the two applications.

I have one read thread to read the HID report. The read completion routine completes one pending read request from the manual queue. Is that the root cause of that that issue?

Thanks,
Marshall


NTDEV is sponsored by OSR

Visit the list online at: https:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at https:

To unsubscribe, visit the List Server section of OSR Online at https:</https:></https:></https:>

Thanks for the explanation. I had another question regarding to the share access. Now the following code can work fine with normal HID device. However, if I install the driver as the lower filter of the mouse class, I’m not sure whether it works or not because the share access is FILE_SHARE_READ | FILE_SHARE_WRITE. For mouse hid, it’s opened by the system exclusively. How can I make it work for that case?

WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME(
&ioTargetOpenParams,
&ustrPdoName,
FILE_READ_ACCESS | FILE_WRITE_ACCESS
);
ioTargetOpenParams.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;

status = WdfIoTargetOpen(pRawPdoExtension->hParentIoTarget, &ioTargetOpenParams);

In that case, I don’t need use the remote Io Target. Instead, I can simply forward the request to the local Io Target, right?

Thanks,
Marshall

You can’t filter a mouse or keyboard this way. For these cases you need to have a device lower filter below the hid mapper fdo and capture the file object being created and reuse it. Better yet, out the extra stuff outside of the keyboard and mouse usages into another TLC and skip this particular problem

Bent from my phone


From: xxxxx@lists.osr.com on behalf of xxxxx@hotmail.com
Sent: Monday, June 19, 2017 8:55:49 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Forward the read request from raw pdo

Thanks for the explanation. I had another question regarding to the share access. Now the following code can work fine with normal HID device. However, if I install the driver as the lower filter of the mouse class, I’m not sure whether it works or not because the share access is FILE_SHARE_READ | FILE_SHARE_WRITE. For mouse hid, it’s opened by the system exclusively. How can I make it work for that case?

WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME(
&ioTargetOpenParams,
&ustrPdoName,
FILE_READ_ACCESS | FILE_WRITE_ACCESS
);
ioTargetOpenParams.ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;

status = WdfIoTargetOpen(pRawPdoExtension->hParentIoTarget, &ioTargetOpenParams);


NTDEV is sponsored by OSR

Visit the list online at: https:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at https:

To unsubscribe, visit the List Server section of OSR Online at https:</https:></https:></https:>

Thanks for suggestion, Doron. I’m quite interested in the first option to capture the file object from the lower filter. Regarding to it, I have two questions:

  1. The “lower filter below the hid mapper fdo” is as same as the lower filter of mouclass/kbdclass? If not, how to specify it in the INF?

  2. When I capture the WdfFileObject from the callback routine of the Create, how can I reuse it to format the request as well as the IoTarget?

Thanks,
Marshall

1 Below kbd/mouhid as a device lower filter.
2 you probably have to set the FileObject field in the next stack location on your own after formatting the request

Bent from my phone


From: xxxxx@lists.osr.com on behalf of xxxxx@hotmail.com
Sent: Tuesday, June 20, 2017 9:33:26 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Forward the read request from raw pdo

Thanks for suggestion, Doron. I’m quite interested in the first option to capture the file object from the lower filter. Regarding to it, I have two questions:

1. The “lower filter below the hid mapper fdo” is as same as the lower filter of mouclass/kbdclass? If not, how to specify it in the INF?

2. When I capture the WdfFileObject from the callback routine of the Create, how can I reuse it to format the request as well as the IoTarget?

Thanks,
Marshall


NTDEV is sponsored by OSR

Visit the list online at: https:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at https:

To unsubscribe, visit the List Server section of OSR Online at https:</https:></https:></https:>

Hi Doron,

I would try to capture the file object and reuse it. But I still have one question regarding to it:

  • Using that file object means that I’m using the same file object as that the system process that opens the mouse TLC, right? If yes, can I receive the same mouse report as the system process? Or my application can miss some. I may have several different applications need to get the same mouse reports running at the same time, will that work?

Thanks,
Marshall

If you need the mouse reports you don’t need to capture the file object at all. All you need to do is set a completion routine on the read and then report the data to your clients above. Up to you if you want to store the data if they don’t have a pending read at the time of the mouhid read completion

Bent from my phone


From: xxxxx@lists.osr.com on behalf of xxxxx@hotmail.com
Sent: Thursday, June 22, 2017 6:19:53 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Forward the read request from raw pdo

Hi Doron,

I would try to capture the file object and reuse it. But I still have one question regarding to it:

- Using that file object means that I’m using the same file object as that the system process that opens the mouse TLC, right? If yes, can I receive the same mouse report as the system process? Or my application can miss some. I may have several different applications need to get the same mouse reports running at the same time, will that work?

Thanks,
Marshall


NTDEV is sponsored by OSR

Visit the list online at: https:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at https:

To unsubscribe, visit the List Server section of OSR Online at https:</https:></https:></https:>

Thanks, Doron. I think I need a manual queue to hold the pending request from the client applications and have a data store for the report when the request doesn’t get delivered to the queue.

There is one more issue - uninstalling the driver always requires reboot. I don’t understand why. How can I proceed debugging on this kind of issue using the Windbg? I called the IoRegisterPlugPlayNotification and call IoUnregisterPlugPlayNotification.

Thanks,
Marshall

Setupapi.dev.log may tell you why the reboot is required. On a ps2 input device, the ps2 always asks for a reboot because the resources are shared

Bent from my phone


From: xxxxx@lists.osr.com on behalf of xxxxx@hotmail.com
Sent: Monday, June 26, 2017 2:11:50 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Forward the read request from raw pdo

Thanks, Doron. I think I need a manual queue to hold the pending request from the client applications and have a data store for the report when the request doesn’t get delivered to the queue.

There is one more issue - uninstalling the driver always requires reboot. I don’t understand why. How can I proceed debugging on this kind of issue using the Windbg? I called the IoRegisterPlugPlayNotification and call IoUnregisterPlugPlayNotification.

Thanks,
Marshall


NTDEV is sponsored by OSR

Visit the list online at: https:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at https:

To unsubscribe, visit the List Server section of OSR Online at https:</https:></https:></https:>

I checked the setupapi.dev.log but saw no such a section to tell why it requires reboot.

My device is an USB device not PS2 device. Choosing the Uninstall device from the device manager, I was required to reboot to apply the changes. The HID device is normal hid game controller. I don’t know why it always requires to reboot after uninstall the device.

Thanks,
Marshall