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);