From: "Rémi Bernon" Subject: [PATCH v3 2/6] user32: Implement GetRegisteredRawInputDevices. Message-Id: <20200703095707.720159-2-rbernon@codeweavers.com> Date: Fri, 3 Jul 2020 11:57:03 +0200 In-Reply-To: <20200703095707.720159-1-rbernon@codeweavers.com> References: <20200703095707.720159-1-rbernon@codeweavers.com> Signed-off-by: Rémi Bernon --- v3: return STATUS_BUFFER_TOO_SMALL when appropriate and use wine_server_call_err to set last error from status. The case where client buffer is not NULL but *device_count is 0 is treated as an invalid parameter combination, as it is the case on some windows versions. It then simplifies the server code where we can handle get_reply_max_size() == 0 as the NULL buffer case. dlls/dinput8/tests/device.c | 13 ---------- dlls/user32/rawinput.c | 50 +++++++++++++++++++++++++++++++++++-- dlls/user32/tests/input.c | 15 ----------- server/protocol.def | 6 +++++ server/queue.c | 22 ++++++++++++++++ 5 files changed, 76 insertions(+), 30 deletions(-) diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c index 39c635f2fb9..328174e5796 100644 --- a/dlls/dinput8/tests/device.c +++ b/dlls/dinput8/tests/device.c @@ -602,7 +602,6 @@ static void test_mouse_keyboard(void) raw_devices_count = ARRAY_SIZE(raw_devices); GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - todo_wine ok(raw_devices_count == 0, "Unexpected raw devices registered: %d\n", raw_devices_count); hr = IDirectInputDevice8_Acquire(di_keyboard); @@ -624,7 +623,6 @@ static void test_mouse_keyboard(void) ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr); raw_devices_count = ARRAY_SIZE(raw_devices); GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - todo_wine ok(raw_devices_count == 0, "Unexpected raw devices registered: %d\n", raw_devices_count); if (raw_devices[0].hwndTarget != NULL) @@ -662,7 +660,6 @@ static void test_mouse_keyboard(void) ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr); raw_devices_count = ARRAY_SIZE(raw_devices); GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - todo_wine ok(raw_devices_count == 0, "Unexpected raw devices registered: %d\n", raw_devices_count); /* expect dinput8 to take over any activated raw input devices */ @@ -689,26 +686,18 @@ static void test_mouse_keyboard(void) raw_devices_count = ARRAY_SIZE(raw_devices); memset(raw_devices, 0, sizeof(raw_devices)); hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - todo_wine ok(hr == 3, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count); - todo_wine ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage); - todo_wine ok(raw_devices[0].usUsage == 2, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage); todo_wine ok(raw_devices[0].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags); todo_wine ok(raw_devices[0].hwndTarget == di_hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget); - todo_wine ok(raw_devices[1].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[1].usUsagePage); - todo_wine ok(raw_devices[1].usUsage == 5, "Unexpected raw device usage: %x\n", raw_devices[1].usUsage); ok(raw_devices[1].dwFlags == 0, "Unexpected raw device flags: %x\n", raw_devices[1].dwFlags); - todo_wine ok(raw_devices[1].hwndTarget == hwnd, "Unexpected raw device target: %p\n", raw_devices[1].hwndTarget); - todo_wine ok(raw_devices[2].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[1].usUsagePage); - todo_wine ok(raw_devices[2].usUsage == 6, "Unexpected raw device usage: %x\n", raw_devices[1].usUsage); todo_wine ok(raw_devices[2].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[1].dwFlags); @@ -727,12 +716,10 @@ static void test_mouse_keyboard(void) hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE)); todo_wine ok(hr == 1, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count); - todo_wine ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage); todo_wine ok(raw_devices[0].usUsage == 5, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage); ok(raw_devices[0].dwFlags == 0, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags); - todo_wine ok(raw_devices[0].hwndTarget == hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget); IDirectInputDevice8_Release(di_mouse); diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index b5af008e885..f33f21eee9d 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -732,14 +732,60 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE handle, UINT command, void *data, UINT return *data_size; } +static int compare_raw_input_devices(const void *ap, const void *bp) +{ + const RAWINPUTDEVICE a = *(const RAWINPUTDEVICE *)ap; + const RAWINPUTDEVICE b = *(const RAWINPUTDEVICE *)bp; + + if (a.usUsagePage != b.usUsagePage) return a.usUsagePage - b.usUsagePage; + if (a.usUsage != b.usUsage) return a.usUsage - b.usUsage; + return 0; +} + /*********************************************************************** * GetRegisteredRawInputDevices (USER32.@) */ UINT WINAPI DECLSPEC_HOTPATCH GetRegisteredRawInputDevices(RAWINPUTDEVICE *devices, UINT *device_count, UINT size) { - FIXME("devices %p, device_count %p, size %u stub!\n", devices, device_count, size); + struct rawinput_device *buffer = NULL; + unsigned int i, status, count = ~0U, buffer_size; - return 0; + TRACE("devices %p, device_count %p, size %u\n", devices, device_count, size); + + if (size != sizeof(RAWINPUTDEVICE) || !device_count || (devices && !*device_count)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return ~0U; + } + + buffer_size = *device_count * sizeof(*buffer); + if (devices && !(buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size))) + return ~0U; + + SERVER_START_REQ(get_rawinput_devices) + { + if (buffer) wine_server_set_reply(req, buffer, buffer_size); + status = wine_server_call_err(req); + *device_count = reply->device_count; + } + SERVER_END_REQ; + + if (buffer && !status) + { + for (i = 0, count = *device_count; i < count; ++i) + { + devices[i].usUsagePage = buffer[i].usage_page; + devices[i].usUsage = buffer[i].usage; + devices[i].dwFlags = buffer[i].flags; + devices[i].hwndTarget = wine_server_ptr_handle(buffer[i].target); + } + + qsort(devices, count, sizeof(*devices), compare_raw_input_devices); + } + + if (buffer) HeapFree(GetProcessHeap(), 0, buffer); + else count = 0; + return count; } diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 4310ad1f296..cea8f375398 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -1794,25 +1794,20 @@ static void test_RegisterRawInputDevices(void) SetLastError(0xdeadbeef); count = GetRegisteredRawInputDevices(NULL, NULL, 0); - todo_wine ok(count == ~0U, "GetRegisteredRawInputDevices returned %u\n", count); - todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRegisteredRawInputDevices unexpected error %08x\n", GetLastError()); SetLastError(0xdeadbeef); raw_devices_count = 0; count = GetRegisteredRawInputDevices(NULL, &raw_devices_count, 0); - todo_wine ok(count == ~0U, "GetRegisteredRawInputDevices returned %u\n", count); ok(raw_devices_count == 0, "Unexpected registered devices count: %u\n", raw_devices_count); - todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRegisteredRawInputDevices unexpected error %08x\n", GetLastError()); SetLastError(0xdeadbeef); raw_devices_count = 0; count = GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE)); ok(count == 0, "GetRegisteredRawInputDevices returned %u\n", count); - todo_wine ok(raw_devices_count == 2, "Unexpected registered devices count: %u\n", raw_devices_count); ok(GetLastError() == 0xdeadbeef, "GetRegisteredRawInputDevices unexpected error %08x\n", GetLastError()); @@ -1823,38 +1818,28 @@ static void test_RegisterRawInputDevices(void) win_skip("Ignoring GetRegisteredRawInputDevices success\n"); else { - todo_wine ok(count == ~0U, "GetRegisteredRawInputDevices returned %u\n", count); ok(raw_devices_count == 0, "Unexpected registered devices count: %u\n", raw_devices_count); - todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRegisteredRawInputDevices unexpected error %08x\n", GetLastError()); } SetLastError(0xdeadbeef); raw_devices_count = 1; count = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - todo_wine ok(count == ~0U, "GetRegisteredRawInputDevices returned %u\n", count); - todo_wine ok(raw_devices_count == 2, "Unexpected registered devices count: %u\n", raw_devices_count); - todo_wine ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetRegisteredRawInputDevices unexpected error %08x\n", GetLastError()); SetLastError(0xdeadbeef); memset(raw_devices, 0, sizeof(raw_devices)); raw_devices_count = ARRAY_SIZE(raw_devices); count = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE)); - todo_wine ok(count == 2, "GetRegisteredRawInputDevices returned %u\n", count); ok(raw_devices_count == 2, "Unexpected registered devices count: %u\n", raw_devices_count); ok(GetLastError() == 0xdeadbeef, "GetRegisteredRawInputDevices unexpected error %08x\n", GetLastError()); - todo_wine ok(raw_devices[0].usUsagePage == 0x01, "Unexpected usage page: %x\n", raw_devices[0].usUsagePage); - todo_wine ok(raw_devices[0].usUsage == 0x04, "Unexpected usage: %x\n", raw_devices[0].usUsage); - todo_wine ok(raw_devices[1].usUsagePage == 0x01, "Unexpected usage page: %x\n", raw_devices[1].usUsagePage); - todo_wine ok(raw_devices[1].usUsage == 0x05, "Unexpected usage: %x\n", raw_devices[1].usUsage); /* RIDEV_REMOVE requires hwndTarget == NULL */ diff --git a/server/protocol.def b/server/protocol.def index 6416306c0a1..56fda14932d 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3899,6 +3899,12 @@ struct handle_info VARARG(devices,rawinput_devices); @END +/* Retrieve the list of registered rawinput devices */ +@REQ(get_rawinput_devices) +@REPLY + unsigned int device_count; + VARARG(devices,rawinput_devices); +@END /* Create a new job object */ @REQ(create_job) diff --git a/server/queue.c b/server/queue.c index 432885f9e4c..3ba774ebd1d 100644 --- a/server/queue.c +++ b/server/queue.c @@ -3283,3 +3283,25 @@ DECL_HANDLER(update_rawinput_devices) e = find_rawinput_device( 1, 6 ); current->process->rawinput_kbd = e ? &e->device : NULL; } + +DECL_HANDLER(get_rawinput_devices) +{ + struct rawinput_device_entry *e; + struct rawinput_device *devices; + unsigned int i = 0, device_count = list_count( ¤t->process->rawinput_devices ); + unsigned int size = device_count * sizeof(*devices); + + reply->device_count = device_count; + + /* no buffer provided, nothing else to do */ + if (!get_reply_max_size()) return; + + if (size > get_reply_max_size()) + set_error( STATUS_BUFFER_TOO_SMALL ); + else if ((devices = mem_alloc( size ))) + { + LIST_FOR_EACH_ENTRY( e, ¤t->process->rawinput_devices, struct rawinput_device_entry, entry ) + devices[i++] = e->device; + set_reply_data_ptr( devices, size ); + } +} -- 2.27.0