win32u: Move NtUserGetRawInputBuffer from user32.

This commit is contained in:
Zebediah Figura 2022-05-15 15:35:14 -05:00 committed by Alexandre Julliard
parent db43005cd8
commit 591fd06b6c
10 changed files with 260 additions and 117 deletions

View file

@ -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.@)
*/

View file

@ -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)

View file

@ -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;

View file

@ -1184,6 +1184,7 @@ static struct unix_funcs unix_funcs =
NtUserGetMessage,
NtUserGetPriorityClipboardFormat,
NtUserGetQueueStatus,
NtUserGetRawInputBuffer,
NtUserGetRawInputData,
NtUserGetSystemMenu,
NtUserGetUpdateRect,

View file

@ -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;

View file

@ -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.@)
*/

View file

@ -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

View file

@ -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 );

View file

@ -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;

View file

@ -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 );