From 731ba2fb44187652810a106fe369d6b557ec039f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 26 Aug 2019 16:06:58 +0200
Subject: [PATCH] user32: Implement GetRegisteredRawInputDevices.

---
 dlls/dinput8/tests/device.c | 13 ---------
 dlls/user32/rawinput.c      | 55 +++++++++++++++++++++++++++++++++++--
 server/protocol.def         |  6 ++++
 server/queue.c              | 24 ++++++++++++++++
 4 files changed, 83 insertions(+), 15 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..43da5248faf 100644
--- a/dlls/user32/rawinput.c
+++ b/dlls/user32/rawinput.c
@@ -732,14 +732,65 @@ 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 *d = NULL;
+    unsigned int count = ~0U;
 
-    return 0;
+    TRACE("devices %p, device_count %p, size %u\n", devices, device_count, size);
+
+    if (!device_count)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return ~0U;
+    }
+
+    if (devices && !(d = HeapAlloc( GetProcessHeap(), 0, *device_count * sizeof(*d) )))
+        return ~0U;
+
+    SERVER_START_REQ( get_rawinput_devices )
+    {
+        if (d)
+            wine_server_set_reply( req, d, *device_count * sizeof(*d) );
+
+        if (wine_server_call( req ))
+            goto done;
+
+        if (!d || reply->device_count > *device_count)
+        {
+            *device_count = reply->device_count;
+            SetLastError( ERROR_INSUFFICIENT_BUFFER );
+            goto done;
+        }
+
+        for (count = 0; count < reply->device_count; ++count)
+        {
+            devices[count].usUsagePage = d[count].usage_page;
+            devices[count].usUsage = d[count].usage;
+            devices[count].dwFlags = d[count].flags;
+            devices[count].hwndTarget = wine_server_ptr_handle(d[count].target);
+        }
+    }
+    SERVER_END_REQ;
+
+    qsort(devices, count, sizeof(*devices), compare_raw_input_devices);
+
+done:
+    if (d) HeapFree( GetProcessHeap(), 0, d );
+    return count;
 }
 
 
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..ff9e703d1ff 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -3283,3 +3283,27 @@ DECL_HANDLER(update_rawinput_devices)
     e = find_rawinput_device( 1, 6 );
     current->process->rawinput_kbd   = e ? &e->device : NULL;
 }
+
+DECL_HANDLER(get_rawinput_devices)
+{
+    unsigned int device_count = list_count(&current->process->rawinput_devices);
+    struct rawinput_device *devices;
+    struct rawinput_device_entry *e;
+    unsigned int i;
+
+    reply->device_count = device_count;
+    if (get_reply_max_size() / sizeof (*devices) < device_count)
+        return;
+
+    if (!(devices = mem_alloc( device_count * sizeof (*devices) )))
+    {
+        set_error( STATUS_NO_MEMORY );
+        return;
+    }
+
+    i = 0;
+    LIST_FOR_EACH_ENTRY( e, &current->process->rawinput_devices, struct rawinput_device_entry, entry )
+        devices[i++] = e->device;
+
+    set_reply_data_ptr( devices, device_count * sizeof (*devices) );
+}
-- 
2.27.0

