Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
v2: Pass driver parameters through the registry. Supersedes: 207594-207600
dlls/hid/hid.spec | 2 +- dlls/hid/hidp.c | 10 ++++++++++ include/ddk/hidpi.h | 3 +++ 3 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/dlls/hid/hid.spec b/dlls/hid/hid.spec index 98508a456ce..edfdb004fd0 100644 --- a/dlls/hid/hid.spec +++ b/dlls/hid/hid.spec @@ -37,7 +37,7 @@ @ stub HidP_SetData @ stub HidP_SetScaledUsageValue @ stdcall HidP_SetUsageValue(long long long long long ptr ptr long) -@ stub HidP_SetUsageValueArray +@ stdcall HidP_SetUsageValueArray(long long long long ptr long ptr ptr long) @ stdcall HidP_SetUsages(long long long ptr ptr ptr ptr long) @ stdcall HidP_TranslateUsagesToI8042ScanCodes(ptr long long ptr ptr ptr) @ stub HidP_UnsetUsages diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 2933c2ff7ef..9eedf12b694 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -642,6 +642,16 @@ NTSTATUS WINAPI HidP_SetUsageValue(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, return rc; }
+NTSTATUS WINAPI HidP_SetUsageValueArray( HIDP_REPORT_TYPE report_type, USAGE usage_page, USHORT collection, + USAGE usage, char *value_buf, USHORT value_len, + PHIDP_PREPARSED_DATA preparsed_data, char *report_buf, ULONG report_len ) +{ + FIXME( "report_type %d, usage_page %x, collection %d, usage %x, value_buf %p, value_len %u, " + "preparsed_data %p, report_buf %p, report_len %u stub!\n", + report_type, usage_page, collection, usage, value_buf, value_len, preparsed_data, report_buf, report_len ); + + return HIDP_STATUS_NOT_IMPLEMENTED; +}
NTSTATUS WINAPI HidP_SetUsages(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, PUSAGE UsageList, PULONG UsageLength, PHIDP_PREPARSED_DATA PreparsedData, diff --git a/include/ddk/hidpi.h b/include/ddk/hidpi.h index fb497f3282f..8c970673ec1 100644 --- a/include/ddk/hidpi.h +++ b/include/ddk/hidpi.h @@ -201,6 +201,9 @@ NTSTATUS WINAPI HidP_InitializeReportForID(HIDP_REPORT_TYPE ReportType, UCHAR Re ULONG WINAPI HidP_MaxUsageListLength(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, PHIDP_PREPARSED_DATA PreparsedData); NTSTATUS WINAPI HidP_GetScaledUsageValue(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, PLONG UsageValue, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength); NTSTATUS WINAPI HidP_SetUsageValue(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, ULONG UsageValue, PHIDP_PREPARSED_DATA PreparsedData, CHAR *Report, ULONG ReportLength); +NTSTATUS WINAPI HidP_SetUsageValueArray( HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, + USAGE Usage, PCHAR UsageValue, USHORT UsageValueByteLength, + PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength ); NTSTATUS WINAPI HidP_SetUsages(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, PUSAGE UsageList, PULONG UsageLength, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength);
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 4 +- dlls/ntoskrnl.exe/tests/driver_hid.c | 108 +++++++++++++++++---------- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 56 +++++++++++--- 3 files changed, 114 insertions(+), 54 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 2f7e27e0d87..5fdaa922f45 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -1436,7 +1436,7 @@ @ stdcall -private ZwOpenEvent(ptr long ptr) NtOpenEvent @ stdcall ZwOpenFile(ptr long ptr ptr long long) NtOpenFile @ stdcall -private ZwOpenJobObject(ptr long ptr) NtOpenJobObject -@ stdcall -private ZwOpenKey(ptr long ptr) NtOpenKey +@ stdcall ZwOpenKey(ptr long ptr) NtOpenKey @ stdcall -private ZwOpenKeyEx(ptr long ptr long) NtOpenKeyEx @ stdcall -private ZwOpenKeyTransacted(ptr long ptr long) NtOpenKeyTransacted @ stdcall -private ZwOpenKeyTransactedEx(ptr long ptr long long) NtOpenKeyTransactedEx @@ -1476,7 +1476,7 @@ @ stdcall -private ZwQuerySystemInformation(long ptr long ptr) NtQuerySystemInformation @ stdcall -private ZwQuerySystemInformationEx(long ptr long ptr long ptr) NtQuerySystemInformationEx @ stdcall -private ZwQueryTimerResolution(ptr ptr ptr) NtQueryTimerResolution -@ stdcall -private ZwQueryValueKey(long ptr long ptr long ptr) NtQueryValueKey +@ stdcall ZwQueryValueKey(long ptr long ptr long ptr) NtQueryValueKey @ stdcall -private ZwQueryVirtualMemory(long ptr long ptr long ptr) NtQueryVirtualMemory @ stdcall -private ZwQueryVolumeInformationFile(long ptr ptr long long) NtQueryVolumeInformationFile @ stdcall -private ZwReadFile(long long ptr ptr ptr ptr long ptr ptr) NtReadFile diff --git a/dlls/ntoskrnl.exe/tests/driver_hid.c b/dlls/ntoskrnl.exe/tests/driver_hid.c index 1fe644250f7..3a9f4867de4 100644 --- a/dlls/ntoskrnl.exe/tests/driver_hid.c +++ b/dlls/ntoskrnl.exe/tests/driver_hid.c @@ -40,6 +40,7 @@ static UNICODE_STRING control_symlink;
static unsigned int got_start_device; +static DWORD report_id;
static NTSTATUS WINAPI driver_pnp(DEVICE_OBJECT *device, IRP *irp) { @@ -85,49 +86,54 @@ static NTSTATUS WINAPI driver_power(DEVICE_OBJECT *device, IRP *irp) return PoCallDriver(ext->NextDeviceObject, irp); }
-#include "psh_hid_macros.h" - -static const unsigned char report_descriptor[] = +static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) { - USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), - USAGE(1, HID_USAGE_GENERIC_JOYSTICK), - COLLECTION(1, Application), - USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), - USAGE(1, HID_USAGE_GENERIC_X), - USAGE(1, HID_USAGE_GENERIC_Y), - LOGICAL_MINIMUM(1, -128), - LOGICAL_MAXIMUM(1, 127), - REPORT_SIZE(1, 8), - REPORT_COUNT(1, 2), - INPUT(1, Data|Var|Abs), - - USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON), - USAGE_MINIMUM(1, 1), - USAGE_MAXIMUM(1, 8), - LOGICAL_MINIMUM(1, 0), - LOGICAL_MAXIMUM(1, 1), - PHYSICAL_MINIMUM(1, 0), - PHYSICAL_MAXIMUM(1, 1), - REPORT_COUNT(1, 8), - REPORT_SIZE(1, 1), - INPUT(1, Data|Var|Abs), - +#include "psh_hid_macros.h" +/* Replace REPORT_ID with USAGE_PAGE when id is 0 */ +#define REPORT_ID_OR_USAGE_PAGE(size, id) SHORT_ITEM_1((id ? 8 : 0), 1, id) + const unsigned char report_descriptor[] = + { USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), - USAGE(1, HID_USAGE_GENERIC_HATSWITCH), - LOGICAL_MINIMUM(1, 1), - LOGICAL_MAXIMUM(1, 8), - PHYSICAL_MINIMUM(1, 0), - PHYSICAL_MAXIMUM(1, 8), - REPORT_SIZE(1, 4), - REPORT_COUNT(1, 2), - INPUT(1, Data|Var|Abs), - END_COLLECTION, -}; - + USAGE(1, HID_USAGE_GENERIC_JOYSTICK), + COLLECTION(1, Application), + USAGE(1, HID_USAGE_GENERIC_JOYSTICK), + COLLECTION(1, Logical), + REPORT_ID_OR_USAGE_PAGE(1, report_id), + USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), + USAGE(1, HID_USAGE_GENERIC_X), + USAGE(1, HID_USAGE_GENERIC_Y), + LOGICAL_MINIMUM(1, -128), + LOGICAL_MAXIMUM(1, 127), + REPORT_SIZE(1, 8), + REPORT_COUNT(1, 2), + INPUT(1, Data|Var|Abs), + + USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON), + USAGE_MINIMUM(1, 1), + USAGE_MAXIMUM(1, 8), + LOGICAL_MINIMUM(1, 0), + LOGICAL_MAXIMUM(1, 1), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 1), + REPORT_COUNT(1, 8), + REPORT_SIZE(1, 1), + INPUT(1, Data|Var|Abs), + + USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), + USAGE(1, HID_USAGE_GENERIC_HATSWITCH), + LOGICAL_MINIMUM(1, 1), + LOGICAL_MAXIMUM(1, 8), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 8), + REPORT_SIZE(1, 4), + REPORT_COUNT(1, 2), + INPUT(1, Data|Var|Abs), + END_COLLECTION, + END_COLLECTION, + }; +#undef REPORT_ID_OR_USAGE_PAGE #include "pop_hid_macros.h"
-static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) -{ static BOOL test_failed; IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); const ULONG in_size = stack->Parameters.DeviceIoControl.InputBufferLength; @@ -202,9 +208,13 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
case IOCTL_HID_READ_REPORT: { - ULONG expected_size = 4; + ULONG expected_size = report_id ? 5 : 4; ok(!in_size, "got input size %u\n", in_size); - if (!test_failed) todo_wine ok(out_size == expected_size, "got output size %u\n", out_size); + if (!test_failed) + { + todo_wine_if(!report_id) + ok(out_size == expected_size, "got output size %u\n", out_size); + } if (out_size != expected_size) test_failed = TRUE;
ret = STATUS_NOT_IMPLEMENTED; @@ -278,17 +288,33 @@ static void WINAPI driver_unload(DRIVER_OBJECT *driver)
NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *registry) { + static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ); + char buffer[offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ) + sizeof(DWORD)]; HID_MINIDRIVER_REGISTRATION params = { .Revision = HID_REVISION, .DriverObject = driver, .RegistryPath = registry, }; + UNICODE_STRING name_str; + OBJECT_ATTRIBUTES attr; NTSTATUS ret; + HANDLE hkey; + DWORD size;
if ((ret = winetest_init())) return ret;
+ InitializeObjectAttributes(&attr, registry, 0, NULL, NULL); + ret = ZwOpenKey(&hkey, KEY_ALL_ACCESS, &attr); + ok(!ret, "ZwOpenKey returned %#x\n", ret); + + RtlInitUnicodeString(&name_str, L"ReportID"); + size = info_size + sizeof(report_id); + ret = ZwQueryValueKey(hkey, &name_str, KeyValuePartialInformation, buffer, size, &size); + ok(!ret, "ZwQueryValueKey returned %#x\n", ret); + memcpy(&report_id, buffer + info_size, size - info_size); + driver->DriverExtension->AddDevice = driver_add_device; driver->DriverUnload = driver_unload; driver->MajorFunction[IRP_MJ_PNP] = driver_pnp; diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index ff73e8eae18..578c8057dd7 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1638,25 +1638,27 @@ static inline void check_hidp_value_caps_(int line, HIDP_VALUE_CAPS *caps, const } }
-static void test_hidp(HANDLE file) +static void test_hidp(HANDLE file, int report_id) { - static const HIDP_CAPS expect_hidp_caps = + const HIDP_CAPS expect_hidp_caps = { .Usage = HID_USAGE_GENERIC_JOYSTICK, .UsagePage = HID_USAGE_PAGE_GENERIC, .InputReportByteLength = 5, - .NumberLinkCollectionNodes = 1, + .NumberLinkCollectionNodes = 2, .NumberInputButtonCaps = 1, .NumberInputValueCaps = 3, .NumberInputDataIndices = 11, }; - static const HIDP_BUTTON_CAPS expect_button_caps[] = + const HIDP_BUTTON_CAPS expect_button_caps[] = { { .UsagePage = HID_USAGE_PAGE_BUTTON, + .ReportID = report_id, .BitField = 2, .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, .LinkUsagePage = HID_USAGE_PAGE_GENERIC, + .LinkCollection = 1, .IsRange = TRUE, .IsAbsolute = TRUE, .Range.UsageMin = 1, @@ -1665,13 +1667,15 @@ static void test_hidp(HANDLE file) .Range.DataIndexMax = 9, }, }; - static const HIDP_VALUE_CAPS expect_value_caps[] = + const HIDP_VALUE_CAPS expect_value_caps[] = { { .UsagePage = HID_USAGE_PAGE_GENERIC, + .ReportID = report_id, .BitField = 2, .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, .LinkUsagePage = HID_USAGE_PAGE_GENERIC, + .LinkCollection = 1, .IsAbsolute = TRUE, .BitSize = 8, .ReportCount = 1, @@ -1681,9 +1685,11 @@ static void test_hidp(HANDLE file) }, { .UsagePage = HID_USAGE_PAGE_GENERIC, + .ReportID = report_id, .BitField = 2, .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, .LinkUsagePage = HID_USAGE_PAGE_GENERIC, + .LinkCollection = 1, .IsAbsolute = TRUE, .BitSize = 8, .ReportCount = 1, @@ -1694,9 +1700,11 @@ static void test_hidp(HANDLE file) }, { .UsagePage = HID_USAGE_PAGE_GENERIC, + .ReportID = report_id, .BitField = 2, .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, .LinkUsagePage = HID_USAGE_PAGE_GENERIC, + .LinkCollection = 1, .IsAbsolute = TRUE, .BitSize = 4, .ReportCount = 2, @@ -1713,6 +1721,13 @@ static void test_hidp(HANDLE file) .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, .LinkUsagePage = HID_USAGE_PAGE_GENERIC, .CollectionType = 1, + .NumberOfChildren = 1, + .FirstChild = 1, + }, + { + .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, + .LinkUsagePage = HID_USAGE_PAGE_GENERIC, + .CollectionType = 2, }, };
@@ -1960,20 +1975,26 @@ static void test_hidp(HANDLE file) ok(status == HIDP_STATUS_INVALID_REPORT_LENGTH, "HidP_InitializeReportForID returned %#x\n", status); status = HidP_InitializeReportForID(HidP_Input, 0, preparsed_data, report, caps.InputReportByteLength + 1); ok(status == HIDP_STATUS_INVALID_REPORT_LENGTH, "HidP_InitializeReportForID returned %#x\n", status); + status = HidP_InitializeReportForID(HidP_Input, 1 - report_id, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(!report_id) + ok(status == HIDP_STATUS_REPORT_DOES_NOT_EXIST, "HidP_InitializeReportForID returned %#x\n", status);
memset(report, 0xcd, sizeof(report)); - status = HidP_InitializeReportForID(HidP_Input, 0, preparsed_data, report, caps.InputReportByteLength); + status = HidP_InitializeReportForID(HidP_Input, report_id, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) ok(status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status);
memset(buffer, 0xcd, sizeof(buffer)); memset(buffer, 0, caps.InputReportByteLength); + buffer[0] = report_id; + todo_wine_if(report_id) ok(!memcmp(buffer, report, sizeof(buffer)), "unexpected report data\n");
HidD_FreePreparsedData(preparsed_data); CloseHandle(file); }
-static void test_hid_device(void) +static void test_hid_device(DWORD report_id) { char buffer[200]; SP_DEVICE_INTERFACE_DETAIL_DATA_A *iface_detail = (void *)buffer; @@ -1988,6 +2009,8 @@ static void test_hid_device(void) HDEVINFO set; HANDLE file;
+ winetest_push_context("report %d", report_id); + set = SetupDiGetClassDevsA(&GUID_DEVINTERFACE_HID, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); ok(set != INVALID_HANDLE_VALUE, "failed to get device list, error %#x\n", GetLastError());
@@ -2018,7 +2041,7 @@ 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());
- test_hidp(file); + test_hidp(file, report_id);
CloseHandle(file);
@@ -2026,9 +2049,11 @@ static void test_hid_device(void) InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE, NULL, NULL); status = NtOpenFile(&file, SYNCHRONIZE, &attr, &io, 0, FILE_SYNCHRONOUS_IO_NONALERT); todo_wine ok(status == STATUS_UNSUCCESSFUL, "got %#x\n", status); + + winetest_pop_context(); }
-static void test_hid_driver(struct testsign_context *ctx) +static void test_hid_driver(struct testsign_context *ctx, DWORD report_id) { static const char hardware_id[] = "test_hardware_id\0"; char path[MAX_PATH], dest[MAX_PATH], *filepart; @@ -2038,13 +2063,21 @@ static void test_hid_driver(struct testsign_context *ctx) SC_HANDLE manager, service; BOOL ret, need_reboot; HANDLE catalog, file; + LSTATUS status; HDEVINFO set; + HKEY hkey; FILE *f;
GetCurrentDirectoryA(ARRAY_SIZE(cwd), cwd); GetTempPathA(ARRAY_SIZE(tempdir), tempdir); SetCurrentDirectoryA(tempdir);
+ status = RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"System\CurrentControlSet\Services\winetest", 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL); + ok(!status, "RegCreateKeyExW returned %#x\n", status); + + status = RegSetValueExW(hkey, L"ReportID", 0, REG_DWORD, (void *)&report_id, sizeof(report_id)); + ok(!status, "RegSetValueExW returned %#x\n", status); + load_resource(L"driver_hid.dll", driver_filename); ret = MoveFileExW(driver_filename, L"winetest.sys", MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING); ok(ret, "failed to move file, error %u\n", GetLastError()); @@ -2092,7 +2125,7 @@ static void test_hid_driver(struct testsign_context *ctx)
/* Tests. */
- test_hid_device(); + test_hid_device(report_id);
/* Clean up. */
@@ -2223,7 +2256,8 @@ START_TEST(ntoskrnl) test_pnp_driver(&ctx);
subtest("driver_hid"); - test_hid_driver(&ctx); + test_hid_driver(&ctx, 0); + test_hid_driver(&ctx, 1);
out: testsign_cleanup(&ctx);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=92438
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
ntoskrnl.exe: ntoskrnl.c:1236: Test failed: got 0 bus arrival messages ntoskrnl.c:1252: Test failed: got 0 bus arrival messages
=== w864 (64 bit report) ===
Report validation errors: ntoskrnl.exe:ntoskrnl crashed (c0000374)
On 6/14/21 9:26 AM, Marvin wrote:
=== w864 (64 bit report) ===
Report validation errors: ntoskrnl.exe:ntoskrnl crashed (c0000374)
FWIW this is crashing there:
ret = CertCloseStore(ctx->root_store, CERT_CLOSE_STORE_CHECK_FLAG);
But I have absolutely no idea why. Somehow the certificate store got corrupted? It's not related to the patches, but it doesn't crash all the time.
On 6/15/21 11:29 AM, Rémi Bernon wrote:
On 6/14/21 9:26 AM, Marvin wrote:
=== w864 (64 bit report) ===
Report validation errors: ntoskrnl.exe:ntoskrnl crashed (c0000374)
FWIW this is crashing there:
ret = CertCloseStore(ctx->root_store, CERT_CLOSE_STORE_CHECK_FLAG);
But I have absolutely no idea why. Somehow the certificate store got corrupted? It's not related to the patches, but it doesn't crash all the time.
It seems it's been happening for a while now. Probably something's wrong with the cert code in the test. Unfortunately I haven't been able to find any errors from manual reëxamination, and I'm not sure how else to proceed.
Does anyone know of a memory checker that can be used on Windows? It may be tricky to use it while avoiding looking at crypt32 internals, but it's at least worth a try...
On 6/15/21 6:39 PM, Zebediah Figura (she/her) wrote:
On 6/15/21 11:29 AM, Rémi Bernon wrote:
On 6/14/21 9:26 AM, Marvin wrote:
=== w864 (64 bit report) ===
Report validation errors: ntoskrnl.exe:ntoskrnl crashed (c0000374)
FWIW this is crashing there:
ret = CertCloseStore(ctx->root_store, CERT_CLOSE_STORE_CHECK_FLAG);
But I have absolutely no idea why. Somehow the certificate store got corrupted? It's not related to the patches, but it doesn't crash all the time.
It seems it's been happening for a while now. Probably something's wrong with the cert code in the test. Unfortunately I haven't been able to find any errors from manual reëxamination, and I'm not sure how else to proceed.
Does anyone know of a memory checker that can be used on Windows? It may be tricky to use it while avoiding looking at crypt32 internals, but it's at least worth a try...
I think it may be coming from CertFreeCertificateContext, which either is not necessary after CertDeleteCertificateFromStore, or w8 messed up its refcounts.
MSDN states:
The CertDeleteCertificateFromStore function always frees pCertContext by calling the CertFreeCertificateContext function, even if an error is encountered. Freeing the context reduces the context's reference count by one. If the reference count reaches zero, memory allocated for the certificate is freed.
Which is not completely clear to me if that means CertFreeCertificateContext should not be called, and maybe w8 implemented it that way?
I'm sending a patch which removes the calls, it seems to have fixed the crash according to 10 flawless runs.
On 6/15/21 12:05 PM, Rémi Bernon wrote:
On 6/15/21 6:39 PM, Zebediah Figura (she/her) wrote:
On 6/15/21 11:29 AM, Rémi Bernon wrote:
On 6/14/21 9:26 AM, Marvin wrote:
=== w864 (64 bit report) ===
Report validation errors: ntoskrnl.exe:ntoskrnl crashed (c0000374)
FWIW this is crashing there:
ret = CertCloseStore(ctx->root_store, CERT_CLOSE_STORE_CHECK_FLAG);
But I have absolutely no idea why. Somehow the certificate store got corrupted? It's not related to the patches, but it doesn't crash all the time.
It seems it's been happening for a while now. Probably something's wrong with the cert code in the test. Unfortunately I haven't been able to find any errors from manual reëxamination, and I'm not sure how else to proceed.
Does anyone know of a memory checker that can be used on Windows? It may be tricky to use it while avoiding looking at crypt32 internals, but it's at least worth a try...
I think it may be coming from CertFreeCertificateContext, which either is not necessary after CertDeleteCertificateFromStore, or w8 messed up its refcounts.
MSDN states:
The CertDeleteCertificateFromStore function always frees pCertContext by calling the CertFreeCertificateContext function, even if an error is encountered. Freeing the context reduces the context's reference count by one. If the reference count reaches zero, memory allocated for the certificate is freed.
Which is not completely clear to me if that means CertFreeCertificateContext should not be called, and maybe w8 implemented it that way?
Nope, I think you're right. I probably misinterpreted CertAddCertificateContextToStore() somehow, and thought that it would hand us an extra reference when returning the context copy, but the documentation doesn't actually say it does, and clearly it doesn't in practice.
I'm sending a patch which removes the calls, it seems to have fixed the crash according to 10 flawless runs.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntoskrnl.exe/tests/driver_hid.c | 124 +++++++++++++- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 246 ++++++++++++++++++++++++--- 2 files changed, 335 insertions(+), 35 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/driver_hid.c b/dlls/ntoskrnl.exe/tests/driver_hid.c index 3a9f4867de4..74e9029a476 100644 --- a/dlls/ntoskrnl.exe/tests/driver_hid.c +++ b/dlls/ntoskrnl.exe/tests/driver_hid.c @@ -90,7 +90,7 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) { #include "psh_hid_macros.h" /* Replace REPORT_ID with USAGE_PAGE when id is 0 */ -#define REPORT_ID_OR_USAGE_PAGE(size, id) SHORT_ITEM_1((id ? 8 : 0), 1, id) +#define REPORT_ID_OR_USAGE_PAGE(size, id, off) SHORT_ITEM_1((id ? 8 : 0), 1, (id + off)) const unsigned char report_descriptor[] = { USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), @@ -98,7 +98,7 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) COLLECTION(1, Application), USAGE(1, HID_USAGE_GENERIC_JOYSTICK), COLLECTION(1, Logical), - REPORT_ID_OR_USAGE_PAGE(1, report_id), + REPORT_ID_OR_USAGE_PAGE(1, report_id, 0), USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), USAGE(1, HID_USAGE_GENERIC_X), USAGE(1, HID_USAGE_GENERIC_Y), @@ -113,22 +113,132 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) USAGE_MAXIMUM(1, 8), LOGICAL_MINIMUM(1, 0), LOGICAL_MAXIMUM(1, 1), - PHYSICAL_MINIMUM(1, 0), - PHYSICAL_MAXIMUM(1, 1), REPORT_COUNT(1, 8), REPORT_SIZE(1, 1), INPUT(1, Data|Var|Abs),
+ USAGE_MINIMUM(1, 0x18), + USAGE_MAXIMUM(1, 0x1f), + LOGICAL_MINIMUM(1, 0), + LOGICAL_MAXIMUM(1, 1), + REPORT_COUNT(1, 8), + REPORT_SIZE(1, 1), + INPUT(1, Cnst|Var|Abs), + REPORT_COUNT(1, 8), + REPORT_SIZE(1, 1), + INPUT(1, Cnst|Var|Abs), + /* needs to be 8 bit aligned as next has Buff */ + + USAGE_MINIMUM(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0x8), + USAGE_MAXIMUM(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0xf), + LOGICAL_MINIMUM(1, 0), + LOGICAL_MAXIMUM(1, 8), + REPORT_COUNT(1, 2), + REPORT_SIZE(1, 8), + INPUT(2, Data|Ary|Rel|Wrap|Lin|Pref|Null|Vol|Buff), + + /* needs to be 8 bit aligned as previous has Buff */ + USAGE(1, 0x20), + LOGICAL_MINIMUM(1, 0), + LOGICAL_MAXIMUM(1, 1), + REPORT_COUNT(1, 8), + REPORT_SIZE(1, 1), + INPUT(1, Data|Var|Abs), + USAGE_MINIMUM(1, 0x21), + USAGE_MAXIMUM(1, 0x22), + REPORT_COUNT(1, 2), + REPORT_SIZE(1, 0), + INPUT(1, Data|Var|Abs), + USAGE(1, 0x23), + REPORT_COUNT(1, 0), + REPORT_SIZE(1, 1), + INPUT(1, Data|Var|Abs), + USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), USAGE(1, HID_USAGE_GENERIC_HATSWITCH), LOGICAL_MINIMUM(1, 1), LOGICAL_MAXIMUM(1, 8), - PHYSICAL_MINIMUM(1, 0), - PHYSICAL_MAXIMUM(1, 8), REPORT_SIZE(1, 4), REPORT_COUNT(1, 2), INPUT(1, Data|Var|Abs), END_COLLECTION, + + USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), + USAGE(1, HID_USAGE_GENERIC_JOYSTICK), + COLLECTION(1, Report), + REPORT_ID_OR_USAGE_PAGE(1, report_id, 1), + USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON), + USAGE_MINIMUM(1, 9), + USAGE_MAXIMUM(1, 10), + LOGICAL_MINIMUM(1, 0), + LOGICAL_MAXIMUM(1, 1), + REPORT_COUNT(1, 8), + REPORT_SIZE(1, 1), + INPUT(1, Data|Var|Abs), + END_COLLECTION, + + USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS), + USAGE(1, HID_USAGE_HAPTICS_SIMPLE_CONTROLLER), + COLLECTION(1, Logical), + REPORT_ID_OR_USAGE_PAGE(1, report_id, 0), + USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS), + + USAGE(1, HID_USAGE_HAPTICS_WAVEFORM_LIST), + COLLECTION(1, NamedArray), + USAGE_PAGE(1, HID_USAGE_PAGE_ORDINAL), + USAGE(1, 3), /* HID_USAGE_HAPTICS_WAVEFORM_RUMBLE */ + USAGE(1, 4), /* HID_USAGE_HAPTICS_WAVEFORM_BUZZ */ + LOGICAL_MINIMUM(2, 0x0000), + LOGICAL_MAXIMUM(2, 0xffff), + REPORT_COUNT(1, 2), + REPORT_SIZE(1, 16), + FEATURE(1, Data|Var|Abs|Null), + END_COLLECTION, + + USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS), + USAGE(1, HID_USAGE_HAPTICS_DURATION_LIST), + COLLECTION(1, NamedArray), + USAGE_PAGE(1, HID_USAGE_PAGE_ORDINAL), + USAGE(1, 3), /* 0 (HID_USAGE_HAPTICS_WAVEFORM_RUMBLE) */ + USAGE(1, 4), /* 0 (HID_USAGE_HAPTICS_WAVEFORM_BUZZ) */ + LOGICAL_MINIMUM(2, 0x0000), + LOGICAL_MAXIMUM(2, 0xffff), + REPORT_COUNT(1, 2), + REPORT_SIZE(1, 16), + FEATURE(1, Data|Var|Abs|Null), + END_COLLECTION, + + USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS), + USAGE(1, HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME), + UNIT(2, 0x1001), /* seconds */ + UNIT_EXPONENT(1, -3), /* 10^-3 */ + LOGICAL_MINIMUM(2, 0x8000), + LOGICAL_MAXIMUM(2, 0x7fff), + PHYSICAL_MINIMUM(4, 0x00000000), + PHYSICAL_MAXIMUM(4, 0xffffffff), + REPORT_SIZE(1, 32), + REPORT_COUNT(1, 1), + FEATURE(1, Data|Var|Abs), + /* reset global items */ + UNIT(1, 0), /* None */ + UNIT_EXPONENT(1, 0), + END_COLLECTION, + + USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), + USAGE(1, HID_USAGE_GENERIC_JOYSTICK), + COLLECTION(1, Report), + REPORT_ID_OR_USAGE_PAGE(1, report_id, 1), + USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON), + USAGE_MINIMUM(1, 9), + USAGE_MAXIMUM(1, 10), + LOGICAL_MINIMUM(1, 0), + LOGICAL_MAXIMUM(1, 1), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 1), + REPORT_COUNT(1, 8), + REPORT_SIZE(1, 1), + FEATURE(1, Data|Var|Abs), + END_COLLECTION, END_COLLECTION, }; #undef REPORT_ID_OR_USAGE_PAGE @@ -208,7 +318,7 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
case IOCTL_HID_READ_REPORT: { - ULONG expected_size = report_id ? 5 : 4; + ULONG expected_size = 10; ok(!in_size, "got input size %u\n", in_size); if (!test_failed) { diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 578c8057dd7..497c9a10adf 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1640,15 +1640,36 @@ static inline void check_hidp_value_caps_(int line, HIDP_VALUE_CAPS *caps, const
static void test_hidp(HANDLE file, int report_id) { - const HIDP_CAPS expect_hidp_caps = + const HIDP_CAPS expect_hidp_caps[] = { - .Usage = HID_USAGE_GENERIC_JOYSTICK, - .UsagePage = HID_USAGE_PAGE_GENERIC, - .InputReportByteLength = 5, - .NumberLinkCollectionNodes = 2, - .NumberInputButtonCaps = 1, - .NumberInputValueCaps = 3, - .NumberInputDataIndices = 11, + /* without report id */ + { + .Usage = HID_USAGE_GENERIC_JOYSTICK, + .UsagePage = HID_USAGE_PAGE_GENERIC, + .InputReportByteLength = 11, + .FeatureReportByteLength = 14, + .NumberLinkCollectionNodes = 7, + .NumberInputButtonCaps = 5, + .NumberInputValueCaps = 4, + .NumberInputDataIndices = 32, + .NumberFeatureButtonCaps = 1, + .NumberFeatureValueCaps = 5, + .NumberFeatureDataIndices = 7, + }, + /* with report id */ + { + .Usage = HID_USAGE_GENERIC_JOYSTICK, + .UsagePage = HID_USAGE_PAGE_GENERIC, + .InputReportByteLength = 10, + .FeatureReportByteLength = 13, + .NumberLinkCollectionNodes = 7, + .NumberInputButtonCaps = 5, + .NumberInputValueCaps = 4, + .NumberInputDataIndices = 32, + .NumberFeatureButtonCaps = 1, + .NumberFeatureValueCaps = 5, + .NumberFeatureDataIndices = 7, + }, }; const HIDP_BUTTON_CAPS expect_button_caps[] = { @@ -1666,6 +1687,48 @@ static void test_hidp(HANDLE file, int report_id) .Range.DataIndexMin = 2, .Range.DataIndexMax = 9, }, + { + .UsagePage = HID_USAGE_PAGE_BUTTON, + .ReportID = report_id, + .BitField = 3, + .LinkCollection = 1, + .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, + .LinkUsagePage = HID_USAGE_PAGE_GENERIC, + .IsRange = TRUE, + .IsAbsolute = TRUE, + .Range.UsageMin = 0x18, + .Range.UsageMax = 0x1f, + .Range.DataIndexMin = 10, + .Range.DataIndexMax = 17, + }, + { + .UsagePage = HID_USAGE_PAGE_KEYBOARD, + .ReportID = report_id, + .BitField = 0x1fc, + .LinkCollection = 1, + .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, + .LinkUsagePage = HID_USAGE_PAGE_GENERIC, + .IsRange = TRUE, + .IsAbsolute = FALSE, + .Range.UsageMin = 0x8, + .Range.UsageMax = 0xf, + .Range.DataIndexMin = 18, + .Range.DataIndexMax = 25, + }, + { + .UsagePage = HID_USAGE_PAGE_BUTTON, + .ReportID = report_id, + .BitField = 2, + .LinkCollection = 1, + .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, + .LinkUsagePage = HID_USAGE_PAGE_GENERIC, + .IsRange = FALSE, + .IsAbsolute = TRUE, + .NotRange.Usage = 0x20, + .NotRange.Reserved1 = 0x20, + .NotRange.DataIndex = 26, + .NotRange.Reserved4 = 26, + }, }; const HIDP_VALUE_CAPS expect_value_caps[] = { @@ -1682,6 +1745,7 @@ static void test_hidp(HANDLE file, int report_id) .LogicalMin = -128, .LogicalMax = 127, .NotRange.Usage = HID_USAGE_GENERIC_Y, + .NotRange.Reserved1 = HID_USAGE_GENERIC_Y, }, { .UsagePage = HID_USAGE_PAGE_GENERIC, @@ -1696,7 +1760,25 @@ static void test_hidp(HANDLE file, int report_id) .LogicalMin = -128, .LogicalMax = 127, .NotRange.Usage = HID_USAGE_GENERIC_X, + .NotRange.Reserved1 = HID_USAGE_GENERIC_X, .NotRange.DataIndex = 1, + .NotRange.Reserved4 = 1, + }, + { + .UsagePage = HID_USAGE_PAGE_BUTTON, + .ReportID = report_id, + .BitField = 2, + .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, + .LinkUsagePage = HID_USAGE_PAGE_GENERIC, + .LinkCollection = 1, + .IsAbsolute = TRUE, + .ReportCount = 1, + .LogicalMax = 1, + .IsRange = TRUE, + .Range.UsageMin = 0x21, + .Range.UsageMax = 0x22, + .Range.DataIndexMin = 27, + .Range.DataIndexMax = 28, }, { .UsagePage = HID_USAGE_PAGE_GENERIC, @@ -1710,9 +1792,10 @@ static void test_hidp(HANDLE file, int report_id) .ReportCount = 2, .LogicalMin = 1, .LogicalMax = 8, - .PhysicalMax = 8, .NotRange.Usage = HID_USAGE_GENERIC_HATSWITCH, - .NotRange.DataIndex = 10, + .NotRange.Reserved1 = HID_USAGE_GENERIC_HATSWITCH, + .NotRange.DataIndex = 29, + .NotRange.Reserved4 = 29, }, }; static const HIDP_LINK_COLLECTION_NODE expect_collections[] = @@ -1721,8 +1804,8 @@ static void test_hidp(HANDLE file, int report_id) .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, .LinkUsagePage = HID_USAGE_PAGE_GENERIC, .CollectionType = 1, - .NumberOfChildren = 1, - .FirstChild = 1, + .NumberOfChildren = 4, + .FirstChild = 6, }, { .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, @@ -1751,7 +1834,25 @@ static void test_hidp(HANDLE file, int report_id) 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); + check_member(caps, expect_hidp_caps[report_id], "%04x", Usage); + check_member(caps, expect_hidp_caps[report_id], "%04x", UsagePage); + check_member(caps, expect_hidp_caps[report_id], "%d", InputReportByteLength); + check_member(caps, expect_hidp_caps[report_id], "%d", OutputReportByteLength); + check_member(caps, expect_hidp_caps[report_id], "%d", FeatureReportByteLength); + check_member(caps, expect_hidp_caps[report_id], "%d", NumberLinkCollectionNodes); + todo_wine + check_member(caps, expect_hidp_caps[report_id], "%d", NumberInputButtonCaps); + todo_wine + check_member(caps, expect_hidp_caps[report_id], "%d", NumberInputValueCaps); + todo_wine + check_member(caps, expect_hidp_caps[report_id], "%d", NumberInputDataIndices); + check_member(caps, expect_hidp_caps[report_id], "%d", NumberOutputButtonCaps); + check_member(caps, expect_hidp_caps[report_id], "%d", NumberOutputValueCaps); + check_member(caps, expect_hidp_caps[report_id], "%d", NumberOutputDataIndices); + check_member(caps, expect_hidp_caps[report_id], "%d", NumberFeatureButtonCaps); + check_member(caps, expect_hidp_caps[report_id], "%d", NumberFeatureValueCaps); + todo_wine + check_member(caps, expect_hidp_caps[report_id], "%d", NumberFeatureDataIndices);
collection_count = 0; status = HidP_GetLinkCollectionNodes(collections, &collection_count, preparsed_data); @@ -1770,7 +1871,16 @@ static void test_hidp(HANDLE file, int report_id) for (i = 0; i < ARRAY_SIZE(expect_collections); ++i) { winetest_push_context("collections[%d]", i); - check_hidp_link_collection_node(collections + i, expect_collections + i); + check_member(collections[i], expect_collections[i], "%04x", LinkUsage); + check_member(collections[i], expect_collections[i], "%04x", LinkUsagePage); + check_member(collections[i], expect_collections[i], "%d", Parent); + check_member(collections[i], expect_collections[i], "%d", NumberOfChildren); + todo_wine_if(i == 1) + check_member(collections[i], expect_collections[i], "%d", NextSibling); + todo_wine_if(i == 0) + check_member(collections[i], expect_collections[i], "%d", FirstChild); + check_member(collections[i], expect_collections[i], "%d", CollectionType); + check_member(collections[i], expect_collections[i], "%d", IsAlias); winetest_pop_context(); }
@@ -1790,6 +1900,7 @@ static void test_hidp(HANDLE file, int report_id) 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); + memset(button_caps, 0, sizeof(button_caps)); 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", @@ -1798,25 +1909,36 @@ static void test_hidp(HANDLE file, int report_id) for (i = 0; i < ARRAY_SIZE(expect_button_caps); ++i) { winetest_push_context("button_caps[%d]", i); + todo_wine_if(i >= 2) check_member(button_caps[i], expect_button_caps[i], "%04x", UsagePage); + todo_wine_if(i >= 2 && report_id) check_member(button_caps[i], expect_button_caps[i], "%d", ReportID); check_member(button_caps[i], expect_button_caps[i], "%d", IsAlias); todo_wine check_member(button_caps[i], expect_button_caps[i], "%d", BitField); + todo_wine_if(i >= 2) check_member(button_caps[i], expect_button_caps[i], "%d", LinkCollection); + todo_wine_if(i >= 3) check_member(button_caps[i], expect_button_caps[i], "%04x", LinkUsage); + todo_wine_if(i >= 3) check_member(button_caps[i], expect_button_caps[i], "%04x", LinkUsagePage); + todo_wine_if(i == 1) check_member(button_caps[i], expect_button_caps[i], "%d", IsRange); check_member(button_caps[i], expect_button_caps[i], "%d", IsStringRange); check_member(button_caps[i], expect_button_caps[i], "%d", IsDesignatorRange); + todo_wine_if(i >= 2) check_member(button_caps[i], expect_button_caps[i], "%d", IsAbsolute); + todo_wine_if(i >= 1) check_member(button_caps[i], expect_button_caps[i], "%04x", Range.UsageMin); + todo_wine_if(i >= 1) check_member(button_caps[i], expect_button_caps[i], "%04x", Range.UsageMax); check_member(button_caps[i], expect_button_caps[i], "%d", Range.StringMin); check_member(button_caps[i], expect_button_caps[i], "%d", Range.StringMax); check_member(button_caps[i], expect_button_caps[i], "%d", Range.DesignatorMin); check_member(button_caps[i], expect_button_caps[i], "%d", Range.DesignatorMax); + todo_wine_if(i >= 1) check_member(button_caps[i], expect_button_caps[i], "%d", Range.DataIndexMin); + todo_wine_if(i >= 1) check_member(button_caps[i], expect_button_caps[i], "%d", Range.DataIndexMax); winetest_pop_context(); } @@ -1890,6 +2012,7 @@ static void test_hidp(HANDLE file, int report_id) for (i = 0; i < ARRAY_SIZE(expect_value_caps); ++i) { winetest_push_context("value_caps[%d]", i); + todo_wine_if(i == 3) check_member(value_caps[i], expect_value_caps[i], "%04x", UsagePage); check_member(value_caps[i], expect_value_caps[i], "%d", ReportID); check_member(value_caps[i], expect_value_caps[i], "%d", IsAlias); @@ -1898,28 +2021,42 @@ static void test_hidp(HANDLE file, int report_id) check_member(value_caps[i], expect_value_caps[i], "%d", LinkCollection); check_member(value_caps[i], expect_value_caps[i], "%04x", LinkUsage); check_member(value_caps[i], expect_value_caps[i], "%04x", LinkUsagePage); + todo_wine_if(i == 3) check_member(value_caps[i], expect_value_caps[i], "%d", IsRange); check_member(value_caps[i], expect_value_caps[i], "%d", IsStringRange); check_member(value_caps[i], expect_value_caps[i], "%d", IsDesignatorRange); + todo_wine_if(i == 2) check_member(value_caps[i], expect_value_caps[i], "%d", IsAbsolute); + todo_wine_if(i == 2) check_member(value_caps[i], expect_value_caps[i], "%d", HasNull); + todo_wine_if(i >= 2) check_member(value_caps[i], expect_value_caps[i], "%d", BitSize); + todo_wine_if(i == 2) check_member(value_caps[i], expect_value_caps[i], "%d", ReportCount); check_member(value_caps[i], expect_value_caps[i], "%d", UnitsExp); check_member(value_caps[i], expect_value_caps[i], "%d", Units); + todo_wine_if(i >= 3) check_member(value_caps[i], expect_value_caps[i], "%d", LogicalMin); + todo_wine_if(i >= 2) check_member(value_caps[i], expect_value_caps[i], "%d", LogicalMax); check_member(value_caps[i], expect_value_caps[i], "%d", PhysicalMin); check_member(value_caps[i], expect_value_caps[i], "%d", PhysicalMax); - todo_wine_if(i != 2) - check_member(value_caps[i], expect_value_caps[i], "%04x", NotRange.Usage); - check_member(value_caps[i], expect_value_caps[i], "%d", NotRange.StringIndex); - check_member(value_caps[i], expect_value_caps[i], "%d", NotRange.DesignatorIndex); - check_member(value_caps[i], expect_value_caps[i], "%d", NotRange.DataIndex); + todo_wine + check_member(value_caps[i], expect_value_caps[i], "%04x", Range.UsageMin); + todo_wine + check_member(value_caps[i], expect_value_caps[i], "%04x", Range.UsageMax); + check_member(value_caps[i], expect_value_caps[i], "%d", Range.StringMin); + check_member(value_caps[i], expect_value_caps[i], "%d", Range.StringMax); + check_member(value_caps[i], expect_value_caps[i], "%d", Range.DesignatorMin); + check_member(value_caps[i], expect_value_caps[i], "%d", Range.DesignatorMax); + todo_wine_if(i >= 2) + check_member(value_caps[i], expect_value_caps[i], "%d", Range.DataIndexMin); + todo_wine_if(i >= 2) + check_member(value_caps[i], expect_value_caps[i], "%d", Range.DataIndexMax); winetest_pop_context(); }
- count = ARRAY_SIZE(value_caps) - 3; + count = ARRAY_SIZE(value_caps) - 4; 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); @@ -1932,24 +2069,61 @@ static void test_hidp(HANDLE file, int report_id) 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); + count = ARRAY_SIZE(value_caps) - 4; + status = HidP_GetSpecificValueCaps(HidP_Input, 0, 0, 0, value_caps + 4, &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); + status = HidP_GetSpecificValueCaps(HidP_Input, 0, 0, 0, value_caps + 4, &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]); + check_hidp_value_caps(&value_caps[4], &value_caps[0]); + check_hidp_value_caps(&value_caps[5], &value_caps[1]); + check_hidp_value_caps(&value_caps[6], &value_caps[2]); + check_hidp_value_caps(&value_caps[7], &value_caps[3]);
count = 1; status = HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH, - value_caps + 3, &count, preparsed_data); + value_caps + 4, &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]); + + todo_wine + check_member(value_caps[4], value_caps[3], "%04x", UsagePage); + check_member(value_caps[4], value_caps[3], "%d", ReportID); + check_member(value_caps[4], value_caps[3], "%d", IsAlias); + check_member(value_caps[4], value_caps[3], "%d", BitField); + check_member(value_caps[4], value_caps[3], "%d", LinkCollection); + check_member(value_caps[4], value_caps[3], "%04x", LinkUsage); + check_member(value_caps[4], value_caps[3], "%04x", LinkUsagePage); + todo_wine + check_member(value_caps[4], value_caps[3], "%d", IsRange); + check_member(value_caps[4], value_caps[3], "%d", IsStringRange); + check_member(value_caps[4], value_caps[3], "%d", IsDesignatorRange); + check_member(value_caps[4], value_caps[3], "%d", IsAbsolute); + check_member(value_caps[4], value_caps[3], "%d", HasNull); + todo_wine + check_member(value_caps[4], value_caps[3], "%d", BitSize); + check_member(value_caps[4], value_caps[3], "%d", ReportCount); + check_member(value_caps[4], value_caps[3], "%d", UnitsExp); + check_member(value_caps[4], value_caps[3], "%d", Units); + todo_wine + check_member(value_caps[4], value_caps[3], "%d", LogicalMin); + todo_wine + check_member(value_caps[4], value_caps[3], "%d", LogicalMax); + check_member(value_caps[4], value_caps[3], "%d", PhysicalMin); + check_member(value_caps[4], value_caps[3], "%d", PhysicalMax); + todo_wine + check_member(value_caps[4], value_caps[3], "%04x", Range.UsageMin); + check_member(value_caps[4], value_caps[3], "%04x", Range.UsageMax); + check_member(value_caps[4], value_caps[3], "%d", Range.StringMin); + check_member(value_caps[4], value_caps[3], "%d", Range.StringMax); + check_member(value_caps[4], value_caps[3], "%d", Range.DesignatorMin); + check_member(value_caps[4], value_caps[3], "%d", Range.DesignatorMax); + todo_wine + check_member(value_caps[4], value_caps[3], "%d", Range.DataIndexMin); + todo_wine + check_member(value_caps[4], value_caps[3], "%d", Range.DataIndexMax);
count = 0xdead; status = HidP_GetSpecificValueCaps(HidP_Input, 0xfffe, 0, 0, value_caps, &count, preparsed_data); @@ -1990,6 +2164,22 @@ static void test_hidp(HANDLE file, int report_id) todo_wine_if(report_id) ok(!memcmp(buffer, report, sizeof(buffer)), "unexpected report data\n");
+ memset(report, 0xcd, sizeof(report)); + status = HidP_InitializeReportForID(HidP_Feature, 3, preparsed_data, report, caps.FeatureReportByteLength); + todo_wine_if(!report_id) + ok(status == HIDP_STATUS_REPORT_DOES_NOT_EXIST, "HidP_InitializeReportForID returned %#x\n", status); + + memset(report, 0xcd, sizeof(report)); + status = HidP_InitializeReportForID(HidP_Feature, report_id, preparsed_data, report, caps.FeatureReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status); + + memset(buffer, 0xcd, sizeof(buffer)); + memset(buffer, 0, caps.FeatureReportByteLength); + buffer[0] = report_id; + todo_wine_if(report_id) + ok(!memcmp(buffer, report, sizeof(buffer)), "unexpected report data\n"); + HidD_FreePreparsedData(preparsed_data); CloseHandle(file); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=92439
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
ntoskrnl.exe: ntoskrnl.c:1236: Test failed: got 0 bus arrival messages ntoskrnl.c:1252: Test failed: got 0 bus arrival messages
=== w8 (32 bit report) ===
ntoskrnl.exe: driver.c:759: Test failed: got 0
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntoskrnl.exe/tests/driver_hid.c | 33 +++- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 275 ++++++++++++++++++++++++++- 2 files changed, 298 insertions(+), 10 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/driver_hid.c b/dlls/ntoskrnl.exe/tests/driver_hid.c index 74e9029a476..91e3a29e1df 100644 --- a/dlls/ntoskrnl.exe/tests/driver_hid.c +++ b/dlls/ntoskrnl.exe/tests/driver_hid.c @@ -161,6 +161,35 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) REPORT_SIZE(1, 4), REPORT_COUNT(1, 2), INPUT(1, Data|Var|Abs), + + USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), + USAGE(1, HID_USAGE_GENERIC_Z), + LOGICAL_MINIMUM(4, 0x00000000), + LOGICAL_MAXIMUM(4, 0x3fffffff), + PHYSICAL_MINIMUM(4, 0x80000000), + PHYSICAL_MAXIMUM(4, 0x7fffffff), + REPORT_SIZE(1, 32), + REPORT_COUNT(1, 1), + INPUT(1, Data|Var|Abs), + + /* reset physical range to its default interpretation */ + USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), + USAGE(1, HID_USAGE_GENERIC_RX), + PHYSICAL_MINIMUM(4, 0), + PHYSICAL_MAXIMUM(4, 0), + REPORT_SIZE(1, 32), + REPORT_COUNT(1, 1), + INPUT(1, Data|Var|Abs), + + USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), + USAGE(1, HID_USAGE_GENERIC_RY), + LOGICAL_MINIMUM(4, 0x7fff), + LOGICAL_MAXIMUM(4, 0x0000), + PHYSICAL_MINIMUM(4, 0x0000), + PHYSICAL_MAXIMUM(4, 0x7fff), + REPORT_SIZE(1, 32), + REPORT_COUNT(1, 1), + INPUT(1, Data|Var|Abs), END_COLLECTION,
USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), @@ -217,7 +246,7 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) PHYSICAL_MINIMUM(4, 0x00000000), PHYSICAL_MAXIMUM(4, 0xffffffff), REPORT_SIZE(1, 32), - REPORT_COUNT(1, 1), + REPORT_COUNT(1, 2), FEATURE(1, Data|Var|Abs), /* reset global items */ UNIT(1, 0), /* None */ @@ -318,7 +347,7 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
case IOCTL_HID_READ_REPORT: { - ULONG expected_size = 10; + ULONG expected_size = 22; ok(!in_size, "got input size %u\n", in_size); if (!test_failed) { diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 497c9a10adf..9ab7d1aa224 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1646,12 +1646,12 @@ static void test_hidp(HANDLE file, int report_id) { .Usage = HID_USAGE_GENERIC_JOYSTICK, .UsagePage = HID_USAGE_PAGE_GENERIC, - .InputReportByteLength = 11, - .FeatureReportByteLength = 14, + .InputReportByteLength = 23, + .FeatureReportByteLength = 18, .NumberLinkCollectionNodes = 7, .NumberInputButtonCaps = 5, - .NumberInputValueCaps = 4, - .NumberInputDataIndices = 32, + .NumberInputValueCaps = 7, + .NumberInputDataIndices = 35, .NumberFeatureButtonCaps = 1, .NumberFeatureValueCaps = 5, .NumberFeatureDataIndices = 7, @@ -1660,12 +1660,12 @@ static void test_hidp(HANDLE file, int report_id) { .Usage = HID_USAGE_GENERIC_JOYSTICK, .UsagePage = HID_USAGE_PAGE_GENERIC, - .InputReportByteLength = 10, - .FeatureReportByteLength = 13, + .InputReportByteLength = 22, + .FeatureReportByteLength = 17, .NumberLinkCollectionNodes = 7, .NumberInputButtonCaps = 5, - .NumberInputValueCaps = 4, - .NumberInputDataIndices = 32, + .NumberInputValueCaps = 7, + .NumberInputDataIndices = 35, .NumberFeatureButtonCaps = 1, .NumberFeatureValueCaps = 5, .NumberFeatureDataIndices = 7, @@ -1820,10 +1820,12 @@ static void test_hidp(HANDLE file, int report_id) HIDP_VALUE_CAPS value_caps[16]; char buffer[200], report[200]; DWORD collection_count; + DWORD waveform_list; NTSTATUS status; HIDP_CAPS caps; unsigned int i; USHORT count; + ULONG value; BOOL ret;
ret = HidD_GetPreparsedData(file, &preparsed_data); @@ -2164,6 +2166,151 @@ static void test_hidp(HANDLE file, int report_id) todo_wine_if(report_id) ok(!memcmp(buffer, report, sizeof(buffer)), "unexpected report data\n");
+ status = HidP_SetUsageValueArray(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, buffer, + sizeof(buffer), preparsed_data, report, caps.InputReportByteLength); + todo_wine + ok(status == HIDP_STATUS_NOT_VALUE_ARRAY, "HidP_SetUsageValueArray returned %#x\n", status); + memset(buffer, 0xcd, sizeof(buffer)); + status = HidP_SetUsageValueArray(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH, buffer, + 0, preparsed_data, report, caps.InputReportByteLength); + todo_wine + ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_SetUsageValueArray returned %#x\n", status); + status = HidP_SetUsageValueArray(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH, buffer, + 8, preparsed_data, report, caps.InputReportByteLength); + ok(status == HIDP_STATUS_NOT_IMPLEMENTED, "HidP_SetUsageValueArray returned %#x\n", status); + + status = HidP_GetUsageValueArray(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, buffer, + sizeof(buffer), preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_NOT_VALUE_ARRAY, "HidP_GetUsageValueArray returned %#x\n", status); + memset(buffer, 0xcd, sizeof(buffer)); + status = HidP_GetUsageValueArray(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH, buffer, + 0, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetUsageValueArray returned %#x\n", status); + status = HidP_GetUsageValueArray(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH, buffer, + 8, preparsed_data, report, caps.InputReportByteLength); + todo_wine + ok(status == HIDP_STATUS_NOT_IMPLEMENTED, "HidP_GetUsageValueArray returned %#x\n", status); + + value = -128; + status = HidP_SetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, + value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status); + value = 0xdeadbeef; + status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, + &value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status); + todo_wine_if(report_id) + ok(value == 0x80, "got value %x, expected %#x\n", value, 0x80); + value = 0xdeadbeef; + status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, + (LONG *)&value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status); + todo_wine_if(report_id) + ok(value == -128, "got value %x, expected %#x\n", value, -128); + + value = 127; + status = HidP_SetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, + value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status); + value = 0xdeadbeef; + status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, + (LONG *)&value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status); + todo_wine_if(report_id) + ok(value == 127, "got value %x, expected %#x\n", value, 127); + + value = 0; + status = HidP_SetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, + value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status); + value = 0xdeadbeef; + status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, + (LONG *)&value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status); + todo_wine_if(report_id) + ok(value == 0, "got value %x, expected %#x\n", value, 0); + + value = 0x7fffffff; + status = HidP_SetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status); + value = 0xdeadbeef; + status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + (LONG *)&value, preparsed_data, report, caps.InputReportByteLength); + todo_wine + ok(status == HIDP_STATUS_VALUE_OUT_OF_RANGE, "HidP_GetScaledUsageValue returned %#x\n", status); + todo_wine + ok(value == 0, "got value %x, expected %#x\n", value, 0); + value = 0xdeadbeef; + status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + &value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status); + todo_wine + ok(value == 0x7fffffff, "got value %x, expected %#x\n", value, 0x7fffffff); + + value = 0x3fffffff; + status = HidP_SetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status); + value = 0xdeadbeef; + status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + (LONG *)&value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status); + todo_wine + ok(value == 0x7fffffff, "got value %x, expected %#x\n", value, 0x7fffffff); + + value = 0; + status = HidP_SetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status); + value = 0xdeadbeef; + status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + (LONG *)&value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status); + todo_wine_if(report_id) + ok(value == 0x80000000, "got value %x, expected %#x\n", value, 0x80000000); + + value = 0; + status = HidP_SetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RX, + value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status); + value = 0xdeadbeef; + status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RX, + (LONG *)&value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status); + todo_wine_if(report_id) + ok(value == 0, "got value %x, expected %#x\n", value, 0); + + value = 0xfeedcafe; + status = HidP_SetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY, + value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status); + value = 0xdeadbeef; + status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY, + (LONG *)&value, preparsed_data, report, caps.InputReportByteLength); + todo_wine + ok(status == HIDP_STATUS_BAD_LOG_PHY_VALUES, "HidP_GetScaledUsageValue returned %#x\n", status); + todo_wine_if(report_id) + ok(value == 0, "got value %x, expected %#x\n", value, 0); + memset(report, 0xcd, sizeof(report)); status = HidP_InitializeReportForID(HidP_Feature, 3, preparsed_data, report, caps.FeatureReportByteLength); todo_wine_if(!report_id) @@ -2180,6 +2327,118 @@ static void test_hidp(HANDLE file, int report_id) todo_wine_if(report_id) ok(!memcmp(buffer, report, sizeof(buffer)), "unexpected report data\n");
+ for (i = 0; i < caps.NumberLinkCollectionNodes; ++i) + { + if (collections[i].LinkUsagePage != HID_USAGE_PAGE_HAPTICS) continue; + if (collections[i].LinkUsage == HID_USAGE_HAPTICS_WAVEFORM_LIST) break; + } + ok(i < caps.NumberLinkCollectionNodes, + "HID_USAGE_HAPTICS_WAVEFORM_LIST collection not found\n"); + waveform_list = i; + + status = HidP_SetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, + HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, (PHIDP_PREPARSED_DATA)buffer, + report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_SetUsageValue returned %#x\n", status); + status = HidP_SetUsageValue(HidP_Feature + 1, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, + HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, preparsed_data, report, + caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_SetUsageValue returned %#x\n", status); + status = HidP_SetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, + HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, preparsed_data, report, + caps.FeatureReportByteLength + 1); + todo_wine + ok(status == HIDP_STATUS_INVALID_REPORT_LENGTH, "HidP_SetUsageValue returned %#x\n", status); + report[0] = 1 - report_id; + status = HidP_SetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, + HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, preparsed_data, report, + caps.FeatureReportByteLength); + todo_wine + ok(status == (report_id ? HIDP_STATUS_SUCCESS : HIDP_STATUS_INCOMPATIBLE_REPORT_ID), + "HidP_SetUsageValue returned %#x\n", status); + report[0] = 2; + status = HidP_SetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, + HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, preparsed_data, report, + caps.FeatureReportByteLength); + todo_wine + ok(status == HIDP_STATUS_INCOMPATIBLE_REPORT_ID, "HidP_SetUsageValue returned %#x\n", status); + report[0] = report_id; + status = HidP_SetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, 0xdead, 3, HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, + preparsed_data, report, caps.FeatureReportByteLength); + todo_wine + ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_SetUsageValue returned %#x\n", status); + + status = HidP_SetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, + HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, preparsed_data, report, + caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status); + + memset(buffer, 0xcd, sizeof(buffer)); + memset(buffer, 0, caps.FeatureReportByteLength); + buffer[0] = report_id; + value = HID_USAGE_HAPTICS_WAVEFORM_RUMBLE; + memcpy(buffer + 1, &value, 2); + todo_wine + ok(!memcmp(buffer, report, sizeof(buffer)), "unexpected report data\n"); + + status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value, + (PHIDP_PREPARSED_DATA)buffer, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetUsageValue returned %#x\n", status); + status = HidP_GetUsageValue(HidP_Feature + 1, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, + &value, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetUsageValue returned %#x\n", status); + status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value, + preparsed_data, report, caps.FeatureReportByteLength + 1); + todo_wine + ok(status == HIDP_STATUS_INVALID_REPORT_LENGTH, "HidP_GetUsageValue returned %#x\n", status); + report[0] = 1 - report_id; + status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value, + preparsed_data, report, caps.FeatureReportByteLength); + todo_wine + ok(status == (report_id ? HIDP_STATUS_SUCCESS : HIDP_STATUS_INCOMPATIBLE_REPORT_ID), + "HidP_GetUsageValue returned %#x\n", status); + report[0] = 2; + status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value, + preparsed_data, report, caps.FeatureReportByteLength); + todo_wine + ok(status == HIDP_STATUS_INCOMPATIBLE_REPORT_ID, "HidP_GetUsageValue returned %#x\n", status); + report[0] = report_id; + status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, 0xdead, 3, &value, + preparsed_data, report, caps.FeatureReportByteLength); + todo_wine + ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetUsageValue returned %#x\n", status); + + value = 0xdeadbeef; + status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value, + preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status); + todo_wine + ok(value == HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, "got value %x, expected %#x\n", value, + HID_USAGE_HAPTICS_WAVEFORM_RUMBLE); + + memset(buffer, 0xff, sizeof(buffer)); + status = HidP_SetUsageValueArray(HidP_Feature, HID_USAGE_PAGE_HAPTICS, 0, HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME, buffer, + 0, preparsed_data, report, caps.FeatureReportByteLength); + todo_wine + ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_SetUsageValueArray returned %#x\n", status); + status = HidP_SetUsageValueArray(HidP_Feature, HID_USAGE_PAGE_HAPTICS, 0, HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME, buffer, + 64, preparsed_data, report, caps.FeatureReportByteLength); + todo_wine + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValueArray returned %#x\n", status); + todo_wine + ok(!memcmp(report + 9, buffer, 8), "unexpected report data\n"); + + memset(buffer, 0, sizeof(buffer)); + status = HidP_GetUsageValueArray(HidP_Feature, HID_USAGE_PAGE_HAPTICS, 0, HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME, buffer, + 0, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetUsageValueArray returned %#x\n", status); + status = HidP_GetUsageValueArray(HidP_Feature, HID_USAGE_PAGE_HAPTICS, 0, HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME, buffer, + 64, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValueArray returned %#x\n", status); + memset(buffer + 16, 0xff, 8); + todo_wine + ok(!memcmp(buffer, buffer + 16, 16), "unexpected report value\n"); + HidD_FreePreparsedData(preparsed_data); CloseHandle(file); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=92440
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
ntoskrnl.exe: ntoskrnl.c:1236: Test failed: got 0 bus arrival messages ntoskrnl.c:1252: Test failed: got 0 bus arrival messages ntoskrnl.c:1253: Test failed: got 0 bus removal messages ntoskrnl.c:1278: Test failed: got 0 child arrival messages ntoskrnl.c:1285: Test failed: failed to get device, error 0x103 ntoskrnl.c:1286: Test failed: wrong class {4d36e97d-e325-11ce-bfc1-08002be10318} ntoskrnl.c:1289: Test failed: failed to get device ID, error 0x57 ntoskrnl.c:1290: Test failed: got ID "\x05" ntoskrnl.c:1294: Test failed: got error 0x57 ntoskrnl.c:1311: Test failed: got error 0x57 ntoskrnl.c:1316: Test failed: got error 0x57 ntoskrnl.c:1320: Test failed: got error 0x57 ntoskrnl.c:1321: Test failed: got type 6357104 ntoskrnl.c:1322: Test failed: got size 0 ntoskrnl.c:1327: Test failed: got error 0x57 ntoskrnl.c:1328: Test failed: got type 6357104 ntoskrnl.c:1329: Test failed: got size 0 ntoskrnl.c:1334: Test failed: got error 0x57 ntoskrnl.c:1361: Test failed: got 0 child arrival messages ntoskrnl.c:1362: Test failed: got 0 child removal messages ntoskrnl.c:1365: Test failed: got 0 ntoskrnl.c:1464: Test failed: failed to get device list, error 0xd ntoskrnl.c:294: Test failed: expected SERVICE_STOPPED, got 4 ntoskrnl.c:2572: Test failed: failed to install device, error 0x430 ntoskrnl.c:2487: Test failed: report 0: didn't find device ntoskrnl.c:2491: Test failed: report 0: got error 123 ntoskrnl.c:1832: Test failed: report 0: HidD_GetPreparsedData failed with error 6 0450:ntoskrnl: unhandled exception c0000005 at 73921B19
=== w864 (64 bit report) ===
Report validation errors: ntoskrnl.exe:ntoskrnl crashed (c0000374)
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntoskrnl.exe/tests/driver_hid.c | 24 ++++- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 154 ++++++++++++++++++++++++--- 2 files changed, 162 insertions(+), 16 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/driver_hid.c b/dlls/ntoskrnl.exe/tests/driver_hid.c index 91e3a29e1df..acb51d99816 100644 --- a/dlls/ntoskrnl.exe/tests/driver_hid.c +++ b/dlls/ntoskrnl.exe/tests/driver_hid.c @@ -206,6 +206,28 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) INPUT(1, Data|Var|Abs), END_COLLECTION,
+ USAGE_PAGE(1, HID_USAGE_PAGE_LED), + USAGE(1, HID_USAGE_LED_GREEN), + COLLECTION(1, Report), + REPORT_ID_OR_USAGE_PAGE(1, report_id, 0), + USAGE_PAGE(1, HID_USAGE_PAGE_LED), + USAGE(1, 1), + USAGE(1, 2), + USAGE(1, 3), + USAGE(1, 4), + USAGE(1, 5), + USAGE(1, 6), + USAGE(1, 7), + USAGE(1, 8), + LOGICAL_MINIMUM(1, 0), + LOGICAL_MAXIMUM(1, 1), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 1), + REPORT_COUNT(1, 8), + REPORT_SIZE(1, 1), + INPUT(1, Data|Var|Abs), + END_COLLECTION, + USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS), USAGE(1, HID_USAGE_HAPTICS_SIMPLE_CONTROLLER), COLLECTION(1, Logical), @@ -347,7 +369,7 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
case IOCTL_HID_READ_REPORT: { - ULONG expected_size = 22; + ULONG expected_size = 23; ok(!in_size, "got input size %u\n", in_size); if (!test_failed) { diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 9ab7d1aa224..3b767f27ae7 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1646,12 +1646,12 @@ static void test_hidp(HANDLE file, int report_id) { .Usage = HID_USAGE_GENERIC_JOYSTICK, .UsagePage = HID_USAGE_PAGE_GENERIC, - .InputReportByteLength = 23, + .InputReportByteLength = 24, .FeatureReportByteLength = 18, - .NumberLinkCollectionNodes = 7, - .NumberInputButtonCaps = 5, + .NumberLinkCollectionNodes = 8, + .NumberInputButtonCaps = 13, .NumberInputValueCaps = 7, - .NumberInputDataIndices = 35, + .NumberInputDataIndices = 43, .NumberFeatureButtonCaps = 1, .NumberFeatureValueCaps = 5, .NumberFeatureDataIndices = 7, @@ -1660,12 +1660,12 @@ static void test_hidp(HANDLE file, int report_id) { .Usage = HID_USAGE_GENERIC_JOYSTICK, .UsagePage = HID_USAGE_PAGE_GENERIC, - .InputReportByteLength = 22, + .InputReportByteLength = 23, .FeatureReportByteLength = 17, - .NumberLinkCollectionNodes = 7, - .NumberInputButtonCaps = 5, + .NumberLinkCollectionNodes = 8, + .NumberInputButtonCaps = 13, .NumberInputValueCaps = 7, - .NumberInputDataIndices = 35, + .NumberInputDataIndices = 43, .NumberFeatureButtonCaps = 1, .NumberFeatureValueCaps = 5, .NumberFeatureDataIndices = 7, @@ -1804,8 +1804,8 @@ static void test_hidp(HANDLE file, int report_id) .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, .LinkUsagePage = HID_USAGE_PAGE_GENERIC, .CollectionType = 1, - .NumberOfChildren = 4, - .FirstChild = 6, + .NumberOfChildren = 5, + .FirstChild = 7, }, { .LinkUsage = HID_USAGE_GENERIC_JOYSTICK, @@ -1816,11 +1816,13 @@ static void test_hidp(HANDLE file, int report_id)
HIDP_LINK_COLLECTION_NODE collections[16]; PHIDP_PREPARSED_DATA preparsed_data; + USAGE_AND_PAGE usage_and_pages[16]; HIDP_BUTTON_CAPS button_caps[16]; HIDP_VALUE_CAPS value_caps[16]; char buffer[200], report[200]; DWORD collection_count; DWORD waveform_list; + USAGE usages[16]; NTSTATUS status; HIDP_CAPS caps; unsigned int i; @@ -1913,22 +1915,21 @@ static void test_hidp(HANDLE file, int report_id) winetest_push_context("button_caps[%d]", i); todo_wine_if(i >= 2) check_member(button_caps[i], expect_button_caps[i], "%04x", UsagePage); - todo_wine_if(i >= 2 && report_id) check_member(button_caps[i], expect_button_caps[i], "%d", ReportID); check_member(button_caps[i], expect_button_caps[i], "%d", IsAlias); todo_wine check_member(button_caps[i], expect_button_caps[i], "%d", BitField); todo_wine_if(i >= 2) check_member(button_caps[i], expect_button_caps[i], "%d", LinkCollection); - todo_wine_if(i >= 3) + todo_wine_if(i >= (report_id ? 2 : 3)) check_member(button_caps[i], expect_button_caps[i], "%04x", LinkUsage); - todo_wine_if(i >= 3) + todo_wine_if(i >= (report_id ? 2 : 3)) check_member(button_caps[i], expect_button_caps[i], "%04x", LinkUsagePage); - todo_wine_if(i == 1) + todo_wine_if(i >= 1 && i <= (report_id ? 2 : 1)) check_member(button_caps[i], expect_button_caps[i], "%d", IsRange); check_member(button_caps[i], expect_button_caps[i], "%d", IsStringRange); check_member(button_caps[i], expect_button_caps[i], "%d", IsDesignatorRange); - todo_wine_if(i >= 2) + todo_wine_if(i == 2) check_member(button_caps[i], expect_button_caps[i], "%d", IsAbsolute); todo_wine_if(i >= 1) check_member(button_caps[i], expect_button_caps[i], "%04x", Range.UsageMin); @@ -2311,6 +2312,129 @@ static void test_hidp(HANDLE file, int report_id) todo_wine_if(report_id) ok(value == 0, "got value %x, expected %#x\n", value, 0);
+ value = HidP_MaxUsageListLength(HidP_Feature + 1, 0, preparsed_data); + todo_wine + ok(value == 0, "HidP_MaxUsageListLength(HidP_Feature + 1, 0) returned %d, expected %d\n", value, 0); + value = HidP_MaxUsageListLength(HidP_Input, 0, preparsed_data); + todo_wine + ok(value == 42, "HidP_MaxUsageListLength(HidP_Input, 0) returned %d, expected %d\n", value, 42); + value = HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_BUTTON, preparsed_data); + todo_wine + ok(value == 32, "HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_BUTTON) returned %d, expected %d\n", value, 32); + value = HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_LED, preparsed_data); + ok(value == 8, "HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_LED) returned %d, expected %d\n", value, 8); + value = HidP_MaxUsageListLength(HidP_Feature, HID_USAGE_PAGE_BUTTON, preparsed_data); + todo_wine + ok(value == 8, "HidP_MaxUsageListLength(HidP_Feature, HID_USAGE_PAGE_BUTTON) returned %d, expected %d\n", value, 8); + value = HidP_MaxUsageListLength(HidP_Feature, HID_USAGE_PAGE_LED, preparsed_data); + ok(value == 0, "HidP_MaxUsageListLength(HidP_Feature, HID_USAGE_PAGE_LED) returned %d, expected %d\n", value, 0); + + usages[0] = 0xff; + value = 1; + status = HidP_SetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &value, + preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_SetUsages returned %#x\n", status); + usages[1] = 2; + usages[2] = 0xff; + value = 3; + status = HidP_SetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &value, + preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_SetUsages returned %#x\n", status); + usages[0] = 4; + usages[1] = 6; + value = 2; + status = HidP_SetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &value, + preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsages returned %#x\n", status); + usages[0] = 4; + usages[1] = 6; + value = 2; + status = HidP_SetUsages(HidP_Input, HID_USAGE_PAGE_LED, 0, usages, &value, preparsed_data, + report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsages returned %#x\n", status); + + status = HidP_SetUsageValue(HidP_Input, HID_USAGE_PAGE_LED, 0, 6, 1, + preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_SetUsageValue returned %#x\n", status); + + value = 0xdeadbeef; + status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_LED, 0, 6, &value, + preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_SetUsageValue returned %#x\n", status); + ok(value == 0xdeadbeef, "got value %x, expected %#x\n", value, 0xdeadbeef); + + value = 1; + status = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &value, + preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetUsages returned %#x\n", status); + todo_wine + ok(value == 2, "got usage count %d, expected %d\n", value, 2); + value = ARRAY_SIZE(usages); + memset(usages, 0xcd, sizeof(usages)); + status = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &value, + preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsages returned %#x\n", status); + todo_wine_if(report_id) + ok(value == 2, "got usage count %d, expected %d\n", value, 2); + todo_wine_if(report_id) + ok(usages[0] == 4, "got usages[0] %x, expected %x\n", usages[0], 4); + todo_wine_if(report_id) + ok(usages[1] == 6, "got usages[1] %x, expected %x\n", usages[1], 6); + + value = ARRAY_SIZE(usages); + memset(usages, 0xcd, sizeof(usages)); + status = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_LED, 0, usages, &value, preparsed_data, + report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsages returned %#x\n", status); + todo_wine_if(report_id) + ok(value == 2, "got usage count %d, expected %d\n", value, 2); + todo_wine + ok(usages[0] == 6, "got usages[0] %x, expected %x\n", usages[0], 6); + todo_wine + ok(usages[1] == 4, "got usages[1] %x, expected %x\n", usages[1], 4); + + value = ARRAY_SIZE(usage_and_pages); + memset(usage_and_pages, 0xcd, sizeof(usage_and_pages)); + status = HidP_GetUsagesEx(HidP_Input, 0, usage_and_pages, &value, preparsed_data, report, + caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsagesEx returned %#x\n", status); + todo_wine_if(report_id) + ok(value == 4, "got usage count %d, expected %d\n", value, 4); + todo_wine_if(report_id) + ok(usage_and_pages[0].UsagePage == HID_USAGE_PAGE_BUTTON, "got usage_and_pages[0] UsagePage %x, expected %x\n", + usage_and_pages[0].UsagePage, HID_USAGE_PAGE_BUTTON); + todo_wine_if(report_id) + ok(usage_and_pages[1].UsagePage == HID_USAGE_PAGE_BUTTON, "got usage_and_pages[1] UsagePage %x, expected %x\n", + usage_and_pages[1].UsagePage, HID_USAGE_PAGE_BUTTON); + todo_wine_if(report_id) + ok(usage_and_pages[2].UsagePage == HID_USAGE_PAGE_LED, "got usage_and_pages[2] UsagePage %x, expected %x\n", + usage_and_pages[2].UsagePage, HID_USAGE_PAGE_LED); + todo_wine_if(report_id) + ok(usage_and_pages[3].UsagePage == HID_USAGE_PAGE_LED, "got usage_and_pages[3] UsagePage %x, expected %x\n", + usage_and_pages[3].UsagePage, HID_USAGE_PAGE_LED); + todo_wine_if(report_id) + ok(usage_and_pages[0].Usage == 4, "got usage_and_pages[0] Usage %x, expected %x\n", + usage_and_pages[0].Usage, 4); + todo_wine_if(report_id) + ok(usage_and_pages[1].Usage == 6, "got usage_and_pages[1] Usage %x, expected %x\n", + usage_and_pages[1].Usage, 6); + todo_wine + ok(usage_and_pages[2].Usage == 6, "got usage_and_pages[2] Usage %x, expected %x\n", + usage_and_pages[2].Usage, 6); + todo_wine + ok(usage_and_pages[3].Usage == 4, "got usage_and_pages[3] Usage %x, expected %x\n", + usage_and_pages[3].Usage, 4); + memset(report, 0xcd, sizeof(report)); status = HidP_InitializeReportForID(HidP_Feature, 3, preparsed_data, report, caps.FeatureReportByteLength); todo_wine_if(!report_id)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=92441
Your paranoid android.
=== w864 (64 bit report) ===
Report validation errors: ntoskrnl.exe:ntoskrnl crashed (c0000374)
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 43 ++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 3b767f27ae7..f9549b804bd 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1813,6 +1813,18 @@ static void test_hidp(HANDLE file, int report_id) .CollectionType = 2, }, }; + static const HIDP_DATA expect_data[] = + { + { .DataIndex = 0, }, + { .DataIndex = 1, }, + { .DataIndex = 5, .RawValue = 1, }, + { .DataIndex = 7, .RawValue = 1, }, + { .DataIndex = 30, }, + { .DataIndex = 31, }, + { .DataIndex = 32, .RawValue = 0xfeedcafe, }, + { .DataIndex = 37, .RawValue = 1, }, + { .DataIndex = 39, .RawValue = 1, }, + };
HIDP_LINK_COLLECTION_NODE collections[16]; PHIDP_PREPARSED_DATA preparsed_data; @@ -1822,6 +1834,7 @@ static void test_hidp(HANDLE file, int report_id) char buffer[200], report[200]; DWORD collection_count; DWORD waveform_list; + HIDP_DATA data[32]; USAGE usages[16]; NTSTATUS status; HIDP_CAPS caps; @@ -2435,6 +2448,36 @@ static void test_hidp(HANDLE file, int report_id) ok(usage_and_pages[3].Usage == 4, "got usage_and_pages[3] Usage %x, expected %x\n", usage_and_pages[3].Usage, 4);
+ value = HidP_MaxDataListLength(HidP_Feature + 1, preparsed_data); + ok(value == 0, "HidP_MaxDataListLength(HidP_Feature + 1) returned %d, expected %d\n", value, 0); + value = HidP_MaxDataListLength(HidP_Input, preparsed_data); + todo_wine + ok(value == 50, "HidP_MaxDataListLength(HidP_Input) returned %d, expected %d\n", value, 50); + value = HidP_MaxDataListLength(HidP_Output, preparsed_data); + ok(value == 0, "HidP_MaxDataListLength(HidP_Output) returned %d, expected %d\n", value, 0); + value = HidP_MaxDataListLength(HidP_Feature, preparsed_data); + ok(value == 13, "HidP_MaxDataListLength(HidP_Feature) returned %d, expected %d\n", value, 13); + + value = 1; + status = HidP_GetData(HidP_Input, data, &value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetData returned %#x\n", status); + todo_wine + ok(value == 9, "got data count %d, expected %d\n", value, 9); + memset(data, 0, sizeof(data)); + status = HidP_GetData(HidP_Input, data, &value, preparsed_data, report, caps.InputReportByteLength); + todo_wine_if(report_id) + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetData returned %#x\n", status); + if (status == HIDP_STATUS_SUCCESS) for (i = 0; i < ARRAY_SIZE(expect_data); ++i) + { + winetest_push_context("data[%d]", i); + todo_wine_if(i >= 4) + check_member(data[i], expect_data[i], "%d", DataIndex); + todo_wine_if(i == 6 || i == 7 || i == 8) + check_member(data[i], expect_data[i], "%d", RawValue); + winetest_pop_context(); + } + memset(report, 0xcd, sizeof(report)); status = HidP_InitializeReportForID(HidP_Feature, 3, preparsed_data, report, caps.FeatureReportByteLength); todo_wine_if(!report_id)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=92442
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
ntoskrnl.exe: ntoskrnl.c:1236: Test failed: got 0 bus arrival messages ntoskrnl.c:1252: Test failed: got 0 bus arrival messages
=== w864 (64 bit report) ===
Report validation errors: ntoskrnl.exe:ntoskrnl crashed (c0000374)