Commit e0e3b6bc authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

user32: Use WM_INPUT message hw_id as RAWINPUT handle.

This fixes the GetRawInputData regression introduced with 359ee2ec where the message data couldn't be read twice, while keeping the overwrite logic it introduced. This also adds some SetLastError to fix some unit tests todos. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49522Signed-off-by: 's avatarRémi Bernon <rbernon@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent b58a899a
......@@ -2283,13 +2283,14 @@ static void accept_hardware_message( UINT hw_id )
}
static BOOL process_rawinput_message( MSG *msg, const struct hardware_msg_data *msg_data )
static BOOL process_rawinput_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data )
{
RAWINPUT *rawinput = rawinput_thread_data();
if (!rawinput_from_hardware_message(rawinput, msg_data))
struct rawinput_thread_data *thread_data = rawinput_thread_data();
if (!rawinput_from_hardware_message( thread_data->buffer, msg_data ))
return FALSE;
msg->lParam = (LPARAM)rawinput;
thread_data->hw_id = hw_id;
msg->lParam = (LPARAM)hw_id;
msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt );
return TRUE;
}
......@@ -2610,7 +2611,7 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar
context = SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
if (msg->message == WM_INPUT)
ret = process_rawinput_message( msg, msg_data );
ret = process_rawinput_message( msg, hw_id, msg_data );
else if (is_keyboard_message( msg->message ))
ret = process_keyboard_message( msg, hw_id, hwnd_filter, first, last, remove );
else if (is_mouse_message( msg->message ))
......
......@@ -223,12 +223,14 @@ static void find_devices(void)
}
RAWINPUT *rawinput_thread_data(void)
struct rawinput_thread_data *rawinput_thread_data(void)
{
struct user_thread_info *thread_info = get_user_thread_info();
RAWINPUT *rawinput = thread_info->rawinput;
if (!rawinput) rawinput = thread_info->rawinput = HeapAlloc( GetProcessHeap(), 0, RAWINPUT_BUFFER_SIZE );
return rawinput;
struct rawinput_thread_data *data = thread_info->rawinput;
if (data) return data;
data = thread_info->rawinput = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
RAWINPUT_BUFFER_SIZE + sizeof(struct user_thread_info) );
return data;
}
......@@ -453,43 +455,51 @@ BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(RAWINPUTDEVICE *devices, U
*/
UINT WINAPI GetRawInputData(HRAWINPUT rawinput, UINT command, void *data, UINT *data_size, UINT header_size)
{
RAWINPUT *ri = (RAWINPUT *)rawinput;
UINT s;
struct rawinput_thread_data *thread_data = rawinput_thread_data();
UINT size;
TRACE("rawinput %p, command %#x, data %p, data_size %p, header_size %u.\n",
rawinput, command, data, data_size, header_size);
if (!ri || !ri->header.dwSize)
if (!rawinput || thread_data->hw_id != (UINT_PTR)rawinput)
{
SetLastError(ERROR_INVALID_HANDLE);
return ~0U;
}
if (header_size != sizeof(RAWINPUTHEADER))
{
WARN("Invalid structure size %u.\n", header_size);
SetLastError(ERROR_INVALID_PARAMETER);
return ~0U;
}
switch (command)
{
case RID_INPUT:
s = ri->header.dwSize;
size = thread_data->buffer->header.dwSize;
break;
case RID_HEADER:
s = sizeof(RAWINPUTHEADER);
size = sizeof(RAWINPUTHEADER);
break;
default:
SetLastError(ERROR_INVALID_PARAMETER);
return ~0U;
}
if (!data)
{
*data_size = s;
*data_size = size;
return 0;
}
if (*data_size < s) return ~0U;
memcpy(data, ri, s);
ri->header.dwSize = 0;
return s;
if (*data_size < size)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return ~0U;
}
memcpy(data, thread_data->buffer, size);
return size;
}
#ifdef _WIN64
......@@ -513,6 +523,7 @@ typedef struct
UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(RAWINPUT *data, UINT *data_size, UINT header_size)
{
struct hardware_msg_data *msg_data;
struct rawinput_thread_data *thread_data;
RAWINPUT *rawinput;
UINT count = 0, rawinput_size, next_size, overhead;
BOOL is_wow64;
......@@ -551,8 +562,10 @@ UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(RAWINPUT *data, UINT *data_size,
return 0;
}
if (!(rawinput = rawinput_thread_data())) return ~0U;
if (!(thread_data = 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 )
{
......
......@@ -1760,7 +1760,6 @@ static void test_GetRawInputData(void)
SetLastError(0xdeadbeef);
ret = GetRawInputData(NULL, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
ok(ret == ~0U, "Expect ret %u, got %u\n", ~0U, ret);
todo_wine
ok(GetLastError() == ERROR_INVALID_HANDLE, "GetRawInputData returned %08x\n", GetLastError());
}
......@@ -1916,36 +1915,30 @@ static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wpara
SetLastError(0xdeadbeef);
count = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &ri, &size, 0);
ok(count == ~0U, "GetRawInputData succeeded\n");
todo_wine
ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputData returned %08x\n", GetLastError());
SetLastError(0xdeadbeef);
size = 0;
count = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER));
ok(count == ~0U, "GetRawInputData succeeded\n");
todo_wine
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetRawInputData returned %08x\n", GetLastError());
SetLastError(0xdeadbeef);
size = sizeof(ri);
count = GetRawInputData((HRAWINPUT)lparam, 0, &ri, &size, sizeof(RAWINPUTHEADER));
ok(count == ~0U, "GetRawInputData succeeded\n");
todo_wine
ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputData returned %08x\n", GetLastError());
SetLastError(0xdeadbeef);
size = sizeof(ri);
count = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER));
todo_wine
ok(count == sizeof(ri), "GetRawInputData failed\n");
todo_wine
ok(ri.data.mouse.lLastX == 6, "Unexpected rawinput data: %d\n", ri.data.mouse.lLastX);
ok(GetLastError() == 0xdeadbeef, "GetRawInputData returned %08x\n", GetLastError());
}
else
{
ok(count == ~0U, "GetRawInputData succeeded\n");
todo_wine
ok(GetLastError() == ERROR_INVALID_HANDLE, "GetRawInputData returned %08x\n", GetLastError());
}
......
......@@ -173,6 +173,12 @@ struct wm_char_mapping_data
/* hold up to 10s of 1kHz mouse rawinput events */
#define RAWINPUT_BUFFER_SIZE (512*1024)
struct rawinput_thread_data
{
UINT hw_id; /* current rawinput message id */
RAWINPUT buffer[1]; /* rawinput message data buffer */
};
/* this is the structure stored in TEB->Win32ClientInfo */
/* no attempt is made to keep the layout compatible with the Windows one */
struct user_thread_info
......@@ -196,7 +202,7 @@ struct user_thread_info
struct user_key_state_info *key_state; /* Cache of global key state */
HWND top_window; /* Desktop window */
HWND msg_window; /* HWND_MESSAGE parent window */
RAWINPUT *rawinput;
struct rawinput_thread_data *rawinput; /* RawInput thread local data / buffer */
};
C_ASSERT( sizeof(struct user_thread_info) <= sizeof(((TEB *)0)->Win32ClientInfo) );
......@@ -236,7 +242,7 @@ struct tagWND;
struct hardware_msg_data;
extern BOOL rawinput_from_hardware_message(RAWINPUT *rawinput, const struct hardware_msg_data *msg_data);
extern RAWINPUT *rawinput_thread_data(void);
extern struct rawinput_thread_data *rawinput_thread_data(void);
extern void CLIPBOARD_ReleaseOwner( HWND hwnd ) DECLSPEC_HIDDEN;
extern BOOL FOCUS_MouseActivate( HWND hwnd ) DECLSPEC_HIDDEN;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment