From 5befb959dd6f6e3567f0cd4fabd28b3b3b92966d Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Sat, 8 Sep 2012 11:26:26 +0200 Subject: [PATCH] user32: Implement RegisterRawInputDevices(). --- dlls/user32/input.c | 41 +++++++++++++++++++++++++++--- include/wine/server_protocol.h | 26 ++++++++++++++++++- server/process.c | 7 ++++++ server/process.h | 7 ++++++ server/protocol.def | 14 +++++++++++ server/queue.c | 46 ++++++++++++++++++++++++++++++++++ server/request.h | 3 +++ server/trace.c | 26 +++++++++++++++++++ 8 files changed, 166 insertions(+), 4 deletions(-) diff --git a/dlls/user32/input.c b/dlls/user32/input.c index 050fb2b03b9..5c531297b43 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/include/wine/server_protocol.h b/include/wine/server_protocol.h index 41e8e2800e4..cc9319022ef 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -594,6 +594,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; +}; + @@ -4866,6 +4874,19 @@ struct set_cursor_reply +struct update_rawinput_devices_request +{ + struct request_header __header; + /* VARARG(devices,rawinput_devices); */ + char __pad_12[4]; +}; +struct update_rawinput_devices_reply +{ + struct reply_header __header; +}; + + + struct get_suspend_context_request { struct request_header __header; @@ -5138,6 +5159,7 @@ enum request REQ_alloc_user_handle, REQ_free_user_handle, REQ_set_cursor, + REQ_update_rawinput_devices, REQ_get_suspend_context, REQ_set_suspend_context, REQ_NB_REQUESTS @@ -5392,6 +5414,7 @@ union generic_request struct alloc_user_handle_request alloc_user_handle_request; struct free_user_handle_request free_user_handle_request; struct set_cursor_request set_cursor_request; + struct update_rawinput_devices_request update_rawinput_devices_request; struct get_suspend_context_request get_suspend_context_request; struct set_suspend_context_request set_suspend_context_request; }; @@ -5644,10 +5667,11 @@ union generic_reply struct alloc_user_handle_reply alloc_user_handle_reply; struct free_user_handle_reply free_user_handle_reply; struct set_cursor_reply set_cursor_reply; + struct update_rawinput_devices_reply update_rawinput_devices_reply; struct get_suspend_context_reply get_suspend_context_reply; struct set_suspend_context_reply set_suspend_context_reply; }; -#define SERVER_PROTOCOL_VERSION 432 +#define SERVER_PROTOCOL_VERSION 433 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/process.c b/server/process.c index 6a5f4b1b6b9..b8d547451b8 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 976dd38488e..5ddefc2bee1 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 33cbb30f82a..e1ff3e6f983 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 */ +@REQ(update_rawinput_devices) + VARARG(devices,rawinput_devices); +@END + + /* Retrieve the suspended context of a thread */ @REQ(get_suspend_context) @REPLY diff --git a/server/queue.c b/server/queue.c index 4fd32ed0e99..6c61bdef204 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, ¤t->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( ¤t->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/request.h b/server/request.h index 8f9308546c7..7ec16cf4c80 100644 --- a/server/request.h +++ b/server/request.h @@ -356,6 +356,7 @@ DECL_HANDLER(set_window_layered_info); DECL_HANDLER(alloc_user_handle); DECL_HANDLER(free_user_handle); DECL_HANDLER(set_cursor); +DECL_HANDLER(update_rawinput_devices); DECL_HANDLER(get_suspend_context); DECL_HANDLER(set_suspend_context); @@ -609,6 +610,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_alloc_user_handle, (req_handler)req_free_user_handle, (req_handler)req_set_cursor, + (req_handler)req_update_rawinput_devices, (req_handler)req_get_suspend_context, (req_handler)req_set_suspend_context, }; @@ -2141,6 +2143,7 @@ C_ASSERT( FIELD_OFFSET(struct set_cursor_reply, new_y) == 28 ); C_ASSERT( FIELD_OFFSET(struct set_cursor_reply, new_clip) == 32 ); C_ASSERT( FIELD_OFFSET(struct set_cursor_reply, last_change) == 48 ); C_ASSERT( sizeof(struct set_cursor_reply) == 56 ); +C_ASSERT( sizeof(struct update_rawinput_devices_request) == 16 ); C_ASSERT( sizeof(struct get_suspend_context_request) == 16 ); C_ASSERT( sizeof(struct get_suspend_context_reply) == 8 ); C_ASSERT( sizeof(struct set_suspend_context_request) == 16 ); diff --git a/server/trace.c b/server/trace.c index 4318a34857b..b7b3b104bae 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=%04x,usage=%04x,flags=%08x,target=%08x}", + 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 */ @@ -3900,6 +3917,11 @@ static void dump_set_cursor_reply( const struct set_cursor_reply *req ) fprintf( stderr, ", last_change=%08x", req->last_change ); } +static void dump_update_rawinput_devices_request( const struct update_rawinput_devices_request *req ) +{ + dump_varargs_rawinput_devices( " devices=", cur_size ); +} + static void dump_get_suspend_context_request( const struct get_suspend_context_request *req ) { } @@ -4160,6 +4182,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_alloc_user_handle_request, (dump_func)dump_free_user_handle_request, (dump_func)dump_set_cursor_request, + (dump_func)dump_update_rawinput_devices_request, (dump_func)dump_get_suspend_context_request, (dump_func)dump_set_suspend_context_request, }; @@ -4410,6 +4433,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_alloc_user_handle_reply, NULL, (dump_func)dump_set_cursor_reply, + NULL, (dump_func)dump_get_suspend_context_reply, NULL, }; @@ -4660,6 +4684,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "alloc_user_handle", "free_user_handle", "set_cursor", + "update_rawinput_devices", "get_suspend_context", "set_suspend_context", }; @@ -4724,6 +4749,7 @@ static const struct { "IO_TIMEOUT", STATUS_IO_TIMEOUT }, { "KEY_DELETED", STATUS_KEY_DELETED }, { "MAPPED_FILE_SIZE_ZERO", STATUS_MAPPED_FILE_SIZE_ZERO }, + { "MORE_PROCESSING_REQUIRED", STATUS_MORE_PROCESSING_REQUIRED }, { "MUTANT_NOT_OWNED", STATUS_MUTANT_NOT_OWNED }, { "NAME_TOO_LONG", STATUS_NAME_TOO_LONG }, { "NETWORK_BUSY", STATUS_NETWORK_BUSY },