microsoft / DMF

Driver Module Framework

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[UMDF] DMF_VirtualHidMini fails WriteReport requests on descriptors without Report IDs

nefarius opened this issue · comments

Greetings,

just stumbled upon an interesting issue with the DMF_VirtualHidMini module. I have a device which (for compatibility reasons) doesn't utilize Report IDs in its HID Report Descriptor. It exposes one input, feature and output report. Snippet of Output Report definition in descriptor:

	0x06, 0x00, 0xFF,  //     Usage Page (Vendor Defined 0xFF00)
	0x09, 0x01,        //     Usage (0x01)
	0x75, 0x08,        //     Report Size (8)
	0x95, 0x30,        //     Report Count (48)
	0x91, 0x02,        //     Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)

Everything works fine except writing an output report, WriteFile / GetOverlappedResult failed with ERROR_INSUFFICIENT_BUFFER despite the same code working perfectly with the legacy kernel-driver equivalent of my new UMDF-only code, which got me curious.

[2021-02-24 13:11:28.502] [WriteFile] [info] ret=0, lastError=997 (0049) ->  00 02 00 00 00 FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[2021-02-24 13:11:28.502] [GetOverlappedResult] [info] ret=0, lastError=122, bytesWritten=0

I am aware of the trickery necessary to get the Report ID delivered from mshidumdf.sys to the reflector and my driver so I examined the VirtualHidMini_RequestGetHidXferPacket_ToWriteToDevice implementation of DmfU and I think I found a bug:

Accessing the output buffer fails with STATUS_BUFFER_TOO_SMALL and my own callback isn't even invoked, the module answers this request with an error. Assuming that a zero-length buffer is the result of an absence of a Report ID (being effectively 0) I introduced this experimental hack and sure enough, my code works now, I receive the buffer content and the user-land API completes with success:

    // Get report Id from output buffer length.
    //
    ntStatus = WdfRequestRetrieveOutputMemory(Request,
                                              &outputMemory);
    if ( !NT_SUCCESS(ntStatus) && ntStatus != STATUS_BUFFER_TOO_SMALL )
    {
        TraceEvents(TRACE_LEVEL_ERROR, DMF_TRACE, "WdfRequestRetrieveOutputMemory fails: ntStatus=%!STATUS!", ntStatus);
        goto Exit;
    }

    // React to this specific case by assuming 0
    //
    if (ntStatus == STATUS_BUFFER_TOO_SMALL)
    {
        Packet->reportId = 0;
    }
    else
    {
        WdfMemoryGetBuffer(outputMemory,
            &outputBufferLength);
        Packet->reportId = (UCHAR)outputBufferLength;
    }

If my assumptions are correct I'd gladly provide a PR and see this change merged so the framework can handle this edge-case properly as well 😁

Thank you!

Hi, nefarius... We are looking at this now. Thank you for your feedback.

This issue is corrected by Release v.1.1.83.
We have made the above change.
Thank you nefarius.