[PATCH v2 4/4] win32u: Move NtUserGetRawInputBuffer from user32.
Zebediah Figura
wine at gitlab.winehq.org
Fri Jun 17 01:07:02 CDT 2022
From: Zebediah Figura <zfigura at 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 de20e692157..70f523da804 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 77c3e16242a..3eb24a7bc32 100644
--- a/dlls/win32u/gdiobj.c
+++ b/dlls/win32u/gdiobj.c
@@ -1183,6 +1183,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 c984316e7c9..02c2cddcf5e 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 f431b967c32..d6885e97291 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -245,6 +245,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 56ffef8f478..40c037b3fd7 100644
--- a/dlls/win32u/wrappers.c
+++ b/dlls/win32u/wrappers.c
@@ -1041,6 +1041,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 269ba3ae490..bacba52db76 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -604,6 +604,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 );
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/233
More information about the wine-devel
mailing list