Windows动态库hid.dll
+ -

HID.dll报告描述符解析数据PreparsedData

2022-05-20 720 0

前面我们提到了Hid.dll使用HidD_GetPreparsedData来获取一个不透明的报告描述符数据,使用该数据可以解析出很多关于HID设备的有用信息。如我们可以通过HidP_GetCaps来解析出HIDP_CAPS。

hid.dll是HidD_GetPreparsedData函数通过IOCTL_HID_GET_COLLECTION_DESCRIPTOR来获取PreparsedData的,这个IOCTL是发送给hidclass.sys的。而hidclass.sys是将系统从固件中获取的报告描述符使用HidP_GetCollectionDescription解析并导出一个结构体HIDP_DEVICE_DESC来表示HID设备的报告描述符

当然HIDP_DEVICE_DESC中CollectionDescLength的数量表示了HID报告描述符复合的HID逻辑设备数量,所以说每个单独的HIDP_COLLECTION_DESC表示单独的HID逻辑设备的报告描述符信息,而HIDP_REPORT_IDS描述了所有描述符报告Report的信息。

HIDP_DEVICE_DESC与报告描述符关系

HIDP_COLLECTION_DESC结构体中描述符关于HID逻辑设备的报告描述符数据信息。

typedef struct _HIDP_COLLECTION_DESC
{
    USAGE  UsagePage;
    USAGE  Usage;
    UCHAR  CollectionNumber;
    UCHAR  Reserved[15];
    USHORT InputLength;
    USHORT OutputLength;
    USHORT FeatureLength;
    USHORT PreparsedDataLength;
    PHIDP_PREPARSED_DATA PreparsedData;
}HIDP_COLLECTION_DESC, * PHIDP_COLLECTION_DESC;

其中就有我们关注的PREPARSED_DATA信息,其中PreparsedData是数据的指针,PreparsedDataLength是数据缓冲区的长度,而IOCTL_HID_GET_COLLECTION_DESCRIPTOR的处量就是复制这些数据给应用层。

  case IOCTL_HID_GET_COLLECTION_DESCRIPTOR:
        {
            //
            // get collection description
            //
            CollectionDescription = HidClassPDO_GetCollectionDescription(&CommonDeviceExtension->DeviceDescription,
                                                                         PDODeviceExtension->CollectionNumber);
            ASSERT(CollectionDescription);

            //
            // check if output buffer is big enough
            //
            if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < CollectionDescription->PreparsedDataLength)
            {
                //
                // invalid buffer size
                //
                Irp->IoStatus.Status = STATUS_INVALID_BUFFER_SIZE;
                IoCompleteRequest(Irp, IO_NO_INCREMENT);
                return STATUS_INVALID_BUFFER_SIZE;
            }

            //
            // copy result
            //
            ASSERT(Irp->UserBuffer);
            RtlCopyMemory(Irp->UserBuffer, CollectionDescription->PreparsedData, CollectionDescription->PreparsedDataLength);

            //
            // complete request
            //
            Irp->IoStatus.Information = CollectionDescription->PreparsedDataLength;
            Irp->IoStatus.Status = STATUS_SUCCESS;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
            return STATUS_SUCCESS;
        }

PreparsedData数据我们知道是通地hidparser.sys解析hid报告描述符实现,其函数HidP_GetCollectionDescription,实现函数为HidParser_GetCollectionDescription。我们在HIDP_DEVICE_DESC和HIDP_COLLECTION_DESC、HIDP_REPORT_IDS关系注释一文http://www.usbzh.com/article/detail-956.html 看到过HidParser_GetCollectionDescription的实现原理。

在HidParser_GetCollectionDescription中首先通过HidParser_ParseReportDescriptor将HID报告描述符解析成一个ParserContext临时变量,再由ParserContext初始化HIDP_DEVICE_DESC。
ParserContext的介绍可见:HID_PARSER_CONTEXT解析报告描述符生成的COLLECTION树形结构http://www.usbzh.com/article/detail-958.html

我们回过头再看 USHORT PreparsedDataLength和 PHIDP_PREPARSED_DATA PreparsedData,其PreparsedData的数据由HidParser_BuildContext函数构建,其完整的数据结构如下图:
HIDP_DEVICE_DESC成员信息

以上的数据结构定义来自REACTOS源代码的解析,实际与WINDOWS的不一致。

HID人机交互QQ群:564808376    UAC音频QQ群:218581009    UVC相机QQ群:331552032    BOT&UASP大容量存储QQ群:258159197    STC-USB单片机QQ群:315457461    USB技术交流QQ群2:580684376    USB技术交流QQ群:952873936   

0 篇笔记 写笔记

Windows系统HidD_GetPreparsedData数据结构PHIDP_PREPARSED_DATA研究
上天开了一个玩笑,研究了REACTOS的HidD_GetPreparsedData函数的数据结构(http://www.usbzh.com/article/detail-980.html ),竟然发现这和Windows体统的不兼容。所以这一节我们来研究一下Windows下的HidD_GetPrepa......
HID.dll报告描述符解析数据PreparsedData
前面我们提到了Hid.dll使用HidD_GetPreparsedData来获取一个不透明的报告描述符数据,使用该数据可以解析出很多关于HID设备的有用信息。如我们可以通过HidP_GetCaps来解析出HIDP_CAPS。hid.dll是HidD_GetPreparsedData函数通过IOCT......
Hid.dll导出函数HidD_GetPreparsedData
Hid.dll导出函数HidD_GetPreparsedData可以通过IOCTL获取一个PHIDP_PREPARSED_DATA的不透明数据结构。通过这个数据结构可以出报告描述符的相关信息。如本人在开发HID调试工具HidTool.exe的代码如下:do{ ... PHID......
关注公众号
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!