-- v3: win32u: Move NtUserGetRawInputBuffer from user32. win32u: Move NtUserGetRawInputData from user32. user32: Correctly fill the RAWINPUT structure on WoW64. user32/tests: Add some more tests related to the RAWINPUT structure.
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/user32/tests/input.c | 96 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 5 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c index 6232a7456e8..0d003c6cc21 100644 --- a/dlls/user32/tests/input.c +++ b/dlls/user32/tests/input.c @@ -2101,13 +2101,29 @@ static void test_RegisterRawInputDevices(void)
static int rawinputbuffer_wndproc_count;
+typedef struct +{ + DWORD dwType; + DWORD dwSize; + ULONG hDevice; + ULONG wParam; +} RAWINPUTHEADER32; + #ifdef _WIN64 +typedef RAWINPUTHEADER RAWINPUTHEADER64; typedef RAWINPUT RAWINPUT64; #else typedef struct { - RAWINPUTHEADER header; - char pad[8]; + DWORD dwType; + DWORD dwSize; + ULONGLONG hDevice; + ULONGLONG wParam; +} RAWINPUTHEADER64; + +typedef struct +{ + RAWINPUTHEADER64 header; union { RAWMOUSE mouse; RAWKEYBOARD keyboard; @@ -2124,9 +2140,9 @@ static int rawinput_buffer_mouse_x(void *buffer, size_t index)
static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + UINT i, size, count, rawinput_size, iteration = rawinputbuffer_wndproc_count++; RAWINPUT ri; char buffer[16 * sizeof(RAWINPUT64)]; - UINT size, count, rawinput_size, iteration = rawinputbuffer_wndproc_count++; MSG message;
if (is_wow64) rawinput_size = sizeof(RAWINPUT64); @@ -2134,8 +2150,10 @@ static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wpara
if (msg == WM_INPUT) { + SetLastError(0xdeadbeef); count = GetRawInputBuffer(NULL, NULL, sizeof(RAWINPUTHEADER)); ok(count == ~0U, "GetRawInputBuffer succeeded\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError());
size = sizeof(buffer); count = GetRawInputBuffer(NULL, &size, sizeof(RAWINPUTHEADER)); @@ -2147,6 +2165,27 @@ static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wpara count = GetRawInputBuffer((RAWINPUT*)buffer, &size, sizeof(RAWINPUTHEADER)); ok(count == 3, "GetRawInputBuffer returned %u\n", count); ok(size == sizeof(buffer), "GetRawInputBuffer returned unexpected size: %u\n", size); + + for (i = 0; i < 3; ++i) + { + if (is_wow64) + { + const RAWINPUT64 *data = &((RAWINPUT64 *)buffer)[i]; + ok(data->header.dwType == RIM_TYPEMOUSE, "Unexpected rawinput type: %lu\n", data->header.dwType); + ok(data->header.dwSize == sizeof(*data), "Unexpected rawinput size: %lu\n", data->header.dwSize); + todo_wine_if (wparam) + ok(data->header.wParam == wparam, "Unexpected wparam: %#I64x\n", data->header.wParam); + } + else + { + const RAWINPUT *data = &((RAWINPUT *)buffer)[i]; + ok(data->header.dwType == RIM_TYPEMOUSE, "Unexpected rawinput type: %lu\n", data->header.dwType); + ok(data->header.dwSize == sizeof(*data), "Unexpected rawinput size: %lu\n", data->header.dwSize); + todo_wine_if (wparam) + ok(data->header.wParam == wparam, "Unexpected wparam: %#Ix\n", data->header.wParam); + } + } + ok(rawinput_buffer_mouse_x(buffer, 0) == 2, "Unexpected rawinput data: %d\n", rawinput_buffer_mouse_x(buffer, 0)); ok(rawinput_buffer_mouse_x(buffer, 1) == 3, "Unexpected rawinput data: %d\n", rawinput_buffer_mouse_x(buffer, 1)); ok(rawinput_buffer_mouse_x(buffer, 2) == 4, "Unexpected rawinput data: %d\n", rawinput_buffer_mouse_x(buffer, 2)); @@ -2183,7 +2222,12 @@ 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"); + ok(count == ~0u, "GetRawInputData returned %d\n", count); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputData returned %08lx\n", GetLastError()); + + SetLastError(0xdeadbeef); + count = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER) + 1); + ok(count == ~0u, "GetRawInputData returned %d\n", count); ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputData returned %08lx\n", GetLastError());
SetLastError(0xdeadbeef); @@ -2204,6 +2248,30 @@ static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wpara ok(count == sizeof(ri), "GetRawInputData failed\n"); ok(ri.data.mouse.lLastX == 6, "Unexpected rawinput data: %ld\n", ri.data.mouse.lLastX); ok(GetLastError() == 0xdeadbeef, "GetRawInputData returned %08lx\n", GetLastError()); + + SetLastError(0xdeadbeef); + size = sizeof(buffer); + if (sizeof(void *) == 8) + { + count = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER32)); + ok(count == ~0u, "GetRawInputData returned %d\n", count); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputData returned %08lx\n", GetLastError()); + } + else + { + count = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER64)); + if (is_wow64) + { + todo_wine ok(count == sizeof(ri), "GetRawInputData returned %d\n", count); + ok(ri.data.mouse.lLastX == 6, "Unexpected rawinput data: %ld\n", ri.data.mouse.lLastX); + todo_wine ok(GetLastError() == 0xdeadbeef, "GetRawInputData returned %08lx\n", GetLastError()); + } + else + { + ok(count == ~0u, "GetRawInputData returned %d\n", count); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputData returned %08lx\n", GetLastError()); + } + } } else { @@ -2219,9 +2287,9 @@ static LRESULT CALLBACK rawinputbuffer_wndproc(HWND hwnd, UINT msg, WPARAM wpara
static void test_GetRawInputBuffer(void) { + unsigned int size, count, rawinput_size, header_size; RAWINPUTDEVICE raw_devices[1]; char buffer[16 * sizeof(RAWINPUT64)]; - UINT size, count, rawinput_size; HWND hwnd; BOOL ret; POINT pt; @@ -2295,6 +2363,21 @@ static void test_GetRawInputBuffer(void) ok(count == ~0U, "GetRawInputBuffer succeeded\n"); ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputBuffer returned %08lx\n", GetLastError());
+ SetLastError(0xdeadbeef); + size = sizeof(buffer); + count = GetRawInputBuffer((RAWINPUT*)buffer, &size, sizeof(RAWINPUTHEADER) + 1); + ok(count == ~0U, "GetRawInputBuffer succeeded\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputBuffer returned %08lx\n", GetLastError()); + + /* the function returns 64-bit RAWINPUT structures on WoW64, but still + * forbids sizeof(RAWINPUTHEADER) from the wrong architecture */ + SetLastError(0xdeadbeef); + size = sizeof(buffer); + header_size = (sizeof(void *) == 8 ? sizeof(RAWINPUTHEADER32) : sizeof(RAWINPUTHEADER64)); + count = GetRawInputBuffer((RAWINPUT*)buffer, &size, header_size); + ok(count == ~0U, "GetRawInputBuffer succeeded\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetRawInputBuffer returned %08lx\n", GetLastError()); + size = sizeof(buffer); memset(buffer, 0, sizeof(buffer)); count = GetRawInputBuffer((RAWINPUT*)buffer, &size, sizeof(RAWINPUTHEADER)); @@ -2365,6 +2448,9 @@ static LRESULT CALLBACK rawinput_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPA ret = GetRawInputData((HRAWINPUT)lparam, RID_INPUT, &raw, &raw_size, sizeof(RAWINPUTHEADER)); ok(ret > 0 && ret != (UINT)-1, "GetRawInputData failed\n"); ok(raw.header.dwType == RIM_TYPEMOUSE, "Unexpected rawinput type: %lu\n", raw.header.dwType); + ok(raw.header.dwSize == raw_size, "Expected size %u, got %lu\n", raw_size, raw.header.dwSize); + todo_wine_if (wparam) + ok(raw.header.wParam == wparam, "Expected wparam %Iu, got %Iu\n", wparam, raw.header.wParam);
ok(!(raw.data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE), "Unexpected absolute rawinput motion\n"); ok(!(raw.data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP), "Unexpected virtual desktop rawinput motion\n");
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=117202
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
user32: input.c:745: Test failed: 0 (a4/0): 00 from 00 -> 80 unexpected input.c:745: Test failed: 0 (a4/0): 41 from 01 -> 00 unexpected
=== w7u_el (32 bit report) ===
user32: input.c:4525: Test failed: SendInput triggered unexpected message 0xc042
=== w10pro64 (32 bit report) ===
user32: input.c:4176: Test failed: 7:0: WaitForSingleObject returned 258 input.c:4119: Test failed: 7:0: expected that X highest bit is set, got 0 input.c:4120: Test failed: 7:0: expected that X keystate is set input.c:4120: Test failed: 7:0: expected that X keystate is set input.c:4127: Test failed: 7:0: expected that X keystate is set input.c:4127: Test failed: 7:0: expected that X keystate is set input.c:4119: Test failed: 7:1: expected that X highest bit is set, got 0x1 input.c:4120: Test failed: 7:1: expected that X keystate is set input.c:4120: Test failed: 7:1: expected that X keystate is set input.c:4127: Test failed: 7:1: expected that X keystate is set input.c:4127: Test failed: 7:1: expected that X keystate is set input.c:4119: Test failed: 7:2: expected that X highest bit is set, got 0 input.c:4120: Test failed: 7:2: expected that X keystate is set input.c:4120: Test failed: 7:2: expected that X keystate is set input.c:4127: Test failed: 7:2: expected that X keystate is set input.c:4127: Test failed: 7:2: expected that X keystate is set input.c:4119: Test failed: 7:3: expected that X highest bit is set, got 0x1 input.c:4120: Test failed: 7:3: expected that X keystate is set input.c:4120: Test failed: 7:3: expected that X keystate is set input.c:4127: Test failed: 7:3: expected that X keystate is set input.c:4127: Test failed: 7:3: expected that X keystate is set input.c:4119: Test failed: 8:0: expected that X highest bit is set, got 0 input.c:4120: Test failed: 8:0: expected that X keystate is set input.c:4120: Test failed: 8:0: expected that X keystate is set input.c:4127: Test failed: 8:0: expected that X keystate is set input.c:4127: Test failed: 8:0: expected that X keystate is set input.c:4119: Test failed: 8:1: expected that X highest bit is set, got 0x1 input.c:4120: Test failed: 8:1: expected that X keystate is set input.c:4120: Test failed: 8:1: expected that X keystate is set input.c:4127: Test failed: 8:1: expected that X keystate is set input.c:4127: Test failed: 8:1: expected that X keystate is set input.c:4119: Test failed: 8:2: expected that X highest bit is set, got 0 input.c:4120: Test failed: 8:2: expected that X keystate is set input.c:4120: Test failed: 8:2: expected that X keystate is set input.c:4127: Test failed: 8:2: expected that X keystate is set input.c:4127: Test failed: 8:2: expected that X keystate is set input.c:4119: Test failed: 8:3: expected that X highest bit is set, got 0x1 input.c:4120: Test failed: 8:3: expected that X keystate is set input.c:4120: Test failed: 8:3: expected that X keystate is set input.c:4127: Test failed: 8:3: expected that X keystate is set input.c:4127: Test failed: 8:3: expected that X keystate is set
=== w1064_tsign (64 bit report) ===
user32: input.c:1291: Test failed: Wrong set pos: (100,100) input.c:1311: Test failed: GetCursorPos: (100,100)
From: Zebediah Figura zfigura@codeweavers.com
This changes the offset of the wParam field. --- dlls/user32/rawinput.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index ab542956f11..99e2270b77c 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -646,12 +646,20 @@ UINT WINAPI GetRawInputData(HRAWINPUT rawinput, UINT command, void *data, UINT * }
#ifdef _WIN64 +typedef RAWINPUTHEADER RAWINPUTHEADER64; typedef RAWINPUT RAWINPUT64; #else typedef struct { - RAWINPUTHEADER header; - char pad[8]; + DWORD dwType; + DWORD dwSize; + ULONGLONG hDevice; + ULONGLONG wParam; +} RAWINPUTHEADER64; + +typedef struct +{ + RAWINPUTHEADER64 header; union { RAWMOUSE mouse; RAWKEYBOARD keyboard;
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=117203
Your paranoid android.
=== debian11 (32 bit report) ===
user32: win.c:11770: Test succeeded inside todo block: child should be topmost win.c:11773: Test failed: grandchild should be topmost win.c:11781: Test failed: child should NOT be topmost win.c:11784: Test succeeded inside todo block: grandchild should NOT be topmost win.c:11787: Test failed: 007200BA: expected NOT topmost win.c:11606: Test succeeded inside todo block: 5: hwnd 01610052 is still topmost
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/user32/rawinput.c | 54 +-------------------- dlls/user32/user32.spec | 2 +- dlls/user32/user_main.c | 1 + dlls/user32/user_private.h | 8 +--- dlls/win32u/Makefile.in | 1 + dlls/win32u/gdiobj.c | 1 + dlls/win32u/ntuser_private.h | 7 +++ dlls/win32u/rawinput.c | 91 ++++++++++++++++++++++++++++++++++++ dlls/win32u/win32u.spec | 2 +- dlls/win32u/win32u_private.h | 2 + dlls/win32u/wrappers.c | 6 +++ include/ntuser.h | 1 + 12 files changed, 114 insertions(+), 62 deletions(-) create mode 100644 dlls/win32u/rawinput.c
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index 99e2270b77c..b1c79b4e186 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -351,7 +351,7 @@ BOOL rawinput_device_get_usages(HANDLE handle, USAGE *usage_page, USAGE *usage) }
-struct rawinput_thread_data *rawinput_thread_data(void) +struct rawinput_thread_data * WINAPI rawinput_thread_data(void) { struct user_thread_info *thread_info = get_user_thread_info(); struct rawinput_thread_data *data = thread_info->rawinput; @@ -593,58 +593,6 @@ BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(const RAWINPUTDEVICE *devi return ret; }
-/*********************************************************************** - * GetRawInputData (USER32.@) - */ -UINT WINAPI GetRawInputData(HRAWINPUT rawinput, UINT command, void *data, UINT *data_size, UINT header_size) -{ - 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 (!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: - size = thread_data->buffer->header.dwSize; - break; - case RID_HEADER: - size = sizeof(RAWINPUTHEADER); - break; - default: - SetLastError(ERROR_INVALID_PARAMETER); - return ~0U; - } - - if (!data) - { - *data_size = size; - return 0; - } - - if (*data_size < size) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return ~0U; - } - memcpy(data, thread_data->buffer, size); - return size; -} - #ifdef _WIN64 typedef RAWINPUTHEADER RAWINPUTHEADER64; typedef RAWINPUT RAWINPUT64; diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index 90ddad761f0..b546365703b 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -367,7 +367,7 @@ @ stdcall GetPropW(long wstr) @ stdcall GetQueueStatus(long) NtUserGetQueueStatus @ stdcall GetRawInputBuffer(ptr ptr long) -@ stdcall GetRawInputData(ptr long ptr ptr long) +@ stdcall GetRawInputData(ptr long ptr ptr long) NtUserGetRawInputData @ stdcall GetRawInputDeviceInfoA(ptr long ptr ptr) @ stdcall GetRawInputDeviceInfoW(ptr long ptr ptr) @ stdcall GetRawInputDeviceList(ptr ptr long) diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c index 3cb42e15b1e..4901bcf7193 100644 --- a/dlls/user32/user_main.c +++ b/dlls/user32/user_main.c @@ -169,6 +169,7 @@ static const struct user_callbacks user_funcs = register_imm, unregister_imm, try_finally, + rawinput_thread_data, };
static NTSTATUS WINAPI User32CopyImage( const struct copy_image_params *params, ULONG size ) diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index a3a3d28c2d9..a31a2bd8a01 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -51,12 +51,6 @@ 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 */ -}; - extern BOOL (WINAPI *imm_register_window)(HWND) DECLSPEC_HIDDEN; extern void (WINAPI *imm_unregister_window)(HWND) DECLSPEC_HIDDEN;
@@ -73,7 +67,7 @@ struct tagWND; struct hardware_msg_data; extern BOOL rawinput_from_hardware_message(RAWINPUT *rawinput, const struct hardware_msg_data *msg_data); extern BOOL rawinput_device_get_usages(HANDLE handle, USAGE *usage_page, USAGE *usage); -extern struct rawinput_thread_data *rawinput_thread_data(void); +extern struct rawinput_thread_data * WINAPI rawinput_thread_data(void); extern void rawinput_update_device_list(void);
extern BOOL post_dde_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, DWORD dest_tid, diff --git a/dlls/win32u/Makefile.in b/dlls/win32u/Makefile.in index d58ed6bb41c..cc429836de3 100644 --- a/dlls/win32u/Makefile.in +++ b/dlls/win32u/Makefile.in @@ -43,6 +43,7 @@ C_SRCS = \ path.c \ pen.c \ printdrv.c \ + rawinput.c \ region.c \ spy.c \ syscall.c \ diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index 9d95d3cf94a..0a65b6732f4 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -1184,6 +1184,7 @@ static struct unix_funcs unix_funcs = NtUserGetMessage, NtUserGetPriorityClipboardFormat, NtUserGetQueueStatus, + NtUserGetRawInputData, NtUserGetSystemMenu, NtUserGetUpdateRect, NtUserGetUpdateRgn, diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 075fc714744..babbc8208bc 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -50,6 +50,7 @@ struct user_callbacks void (WINAPI *unregister_imm)( HWND hwnd ); NTSTATUS (CDECL *try_finally)( NTSTATUS (CDECL *func)( void *), void *arg, void (CALLBACK *finally_func)( BOOL )); + struct rawinput_thread_data *(WINAPI *get_rawinput_thread_data)(void); };
#define WM_SYSTIMER 0x0118 @@ -61,6 +62,12 @@ enum system_timer_id SYSTEM_TIMER_CARET = 0xffff, };
+struct rawinput_thread_data +{ + UINT hw_id; /* current rawinput message id */ + RAWINPUT buffer[1]; /* rawinput message data buffer */ +}; + struct user_object { HANDLE handle; diff --git a/dlls/win32u/rawinput.c b/dlls/win32u/rawinput.c new file mode 100644 index 00000000000..0d2c585c36e --- /dev/null +++ b/dlls/win32u/rawinput.c @@ -0,0 +1,91 @@ +/* + * Raw Input + * + * Copyright 2012 Henri Verbeet + * Copyright 2018 Zebediah Figura for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep unix +#endif + +#include "win32u_private.h" +#include "ntuser_private.h" +#include "wine/server.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(rawinput); + +/********************************************************************** + * NtUserGetRawInputData (win32u.@) + */ +UINT WINAPI NtUserGetRawInputData( HRAWINPUT rawinput, UINT command, void *data, UINT *data_size, UINT header_size ) +{ + struct rawinput_thread_data *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 (!user_callbacks || !(thread_data = user_callbacks->get_rawinput_thread_data())) + { + SetLastError( ERROR_OUTOFMEMORY ); + return ~0u; + } + + 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: + size = thread_data->buffer->header.dwSize; + break; + + case RID_HEADER: + size = sizeof(RAWINPUTHEADER); + break; + + default: + SetLastError( ERROR_INVALID_PARAMETER ); + return ~0u; + } + + if (!data) + { + *data_size = size; + return 0; + } + + if (*data_size < size) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return ~0u; + } + memcpy( data, thread_data->buffer, size ); + return size; +} diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 8d8f46705b8..612a1328e6d 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -984,7 +984,7 @@ @ stdcall NtUserGetQueueStatus(long) @ stub NtUserGetQueueStatusReadonly @ stub NtUserGetRawInputBuffer -@ stub NtUserGetRawInputData +@ stdcall NtUserGetRawInputData(ptr long ptr ptr long) @ stub NtUserGetRawInputDeviceInfo @ stub NtUserGetRawInputDeviceList @ stub NtUserGetRawPointerDeviceData diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 6536518c604..3262279fe12 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -247,6 +247,8 @@ struct unix_funcs BOOL (WINAPI *pNtUserGetMessage)( MSG *msg, HWND hwnd, UINT first, UINT last ); INT (WINAPI *pNtUserGetPriorityClipboardFormat)( UINT *list, INT count ); DWORD (WINAPI *pNtUserGetQueueStatus)( UINT flags ); + UINT (WINAPI *pNtUserGetRawInputData)( HRAWINPUT rawinput, UINT command, + void *data, UINT *data_size, UINT header_size ); HMENU (WINAPI *pNtUserGetSystemMenu)( HWND hwnd, BOOL revert ); BOOL (WINAPI *pNtUserGetUpdateRect)( HWND hwnd, RECT *rect, BOOL erase ); INT (WINAPI *pNtUserGetUpdateRgn)( HWND hwnd, HRGN hrgn, BOOL erase ); diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c index b451e57e3b1..cde9b2c8e4b 100644 --- a/dlls/win32u/wrappers.c +++ b/dlls/win32u/wrappers.c @@ -1048,6 +1048,12 @@ DWORD WINAPI NtUserGetQueueStatus( UINT flags ) return unix_funcs->pNtUserGetQueueStatus( flags ); }
+UINT WINAPI NtUserGetRawInputData( HRAWINPUT rawinput, UINT command, void *data, UINT *data_size, UINT header_size ) +{ + if (!unix_funcs) return ~0u; + return unix_funcs->pNtUserGetRawInputData( rawinput, command, data, data_size, header_size ); +} + BOOL WINAPI NtUserGetUpdatedClipboardFormats( UINT *formats, UINT size, UINT *out_size ) { if (!unix_funcs) return FALSE; diff --git a/include/ntuser.h b/include/ntuser.h index 76d0387eed7..17ae38b427a 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -606,6 +606,7 @@ HWINSTA WINAPI NtUserGetProcessWindowStation(void); HANDLE WINAPI NtUserGetProp( HWND hwnd, const WCHAR *str ); ULONG WINAPI NtUserGetProcessDpiAwarenessContext( HANDLE process ); DWORD WINAPI NtUserGetQueueStatus( UINT flags ); +UINT WINAPI NtUserGetRawInputData( HRAWINPUT rawinput, UINT command, void *data, UINT *data_size, UINT header_size ); ULONG WINAPI NtUserGetSystemDpiForProcess( HANDLE process ); HMENU WINAPI NtUserGetSystemMenu( HWND hwnd, BOOL revert ); HDESK WINAPI NtUserGetThreadDesktop( DWORD thread );
This merge request was approved by Alexandre Julliard.
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/user32/rawinput.c | 111 ---------------- dlls/user32/user32.spec | 2 +- dlls/user32/user_private.h | 4 - dlls/win32u/gdiobj.c | 1 + dlls/win32u/ntuser_private.h | 4 + dlls/win32u/rawinput.c | 245 +++++++++++++++++++++++++++++++++++ dlls/win32u/win32u.spec | 2 +- dlls/win32u/win32u_private.h | 1 + dlls/win32u/wrappers.c | 6 + include/ntuser.h | 1 + 10 files changed, 260 insertions(+), 117 deletions(-)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c index b1c79b4e186..f8980f03e9e 100644 --- a/dlls/user32/rawinput.c +++ b/dlls/user32/rawinput.c @@ -593,117 +593,6 @@ BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(const RAWINPUTDEVICE *devi return ret; }
-#ifdef _WIN64 -typedef RAWINPUTHEADER RAWINPUTHEADER64; -typedef RAWINPUT RAWINPUT64; -#else -typedef struct -{ - DWORD dwType; - DWORD dwSize; - ULONGLONG hDevice; - ULONGLONG wParam; -} RAWINPUTHEADER64; - -typedef struct -{ - RAWINPUTHEADER64 header; - union { - RAWMOUSE mouse; - RAWKEYBOARD keyboard; - RAWHID hid; - } data; -} RAWINPUT64; -#endif - -/*********************************************************************** - * GetRawInputBuffer (USER32.@) - */ -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, remaining, rawinput_size, next_size, overhead; - BOOL is_wow64; - int i; - - if (IsWow64Process( GetCurrentProcess(), &is_wow64 ) && is_wow64) - rawinput_size = sizeof(RAWINPUT64); - else - rawinput_size = sizeof(RAWINPUT); - overhead = rawinput_size - sizeof(RAWINPUT); - - if (header_size != sizeof(RAWINPUTHEADER)) - { - WARN("Invalid structure size %u.\n", header_size); - SetLastError(ERROR_INVALID_PARAMETER); - return ~0U; - } - - if (!data_size) - { - SetLastError(ERROR_INVALID_PARAMETER); - return ~0U; - } - - 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; - } - - 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 ) - { - 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; - } - 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) memmove((char *)&data->data + overhead, &data->data, - data->header.dwSize - sizeof(RAWINPUTHEADER)); - data->header.dwSize += overhead; - remaining -= data->header.dwSize; - data = NEXTRAWINPUTBLOCK(data); - msg_data = (struct hardware_msg_data *)((char *)msg_data + msg_data->size); - } - - if (count == 0 && next_size == 0) *data_size = 0; - else if (next_size == 0) next_size = rawinput_size; - - if (next_size && *data_size <= next_size) - { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - *data_size = next_size; - count = ~0U; - } - - if (count) TRACE("data %p, data_size %p (%u), header_size %u, count %u\n", data, data_size, *data_size, header_size, count); - return count; -} - /*********************************************************************** * GetRawInputDeviceInfoA (USER32.@) */ diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index b546365703b..887394227a3 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -366,7 +366,7 @@ @ stdcall GetPropA(long str) @ stdcall GetPropW(long wstr) @ stdcall GetQueueStatus(long) NtUserGetQueueStatus -@ stdcall GetRawInputBuffer(ptr ptr long) +@ stdcall GetRawInputBuffer(ptr ptr long) NtUserGetRawInputBuffer @ stdcall GetRawInputData(ptr long ptr ptr long) NtUserGetRawInputData @ stdcall GetRawInputDeviceInfoA(ptr long ptr ptr) @ stdcall GetRawInputDeviceInfoW(ptr long ptr ptr) diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index a31a2bd8a01..9a2b7de4509 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -47,10 +47,6 @@ struct wm_char_mapping_data MSG get_msg; };
-/* on windows the buffer capacity is quite large as well, enough to */ -/* hold up to 10s of 1kHz mouse rawinput events */ -#define RAWINPUT_BUFFER_SIZE (512*1024) - extern BOOL (WINAPI *imm_register_window)(HWND) DECLSPEC_HIDDEN; extern void (WINAPI *imm_unregister_window)(HWND) DECLSPEC_HIDDEN;
diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index 0a65b6732f4..121ed4bbefd 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -1184,6 +1184,7 @@ static struct unix_funcs unix_funcs = NtUserGetMessage, NtUserGetPriorityClipboardFormat, NtUserGetQueueStatus, + NtUserGetRawInputBuffer, NtUserGetRawInputData, NtUserGetSystemMenu, NtUserGetUpdateRect, diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index babbc8208bc..e8051ac39d3 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -68,6 +68,10 @@ struct rawinput_thread_data RAWINPUT buffer[1]; /* rawinput message data buffer */ };
+/* on windows the buffer capacity is quite large as well, enough to */ +/* hold up to 10s of 1kHz mouse rawinput events */ +#define RAWINPUT_BUFFER_SIZE (512 * 1024) + struct user_object { HANDLE handle; diff --git a/dlls/win32u/rawinput.c b/dlls/win32u/rawinput.c index 0d2c585c36e..d6f38382b4b 100644 --- a/dlls/win32u/rawinput.c +++ b/dlls/win32u/rawinput.c @@ -23,6 +23,7 @@ #pragma makedep unix #endif
+#include <stdbool.h> #include "win32u_private.h" #include "ntuser_private.h" #include "wine/server.h" @@ -30,6 +31,250 @@
WINE_DEFAULT_DEBUG_CHANNEL(rawinput);
+#define WINE_MOUSE_HANDLE ((HANDLE)1) +#define WINE_KEYBOARD_HANDLE ((HANDLE)2) + +#ifdef _WIN64 +typedef RAWINPUTHEADER RAWINPUTHEADER64; +typedef RAWINPUT RAWINPUT64; +#else +typedef struct +{ + DWORD dwType; + DWORD dwSize; + ULONGLONG hDevice; + ULONGLONG wParam; +} RAWINPUTHEADER64; + +typedef struct +{ + RAWINPUTHEADER64 header; + union + { + RAWMOUSE mouse; + RAWKEYBOARD keyboard; + RAWHID hid; + } data; +} RAWINPUT64; +#endif + +static bool rawinput_from_hardware_message( RAWINPUT *rawinput, const struct hardware_msg_data *msg_data ) +{ + SIZE_T size; + + rawinput->header.dwType = msg_data->rawinput.type; + if (msg_data->rawinput.type == RIM_TYPEMOUSE) + { + static const unsigned int button_flags[] = + { + 0, /* MOUSEEVENTF_MOVE */ + RI_MOUSE_LEFT_BUTTON_DOWN, /* MOUSEEVENTF_LEFTDOWN */ + RI_MOUSE_LEFT_BUTTON_UP, /* MOUSEEVENTF_LEFTUP */ + RI_MOUSE_RIGHT_BUTTON_DOWN, /* MOUSEEVENTF_RIGHTDOWN */ + RI_MOUSE_RIGHT_BUTTON_UP, /* MOUSEEVENTF_RIGHTUP */ + RI_MOUSE_MIDDLE_BUTTON_DOWN, /* MOUSEEVENTF_MIDDLEDOWN */ + RI_MOUSE_MIDDLE_BUTTON_UP, /* MOUSEEVENTF_MIDDLEUP */ + }; + unsigned int i; + + rawinput->header.dwSize = FIELD_OFFSET(RAWINPUT, data) + sizeof(RAWMOUSE); + rawinput->header.hDevice = WINE_MOUSE_HANDLE; + rawinput->header.wParam = 0; + + rawinput->data.mouse.usFlags = MOUSE_MOVE_RELATIVE; + rawinput->data.mouse.usButtonFlags = 0; + rawinput->data.mouse.usButtonData = 0; + for (i = 1; i < ARRAY_SIZE(button_flags); ++i) + { + if (msg_data->flags & (1 << i)) + rawinput->data.mouse.usButtonFlags |= button_flags[i]; + } + if (msg_data->flags & MOUSEEVENTF_WHEEL) + { + rawinput->data.mouse.usButtonFlags |= RI_MOUSE_WHEEL; + rawinput->data.mouse.usButtonData = msg_data->rawinput.mouse.data; + } + if (msg_data->flags & MOUSEEVENTF_HWHEEL) + { + rawinput->data.mouse.usButtonFlags |= RI_MOUSE_HORIZONTAL_WHEEL; + rawinput->data.mouse.usButtonData = msg_data->rawinput.mouse.data; + } + if (msg_data->flags & MOUSEEVENTF_XDOWN) + { + if (msg_data->rawinput.mouse.data == XBUTTON1) + rawinput->data.mouse.usButtonFlags |= RI_MOUSE_BUTTON_4_DOWN; + else if (msg_data->rawinput.mouse.data == XBUTTON2) + rawinput->data.mouse.usButtonFlags |= RI_MOUSE_BUTTON_5_DOWN; + } + if (msg_data->flags & MOUSEEVENTF_XUP) + { + if (msg_data->rawinput.mouse.data == XBUTTON1) + rawinput->data.mouse.usButtonFlags |= RI_MOUSE_BUTTON_4_UP; + else if (msg_data->rawinput.mouse.data == XBUTTON2) + rawinput->data.mouse.usButtonFlags |= RI_MOUSE_BUTTON_5_UP; + } + + rawinput->data.mouse.ulRawButtons = 0; + rawinput->data.mouse.lLastX = msg_data->rawinput.mouse.x; + rawinput->data.mouse.lLastY = msg_data->rawinput.mouse.y; + rawinput->data.mouse.ulExtraInformation = msg_data->info; + } + else if (msg_data->rawinput.type == RIM_TYPEKEYBOARD) + { + rawinput->header.dwSize = FIELD_OFFSET(RAWINPUT, data) + sizeof(RAWKEYBOARD); + rawinput->header.hDevice = WINE_KEYBOARD_HANDLE; + rawinput->header.wParam = 0; + + rawinput->data.keyboard.MakeCode = msg_data->rawinput.kbd.scan; + rawinput->data.keyboard.Flags = (msg_data->flags & KEYEVENTF_KEYUP) ? RI_KEY_BREAK : RI_KEY_MAKE; + if (msg_data->flags & KEYEVENTF_EXTENDEDKEY) + rawinput->data.keyboard.Flags |= RI_KEY_E0; + rawinput->data.keyboard.Reserved = 0; + + switch (msg_data->rawinput.kbd.vkey) + { + case VK_LSHIFT: + case VK_RSHIFT: + rawinput->data.keyboard.VKey = VK_SHIFT; + rawinput->data.keyboard.Flags &= ~RI_KEY_E0; + break; + + case VK_LCONTROL: + case VK_RCONTROL: + rawinput->data.keyboard.VKey = VK_CONTROL; + break; + + case VK_LMENU: + case VK_RMENU: + rawinput->data.keyboard.VKey = VK_MENU; + break; + + default: + rawinput->data.keyboard.VKey = msg_data->rawinput.kbd.vkey; + break; + } + + rawinput->data.keyboard.Message = msg_data->rawinput.kbd.message; + rawinput->data.keyboard.ExtraInformation = msg_data->info; + } + else if (msg_data->rawinput.type == RIM_TYPEHID) + { + size = msg_data->size - sizeof(*msg_data); + if (size > rawinput->header.dwSize - sizeof(*rawinput)) return false; + + rawinput->header.dwSize = FIELD_OFFSET( RAWINPUT, data.hid.bRawData ) + size; + rawinput->header.hDevice = ULongToHandle( msg_data->rawinput.hid.device ); + rawinput->header.wParam = 0; + + rawinput->data.hid.dwCount = msg_data->rawinput.hid.count; + rawinput->data.hid.dwSizeHid = msg_data->rawinput.hid.length; + memcpy( rawinput->data.hid.bRawData, msg_data + 1, size ); + } + else + { + FIXME( "Unhandled rawinput type %#x.\n", msg_data->rawinput.type ); + return false; + } + + return true; +} + +/********************************************************************** + * NtUserGetRawInputBuffer (win32u.@) + */ +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; + + if (NtCurrentTeb()->WowTebOffset) + rawinput_size = sizeof(RAWINPUT64); + else + rawinput_size = sizeof(RAWINPUT); + overhead = rawinput_size - sizeof(RAWINPUT); + + if (header_size != sizeof(RAWINPUTHEADER)) + { + WARN( "Invalid structure size %u.\n", header_size ); + SetLastError( ERROR_INVALID_PARAMETER ); + return ~0u; + } + + if (!data_size) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return ~0u; + } + + 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; + } + + if (!user_callbacks || !(thread_data = user_callbacks->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; + } + 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) + { + memmove( (char *)&data->data + overhead, &data->data, + data->header.dwSize - sizeof(RAWINPUTHEADER) ); + } + data->header.dwSize += overhead; + 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) + { + SetLastError( 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; +} + /********************************************************************** * NtUserGetRawInputData (win32u.@) */ diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 612a1328e6d..4a8d839007e 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -983,7 +983,7 @@ @ stdcall -syscall NtUserGetProp(long wstr) @ stdcall NtUserGetQueueStatus(long) @ stub NtUserGetQueueStatusReadonly -@ stub NtUserGetRawInputBuffer +@ stdcall NtUserGetRawInputBuffer(ptr ptr long) @ stdcall NtUserGetRawInputData(ptr long ptr ptr long) @ stub NtUserGetRawInputDeviceInfo @ stub NtUserGetRawInputDeviceList diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 3262279fe12..b2d16b07d8e 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -247,6 +247,7 @@ struct unix_funcs BOOL (WINAPI *pNtUserGetMessage)( MSG *msg, HWND hwnd, UINT first, UINT last ); INT (WINAPI *pNtUserGetPriorityClipboardFormat)( UINT *list, INT count ); DWORD (WINAPI *pNtUserGetQueueStatus)( UINT flags ); + UINT (WINAPI *pNtUserGetRawInputBuffer)( RAWINPUT *data, UINT *data_size, UINT header_size ); UINT (WINAPI *pNtUserGetRawInputData)( HRAWINPUT rawinput, UINT command, void *data, UINT *data_size, UINT header_size ); HMENU (WINAPI *pNtUserGetSystemMenu)( HWND hwnd, BOOL revert ); diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c index cde9b2c8e4b..05c25a006e9 100644 --- a/dlls/win32u/wrappers.c +++ b/dlls/win32u/wrappers.c @@ -1048,6 +1048,12 @@ DWORD WINAPI NtUserGetQueueStatus( UINT flags ) return unix_funcs->pNtUserGetQueueStatus( flags ); }
+UINT WINAPI DECLSPEC_HOTPATCH NtUserGetRawInputBuffer( RAWINPUT *data, UINT *data_size, UINT header_size ) +{ + if (!unix_funcs) return ~0u; + return unix_funcs->pNtUserGetRawInputBuffer( data, data_size, header_size ); +} + UINT WINAPI NtUserGetRawInputData( HRAWINPUT rawinput, UINT command, void *data, UINT *data_size, UINT header_size ) { if (!unix_funcs) return ~0u; diff --git a/include/ntuser.h b/include/ntuser.h index 17ae38b427a..679179851a9 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -606,6 +606,7 @@ HWINSTA WINAPI NtUserGetProcessWindowStation(void); HANDLE WINAPI NtUserGetProp( HWND hwnd, const WCHAR *str ); ULONG WINAPI NtUserGetProcessDpiAwarenessContext( HANDLE process ); DWORD WINAPI NtUserGetQueueStatus( UINT flags ); +UINT WINAPI NtUserGetRawInputBuffer( RAWINPUT *data, UINT *data_size, UINT header_size ); UINT WINAPI NtUserGetRawInputData( HRAWINPUT rawinput, UINT command, void *data, UINT *data_size, UINT header_size ); ULONG WINAPI NtUserGetSystemDpiForProcess( HANDLE process ); HMENU WINAPI NtUserGetSystemMenu( HWND hwnd, BOOL revert );