Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- server/protocol.def | 2 ++ server/queue.c | 20 ++++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/server/protocol.def b/server/protocol.def index 6af0ae0cff8..ab3af90545b 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2315,6 +2315,8 @@ enum message_type VARARG(keystate,bytes); /* global state array for all the keys */ @END #define SEND_HWMSG_INJECTED 0x01 +#define SEND_HWMSG_ONLY_RAW 0x02 +#define SEND_HWMSG_SKIP_RAW 0x04
/* Get a message from the current queue */ diff --git a/server/queue.c b/server/queue.c index b5e17be18fb..418cd7e524e 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1598,7 +1598,7 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa
/* queue a hardware message for a mouse event */ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input, - unsigned int origin, struct msg_queue *sender ) + unsigned int origin, struct msg_queue *sender, unsigned int req_flags ) { const struct rawinput_device *device; struct hardware_msg_data *msg_data; @@ -1651,7 +1651,8 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons y = desktop->cursor.y; }
- if ((device = current->process->rawinput_mouse)) + if ((device = current->process->rawinput_mouse) && + !(req_flags & SEND_HWMSG_SKIP_RAW)) { if (!(msg = alloc_hardware_message( input->mouse.info, source, time ))) return 0; msg_data = msg->data; @@ -1670,6 +1671,9 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons queue_hardware_message( desktop, msg, 0 ); }
+ if (req_flags & SEND_HWMSG_ONLY_RAW) + return 0; + for (i = 0; i < ARRAY_SIZE( messages ); i++) { if (!messages[i]) continue; @@ -1701,7 +1705,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
/* queue a hardware message for a keyboard event */ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input, - unsigned int origin, struct msg_queue *sender ) + unsigned int origin, struct msg_queue *sender, unsigned int req_flags ) { struct hw_msg_source source = { IMDT_KEYBOARD, origin }; const struct rawinput_device *device; @@ -1777,7 +1781,8 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c break; }
- if ((device = current->process->rawinput_kbd)) + if ((device = current->process->rawinput_kbd) && + !(req_flags & SEND_HWMSG_SKIP_RAW)) { if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0; msg_data = msg->data; @@ -1795,6 +1800,9 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c queue_hardware_message( desktop, msg, 0 ); }
+ if (req_flags & SEND_HWMSG_ONLY_RAW) + return 0; + if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0; msg_data = msg->data;
@@ -2351,10 +2359,10 @@ DECL_HANDLER(send_hardware_message) switch (req->input.type) { case INPUT_MOUSE: - reply->wait = queue_mouse_message( desktop, req->win, &req->input, origin, sender ); + reply->wait = queue_mouse_message( desktop, req->win, &req->input, origin, sender, req->flags ); break; case INPUT_KEYBOARD: - reply->wait = queue_keyboard_message( desktop, req->win, &req->input, origin, sender ); + reply->wait = queue_keyboard_message( desktop, req->win, &req->input, origin, sender, req->flags ); break; case INPUT_HARDWARE: queue_custom_hardware_message( desktop, req->win, origin, &req->input );
We now broadcast rawinput messages to all listening processes when a driver sends input with the SEND_HWMSG_BCAST_RAW flag, instead of looking for registered rawdevices in the current process.
For now, only the foreground window thread will receive the rawinput messages.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- server/protocol.def | 1 + server/queue.c | 95 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 75 insertions(+), 21 deletions(-)
diff --git a/server/protocol.def b/server/protocol.def index ab3af90545b..3b5da8dcaed 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2317,6 +2317,7 @@ enum message_type #define SEND_HWMSG_INJECTED 0x01 #define SEND_HWMSG_ONLY_RAW 0x02 #define SEND_HWMSG_SKIP_RAW 0x04 +#define SEND_HWMSG_BCAST_RAW 0x08
/* Get a message from the current queue */ diff --git a/server/queue.c b/server/queue.c index 418cd7e524e..73174bd01ea 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1596,12 +1596,64 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa return 1; }
+struct rawinput_message +{ + struct desktop *desktop; + struct hw_msg_source source; + unsigned int time; + struct hardware_msg_data data; +}; + +static int queue_rawinput_message( struct process* process, void* user ) +{ + const struct rawinput_message* raw_msg = user; + const struct rawinput_device *device = NULL; + struct desktop *desktop = NULL; + struct thread *thread = NULL; + struct message *msg; + + if (raw_msg->data.rawinput.type == RIM_TYPEMOUSE) + device = process->rawinput_mouse; + else if (raw_msg->data.rawinput.type == RIM_TYPEKEYBOARD) + device = process->rawinput_kbd; + + if (!device) + return 0; + + if (!(desktop = get_desktop_obj( process, process->desktop, 0 )) || + (raw_msg->desktop && desktop != raw_msg->desktop)) + goto done; + + if (!(thread = get_window_thread( device->target ? device->target : desktop->foreground_input->active )) || + process != thread->process) + goto done; + + if (thread->queue->input != desktop->foreground_input) + goto done; + + if (!(msg = alloc_hardware_message( raw_msg->data.info, raw_msg->source, raw_msg->time ))) + goto done; + + msg->win = device->target; + msg->msg = WM_INPUT; + msg->wparam = RIM_INPUT; + msg->lparam = 0; + memcpy( msg->data, &raw_msg->data, sizeof(raw_msg->data) ); + + queue_hardware_message( desktop, msg, 0 ); + +done: + if (thread) release_object( thread ); + if (desktop) release_object( desktop ); + return 0; +} + /* queue a hardware message for a mouse event */ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input, unsigned int origin, struct msg_queue *sender, unsigned int req_flags ) { - const struct rawinput_device *device; struct hardware_msg_data *msg_data; + struct rawinput_message raw_msg; struct message *msg; unsigned int i, time, flags; struct hw_msg_source source = { IMDT_MOUSE, origin }; @@ -1651,24 +1703,24 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons y = desktop->cursor.y; }
- if ((device = current->process->rawinput_mouse) && - !(req_flags & SEND_HWMSG_SKIP_RAW)) + if (!(req_flags & SEND_HWMSG_SKIP_RAW)) { - if (!(msg = alloc_hardware_message( input->mouse.info, source, time ))) return 0; - msg_data = msg->data; - - msg->win = device->target; - msg->msg = WM_INPUT; - msg->wparam = RIM_INPUT; - msg->lparam = 0; + raw_msg.desktop = desktop; + raw_msg.source = source; + raw_msg.time = time;
+ msg_data = &raw_msg.data; + msg_data->info = input->mouse.info; msg_data->flags = flags; msg_data->rawinput.type = RIM_TYPEMOUSE; msg_data->rawinput.mouse.x = x - desktop->cursor.x; msg_data->rawinput.mouse.y = y - desktop->cursor.y; msg_data->rawinput.mouse.data = input->mouse.data;
- queue_hardware_message( desktop, msg, 0 ); + if (req_flags & SEND_HWMSG_BCAST_RAW) + enum_processes( queue_rawinput_message, &raw_msg ); + else + queue_rawinput_message( current->process, &raw_msg ); }
if (req_flags & SEND_HWMSG_ONLY_RAW) @@ -1708,8 +1760,8 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c unsigned int origin, struct msg_queue *sender, unsigned int req_flags ) { struct hw_msg_source source = { IMDT_KEYBOARD, origin }; - const struct rawinput_device *device; struct hardware_msg_data *msg_data; + struct rawinput_message raw_msg; struct message *msg; unsigned char vkey = input->kbd.vkey; unsigned int message_code, time; @@ -1781,23 +1833,24 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c break; }
- if ((device = current->process->rawinput_kbd) && - !(req_flags & SEND_HWMSG_SKIP_RAW)) + if (!(req_flags & SEND_HWMSG_SKIP_RAW)) { - if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0; - msg_data = msg->data; - - msg->win = device->target; - msg->msg = WM_INPUT; - msg->wparam = RIM_INPUT; + raw_msg.desktop = desktop; + raw_msg.source = source; + raw_msg.time = time;
+ msg_data = &raw_msg.data; + msg_data->info = input->kbd.info; msg_data->flags = input->kbd.flags; msg_data->rawinput.type = RIM_TYPEKEYBOARD; msg_data->rawinput.kbd.message = message_code; msg_data->rawinput.kbd.vkey = vkey; msg_data->rawinput.kbd.scan = input->kbd.scan;
- queue_hardware_message( desktop, msg, 0 ); + if (req_flags & SEND_HWMSG_BCAST_RAW) + enum_processes( queue_rawinput_message, &raw_msg ); + else + queue_rawinput_message( current->process, &raw_msg ); }
if (req_flags & SEND_HWMSG_ONLY_RAW)
We need to be able to iterate all registered rawinput devices for foreign processes, not only the current one.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- server/queue.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/server/queue.c b/server/queue.c index 73174bd01ea..eda0258f97e 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1445,11 +1445,11 @@ 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 ) +static struct rawinput_device_entry *find_rawinput_device( struct process *process, 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 ) + LIST_FOR_EACH_ENTRY( e, &process->rawinput_devices, struct rawinput_device_entry, entry ) { if (e->device.usage_page != usage_page || e->device.usage != usage) continue; return e; @@ -1462,7 +1462,7 @@ 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 = find_rawinput_device( current->process, device->usage_page, device->usage ))) { if (!(e = mem_alloc( sizeof(*e) ))) return; list_add_tail( ¤t->process->rawinput_devices, &e->entry ); @@ -3185,8 +3185,8 @@ DECL_HANDLER(update_rawinput_devices) update_rawinput_device(&devices[i]); }
- e = find_rawinput_device( 1, 2 ); + e = find_rawinput_device( current->process, 1, 2 ); current->process->rawinput_mouse = e ? &e->device : NULL; - e = find_rawinput_device( 1, 6 ); + e = find_rawinput_device( current->process, 1, 6 ); current->process->rawinput_kbd = e ? &e->device : NULL; }
The RIM_TYPEHID messages will have to carry the variable length HID report.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- server/queue.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-)
diff --git a/server/queue.c b/server/queue.c index eda0258f97e..8b9a3d73603 100644 --- a/server/queue.c +++ b/server/queue.c @@ -343,13 +343,13 @@ static int assign_thread_input( struct thread *thread, struct thread_input *new_
/* allocate a hardware message and its data */ static struct message *alloc_hardware_message( lparam_t info, struct hw_msg_source source, - unsigned int time ) + unsigned int time, data_size_t extra_len ) { struct hardware_msg_data *msg_data; struct message *msg;
if (!(msg = mem_alloc( sizeof(*msg) ))) return NULL; - if (!(msg_data = mem_alloc( sizeof(*msg_data) ))) + if (!(msg_data = mem_alloc( sizeof(*msg_data) + extra_len ))) { free( msg ); return NULL; @@ -358,9 +358,9 @@ static struct message *alloc_hardware_message( lparam_t info, struct hw_msg_sour msg->type = MSG_HARDWARE; msg->time = time; msg->data = msg_data; - msg->data_size = sizeof(*msg_data); + msg->data_size = sizeof(*msg_data) + extra_len;
- memset( msg_data, 0, sizeof(*msg_data) ); + memset( msg_data, 0, sizeof(*msg_data) + extra_len ); msg_data->info = info; msg_data->source = source; return msg; @@ -372,7 +372,7 @@ static void set_cursor_pos( struct desktop *desktop, int x, int y ) static const struct hw_msg_source source = { IMDT_UNAVAILABLE, IMO_SYSTEM }; struct message *msg;
- if (!(msg = alloc_hardware_message( 0, source, get_tick_count() ))) return; + if (!(msg = alloc_hardware_message( 0, source, get_tick_count(), 0 ))) return;
msg->msg = WM_MOUSEMOVE; msg->x = x; @@ -1602,6 +1602,8 @@ struct rawinput_message struct hw_msg_source source; unsigned int time; struct hardware_msg_data data; + const void *extra; + data_size_t extra_len; };
static int queue_rawinput_message( struct process* process, void* user ) @@ -1611,6 +1613,7 @@ static int queue_rawinput_message( struct process* process, void* user ) struct desktop *desktop = NULL; struct thread *thread = NULL; struct message *msg; + struct hardware_msg_data *msg_data;
if (raw_msg->data.rawinput.type == RIM_TYPEMOUSE) device = process->rawinput_mouse; @@ -1631,14 +1634,18 @@ static int queue_rawinput_message( struct process* process, void* user ) if (thread->queue->input != desktop->foreground_input) goto done;
- if (!(msg = alloc_hardware_message( raw_msg->data.info, raw_msg->source, raw_msg->time ))) + if (!(msg = alloc_hardware_message( raw_msg->data.info, raw_msg->source, raw_msg->time, raw_msg->extra_len ))) goto done; + msg_data = msg->data;
msg->win = device->target; msg->msg = WM_INPUT; msg->wparam = RIM_INPUT; msg->lparam = 0; - memcpy( msg->data, &raw_msg->data, sizeof(raw_msg->data) ); + + memcpy( msg_data, &raw_msg->data, sizeof(*msg_data) ); + if (raw_msg->extra_len && raw_msg->extra) + memcpy( msg_data + 1, raw_msg->extra, raw_msg->extra_len );
queue_hardware_message( desktop, msg, 0 );
@@ -1705,9 +1712,11 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
if (!(req_flags & SEND_HWMSG_SKIP_RAW)) { - raw_msg.desktop = desktop; - raw_msg.source = source; - raw_msg.time = time; + raw_msg.desktop = desktop; + raw_msg.source = source; + raw_msg.time = time; + raw_msg.extra = NULL; + raw_msg.extra_len = 0;
msg_data = &raw_msg.data; msg_data->info = input->mouse.info; @@ -1732,7 +1741,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons if (!(flags & (1 << i))) continue; flags &= ~(1 << i);
- if (!(msg = alloc_hardware_message( input->mouse.info, source, time ))) return 0; + if (!(msg = alloc_hardware_message( input->mouse.info, source, time, 0 ))) return 0; msg_data = msg->data;
msg->win = get_user_full_handle( win ); @@ -1835,9 +1844,11 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
if (!(req_flags & SEND_HWMSG_SKIP_RAW)) { - raw_msg.desktop = desktop; - raw_msg.source = source; - raw_msg.time = time; + raw_msg.desktop = desktop; + raw_msg.source = source; + raw_msg.time = time; + raw_msg.extra = NULL; + raw_msg.extra_len = 0;
msg_data = &raw_msg.data; msg_data->info = input->kbd.info; @@ -1856,7 +1867,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c if (req_flags & SEND_HWMSG_ONLY_RAW) return 0;
- if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0; + if (!(msg = alloc_hardware_message( input->kbd.info, source, time, 0 ))) return 0; msg_data = msg->data;
msg->win = get_user_full_handle( win ); @@ -1894,7 +1905,7 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ struct hw_msg_source source = { IMDT_UNAVAILABLE, origin }; struct message *msg;
- if (!(msg = alloc_hardware_message( 0, source, get_tick_count() ))) return; + if (!(msg = alloc_hardware_message( 0, source, get_tick_count(), 0 ))) return;
msg->win = get_user_full_handle( win ); msg->msg = input->hw.msg;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- server/protocol.def | 28 +++++++++++++++++++++++---- server/queue.c | 47 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 66 insertions(+), 9 deletions(-)
diff --git a/server/protocol.def b/server/protocol.def index 3b5da8dcaed..4352044d795 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -309,6 +309,13 @@ struct hardware_msg_data int y; /* y coordinate */ unsigned int data; /* mouse data */ } mouse; + struct + { + int type; /* RIM_TYPEHID */ + obj_handle_t device; + unsigned int length; /* HID report length */ + /* followed by length bytes of HID report data */ + } hid; } rawinput; };
@@ -332,7 +339,7 @@ typedef union int type; struct { - int type; /* INPUT_KEYBOARD */ + int type; /* HW_INPUT_KEYBOARD */ unsigned short vkey; /* virtual key code */ unsigned short scan; /* scan code */ unsigned int flags; /* event flags */ @@ -341,7 +348,7 @@ typedef union } kbd; struct { - int type; /* INPUT_MOUSE */ + int type; /* HW_INPUT_MOUSE */ int x; /* coordinates */ int y; unsigned int data; /* mouse data */ @@ -351,11 +358,23 @@ typedef union } mouse; struct { - int type; /* INPUT_HARDWARE */ + int type; /* HW_INPUT_HARDWARE */ unsigned int msg; /* message code */ lparam_t lparam; /* message param */ } hw; + struct + { + int type; /* HW_INPUT_HID */ + obj_handle_t device; + unsigned char usage_page; + unsigned char usage; + unsigned int length; + } hid; } hw_input_t; +#define HW_INPUT_KEYBOARD INPUT_KEYBOARD +#define HW_INPUT_MOUSE INPUT_MOUSE +#define HW_INPUT_HARDWARE INPUT_HARDWARE +#define HW_INPUT_HID -1
typedef union { @@ -2304,8 +2323,9 @@ enum message_type /* Send a hardware message to a thread queue */ @REQ(send_hardware_message) user_handle_t win; /* window handle */ - hw_input_t input; /* input data */ + hw_input_t input; unsigned int flags; /* flags (see below) */ + VARARG(data,bytes); /* hid report data */ @REPLY int wait; /* do we need to wait for a reply? */ int prev_x; /* previous cursor position */ diff --git a/server/queue.c b/server/queue.c index 8b9a3d73603..8ea425154cb 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1557,7 +1557,7 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa struct msg_queue *queue; struct message *msg; timeout_t timeout = 2000 * -10000; /* FIXME: load from registry */ - int id = (input->type == INPUT_MOUSE) ? WH_MOUSE_LL : WH_KEYBOARD_LL; + int id = (input->type == HW_INPUT_MOUSE) ? WH_MOUSE_LL : WH_KEYBOARD_LL;
if (!(hook_thread = get_first_global_hook( id ))) return 0; if (!(queue = hook_thread->queue)) return 0; @@ -1575,7 +1575,7 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa msg->data_size = hardware_msg->data_size; msg->result = NULL;
- if (input->type == INPUT_KEYBOARD) + if (input->type == HW_INPUT_KEYBOARD) { unsigned short vkey = input->kbd.vkey; if (input->kbd.flags & KEYEVENTF_UNICODE) vkey = VK_PACKET; @@ -1601,6 +1601,8 @@ struct rawinput_message struct desktop *desktop; struct hw_msg_source source; unsigned int time; + unsigned char usage_page; + unsigned char usage; struct hardware_msg_data data; const void *extra; data_size_t extra_len; @@ -1609,6 +1611,7 @@ struct rawinput_message static int queue_rawinput_message( struct process* process, void* user ) { const struct rawinput_message* raw_msg = user; + const struct rawinput_device_entry *entry; const struct rawinput_device *device = NULL; struct desktop *desktop = NULL; struct thread *thread = NULL; @@ -1619,6 +1622,8 @@ static int queue_rawinput_message( struct process* process, void* user ) device = process->rawinput_mouse; else if (raw_msg->data.rawinput.type == RIM_TYPEKEYBOARD) device = process->rawinput_kbd; + else if ((entry = find_rawinput_device( process, raw_msg->usage_page, raw_msg->usage ))) + device = &entry->device;
if (!device) return 0; @@ -1917,6 +1922,35 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ queue_hardware_message( desktop, msg, 1 ); }
+/* queue a hardware message for an hid event */ +static void queue_hid_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input, + unsigned int origin, struct msg_queue *sender, unsigned int req_flags, + const void *report, data_size_t report_len ) +{ + struct hw_msg_source source = { IMDT_UNAVAILABLE, origin }; + struct hardware_msg_data *msg_data; + struct rawinput_message raw_msg; + + raw_msg.desktop = NULL; /* send to all desktops */ + raw_msg.source = source; + raw_msg.time = get_tick_count(); + raw_msg.usage_page = input->hid.usage_page; + raw_msg.usage = input->hid.usage; + raw_msg.extra = report; + raw_msg.extra_len = report_len; + + msg_data = &raw_msg.data; + msg_data->flags = 0; + msg_data->rawinput.type = RIM_TYPEHID; + msg_data->rawinput.hid.device = input->hid.device; + msg_data->rawinput.hid.length = report_len; + + if (req_flags & SEND_HWMSG_BCAST_RAW) + enum_processes( queue_rawinput_message, &raw_msg ); + else + queue_rawinput_message( current->process, &raw_msg ); +} + /* check message filter for a hardware message */ static int check_hw_message_filter( user_handle_t win, unsigned int msg_code, user_handle_t filter_win, unsigned int first, unsigned int last ) @@ -2422,15 +2456,18 @@ DECL_HANDLER(send_hardware_message)
switch (req->input.type) { - case INPUT_MOUSE: + case HW_INPUT_MOUSE: reply->wait = queue_mouse_message( desktop, req->win, &req->input, origin, sender, req->flags ); break; - case INPUT_KEYBOARD: + case HW_INPUT_KEYBOARD: reply->wait = queue_keyboard_message( desktop, req->win, &req->input, origin, sender, req->flags ); break; - case INPUT_HARDWARE: + case HW_INPUT_HARDWARE: queue_custom_hardware_message( desktop, req->win, origin, &req->input ); break; + case HW_INPUT_HID: + queue_hid_message( desktop, req->win, &req->input, origin, sender, req->flags, get_req_data(), get_req_data_size() ); + break; default: set_error( STATUS_INVALID_PARAMETER ); }
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/user32/message.c | 19 ++++++++++++++++++- dlls/user32/rawinput.c | 37 +++++++++++++++++++++++++++++++++++++ dlls/user32/user_private.h | 2 ++ 3 files changed, 57 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c index 1336865112a..daa92b89ccb 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -2285,10 +2285,17 @@ static BOOL process_rawinput_message( MSG *msg, const struct hardware_msg_data * { struct user_thread_info *thread_info = get_user_thread_info(); RAWINPUT *rawinput = thread_info->rawinput; + SIZE_T data_len = 0; + + if (msg_data->rawinput.type == RIM_TYPEHID) + { + data_len = msg_data->rawinput.hid.length; + rawinput = thread_info->rawinput = HeapReAlloc( GetProcessHeap(), 0, rawinput, sizeof(*rawinput) + data_len ); + }
if (!rawinput) { - thread_info->rawinput = HeapAlloc( GetProcessHeap(), 0, sizeof(*rawinput) ); + thread_info->rawinput = HeapAlloc( GetProcessHeap(), 0, sizeof(*rawinput) + data_len ); if (!(rawinput = thread_info->rawinput)) return FALSE; }
@@ -2383,6 +2390,16 @@ static BOOL process_rawinput_message( MSG *msg, const struct hardware_msg_data * rawinput->data.keyboard.Message = msg_data->rawinput.kbd.message; rawinput->data.keyboard.ExtraInformation = msg_data->info; } + else if (msg_data->rawinput.type == RIM_TYPEHID) + { + rawinput->header.dwSize = FIELD_OFFSET(RAWINPUT, data.hid.bRawData) + data_len; + rawinput->header.hDevice = rawinput_handle_from_device_handle(wine_server_ptr_handle(msg_data->rawinput.hid.device)); + rawinput->header.wParam = 0; + + rawinput->data.hid.dwSizeHid = data_len; + rawinput->data.hid.dwCount = 1; + memcpy(rawinput->data.hid.bRawData, msg_data + 1, data_len); + } else { FIXME("Unhandled rawinput type %#x.\n", msg_data->rawinput.type); diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index 94cf7a9a5d2..511f8ce1755 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -42,6 +42,7 @@ struct hid_device { WCHAR *path; HANDLE file; + HANDLE handle; RID_DEVICE_INFO_HID info; PHIDP_PREPARSED_DATA data; }; @@ -58,6 +59,8 @@ static CRITICAL_SECTION_DEBUG hid_devices_cs_debug = }; static CRITICAL_SECTION hid_devices_cs = { &hid_devices_cs_debug, -1, 0, 0, 0, 0 };
+extern DWORD WINAPI GetFinalPathNameByHandleW(HANDLE file, LPWSTR path, DWORD charcount, DWORD flags); + static BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int count, unsigned int size) { unsigned int new_capacity, max_capacity; @@ -137,10 +140,43 @@ static struct hid_device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *ifa device = &hid_devices[hid_devices_count++]; device->path = path; device->file = file; + device->handle = INVALID_HANDLE_VALUE;
return device; }
+HANDLE rawinput_handle_from_device_handle(HANDLE device) +{ + WCHAR buffer[sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH + 1]; + OBJECT_NAME_INFORMATION *info = (OBJECT_NAME_INFORMATION*)&buffer; + ULONG dummy; + unsigned int i; + + for (i = 0; i < hid_devices_count; ++i) + { + if (hid_devices[i].handle == device) + return &hid_devices[i]; + } + + if (NtQueryObject( device, ObjectNameInformation, &buffer, sizeof(buffer) - sizeof(WCHAR), &dummy ) || !info->Name.Buffer) + return NULL; + + /* replace ??\ with \?\ to match hid_devices paths */ + if (info->Name.Length > 1 && info->Name.Buffer[0] == '\' && info->Name.Buffer[1] == '?') + info->Name.Buffer[1] = '\'; + + for (i = 0; i < hid_devices_count; ++i) + { + if (strcmpW(hid_devices[i].path, info->Name.Buffer) == 0) + { + hid_devices[i].handle = device; + return &hid_devices[i]; + } + } + + return NULL; +} + static void find_hid_devices(void) { static ULONGLONG last_check; @@ -413,6 +449,7 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE device, UINT command, void *data, UINT device, command, data, data_size);
if (!data_size) return ~0U; + if (!device) return ~0U;
switch (command) { diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index c11aae707c9..60ceedf3a6a 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -371,4 +371,6 @@ static inline WCHAR *heap_strdupW(const WCHAR *src) return dst; }
+extern HANDLE rawinput_handle_from_device_handle(HANDLE device); + #endif /* __WINE_USER_PRIVATE_H */
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidclass.sys/device.c | 30 ++++++++++++++++++++++++++++++ dlls/hidclass.sys/hid.h | 1 + dlls/hidclass.sys/pnp.c | 16 ++++++++++++++++ 3 files changed, 47 insertions(+)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c index 0e905c8322f..ed1734ca81b 100644 --- a/dlls/hidclass.sys/device.c +++ b/dlls/hidclass.sys/device.c @@ -26,9 +26,11 @@ #include "winuser.h" #include "setupapi.h"
+#include "wine/server.h" #include "wine/debug.h" #include "ddk/hidsdi.h" #include "ddk/hidtypes.h" +#include "ddk/ntifs.h" #include "ddk/wdm.h"
#include "initguid.h" @@ -123,6 +125,8 @@ NTSTATUS HID_LinkDevice(DEVICE_OBJECT *device) return status; }
+ ext->link_handle = INVALID_HANDLE_VALUE; + /* FIXME: This should probably be done in mouhid.sys. */ if (ext->preparseData->caps.UsagePage == HID_USAGE_PAGE_GENERIC && ext->preparseData->caps.Usage == HID_USAGE_GENERIC_MOUSE) @@ -207,6 +211,8 @@ void HID_DeleteDevice(DEVICE_OBJECT *device) IoCompleteRequest(irp, IO_NO_INCREMENT); }
+ CloseHandle(ext->link_handle); + TRACE("Delete device(%p) %s\n", device, debugstr_w(ext->device_name)); HeapFree(GetProcessHeap(), 0, ext->device_name); RtlFreeUnicodeString(&ext->link_name); @@ -241,6 +247,28 @@ static NTSTATUS copy_packet_into_buffer(HID_XFER_PACKET *packet, BYTE* buffer, U return STATUS_BUFFER_OVERFLOW; }
+static void HID_Device_sendRawInput(DEVICE_OBJECT *device, HID_XFER_PACKET *packet) +{ + BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; + + if (ext->link_handle == INVALID_HANDLE_VALUE) + return; + + SERVER_START_REQ(send_hardware_message) + { + req->win = 0; + req->flags = SEND_HWMSG_BCAST_RAW; + req->input.type = HW_INPUT_HID; + req->input.hid.device = wine_server_obj_handle(ext->link_handle); + req->input.hid.usage_page = ext->preparseData->caps.UsagePage; + req->input.hid.usage = ext->preparseData->caps.Usage; + req->input.hid.length = packet->reportBufferLen; + wine_server_add_data(req, packet->reportBuffer, packet->reportBufferLen); + wine_server_call(req); + } + SERVER_END_REQ; +} + static void HID_Device_processQueue(DEVICE_OBJECT *device) { IRP *irp; @@ -324,6 +352,7 @@ static DWORD CALLBACK hid_device_thread(void *args) if (irp->IoStatus.u.Status == STATUS_SUCCESS) { RingBuffer_Write(ext->ring_buffer, packet); + HID_Device_sendRawInput(device, packet); HID_Device_processQueue(device); }
@@ -370,6 +399,7 @@ static DWORD CALLBACK hid_device_thread(void *args) else packet->reportId = 0; RingBuffer_Write(ext->ring_buffer, packet); + HID_Device_sendRawInput(device, packet); HID_Device_processQueue(device); }
diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h index 86d7bdf98f1..c3ff6a5065b 100644 --- a/dlls/hidclass.sys/hid.h +++ b/dlls/hidclass.sys/hid.h @@ -46,6 +46,7 @@ typedef struct _BASE_DEVICE_EXTENSION { ULONG poll_interval; WCHAR *device_name; UNICODE_STRING link_name; + HANDLE link_handle; WCHAR device_id[MAX_DEVICE_ID_LEN]; WCHAR instance_id[MAX_DEVICE_ID_LEN]; struct ReportRingBuffer *ring_buffer; diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c index 1c130e8dd80..b84a358dba4 100644 --- a/dlls/hidclass.sys/pnp.c +++ b/dlls/hidclass.sys/pnp.c @@ -299,12 +299,28 @@ NTSTATUS WINAPI HID_PNP_Dispatch(DEVICE_OBJECT *device, IRP *irp) case IRP_MN_START_DEVICE: { BASE_DEVICE_EXTENSION *ext = device->DeviceExtension; + OBJECT_ATTRIBUTES attr;
rc = minidriver->PNPDispatch(device, irp);
IoSetDeviceInterfaceState(&ext->link_name, TRUE); if (ext->is_mouse) IoSetDeviceInterfaceState(&ext->mouse_link_name, TRUE); + + attr.Length = sizeof(attr); + attr.RootDirectory = 0; + attr.Attributes = OBJ_CASE_INSENSITIVE; + attr.ObjectName = &ext->link_name; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + NtOpenSymbolicLinkObject(&ext->link_handle, SYMBOLIC_LINK_QUERY, &attr); + ext->link_handle = ConvertToGlobalHandle(ext->link_handle); + + if (ext->link_handle == INVALID_HANDLE_VALUE) + ERR("Failed to open link %s, error %u.\n", debugstr_w(ext->link_name.Buffer), GetLastError()); + else + TRACE("Opened link handle: %p for %s\n", ext->link_handle, debugstr_w(ext->link_name.Buffer)); + return rc; } case IRP_MN_REMOVE_DEVICE:
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=58181
Your paranoid android.
=== debian10 (32 bit report) ===
user32: msg.c:8774: Test failed: WaitForSingleObject failed 102 msg.c:8780: Test failed: destroy child on thread exit: 0: the msg 0x0082 was expected, but got msg 0x000f instead msg.c:8780: Test failed: destroy child on thread exit: 1: the msg 0x000f was expected, but got msg 0x0014 instead msg.c:8780: Test failed: destroy child on thread exit: 2: the msg sequence is not complete: expected 0014 - actual 0000
=== debian10 (64 bit WoW report) ===
user32: clipboard.c:1803: Test failed: gle 5 clipboard.c:1805: Test failed: gle 1418 clipboard.c:1807: Test failed: expected moveable mem 00000000 clipboard.c:1809: Test failed: expected moveable mem 00000000 clipboard.c:1811: Test failed: expected bitmap 00000000 clipboard.c:1813: Test failed: expected bitmap 00000000 clipboard.c:1815: Test failed: expected palette 00000000 clipboard.c:1817: Test failed: expected moveable mem 00000000 clipboard.c:1820: Test failed: expected moveable mem 00000000 clipboard.c:1823: Test failed: expected enhmetafile 00000000 clipboard.c:1826: Test failed: expected enhmetafile 00000000 clipboard.c:1829: Test failed: expected moveable mem 00000000 clipboard.c:1831: Test failed: expected moveable mem 00000000 clipboard.c:1833: Test failed: gle 1418 clipboard.c:1632: Test failed: expected moveable mem 00000000 clipboard.c:1637: Test failed: expected moveable mem 00000000 clipboard.c:1642: Test failed: expected moveable mem 00000000 clipboard.c:1648: Test failed: expected moveable mem 00000000 clipboard.c:1654: Test failed: expected bitmap 00000000 clipboard.c:1655: Test failed: different bitmap 00000000 / 0046003F clipboard.c:1658: Test failed: expected bitmap 00000000 clipboard.c:1659: Test failed: different bitmap 00000000 / 000B0045 clipboard.c:1662: Test failed: expected palette 00000000 clipboard.c:1663: Test failed: different palette 00000000 / 000C0041 clipboard.c:1666: Test failed: expected fixed mem 00000000 clipboard.c:1668: Test failed: expected fixed mem 00000000 clipboard.c:1687: Test failed: expected fixed mem 00000000 Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0xf7ca6a0f). clipboard.c:1841: Test failed: expected moveable mem 00000000 clipboard.c:1843: Test failed: expected moveable mem 00000000 clipboard.c:1845: Test failed: expected moveable mem 00000000 clipboard.c:1847: Test failed: expected moveable mem 00000000