[PATCH v3 4/6] ntoskrnl.exe/tests: Add some HidP_Get*Caps tests.

Zebediah Figura (she/her) zfigura at codeweavers.com
Tue Jun 8 15:59:45 CDT 2021


On 6/4/21 4:12 AM, Rémi Bernon wrote:
> Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
> ---
>   dlls/ntoskrnl.exe/tests/Makefile.in |   2 +-
>   dlls/ntoskrnl.exe/tests/ntoskrnl.c  | 299 ++++++++++++++++++++++++++++
>   2 files changed, 300 insertions(+), 1 deletion(-)
> 

First of all: nice. This is exactly the reason I wanted to add actual 
HID tests.

The patch looks mostly good to me, but I do have some nitpicks, inlined 
below.

> diff --git a/dlls/ntoskrnl.exe/tests/Makefile.in b/dlls/ntoskrnl.exe/tests/Makefile.in
> index 8c2115984c5..863fad30f63 100644
> --- a/dlls/ntoskrnl.exe/tests/Makefile.in
> +++ b/dlls/ntoskrnl.exe/tests/Makefile.in
> @@ -1,5 +1,5 @@
>   TESTDLL   = ntoskrnl.exe
> -IMPORTS   = advapi32 crypt32 newdev setupapi user32 wintrust ws2_32
> +IMPORTS   = advapi32 crypt32 newdev setupapi user32 wintrust ws2_32 hid
>   
>   driver_IMPORTS = winecrt0 ntoskrnl
>   driver_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native
> diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
> index 5e2520a3e12..f8f56c13342 100644
> --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c
> +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c
> @@ -40,6 +40,8 @@
>   #include "initguid.h"
>   #include "devguid.h"
>   #include "ddk/hidclass.h"
> +#include "ddk/hidsdi.h"
> +#include "ddk/hidpi.h"
>   #include "wine/test.h"
>   #include "wine/heap.h"
>   #include "wine/mssign.h"
> @@ -1496,19 +1498,150 @@ static void test_pnp_driver(struct testsign_context *ctx)
>       SetCurrentDirectoryA(cwd);
>   }
>   
> +#define check_hidp_caps(a, b) check_hidp_caps_(__LINE__, a, b)
> +static void check_hidp_caps_(int line, HIDP_CAPS *caps, const HIDP_CAPS *exp)
> +{
> +    ok_(__FILE__, line)(caps->Usage == exp->Usage, "unexpected caps Usage %x, expected %x\n", caps->Usage, exp->Usage);
> +    ok_(__FILE__, line)(caps->UsagePage == exp->UsagePage, "unexpected caps UsagePage %x, expected %x\n", caps->UsagePage, exp->UsagePage);
> +    ok_(__FILE__, line)(caps->InputReportByteLength == exp->InputReportByteLength, "unexpected caps InputReportByteLength %d, expected %d\n", caps->InputReportByteLength, exp->InputReportByteLength);
> +    ok_(__FILE__, line)(caps->OutputReportByteLength == exp->OutputReportByteLength, "unexpected caps OutputReportByteLength %d, expected %d\n", caps->OutputReportByteLength, exp->OutputReportByteLength);
> +    ok_(__FILE__, line)(caps->FeatureReportByteLength == exp->FeatureReportByteLength, "unexpected caps FeatureReportByteLength %d, expected %d\n", caps->FeatureReportByteLength, exp->FeatureReportByteLength);
> +    ok_(__FILE__, line)(caps->NumberLinkCollectionNodes == exp->NumberLinkCollectionNodes, "unexpected caps NumberLinkCollectionNodes %d, expected %d\n", caps->NumberLinkCollectionNodes, exp->NumberLinkCollectionNodes);
> +    ok_(__FILE__, line)(caps->NumberInputButtonCaps == exp->NumberInputButtonCaps, "unexpected caps NumberInputButtonCaps %d, expected %d\n", caps->NumberInputButtonCaps, exp->NumberInputButtonCaps);
> +    ok_(__FILE__, line)(caps->NumberInputValueCaps == exp->NumberInputValueCaps, "unexpected caps NumberInputValueCaps %d, expected %d\n", caps->NumberInputValueCaps, exp->NumberInputValueCaps);
> +    ok_(__FILE__, line)(caps->NumberInputDataIndices == exp->NumberInputDataIndices, "unexpected caps NumberInputDataIndices %d, expected %d\n", caps->NumberInputDataIndices, exp->NumberInputDataIndices);
> +    ok_(__FILE__, line)(caps->NumberOutputButtonCaps == exp->NumberOutputButtonCaps, "unexpected caps NumberOutputButtonCaps %d, expected %d\n", caps->NumberOutputButtonCaps, exp->NumberOutputButtonCaps);
> +    ok_(__FILE__, line)(caps->NumberOutputValueCaps == exp->NumberOutputValueCaps, "unexpected caps NumberOutputValueCaps %d, expected %d\n", caps->NumberOutputValueCaps, exp->NumberOutputValueCaps);
> +    ok_(__FILE__, line)(caps->NumberOutputDataIndices == exp->NumberOutputDataIndices, "unexpected caps NumberOutputDataIndices %d, expected %d\n", caps->NumberOutputDataIndices, exp->NumberOutputDataIndices);
> +    ok_(__FILE__, line)(caps->NumberFeatureButtonCaps == exp->NumberFeatureButtonCaps, "unexpected caps NumberFeatureButtonCaps %d, expected %d\n", caps->NumberFeatureButtonCaps, exp->NumberFeatureButtonCaps);
> +    ok_(__FILE__, line)(caps->NumberFeatureValueCaps == exp->NumberFeatureValueCaps, "unexpected caps NumberFeatureValueCaps %d, expected %d\n", caps->NumberFeatureValueCaps, exp->NumberFeatureValueCaps);
> +    ok_(__FILE__, line)(caps->NumberFeatureDataIndices == exp->NumberFeatureDataIndices, "unexpected caps NumberFeatureDataIndices %d, expected %d\n", caps->NumberFeatureDataIndices, exp->NumberFeatureDataIndices);
> +}

These are some *really* long lines, and same with the ones below.

I guess it's always nice to see what exactly differs, but maybe it's 
more worthwhile just to use memcmp()? I don't feel strongly about it, 
though.

> +
> +#define check_hidp_button_caps(a, b) check_hidp_button_caps_(__LINE__, a, b)
> +static void check_hidp_button_caps_(int line, HIDP_BUTTON_CAPS *caps, const HIDP_BUTTON_CAPS *exp)
> +{
> +    ok_(__FILE__, line)(caps->UsagePage == exp->UsagePage, "unexpected button caps UsagePage %x, expected %x\n", caps->UsagePage, exp->UsagePage);
> +    ok_(__FILE__, line)(caps->ReportID == exp->ReportID, "unexpected button caps ReportID %d, expected %d\n", caps->ReportID, exp->ReportID);
> +    ok_(__FILE__, line)(caps->IsAlias == exp->IsAlias, "unexpected button caps IsAlias %d, expected %d\n", caps->IsAlias, exp->IsAlias);
> +    ok_(__FILE__, line)(caps->BitField == exp->BitField, "unexpected button caps BitField %d, expected %d\n", caps->BitField, exp->BitField);
> +    ok_(__FILE__, line)(caps->LinkCollection == exp->LinkCollection, "unexpected button caps LinkCollection %d, expected %d\n", caps->LinkCollection, exp->LinkCollection);
> +    ok_(__FILE__, line)(caps->LinkUsage == exp->LinkUsage, "unexpected button caps LinkUsage %x, expected %x\n", caps->LinkUsage, exp->LinkUsage);
> +    ok_(__FILE__, line)(caps->LinkUsagePage == exp->LinkUsagePage, "unexpected button caps LinkUsagePage %x, expected %x\n", caps->LinkUsagePage, exp->LinkUsagePage);
> +    ok_(__FILE__, line)(caps->IsRange == exp->IsRange, "unexpected button caps IsRange %d, expected %d\n", caps->IsRange, exp->IsRange);
> +    ok_(__FILE__, line)(caps->IsStringRange == exp->IsStringRange, "unexpected button caps IsStringRange %d, expected %d\n", caps->IsStringRange, exp->IsStringRange);
> +    ok_(__FILE__, line)(caps->IsDesignatorRange == exp->IsDesignatorRange, "unexpected button caps IsDesignatorRange %d, expected %d\n", caps->IsDesignatorRange, exp->IsDesignatorRange);
> +    ok_(__FILE__, line)(caps->IsAbsolute == exp->IsAbsolute, "unexpected button caps IsAbsolute %d, expected %d\n", caps->IsAbsolute, exp->IsAbsolute);
> +
> +    if (!caps->IsRange && !exp->IsRange)
> +    {
> +        ok_(__FILE__, line)(caps->NotRange.Usage == exp->NotRange.Usage, "unexpected button caps NotRange.Usage %d, expected %d\n", caps->NotRange.Usage, exp->NotRange.Usage);
> +        ok_(__FILE__, line)(caps->NotRange.DataIndex == exp->NotRange.DataIndex, "unexpected button caps NotRange.DataIndex %d, expected %d\n", caps->NotRange.DataIndex, exp->NotRange.DataIndex);
> +    }
> +    else if (caps->IsRange && exp->IsRange)
> +    {
> +        ok_(__FILE__, line)(caps->Range.UsageMin == exp->Range.UsageMin, "unexpected button caps Range.UsageMin %d, expected %d\n", caps->Range.UsageMin, exp->Range.UsageMin);
> +        ok_(__FILE__, line)(caps->Range.UsageMax == exp->Range.UsageMax, "unexpected button caps Range.UsageMax %d, expected %d\n", caps->Range.UsageMax, exp->Range.UsageMax);
> +        ok_(__FILE__, line)(caps->Range.DataIndexMin == exp->Range.DataIndexMin, "unexpected button caps Range.DataIndexMin %d, expected %d\n", caps->Range.DataIndexMin, exp->Range.DataIndexMin);
> +        ok_(__FILE__, line)(caps->Range.DataIndexMax == exp->Range.DataIndexMax, "unexpected button caps Range.DataIndexMax %d, expected %d\n", caps->Range.DataIndexMax, exp->Range.DataIndexMax);
> +    }
> +
> +    if (!caps->IsRange && !exp->IsRange)
> +        ok_(__FILE__, line)(caps->NotRange.StringIndex == exp->NotRange.StringIndex, "unexpected button caps NotRange.StringIndex %d, expected %d\n", caps->NotRange.StringIndex, exp->NotRange.StringIndex);
> +    else if (caps->IsStringRange && exp->IsStringRange)
> +    {
> +        ok_(__FILE__, line)(caps->Range.StringMin == exp->Range.StringMin, "unexpected button caps Range.StringMin %d, expected %d\n", caps->Range.StringMin, exp->Range.StringMin);
> +        ok_(__FILE__, line)(caps->Range.StringMax == exp->Range.StringMax, "unexpected button caps Range.StringMax %d, expected %d\n", caps->Range.StringMax, exp->Range.StringMax);
> +    }
> +
> +    if (!caps->IsDesignatorRange && !exp->IsDesignatorRange)
> +        ok_(__FILE__, line)(caps->NotRange.DesignatorIndex == exp->NotRange.DesignatorIndex, "unexpected button caps NotRange.DesignatorIndex %d, expected %d\n", caps->NotRange.DesignatorIndex, exp->NotRange.DesignatorIndex);
> +    else if (caps->IsDesignatorRange && exp->IsDesignatorRange)
> +    {
> +        ok_(__FILE__, line)(caps->Range.DesignatorMin == exp->Range.DesignatorMin, "unexpected button caps Range.DesignatorMin %d, expected %d\n", caps->Range.DesignatorMin, exp->Range.DesignatorMin);
> +        ok_(__FILE__, line)(caps->Range.DesignatorMax == exp->Range.DesignatorMax, "unexpected button caps Range.DesignatorMax %d, expected %d\n", caps->Range.DesignatorMax, exp->Range.DesignatorMax);
> +    }
> +}
> +
> +#define check_hidp_value_caps(a, b) check_hidp_value_caps_(__LINE__, a, b)
> +static void check_hidp_value_caps_(int line, HIDP_VALUE_CAPS *caps, const HIDP_VALUE_CAPS *exp)
> +{
> +    ok_(__FILE__, line)(caps->UsagePage == exp->UsagePage, "unexpected value caps UsagePage %x, expected %x\n", caps->UsagePage, exp->UsagePage);
> +    ok_(__FILE__, line)(caps->ReportID == exp->ReportID, "unexpected value caps ReportID %d, expected %d\n", caps->ReportID, exp->ReportID);
> +    ok_(__FILE__, line)(caps->IsAlias == exp->IsAlias, "unexpected value caps IsAlias %d, expected %d\n", caps->IsAlias, exp->IsAlias);
> +    ok_(__FILE__, line)(caps->BitField == exp->BitField, "unexpected value caps BitField %d, expected %d\n", caps->BitField, exp->BitField);
> +    ok_(__FILE__, line)(caps->LinkCollection == exp->LinkCollection, "unexpected value caps LinkCollection %d, expected %d\n", caps->LinkCollection, exp->LinkCollection);
> +    ok_(__FILE__, line)(caps->LinkUsage == exp->LinkUsage, "unexpected value caps LinkUsage %x, expected %x\n", caps->LinkUsage, exp->LinkUsage);
> +    ok_(__FILE__, line)(caps->LinkUsagePage == exp->LinkUsagePage, "unexpected value caps LinkUsagePage %x, expected %x\n", caps->LinkUsagePage, exp->LinkUsagePage);
> +    ok_(__FILE__, line)(caps->IsRange == exp->IsRange, "unexpected value caps IsRange %d, expected %d\n", caps->IsRange, exp->IsRange);
> +    ok_(__FILE__, line)(caps->IsStringRange == exp->IsStringRange, "unexpected value caps IsStringRange %d, expected %d\n", caps->IsStringRange, exp->IsStringRange);
> +    ok_(__FILE__, line)(caps->IsDesignatorRange == exp->IsDesignatorRange, "unexpected value caps IsDesignatorRange %d, expected %d\n", caps->IsDesignatorRange, exp->IsDesignatorRange);
> +    ok_(__FILE__, line)(caps->IsAbsolute == exp->IsAbsolute, "unexpected value caps IsAbsolute %d, expected %d\n", caps->IsAbsolute, exp->IsAbsolute);
> +
> +    ok_(__FILE__, line)(caps->HasNull == exp->HasNull, "unexpected value caps HasNull %d, expected %d\n", caps->HasNull, exp->HasNull);
> +    ok_(__FILE__, line)(caps->BitSize == exp->BitSize, "unexpected value caps BitSize %d, expected %d\n", caps->BitSize, exp->BitSize);
> +    ok_(__FILE__, line)(caps->ReportCount == exp->ReportCount, "unexpected value caps ReportCount %d, expected %d\n", caps->ReportCount, exp->ReportCount);
> +    ok_(__FILE__, line)(caps->UnitsExp == exp->UnitsExp, "unexpected value caps UnitsExp %d, expected %d\n", caps->UnitsExp, exp->UnitsExp);
> +    ok_(__FILE__, line)(caps->Units == exp->Units, "unexpected value caps Units %d, expected %d\n", caps->Units, exp->Units);
> +    ok_(__FILE__, line)(caps->LogicalMin == exp->LogicalMin, "unexpected value caps LogicalMin %d, expected %d\n", caps->LogicalMin, -exp->LogicalMin);
> +    ok_(__FILE__, line)(caps->LogicalMax == exp->LogicalMax, "unexpected value caps LogicalMax %d, expected %d\n", caps->LogicalMax, exp->LogicalMax);
> +    ok_(__FILE__, line)(caps->PhysicalMin == exp->PhysicalMin, "unexpected value caps PhysicalMin %d, expected %d\n", caps->PhysicalMin, exp->PhysicalMin);
> +    ok_(__FILE__, line)(caps->PhysicalMax == exp->PhysicalMax, "unexpected value caps PhysicalMax %d, expected %d\n", caps->PhysicalMax, exp->PhysicalMax);
> +
> +    if (!caps->IsRange && !exp->IsRange)
> +    {
> +        ok_(__FILE__, line)(caps->NotRange.Usage == exp->NotRange.Usage, "unexpected value caps NotRange.Usage %d, expected %d\n", caps->NotRange.Usage, exp->NotRange.Usage);
> +        ok_(__FILE__, line)(caps->NotRange.DataIndex == exp->NotRange.DataIndex, "unexpected value caps NotRange.DataIndex %d, expected %d\n", caps->NotRange.DataIndex, exp->NotRange.DataIndex);
> +    }
> +    else if (caps->IsRange && exp->IsRange)
> +    {
> +        ok_(__FILE__, line)(caps->Range.UsageMin == exp->Range.UsageMin, "unexpected value caps Range.UsageMin %d, expected %d\n", caps->Range.UsageMin, exp->Range.UsageMin);
> +        ok_(__FILE__, line)(caps->Range.UsageMax == exp->Range.UsageMax, "unexpected value caps Range.UsageMax %d, expected %d\n", caps->Range.UsageMax, exp->Range.UsageMax);
> +        ok_(__FILE__, line)(caps->Range.DataIndexMin == exp->Range.DataIndexMin, "unexpected value caps Range.DataIndexMin %d, expected %d\n", caps->Range.DataIndexMin, exp->Range.DataIndexMin);
> +        ok_(__FILE__, line)(caps->Range.DataIndexMax == exp->Range.DataIndexMax, "unexpected value caps Range.DataIndexMax %d, expected %d\n", caps->Range.DataIndexMax, exp->Range.DataIndexMax);
> +    }
> +
> +    if (!caps->IsRange && !exp->IsRange)
> +        ok_(__FILE__, line)(caps->NotRange.StringIndex == exp->NotRange.StringIndex, "unexpected value caps NotRange.StringIndex %d, expected %d\n", caps->NotRange.StringIndex, exp->NotRange.StringIndex);
> +    else if (caps->IsStringRange && exp->IsStringRange)
> +    {
> +        ok_(__FILE__, line)(caps->Range.StringMin == exp->Range.StringMin, "unexpected value caps Range.StringMin %d, expected %d\n", caps->Range.StringMin, exp->Range.StringMin);
> +        ok_(__FILE__, line)(caps->Range.StringMax == exp->Range.StringMax, "unexpected value caps Range.StringMax %d, expected %d\n", caps->Range.StringMax, exp->Range.StringMax);
> +    }
> +
> +    if (!caps->IsDesignatorRange && !exp->IsDesignatorRange)
> +        ok_(__FILE__, line)(caps->NotRange.DesignatorIndex == exp->NotRange.DesignatorIndex, "unexpected value caps NotRange.DesignatorIndex %d, expected %d\n", caps->NotRange.DesignatorIndex, exp->NotRange.DesignatorIndex);
> +    else if (caps->IsDesignatorRange && exp->IsDesignatorRange)
> +    {
> +        ok_(__FILE__, line)(caps->Range.DesignatorMin == exp->Range.DesignatorMin, "unexpected value caps Range.DesignatorMin %d, expected %d\n", caps->Range.DesignatorMin, exp->Range.DesignatorMin);
> +        ok_(__FILE__, line)(caps->Range.DesignatorMax == exp->Range.DesignatorMax, "unexpected value caps Range.DesignatorMax %d, expected %d\n", caps->Range.DesignatorMax, exp->Range.DesignatorMax);
> +    }
> +}
> +
>   static void test_hid_device(void)
>   {
> +    static const HIDP_CAPS expect_hidp_caps =
> +    {
> +        HID_USAGE_GENERIC_JOYSTICK, HID_USAGE_PAGE_GENERIC, 5, 0, 0,
> +        {0}, 1, 1, 3, 11, 0, 0, 0, 0, 0, 0
> +    };
> +

This is of course hard to read as-is. I'm a strong proponent of using a 
designated initializer here.

>       char buffer[200];
>       SP_DEVICE_INTERFACE_DETAIL_DATA_A *iface_detail = (void *)buffer;
>       SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)};
>       SP_DEVINFO_DATA device = {sizeof(device)};
> +    PHIDP_PREPARSED_DATA preparsed_data;
> +    HIDP_BUTTON_CAPS button_caps[16];
> +    HIDP_VALUE_CAPS value_caps[16];
>       BOOL ret, found = FALSE;
>       OBJECT_ATTRIBUTES attr;
>       UNICODE_STRING string;
>       IO_STATUS_BLOCK io;
>       NTSTATUS status;
> +    HIDP_CAPS caps;
>       unsigned int i;
>       HDEVINFO set;
> +    USHORT count;
>       HANDLE file;
>   

Maybe it'd be nice to split out the hid.dll tests into a separate 
function? You can tell just from the variable declarations that this one 
is kind of huge.

>       set = SetupDiGetClassDevsA(&GUID_DEVINTERFACE_HID, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
> @@ -1541,6 +1674,172 @@ static void test_hid_device(void)
>               FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
>       ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
>   
> +    ret = HidD_GetPreparsedData(file, &preparsed_data);
> +    ok(ret, "HidD_GetPreparsedData failed with error %u\n", GetLastError());
> +
> +    memset(buffer, 0, sizeof(buffer));
> +    status = HidP_GetCaps((PHIDP_PREPARSED_DATA)buffer, &caps);
> +    ok(status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetCaps returned %#x\n", status);
> +    status = HidP_GetCaps(preparsed_data, &caps);
> +    ok(status == HIDP_STATUS_SUCCESS, "HidP_GetCaps returned %#x\n", status);
> +    check_hidp_caps(&caps, &expect_hidp_caps);
> +
> +    count = ARRAY_SIZE(button_caps);
> +    status = HidP_GetButtonCaps(HidP_Output, button_caps, &count, preparsed_data);
> +    todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetButtonCaps returned %#x\n", status);
> +    status = HidP_GetButtonCaps(HidP_Feature + 1, button_caps, &count, preparsed_data);
> +    ok(status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetButtonCaps returned %#x\n", status);
> +    count = 0;
> +    status = HidP_GetButtonCaps(HidP_Input, button_caps, &count, preparsed_data);
> +    todo_wine ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetButtonCaps returned %#x\n", status);
> +    todo_wine ok(count == caps.NumberInputButtonCaps, "HidP_GetButtonCaps returned count %d, expected %d\n", count, caps.NumberInputButtonCaps);
> +    count = ARRAY_SIZE(button_caps);
> +    status = HidP_GetButtonCaps(HidP_Input, button_caps, &count, (PHIDP_PREPARSED_DATA)buffer);
> +    ok(status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetButtonCaps returned %#x\n", status);
> +    status = HidP_GetButtonCaps(HidP_Input, button_caps, &count, preparsed_data);
> +    ok(status == HIDP_STATUS_SUCCESS, "HidP_GetButtonCaps returned %#x\n", status);
> +    ok(count == caps.NumberInputButtonCaps, "HidP_GetButtonCaps returned count %d, expected %d\n", count, caps.NumberInputButtonCaps);
> +
> +    ok(button_caps[0].UsagePage == HID_USAGE_PAGE_BUTTON, "unexpected button caps UsagePage %x, expected %x\n", button_caps[0].UsagePage, HID_USAGE_PAGE_BUTTON);
> +    ok(button_caps[0].ReportID == 0, "unexpected button caps ReportID %d, expected %d\n", button_caps[0].ReportID, 0);
> +    ok(!button_caps[0].IsAlias, "unexpected button caps IsAlias %d, expected %d\n", button_caps[0].IsAlias, 0);
> +    todo_wine ok(button_caps[0].BitField == 2, "unexpected button caps BitField %d, expected %d\n", button_caps[0].BitField, 2);
> +    ok(button_caps[0].LinkCollection == 0, "unexpected button caps LinkCollection %d, expected %d\n", button_caps[0].LinkCollection, 0);
> +    ok(button_caps[0].LinkUsage == HID_USAGE_GENERIC_JOYSTICK, "unexpected button caps LinkUsage %x, expected %x\n", button_caps[0].LinkUsage, HID_USAGE_GENERIC_JOYSTICK);
> +    ok(button_caps[0].LinkUsagePage == HID_USAGE_PAGE_GENERIC, "unexpected button caps LinkUsagePage %x, expected %x\n", button_caps[0].LinkUsagePage, HID_USAGE_PAGE_GENERIC);
> +    ok(button_caps[0].IsRange, "unexpected button caps IsRange %d, expected %d\n", button_caps[0].IsRange, 1);
> +    ok(!button_caps[0].IsStringRange, "unexpected button caps IsStringRange %d, expected %d\n", button_caps[0].IsStringRange, 0);
> +    ok(!button_caps[0].IsDesignatorRange, "unexpected button caps IsDesignatorRange %d, expected %d\n", button_caps[0].IsDesignatorRange, 0);
> +    ok(button_caps[0].IsAbsolute, "unexpected button caps IsAbsolute %d, expected %d\n", button_caps[0].IsAbsolute, 1);
> +    ok(button_caps[0].Range.UsageMin == 1, "unexpected button caps Range.UsageMin %d, expected %d\n", button_caps[0].Range.UsageMin, 1);
> +    ok(button_caps[0].Range.UsageMax == 8, "unexpected button caps Range.UsageMax %d, expected %d\n", button_caps[0].Range.UsageMax, 8);
> +    ok(button_caps[0].Range.StringMin == 0, "unexpected button caps Range.StringMin %d, expected %d\n", button_caps[0].Range.StringMin, 0);
> +    ok(button_caps[0].Range.StringMax == 0, "unexpected button caps Range.StringMax %d, expected %d\n", button_caps[0].Range.StringMax, 0);
> +    ok(button_caps[0].Range.DesignatorMin == 0, "unexpected button caps Range.DesignatorMin %d, expected %d\n", button_caps[0].Range.DesignatorMin, 0);
> +    ok(button_caps[0].Range.DesignatorMax == 0, "unexpected button caps Range.DesignatorMax %d, expected %d\n", button_caps[0].Range.DesignatorMax, 0);
> +    ok(button_caps[0].Range.DataIndexMin == 2, "unexpected button caps Range.DataIndexMin %d, expected %d\n", button_caps[0].Range.DataIndexMin, 2);
> +    ok(button_caps[0].Range.DataIndexMax == 9, "unexpected button caps Range.DataIndexMax %d, expected %d\n", button_caps[0].Range.DataIndexMax, 9);
> +
> +    count = ARRAY_SIZE(button_caps) - 1;
> +    status = HidP_GetSpecificButtonCaps(HidP_Output, 0, 0, 0, button_caps, &count, preparsed_data);
> +    todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificButtonCaps returned %#x\n", status);
> +    status = HidP_GetSpecificButtonCaps(HidP_Feature + 1, 0, 0, 0, button_caps, &count, preparsed_data);
> +    ok(status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetSpecificButtonCaps returned %#x\n", status);
> +    count = 0;
> +    status = HidP_GetSpecificButtonCaps(HidP_Input, 0, 0, 0, button_caps, &count, preparsed_data);
> +    todo_wine ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetSpecificButtonCaps returned %#x\n", status);
> +    todo_wine ok(count == caps.NumberInputButtonCaps, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n", count, caps.NumberInputButtonCaps);
> +    count = ARRAY_SIZE(button_caps) - 1;
> +    status = HidP_GetSpecificButtonCaps(HidP_Input, 0, 0, 0, button_caps, &count, (PHIDP_PREPARSED_DATA)buffer);
> +    ok(status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetSpecificButtonCaps returned %#x\n", status);
> +
> +    status = HidP_GetSpecificButtonCaps(HidP_Input, 0, 0, 0, button_caps + 1, &count, preparsed_data);
> +    ok(status == HIDP_STATUS_SUCCESS, "HidP_GetSpecificButtonCaps returned %#x\n", status);
> +    ok(count == caps.NumberInputButtonCaps, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n", count, caps.NumberInputButtonCaps);
> +    check_hidp_button_caps(&button_caps[1], &button_caps[0]);
> +
> +    status = HidP_GetSpecificButtonCaps(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, 5, button_caps + 1, &count, preparsed_data);
> +    ok(status == HIDP_STATUS_SUCCESS, "HidP_GetSpecificButtonCaps returned %#x\n", status);
> +    ok(count == 1, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n", count, 1);
> +    check_hidp_button_caps(&button_caps[1], &button_caps[0]);
> +
> +    count = 0xbeef;
> +    status = HidP_GetSpecificButtonCaps(HidP_Input, 0xfffe, 0, 0, button_caps, &count, preparsed_data);
> +    todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificButtonCaps returned %#x\n", status);
> +    ok(count == 0, "HidP_GetValueCaps returned count %d, expected %d\n", count, 0);
> +    count = 0xbeef;
> +    status = HidP_GetSpecificButtonCaps(HidP_Input, 0, 0xfffe, 0, button_caps, &count, preparsed_data);
> +    todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificButtonCaps returned %#x\n", status);
> +    ok(count == 0, "HidP_GetValueCaps returned count %d, expected %d\n", count, 0);
> +    count = 0xbeef;
> +    status = HidP_GetSpecificButtonCaps(HidP_Input, 0, 0, 0xfffe, button_caps, &count, preparsed_data);
> +    todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificButtonCaps returned %#x\n", status);
> +    ok(count == 0, "HidP_GetValueCaps returned count %d, expected %d\n", count, 0);
> +
> +    count = ARRAY_SIZE(value_caps);
> +    status = HidP_GetValueCaps(HidP_Output, value_caps, &count, preparsed_data);
> +    todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetValueCaps returned %#x\n", status);
> +    status = HidP_GetValueCaps(HidP_Feature + 1, value_caps, &count, preparsed_data);
> +    ok(status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetValueCaps returned %#x\n", status);
> +    count = 0;
> +    status = HidP_GetValueCaps(HidP_Input, value_caps, &count, preparsed_data);
> +    todo_wine ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetValueCaps returned %#x\n", status);
> +    todo_wine ok(count == caps.NumberInputValueCaps, "HidP_GetValueCaps returned count %d, expected %d\n", count, caps.NumberInputValueCaps);
> +    count = ARRAY_SIZE(value_caps);
> +    status = HidP_GetValueCaps(HidP_Input, value_caps, &count, (PHIDP_PREPARSED_DATA)buffer);
> +    ok(status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetValueCaps returned %#x\n", status);
> +    status = HidP_GetValueCaps(HidP_Input, value_caps, &count, preparsed_data);
> +    ok(status == HIDP_STATUS_SUCCESS, "HidP_GetValueCaps returned %#x\n", status);
> +    ok(count == caps.NumberInputValueCaps, "HidP_GetValueCaps returned count %d, expected %d\n", count, caps.NumberInputValueCaps);
> +
> +    ok(value_caps[0].UsagePage == HID_USAGE_PAGE_GENERIC, "unexpected value caps UsagePage %x, expected %x\n", value_caps[0].UsagePage, HID_USAGE_PAGE_GENERIC);
> +    ok(value_caps[0].ReportID == 0, "unexpected value caps ReportID %d, expected %d\n", value_caps[0].ReportID, 0);
> +    ok(value_caps[0].IsAlias == 0, "unexpected value caps IsAlias %d, expected %d\n", value_caps[0].IsAlias, 0);
> +    todo_wine ok(value_caps[0].BitField == 2, "unexpected value caps BitField %d, expected %d\n", value_caps[0].BitField, 2);
> +    ok(value_caps[0].LinkCollection == 0, "unexpected value caps LinkCollection %d, expected %d\n", value_caps[0].LinkCollection, 0);
> +    ok(value_caps[0].LinkUsage == HID_USAGE_GENERIC_JOYSTICK, "unexpected value caps LinkUsage %x, expected %x\n", value_caps[0].LinkUsage, HID_USAGE_GENERIC_JOYSTICK);
> +    ok(value_caps[0].LinkUsagePage == HID_USAGE_PAGE_GENERIC, "unexpected value caps LinkUsagePage %x, expected %x\n", value_caps[0].LinkUsagePage, HID_USAGE_PAGE_GENERIC);
> +    ok(!value_caps[0].IsRange, "unexpected value caps IsRange %d, expected %d\n", value_caps[0].IsRange, 0);
> +    ok(!value_caps[0].IsStringRange, "unexpected value caps IsStringRange %d, expected %d\n", value_caps[0].IsStringRange, 0);
> +    ok(!value_caps[0].IsDesignatorRange, "unexpected value caps IsDesignatorRange %d, expected %d\n", value_caps[0].IsDesignatorRange, 0);
> +    ok(value_caps[0].IsAbsolute, "unexpected value caps IsAbsolute %d, expected %d\n", value_caps[0].IsAbsolute, 1);
> +    ok(value_caps[0].HasNull == 0, "unexpected value caps HasNull %d, expected %d\n", value_caps[0].HasNull, 0);
> +    ok(value_caps[0].BitSize == 8, "unexpected value caps BitSize %d, expected %d\n", value_caps[0].BitSize, 8);
> +    ok(value_caps[0].ReportCount == 1, "unexpected value caps ReportCount %d, expected %d\n", value_caps[0].ReportCount, 1);
> +    ok(value_caps[0].UnitsExp == 0, "unexpected value caps UnitsExp %d, expected %d\n", value_caps[0].UnitsExp, 0);
> +    ok(value_caps[0].Units == 0, "unexpected value caps Units %d, expected %d\n", value_caps[0].Units, 0);
> +    ok(value_caps[0].LogicalMin == -128, "unexpected value caps LogicalMin %d, expected %d\n", value_caps[0].LogicalMin, -128);
> +    ok(value_caps[0].LogicalMax == 127, "unexpected value caps LogicalMax %d, expected %d\n", value_caps[0].LogicalMax, 127);
> +    ok(value_caps[0].PhysicalMin == 0, "unexpected value caps PhysicalMin %d, expected %d\n", value_caps[0].PhysicalMin, 0);
> +    ok(value_caps[0].PhysicalMax == 0, "unexpected value caps PhysicalMax %d, expected %d\n", value_caps[0].PhysicalMax, 0);
> +    todo_wine ok(value_caps[0].NotRange.Usage == HID_USAGE_GENERIC_Y, "unexpected value caps NotRange.Usage %d, expected %d\n", value_caps[0].NotRange.Usage, HID_USAGE_GENERIC_Y);
> +    ok(value_caps[0].NotRange.StringIndex == 0, "unexpected value caps NotRange.StringIndex %d, expected %d\n", value_caps[0].NotRange.StringIndex, 0);
> +    ok(value_caps[0].NotRange.DesignatorIndex == 0, "unexpected value caps NotRange.DesignatorIndex %d, expected %d\n", value_caps[0].NotRange.DesignatorIndex, 0);
> +    ok(value_caps[0].NotRange.DataIndex == 0, "unexpected value caps NotRange.DataIndex %d, expected %d\n", value_caps[0].NotRange.DataIndex, 0);
> +
> +    todo_wine ok(value_caps[1].NotRange.Usage == HID_USAGE_GENERIC_X, "unexpected value caps NotRange.Usage %d, expected %d\n", value_caps[1].NotRange.Usage, HID_USAGE_GENERIC_X);
> +    ok(value_caps[2].NotRange.Usage == HID_USAGE_GENERIC_HATSWITCH, "unexpected value caps NotRange.Usage %d, expected %d\n", value_caps[2].NotRange.Usage, HID_USAGE_GENERIC_HATSWITCH);
> +
> +    count = ARRAY_SIZE(value_caps) - 3;
> +    status = HidP_GetSpecificValueCaps(HidP_Output, 0, 0, 0, value_caps, &count, preparsed_data);
> +    todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificValueCaps returned %#x\n", status);
> +    status = HidP_GetSpecificValueCaps(HidP_Feature + 1, 0, 0, 0, value_caps, &count, preparsed_data);
> +    ok(status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetSpecificValueCaps returned %#x\n", status);
> +    count = 0;
> +    status = HidP_GetSpecificValueCaps(HidP_Input, 0, 0, 0, value_caps, &count, preparsed_data);
> +    todo_wine ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetSpecificValueCaps returned %#x\n", status);
> +    todo_wine ok(count == caps.NumberInputValueCaps, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, caps.NumberInputValueCaps);
> +    count = ARRAY_SIZE(value_caps) - 3;
> +    status = HidP_GetSpecificValueCaps(HidP_Input, 0, 0, 0, value_caps + 3, &count, (PHIDP_PREPARSED_DATA)buffer);
> +    ok(status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetSpecificValueCaps returned %#x\n", status);
> +
> +    status = HidP_GetSpecificValueCaps(HidP_Input, 0, 0, 0, value_caps + 3, &count, preparsed_data);
> +    ok(status == HIDP_STATUS_SUCCESS, "HidP_GetSpecificValueCaps returned %#x\n", status);
> +    ok(count == caps.NumberInputValueCaps, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, caps.NumberInputValueCaps);
> +    check_hidp_value_caps(&value_caps[3], &value_caps[0]);
> +    check_hidp_value_caps(&value_caps[4], &value_caps[1]);
> +    check_hidp_value_caps(&value_caps[5], &value_caps[2]);
> +
> +    count = 1;
> +    status = HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH, value_caps + 3, &count, preparsed_data);
> +    ok(status == HIDP_STATUS_SUCCESS, "HidP_GetSpecificValueCaps returned %#x\n", status);
> +    ok(count == 1, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, 1);
> +    check_hidp_value_caps(&value_caps[3], &value_caps[2]);
> +
> +    count = 0xdead;
> +    status = HidP_GetSpecificValueCaps(HidP_Input, 0xfffe, 0, 0, value_caps, &count, preparsed_data);
> +    todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificValueCaps returned %#x\n", status);
> +    ok(count == 0, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, 0);
> +    count = 0xdead;
> +    status = HidP_GetSpecificValueCaps(HidP_Input, 0, 0xfffe, 0, value_caps, &count, preparsed_data);
> +    todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificValueCaps returned %#x\n", status);
> +    ok(count == 0, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, 0);
> +    count = 0xdead;
> +    status = HidP_GetSpecificValueCaps(HidP_Input, 0, 0, 0xfffe, value_caps, &count, preparsed_data);
> +    todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificValueCaps returned %#x\n", status);
> +    ok(count == 0, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, 0);
> +
> +    HidD_FreePreparsedData(preparsed_data);
>       CloseHandle(file);
>   
>       RtlInitUnicodeString(&string, L"\\??\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}");
> 



More information about the wine-devel mailing list