[PATCH 4/4] user32: Implement RegisterRawInputDevices().

Henri Verbeet hverbeet at codeweavers.com
Sat Sep 8 04:26:26 CDT 2012


---
 dlls/user32/input.c |   41 ++++++++++++++++++++++++++++++++++++++---
 server/process.c    |    7 +++++++
 server/process.h    |    7 +++++++
 server/protocol.def |   14 ++++++++++++++
 server/queue.c      |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 server/trace.c      |   17 +++++++++++++++++
 6 files changed, 129 insertions(+), 3 deletions(-)

diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index 050fb2b..5c53129 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -486,11 +486,46 @@ UINT WINAPI GetRawInputDeviceList(PRAWINPUTDEVICELIST pRawInputDeviceList, PUINT
 /******************************************************************
 *		RegisterRawInputDevices (USER32.@)
 */
-BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(PRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize)
+BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(RAWINPUTDEVICE *devices, UINT device_count, UINT size)
 {
-    FIXME("(pRawInputDevices=%p, uiNumDevices=%d, cbSize=%d) stub!\n", pRawInputDevices, uiNumDevices, cbSize);
+    struct rawinput_device *d;
+    BOOL ret;
+    UINT i;
 
-    return TRUE;
+    TRACE("devices %p, device_count %u, size %u.\n", devices, device_count, size);
+
+    if (size != sizeof(*devices))
+    {
+        WARN("Invalid structure size %u.\n", size);
+        return FALSE;
+    }
+
+    if (!(d = HeapAlloc( GetProcessHeap(), 0, device_count * sizeof(*d) ))) return FALSE;
+
+    for (i = 0; i < device_count; ++i)
+    {
+        TRACE("device %u: page %#x, usage %#x, flags %#x, target %p.\n",
+                i, devices[i].usUsagePage, devices[i].usUsage,
+                devices[i].dwFlags, devices[i].hwndTarget);
+        if (devices[i].dwFlags & ~RIDEV_REMOVE)
+            FIXME("Unhandled flags %#x for device %u.\n", devices[i].dwFlags, i);
+
+        d[i].usage_page = devices[i].usUsagePage;
+        d[i].usage = devices[i].usUsage;
+        d[i].flags = devices[i].dwFlags;
+        d[i].target = wine_server_user_handle( devices[i].hwndTarget );
+    }
+
+    SERVER_START_REQ( update_rawinput_devices )
+    {
+        wine_server_add_data( req, d, device_count * sizeof(*d) );
+        ret = !wine_server_call( req );
+    }
+    SERVER_END_REQ;
+
+    HeapFree( GetProcessHeap(), 0, d );
+
+    return ret;
 }
 
 
diff --git a/server/process.c b/server/process.c
index 6a5f4b1..b8d5474 100644
--- a/server/process.c
+++ b/server/process.c
@@ -337,6 +337,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit
     list_init( &process->locks );
     list_init( &process->classes );
     list_init( &process->dlls );
+    list_init( &process->rawinput_devices );
 
     process->start_time = current_time;
     process->end_time = 0;
@@ -634,6 +635,12 @@ static void process_killed( struct process *process )
     /* close the console attached to this process, if any */
     free_console( process );
 
+    while ((ptr = list_head( &process->rawinput_devices )))
+    {
+        struct rawinput_device_entry *entry = LIST_ENTRY( ptr, struct rawinput_device_entry, entry );
+        list_remove( &entry->entry );
+        free( entry );
+    }
     while ((ptr = list_head( &process->dlls )))
     {
         struct process_dll *dll = LIST_ENTRY( ptr, struct process_dll, entry );
diff --git a/server/process.h b/server/process.h
index 976dd38..e9861bb 100644
--- a/server/process.h
+++ b/server/process.h
@@ -45,6 +45,12 @@ struct process_dll
     WCHAR               *filename;        /* dll file name */
 };
 
+struct rawinput_device_entry
+{
+    struct               list entry;
+    struct               rawinput_device device;
+};
+
 struct process
 {
     struct object        obj;             /* object header */
@@ -81,6 +87,7 @@ struct process
     client_ptr_t         peb;             /* PEB address in client address space */
     client_ptr_t         ldt_copy;        /* pointer to LDT copy in client addr space */
     unsigned int         trace_data;      /* opaque data used by the process tracing mechanism */
+    struct list          rawinput_devices;/* list of registered rawinput devices */
 };
 
 struct process_snapshot
diff --git a/server/protocol.def b/server/protocol.def
index 33cbb30..e1ff3e6 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -610,6 +610,14 @@ typedef union
     } create_thread;
 } apc_result_t;
 
+struct rawinput_device
+{
+    unsigned short usage_page;
+    unsigned short usage;
+    unsigned int   flags;
+    user_handle_t  target;
+};
+
 /****************************************************************/
 /* Request declarations */
 
@@ -3365,6 +3373,12 @@ enum coords_relative
 #define SET_CURSOR_NOCLIP 0x10
 
 
+/* Modify the list of registered rawinput devices */
+ at REQ(update_rawinput_devices)
+    VARARG(devices,rawinput_devices);
+ at END
+
+
 /* Retrieve the suspended context of a thread */
 @REQ(get_suspend_context)
 @REPLY
diff --git a/server/queue.c b/server/queue.c
index 4fd32ed..6c61bde 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1391,6 +1391,40 @@ static user_handle_t find_hardware_message_window( struct desktop *desktop, stru
     return win;
 }
 
+static struct rawinput_device_entry *find_rawinput_device( unsigned short usage_page, unsigned short usage )
+{
+    struct rawinput_device_entry *e;
+
+    LIST_FOR_EACH_ENTRY( e, &current->process->rawinput_devices, struct rawinput_device_entry, entry )
+    {
+        if (e->device.usage_page != usage_page || e->device.usage != usage) continue;
+        return e;
+    }
+
+    return NULL;
+}
+
+static void update_rawinput_device(const struct rawinput_device *device)
+{
+    struct rawinput_device_entry *e;
+
+    if (!(e = find_rawinput_device( device->usage_page, device->usage )))
+    {
+        if (!(e = mem_alloc( sizeof(*e) ))) return;
+        list_add_tail( &current->process->rawinput_devices, &e->entry );
+    }
+
+    if (device->flags & RIDEV_REMOVE)
+    {
+        list_remove( &e->entry );
+        free( e );
+        return;
+    }
+
+    e->device = *device;
+    e->device.target = get_user_full_handle( e->device.target );
+}
+
 /* queue a hardware message into a given thread input */
 static void queue_hardware_message( struct desktop *desktop, struct message *msg, int always_queue )
 {
@@ -2931,3 +2965,15 @@ DECL_HANDLER(set_cursor)
     reply->new_clip    = input->desktop->cursor.clip;
     reply->last_change = input->desktop->cursor.last_change;
 }
+
+DECL_HANDLER(update_rawinput_devices)
+{
+    const struct rawinput_device *devices = get_req_data();
+    unsigned int device_count = get_req_data_size() / sizeof (*devices);
+    unsigned int i;
+
+    for (i = 0; i < device_count; ++i)
+    {
+        update_rawinput_device(&devices[i]);
+    }
+}
diff --git a/server/trace.c b/server/trace.c
index 4318a34..9afb94f 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1004,6 +1004,23 @@ static void dump_varargs_filesystem_event( const char *prefix, data_size_t size
     fputc( '}', stderr );
 }
 
+static void dump_varargs_rawinput_devices(const char *prefix, data_size_t size )
+{
+    const struct rawinput_device *device;
+
+    fprintf( stderr, "%s{", prefix );
+    while (size >= sizeof(*device))
+    {
+        device = cur_data;
+        fprintf( stderr, "{usage_page=%#x,usage=%#x,flags=%#x,target=%#x}",
+                 device->usage_page, device->usage, device->flags, device->target );
+        size -= sizeof(*device);
+        remove_data( sizeof(*device) );
+        if (size) fputc( ',', stderr );
+    }
+    fputc( '}', stderr );
+}
+
 typedef void (*dump_func)( const void *req );
 
 /* Everything below this line is generated automatically by tools/make_requests */
-- 
1.7.8.6




More information about the wine-patches mailing list