[PATCH v3 4/4] win32u: Move NtUserGetRawInputBuffer from user32.

Zebediah Figura wine at gitlab.winehq.org
Fri Jun 17 14:51:50 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 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 );
-- 
GitLab

https://gitlab.winehq.org/wine/wine/-/merge_requests/233



More information about the wine-devel mailing list