From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/tests/input.c | 3 -- dlls/win32u/rawinput.c | 103 ++++---------------------------------- server/protocol.def | 4 +- server/queue.c | 96 ++++++++++++++++++++++------------- 4 files changed, 75 insertions(+), 131 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 2f3a7fffe0a..03910ce4b46 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -1924,12 +1924,9 @@ static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wpara if (is_wow64) { RAWINPUT64 *rawinput = (RAWINPUT64 *)(buffer + i * rawinput_size); - flaky_wine_if(is_wow64) ok_eq( RIM_TYPEKEYBOARD, rawinput->header.dwType, UINT, "%u" ); - flaky_wine_if(is_wow64) ok_eq( rawinput_size, rawinput->header.dwSize, UINT, "%u" ); ok_eq( wparam, rawinput->header.wParam, WPARAM, "%Iu" ); - flaky_wine_if(is_wow64) ok_eq( i + 2, rawinput->data.keyboard.MakeCode, WPARAM, "%Iu" ); } else diff --git a/dlls/win32u/rawinput.c b/dlls/win32u/rawinput.c index 524d1b820b2..e4f43091b9b 100644 --- a/dlls/win32u/rawinput.c +++ b/dlls/win32u/rawinput.c @@ -42,7 +42,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(rawinput);
#ifdef _WIN64 typedef RAWINPUTHEADER RAWINPUTHEADER64; -typedef RAWINPUT RAWINPUT64; #else typedef struct { @@ -51,17 +50,6 @@ typedef struct ULONGLONG hDevice; ULONGLONG wParam; } RAWINPUTHEADER64; - -typedef struct -{ - RAWINPUTHEADER64 header; - union - { - RAWMOUSE mouse; - RAWKEYBOARD keyboard; - RAWHID hid; - } data; -} RAWINPUT64; #endif
static struct rawinput_thread_data *get_rawinput_thread_data(void) @@ -529,104 +517,35 @@ UINT WINAPI NtUserGetRawInputDeviceInfo( HANDLE handle, UINT command, void *data */ UINT WINAPI NtUserGetRawInputBuffer( RAWINPUT *data, UINT *data_size, UINT header_size ) { - unsigned int count = 0, remaining, rawinput_size, next_size, overhead; - struct rawinput_thread_data *thread_data; - struct hardware_msg_data *msg_data; - RAWINPUT *rawinput; - int i; + UINT count;
- if (NtCurrentTeb()->WowTebOffset) - rawinput_size = sizeof(RAWINPUTHEADER64); - else - rawinput_size = sizeof(RAWINPUTHEADER); - overhead = rawinput_size - sizeof(RAWINPUTHEADER); + TRACE( "data %p, data_size %p, header_size %u\n", data, data_size, header_size );
if (header_size != sizeof(RAWINPUTHEADER)) { - WARN( "Invalid structure size %u.\n", header_size ); RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); - return ~0u; + return -1; }
if (!data_size) { RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); - return ~0u; + return -1; }
- if (!data) - { - TRACE( "data %p, data_size %p (%u), header_size %u\n", data, data_size, *data_size, header_size ); - SERVER_START_REQ( get_rawinput_buffer ) - { - req->rawinput_size = rawinput_size; - req->buffer_size = 0; - if (wine_server_call( req )) return ~0u; - *data_size = reply->next_size; - } - SERVER_END_REQ; - return 0; - } + /* with old WOW64 mode we didn't go through the WOW64 thunks, patch the header size here */ + if (NtCurrentTeb()->WowTebOffset) header_size = sizeof(RAWINPUTHEADER64);
- if (!(thread_data = get_rawinput_thread_data())) return ~0u; - rawinput = thread_data->buffer; - - /* first RAWINPUT block in the buffer is used for WM_INPUT message data */ - msg_data = (struct hardware_msg_data *)NEXTRAWINPUTBLOCK(rawinput); SERVER_START_REQ( get_rawinput_buffer ) { - req->rawinput_size = rawinput_size; - req->buffer_size = *data_size; - wine_server_set_reply( req, msg_data, RAWINPUT_BUFFER_SIZE - rawinput->header.dwSize ); - if (wine_server_call( req )) return ~0u; - next_size = reply->next_size; - count = reply->count; + req->header_size = header_size; + if ((req->read_data = !!data)) wine_server_set_reply( req, data, *data_size ); + if (!wine_server_call_err( req )) count = reply->count; + else count = -1; + *data_size = reply->next_size; } SERVER_END_REQ;
- remaining = *data_size; - for (i = 0; i < count; ++i) - { - data->header.dwSize = remaining; - if (!rawinput_from_hardware_message( data, msg_data )) break; - if (overhead) - { - /* Under WoW64, GetRawInputBuffer always gives 64-bit RAWINPUT structs. */ - RAWINPUT64 *ri64 = (RAWINPUT64 *)data; - memmove( (char *)&data->data + overhead, &data->data, - data->header.dwSize - sizeof(RAWINPUTHEADER) ); - ri64->header.dwSize += overhead; - - /* Need to copy wParam before hDevice so it's not overwritten. */ - ri64->header.wParam = data->header.wParam; -#ifdef _WIN64 - ri64->header.hDevice = data->header.hDevice; -#else - ri64->header.hDevice = HandleToULong(data->header.hDevice); -#endif - } - remaining -= data->header.dwSize; - data = NEXTRAWINPUTBLOCK(data); - msg_data = (struct hardware_msg_data *)((char *)msg_data + msg_data->size); - } - - if (!next_size) - { - if (!count) - *data_size = 0; - else - next_size = rawinput_size; - } - - if (next_size && *data_size <= next_size) - { - RtlSetLastWin32Error( ERROR_INSUFFICIENT_BUFFER ); - *data_size = next_size; - count = ~0u; - } - - TRACE( "data %p, data_size %p (%u), header_size %u, count %u\n", - data, data_size, *data_size, header_size, count ); return count; }
diff --git a/server/protocol.def b/server/protocol.def index 7360bb51fe7..60604812622 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3768,8 +3768,8 @@ struct handle_info
/* Batch read rawinput message data */ @REQ(get_rawinput_buffer) - data_size_t rawinput_size; /* size of RAWINPUT structure */ - data_size_t buffer_size; /* size of output buffer */ + data_size_t header_size; /* size of RAWINPUTHEADER structure */ + int read_data; /* read the rawinput buffer data */ @REPLY data_size_t next_size; /* minimum size to get next message data */ unsigned int count; diff --git a/server/queue.c b/server/queue.c index e3aa0f685ca..6f38227aa84 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1866,7 +1866,6 @@ static void rawkeyboard_init( struct rawinput *rawinput, RAWKEYBOARD *keyboard, case VK_RCONTROL: keyboard->VKey = VK_CONTROL; break; - case VK_LMENU: case VK_RMENU: keyboard->VKey = VK_MENU; @@ -3541,52 +3540,81 @@ DECL_HANDLER(get_cursor_history)
DECL_HANDLER(get_rawinput_buffer) { + const size_t align = is_machine_64bit( current->process->machine ) ? 7 : 3; + data_size_t buffer_size = get_reply_max_size() & ~align; struct thread_input *input = current->queue->input; - data_size_t size = 0, next_size = 0, pos = 0; - struct list *ptr; - char *buf, *tmp; - int count = 0, buf_size = 16 * sizeof(struct hardware_msg_data); + struct message *msg, *next_msg; + int count = 0; + char *buffer;
- if (!req->buffer_size) buf = NULL; - else if (!(buf = mem_alloc( buf_size ))) return; + if (req->header_size != sizeof(RAWINPUTHEADER)) + { + set_error( STATUS_INVALID_PARAMETER ); + return; + }
- ptr = list_head( &input->msg_list ); - while (ptr) + if (!req->read_data) { - struct message *msg = LIST_ENTRY( ptr, struct message, entry ); - struct hardware_msg_data *data = msg->data; - data_size_t extra_size = data->size - sizeof(*data); + LIST_FOR_EACH_ENTRY( msg, &input->msg_list, struct message, entry ) + { + if (msg->msg == WM_INPUT) + { + struct hardware_msg_data *msg_data = msg->data; + data_size_t size = msg_data->size - sizeof(*msg_data); + reply->next_size = sizeof(RAWINPUTHEADER) + size; + break; + } + }
- ptr = list_next( &input->msg_list, ptr ); - if (msg->msg != WM_INPUT) continue; + } + else if ((buffer = mem_alloc( buffer_size ))) + { + size_t total_size = 0, next_size = 0; + + reply->next_size = get_reply_max_size();
- next_size = req->rawinput_size + extra_size; - if (size + next_size > req->buffer_size) break; - if (pos + data->size > get_reply_max_size()) break; - if (pos + data->size > buf_size) + LIST_FOR_EACH_ENTRY_SAFE( msg, next_msg, &input->msg_list, struct message, entry ) { - buf_size += buf_size / 2 + extra_size; - if (!(tmp = realloc( buf, buf_size ))) + if (msg->msg == WM_INPUT) { - free( buf ); - set_error( STATUS_NO_MEMORY ); - return; + RAWINPUT *rawinput = (RAWINPUT *)(buffer + total_size); + struct hardware_msg_data *msg_data = msg->data; + data_size_t data_size = msg_data->size - sizeof(*msg_data); + + if (total_size + sizeof(RAWINPUTHEADER) + data_size > buffer_size) + { + next_size = sizeof(RAWINPUTHEADER) + data_size; + break; + } + + rawinput->header.dwSize = sizeof(RAWINPUTHEADER) + data_size; + rawinput->header.dwType = msg_data->rawinput.type; + rawinput->header.hDevice = UlongToHandle(msg_data->rawinput.device); + rawinput->header.wParam = msg_data->rawinput.wparam; + memcpy( &rawinput->header + 1, msg_data + 1, data_size ); + + total_size += (rawinput->header.dwSize + align) & ~align; + list_remove( &msg->entry ); + free_message( msg ); + count++; } - buf = tmp; }
- memcpy( buf + pos, data, data->size ); - list_remove( &msg->entry ); - free_message( msg ); + if (!next_size) + { + if (count) next_size = sizeof(RAWINPUT); + else reply->next_size = 0; + }
- size += next_size; - pos += sizeof(*data) + extra_size; - count++; - } + if (next_size && get_reply_max_size() <= next_size) + { + set_error( STATUS_BUFFER_TOO_SMALL ); + reply->next_size = next_size; + }
- reply->next_size = next_size; - reply->count = count; - set_reply_data_ptr( buf, pos ); + reply->count = count; + set_reply_data_ptr( buffer, total_size ); + } }
DECL_HANDLER(update_rawinput_devices)