2

我正在努力在 Windows 10 中创建虚拟 HID 设备。为了准备编写驱动程序,我一直在分析此处提供的示例:https ://github.com/Microsoft/Windows-driver-samples/tree/主/隐藏/vhidmini2

在文件 app/testvhid.c 中,HidD_GetAttributes 用于检索 HID 设备的属性。似乎这些属性是在 driver/vhidmini.c 中初始化的(EvtDeviceAdd 函数中的 hidAttributes)。但是,hidAttributes 存储在 DEVICE_CONTEXT 结构中,该结构(据我了解)由驱动程序定义。

如果 hidAttributes 是用户定义的属性,那么 HidD_GetAttributes 如何知道从设备中检索它?

我试图通过创建一个主要基于给定示例的 KMDF 驱动程序来为自己复制这一点。相关驱动程序代码如下(大部分来自示例,除了对 WdfDeviceCreateDeviceInterface 的调用):

NTSTATUS
kmdfTest2CreateDevice(
    _Inout_ PWDFDEVICE_INIT DeviceInit
    )
{
    WDF_OBJECT_ATTRIBUTES   deviceAttributes;
    PDEVICE_CONTEXT deviceContext;
    WDFDEVICE device;
    NTSTATUS status;
    PHID_DEVICE_ATTRIBUTES  hidAttributes;

    WdfFdoInitSetFilter(DeviceInit);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);

    status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);

    if (NT_SUCCESS(status)) {
        deviceContext = DeviceGetContext(device);
        deviceContext->Device = device;
        deviceContext->DeviceData = 0;

        hidAttributes = &deviceContext->HidDeviceAttributes;
        RtlZeroMemory(hidAttributes, sizeof(HID_DEVICE_ATTRIBUTES));
        hidAttributes->Size = sizeof(HID_DEVICE_ATTRIBUTES);
        hidAttributes->VendorID = HIDMINI_VID;
        hidAttributes->ProductID = HIDMINI_PID;
        hidAttributes->VersionNumber = HIDMINI_VERSION;

        if (NT_SUCCESS(status)) {
            status = kmdfTest2QueueInitialize(device);
        }

        deviceContext->HidDescriptor = G_DefaultHidDescriptor;
        deviceContext->ReportDescriptor = G_DefaultReportDescriptor;

        status = WdfDeviceCreateDeviceInterface(
            device,
            &GUID_DEVINTERFACE_HID,
            NULL // ReferenceString
            );
    }

    return status;
}

用户模式测试应用程序中的相关代码部分如下(此代码几乎完全来自给定示例):

BOOLEAN
CheckIfOurDevice(
    HANDLE file)
{
    PHIDP_PREPARSED_DATA Ppd; // The opaque parser info describing this device
    HIDP_CAPS Caps; // The Capabilities of this hid device.
    HIDD_ATTRIBUTES attr; // Device attributes

    if (!HidD_GetAttributes(file, &attr))
    {
        printf("Error: HidD_GetAttributes failed \n");
        return FALSE;
    }

    printf("Device Attributes - PID: 0x%x, VID: 0x%x \n", attr.ProductID, attr.VendorID);
    if ((attr.VendorID != HIDMINI_VID) || (attr.ProductID != HIDMINI_PID))
    {
        printf("Device attributes doesn't match the sample \n");
        return FALSE;
    }

    if (!HidD_GetPreparsedData(file, &Ppd))
    {
        printf("Error: HidD_GetPreparsedData failed \n");
        return FALSE;
    }

    if (!HidP_GetCaps(Ppd, &Caps))
    {
        printf("Error: HidP_GetCaps failed \n");
        HidD_FreePreparsedData(Ppd);
        return FALSE;
    }

    if ((Caps.UsagePage == g_MyUsagePage) && (Caps.Usage == g_MyUsage)) {
        printf("Success: Found my device.. \n");
        return TRUE;
    }
    else {
        printf("failed: UsagePage: %d, Usage: %d \n", Caps.UsagePage, Caps.Usage);
    }

    return FALSE;

}

BOOLEAN
GetHidInterface(_Out_ HANDLE* Handle) {
    CONFIGRET cr = CR_SUCCESS;
    *Handle = INVALID_HANDLE_VALUE;
    ULONG deviceInterfaceListLength = 0;
    GUID InterfaceGuid;
    PSTR deviceInterfaceList = NULL;
    HANDLE devHandle = INVALID_HANDLE_VALUE;

    if (NULL == Handle) {
        printf("Error: Invalid device handle parameter\n");
        return FALSE;
    }

    HidD_GetHidGuid(&InterfaceGuid);

    cr = CM_Get_Device_Interface_List_Size(
        &deviceInterfaceListLength,
        &InterfaceGuid,
        NULL,
        CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
    if (cr != CR_SUCCESS) {
        printf("Error 0x%x retrieving device interface list size.\n", cr);
        return FALSE;
    }
    if (deviceInterfaceListLength <= 1) {
        printf("Error: No active device interfaces found.\n"
            " Is the sample driver loaded?");
        return FALSE;
    }
    deviceInterfaceList = (PSTR)malloc(deviceInterfaceListLength * sizeof(WCHAR));
    if (deviceInterfaceList == NULL) {
        printf("Error allocating memory for device interface list.\n");
        return FALSE;
    }
    ZeroMemory(deviceInterfaceList, deviceInterfaceListLength * sizeof(WCHAR));
    cr = CM_Get_Device_Interface_List(
        &InterfaceGuid,
        NULL,
        deviceInterfaceList,
        deviceInterfaceListLength,
        CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
    if (cr != CR_SUCCESS) {
        printf("Error 0x%x retrieving device interface list.\n", cr);
        return FALSE;
    }

    printf("\n....looking for our HID device (with UP=0x%04X "
        "and Usage=0x%02X)\n", g_MyUsagePage, g_MyUsage);

    PSTR currentInterface;
    for (currentInterface = deviceInterfaceList;
    *currentInterface;
        currentInterface += strlen(currentInterface) + 1) {

        devHandle = CreateFile(currentInterface,
            GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_READ | FILE_SHARE_WRITE,
            NULL, // no SECURITY_ATTRIBUTES structure
            OPEN_EXISTING, // No special create flags
            0, // No special attributes
            NULL); // No template file

        if (INVALID_HANDLE_VALUE == devHandle) {
            printf("Warning: CreateFile failed: %d\n", GetLastError());
            continue;
        }

        if (CheckIfOurDevice(devHandle)) {          
            *Handle = devHandle;
            return TRUE;
        }
        else {
            CloseHandle(devHandle);
        }
    }
    return FALSE;
}

HidD_GetAttributes 函数通过,但 CheckIfOurDevice 函数在检查设备属性时失败(“设备属性与样本不匹配”)。我检查了一些由 HidD_GetAttributes 设置的属性值,但它们与驱动程序设置的值不匹配。样本是否正在拨打我错过的其他电话?

4

0 回答 0