user32-rawinput-*: Replace with new patches from Rémi Bernon.

This commit is contained in:
Zebediah Figura 2021-04-09 17:39:38 -05:00
parent 64ea26c0cb
commit 661df7b889
40 changed files with 3294 additions and 1296 deletions

View File

@ -240,6 +240,9 @@ patch_enable_all ()
enable_user32_ScrollWindowEx="$1"
enable_user32_message_order="$1"
enable_user32_msgbox_Support_WM_COPY_mesg="$1"
enable_user32_rawinput_hid="$1"
enable_user32_rawinput_mouse="$1"
enable_user32_rawinput_mouse_experimental="$1"
enable_user32_recursive_activation="$1"
enable_uxtheme_CloseThemeClass="$1"
enable_version_VerQueryValue="$1"
@ -777,6 +780,15 @@ patch_enable ()
user32-msgbox-Support-WM_COPY-mesg)
enable_user32_msgbox_Support_WM_COPY_mesg="$2"
;;
user32-rawinput-hid)
enable_user32_rawinput_hid="$2"
;;
user32-rawinput-mouse)
enable_user32_rawinput_mouse="$2"
;;
user32-rawinput-mouse-experimental)
enable_user32_rawinput_mouse_experimental="$2"
;;
user32-recursive-activation)
enable_user32_recursive_activation="$2"
;;
@ -1320,6 +1332,27 @@ if test "$enable_wineboot_ProxySettings" -eq 1; then
enable_wineboot_drivers_etc_Stubs=1
fi
if test "$enable_user32_rawinput_mouse_experimental" -eq 1; then
if test "$enable_user32_rawinput_mouse" -gt 1; then
abort "Patchset user32-rawinput-mouse disabled, but user32-rawinput-mouse-experimental depends on that."
fi
enable_user32_rawinput_mouse=1
fi
if test "$enable_user32_rawinput_mouse" -eq 1; then
if test "$enable_user32_rawinput_hid" -gt 1; then
abort "Patchset user32-rawinput-hid disabled, but user32-rawinput-mouse depends on that."
fi
enable_user32_rawinput_hid=1
fi
if test "$enable_user32_rawinput_hid" -eq 1; then
if test "$enable_loader_KeyboardLayouts" -gt 1; then
abort "Patchset loader-KeyboardLayouts disabled, but user32-rawinput-hid depends on that."
fi
enable_loader_KeyboardLayouts=1
fi
if test "$enable_stdole32_tlb_SLTG_Typelib" -eq 1; then
if test "$enable_widl_SLTG_Typelib_Support" -gt 1; then
abort "Patchset widl-SLTG_Typelib_Support disabled, but stdole32.tlb-SLTG_Typelib depends on that."
@ -3864,6 +3897,89 @@ if test "$enable_user32_msgbox_Support_WM_COPY_mesg" -eq 1; then
patch_apply user32-msgbox-Support-WM_COPY-mesg/0002-user32-msgbox-Use-a-windows-hook-to-trap-Ctrl-C.patch
fi
# Patchset user32-rawinput-hid
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * loader-KeyboardLayouts
# |
# | This patchset fixes the following Wine bugs:
# | * [#50506] WM_INPUT messages are not received for HID devices registered with RegisterRawInputDevices
# |
# | Modified files:
# | * dlls/hidclass.sys/Makefile.in, dlls/hidclass.sys/device.c, dlls/hidclass.sys/hid.h, dlls/hidclass.sys/pnp.c,
# | dlls/ntoskrnl.exe/ntoskrnl.exe.spec, dlls/ntoskrnl.exe/pnp.c, dlls/user32/input.c, dlls/user32/message.c,
# | dlls/user32/rawinput.c, dlls/user32/tests/input.c, dlls/user32/user32.spec, dlls/user32/user_private.h,
# | dlls/wineandroid.drv/keyboard.c, dlls/wineandroid.drv/window.c, dlls/winemac.drv/ime.c, dlls/winemac.drv/keyboard.c,
# | dlls/winemac.drv/mouse.c, dlls/winex11.drv/keyboard.c, dlls/winex11.drv/mouse.c, include/ddk/wdm.h, include/winuser.h,
# | server/protocol.def, server/queue.c, server/trace.c
# |
if test "$enable_user32_rawinput_hid" -eq 1; then
patch_apply user32-rawinput-hid/0001-user32-tests-Add-more-SendInput-tests.patch
patch_apply user32-rawinput-hid/0002-user32-Implement-SendInput-INPUT_HARDWARE-check.patch
patch_apply user32-rawinput-hid/0003-user32-Add-RAWINPUT-parameter-to-__wine_send_input.patch
patch_apply user32-rawinput-hid/0004-hidclass.sys-Assign-rawinput-device-handle-in-HID_Li.patch
patch_apply user32-rawinput-hid/0005-hidclass.sys-Use-__wine_send_input-to-send-device-no.patch
patch_apply user32-rawinput-hid/0006-server-Implement-desktop-broadcast-in-queue_rawinput.patch
patch_apply user32-rawinput-hid/0007-server-Add-rawinput-union-to-hw_input_t-INPUT_HARDWA.patch
patch_apply user32-rawinput-hid/0008-server-Add-RIM_TYPEHID-type-hid-member-to-rawinput-u.patch
patch_apply user32-rawinput-hid/0009-user32-Send-WM_INPUT_DEVICE_CHANGE-RAWINPUT-to-the-s.patch
patch_apply user32-rawinput-hid/0010-server-Track-known-HID-rawinput-devices-on-addition-.patch
patch_apply user32-rawinput-hid/0011-server-Add-process-argument-to-find_rawinput_device.patch
patch_apply user32-rawinput-hid/0012-server-Implement-WM_INPUT_DEVICE_CHANGE-message-disp.patch
patch_apply user32-rawinput-hid/0013-hidclass.sys-Send-rawinput-messages-with-HID-report.patch
patch_apply user32-rawinput-hid/0014-server-Add-extra-data-to-hardware_msg_data.patch
patch_apply user32-rawinput-hid/0015-server-Implement-WM_INPUT-RIM_TYPEHID-message-dispat.patch
patch_apply user32-rawinput-hid/0016-ntoskrnl-Implement-IoSetDevicePropertyData.patch
patch_apply user32-rawinput-hid/0017-hidclass.sys-Assign-rawinput-handles-through-device-.patch
patch_apply user32-rawinput-hid/0018-user32-Enumerate-mouse-rawinput-device-before-HID-de.patch
patch_apply user32-rawinput-hid/0019-user32-Use-device-handles-assigned-by-hidclass.sys.patch
fi
# Patchset user32-rawinput-mouse
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * loader-KeyboardLayouts, user32-rawinput-hid
# |
# | This patchset fixes the following Wine bugs:
# | * [#42631] Mouse drift, jump or don't react to small slow movements in Unity-engine games and Fallout 4 (partly fixed in
# | Unity games, have walkaround in Fallout4 )
# | * [#42675] Overwatch: Phantom mouse input / view pulled up to ceiling
# |
# | Modified files:
# | * dlls/user32/input.c, dlls/user32/message.c, dlls/wineandroid.drv/keyboard.c, dlls/wineandroid.drv/window.c,
# | dlls/winemac.drv/ime.c, dlls/winemac.drv/keyboard.c, dlls/winemac.drv/mouse.c, dlls/winex11.drv/desktop.c,
# | dlls/winex11.drv/event.c, dlls/winex11.drv/keyboard.c, dlls/winex11.drv/mouse.c, dlls/winex11.drv/window.c,
# | dlls/winex11.drv/x11drv.h, dlls/winex11.drv/x11drv_main.c, server/protocol.def, server/queue.c
# |
if test "$enable_user32_rawinput_mouse" -eq 1; then
patch_apply user32-rawinput-mouse/0001-winex11.drv-Split-XInput2-thread-initialization.patch
patch_apply user32-rawinput-mouse/0002-winex11.drv-Support-XInput2-events-for-individual-wi.patch
patch_apply user32-rawinput-mouse/0003-winex11.drv-Advertise-XInput2-version-2.1-support.patch
patch_apply user32-rawinput-mouse/0004-winex11.drv-Keep-track-of-pointer-and-device-button-.patch
patch_apply user32-rawinput-mouse/0005-server-Add-send_hardware_message-flags-for-rawinput-.patch
patch_apply user32-rawinput-mouse/0006-user32-Set-SEND_HWMSG_RAWINPUT-flags-only-when-RAWIN.patch
patch_apply user32-rawinput-mouse/0007-user32-Support-sending-RIM_TYPEMOUSE-through-__wine_.patch
patch_apply user32-rawinput-mouse/0008-winex11.drv-Listen-to-RawMotion-and-RawButton-events.patch
fi
# Patchset user32-rawinput-mouse-experimental
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * loader-KeyboardLayouts, user32-rawinput-hid, user32-rawinput-mouse
# |
# | This patchset fixes the following Wine bugs:
# | * [#45882] - Raw Input should use untransformed mouse values (affects Overwatch, several Source games).
# |
# | Modified files:
# | * dlls/user32/rawinput.c, dlls/winex11.drv/mouse.c, dlls/winex11.drv/window.c, dlls/winex11.drv/x11drv.h,
# | dlls/winex11.drv/x11drv_main.c, server/queue.c
# |
if test "$enable_user32_rawinput_mouse_experimental" -eq 1; then
patch_apply user32-rawinput-mouse-experimental/0001-winex11.drv-Add-support-for-absolute-RawMotion-event.patch
patch_apply user32-rawinput-mouse-experimental/0002-winex11.drv-Send-relative-RawMotion-events-unprocess.patch
patch_apply user32-rawinput-mouse-experimental/0003-winex11.drv-Accumulate-mouse-movement-to-avoid-round.patch
fi
# Patchset user32-recursive-activation
# |
# | This patchset fixes the following Wine bugs:

View File

@ -0,0 +1,185 @@
From ce4894689736dc2e49b2b7550802ab1f2a4eb462 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 9 Mar 2021 12:02:18 +0100
Subject: [PATCH] user32/tests: Add more SendInput tests.
Validating that SendInput with INPUT_HARDWARE type should be no-op.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506
---
dlls/user32/input.c | 18 ++++++
dlls/user32/tests/input.c | 122 ++++++++++++++++++++++++++++++++++++++
2 files changed, 140 insertions(+)
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index 8992c463c48..22e53585f00 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -182,6 +182,24 @@ UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size )
UINT i;
NTSTATUS status;
+ if (size != sizeof(INPUT))
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return 0;
+ }
+
+ if (!count)
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return 0;
+ }
+
+ if (!inputs)
+ {
+ SetLastError( ERROR_NOACCESS );
+ return 0;
+ }
+
for (i = 0; i < count; i++)
{
if (inputs[i].type == INPUT_MOUSE)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index 06f90291fd1..0584f89f55a 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -4246,6 +4246,127 @@ static void test_GetKeyboardLayoutList(void)
}
}
+static void test_SendInput(void)
+{
+ INPUT input[16];
+ UINT res, i;
+ HWND hwnd;
+ MSG msg;
+
+ hwnd = CreateWindowW( L"static", L"test", WS_OVERLAPPED, 0, 0, 100, 100, 0, 0, 0, 0 );
+ ok( hwnd != 0, "CreateWindowW failed\n" );
+
+ ShowWindow( hwnd, SW_SHOWNORMAL );
+ UpdateWindow( hwnd );
+ SetForegroundWindow( hwnd );
+ SetFocus( hwnd );
+ empty_message_queue();
+
+ SetLastError( 0xdeadbeef );
+ res = SendInput( 0, NULL, 0 );
+ ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#x\n", res, GetLastError() );
+ SetLastError( 0xdeadbeef );
+ res = SendInput( 1, NULL, 0 );
+ ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#x\n", res, GetLastError() );
+ SetLastError( 0xdeadbeef );
+ res = SendInput( 1, NULL, sizeof(*input) );
+ ok( res == 0 && (GetLastError() == ERROR_NOACCESS || GetLastError() == ERROR_INVALID_PARAMETER),
+ "SendInput returned %u, error %#x\n", res, GetLastError() );
+ SetLastError( 0xdeadbeef );
+ res = SendInput( 0, input, sizeof(*input) );
+ ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#x\n", res, GetLastError() );
+ SetLastError( 0xdeadbeef );
+ res = SendInput( 0, NULL, sizeof(*input) );
+ ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#x\n", res, GetLastError() );
+
+ memset( input, 0, sizeof(input) );
+ SetLastError( 0xdeadbeef );
+ res = SendInput( 1, input, sizeof(*input) );
+ ok( res == 1 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() );
+ SetLastError( 0xdeadbeef );
+ res = SendInput( 16, input, sizeof(*input) );
+ ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() );
+
+ SetLastError( 0xdeadbeef );
+ res = SendInput( 1, input, 0 );
+ ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#x\n", res, GetLastError() );
+ SetLastError( 0xdeadbeef );
+ res = SendInput( 1, input, sizeof(*input) + 1 );
+ ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#x\n", res, GetLastError() );
+ SetLastError( 0xdeadbeef );
+ res = SendInput( 1, input, sizeof(*input) - 1 );
+ ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#x\n", res, GetLastError() );
+
+ for (i = 0; i < ARRAY_SIZE(input); ++i) input[i].type = INPUT_KEYBOARD;
+ SetLastError( 0xdeadbeef );
+ res = SendInput( 16, input, offsetof( INPUT, ki ) + sizeof(KEYBDINPUT) );
+ ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#x\n", res, GetLastError() );
+ SetLastError( 0xdeadbeef );
+ res = SendInput( 16, input, sizeof(*input) );
+ ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() );
+ empty_message_queue();
+
+ for (i = 0; i < ARRAY_SIZE(input); ++i) input[i].type = INPUT_HARDWARE;
+ SetLastError( 0xdeadbeef );
+ res = SendInput( 16, input, offsetof( INPUT, hi ) + sizeof(HARDWAREINPUT) );
+ ok( res == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "SendInput returned %u, error %#x\n", res, GetLastError() );
+
+ input[0].hi.uMsg = WM_KEYDOWN;
+ input[0].hi.wParamL = 0;
+ input[0].hi.wParamH = 'A';
+ input[1].hi.uMsg = WM_KEYUP;
+ input[1].hi.wParamL = 0;
+ input[1].hi.wParamH = 'A' | 0xc000;
+ SetLastError( 0xdeadbeef );
+ res = SendInput( 16, input, sizeof(*input) );
+#ifdef _WIN64
+ todo_wine
+ ok( res == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "SendInput returned %u, error %#x\n", res, GetLastError() );
+#else
+ ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() );
+#endif
+ while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg);
+ todo_wine ok( !res, "SendInput triggered unexpected message %#x\n", msg.message );
+ empty_message_queue();
+
+ memset( input, 0, sizeof(input) );
+ input[0].type = INPUT_HARDWARE;
+ input[1].type = INPUT_KEYBOARD;
+ input[1].ki.wVk = 'A';
+ input[1].ki.dwFlags = 0;
+ input[2].type = INPUT_KEYBOARD;
+ input[2].ki.wVk = 'A';
+ input[2].ki.dwFlags = KEYEVENTF_KEYUP;
+ SetLastError( 0xdeadbeef );
+ res = SendInput( 16, input, sizeof(*input) );
+#ifdef _WIN64
+ todo_wine ok( res == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "SendInput returned %u, error %#x\n", res, GetLastError() );
+ while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg);
+ todo_wine ok( !res, "SendInput triggered unexpected message %#x\n", msg.message );
+ empty_message_queue();
+#else
+ ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() );
+ while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg);
+ ok( !!res, "SendInput did not trigger any message\n" );
+ todo_wine ok( msg.message == WM_KEYDOWN, "SendInput triggered unexpected message %#x\n", msg.message );
+ while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg);
+ ok( !!res, "SendInput did not trigger any message\n" );
+ todo_wine ok( msg.message == WM_KEYUP, "SendInput triggered unexpected message %#x\n", msg.message );
+ empty_message_queue();
+#endif
+
+ for (i = 0; i < ARRAY_SIZE(input); ++i) input[i].type = INPUT_HARDWARE + 1;
+ SetLastError( 0xdeadbeef );
+ res = SendInput( 16, input, sizeof(*input) );
+ todo_wine ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() );
+ while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg);
+ todo_wine ok( !res, "SendInput triggered unexpected message %#x\n", msg.message );
+ empty_message_queue();
+
+ trace( "done\n" );
+ DestroyWindow( hwnd );
+}
+
START_TEST(input)
{
char **argv;
@@ -4268,6 +4389,7 @@ START_TEST(input)
return;
}
+ test_SendInput();
test_Input_blackbox();
test_Input_whitebox();
test_Input_unicode();
--
2.30.2

View File

@ -0,0 +1,106 @@
From d9554c180611116398e700ed7f2d8f021bd06924 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Wed, 7 Apr 2021 10:34:23 +0200
Subject: [PATCH] user32: Implement SendInput INPUT_HARDWARE check.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506
---
dlls/user32/input.c | 16 ++++++++++++----
dlls/user32/tests/input.c | 15 +++++++--------
2 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index 22e53585f00..e97264960ea 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -180,7 +180,7 @@ static void update_mouse_coords( INPUT *input )
UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size )
{
UINT i;
- NTSTATUS status;
+ NTSTATUS status = STATUS_SUCCESS;
if (size != sizeof(INPUT))
{
@@ -202,14 +202,22 @@ UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size )
for (i = 0; i < count; i++)
{
- if (inputs[i].type == INPUT_MOUSE)
+ INPUT input = inputs[i];
+ switch (input.type)
{
+ case INPUT_MOUSE:
/* we need to update the coordinates to what the server expects */
- INPUT input = inputs[i];
update_mouse_coords( &input );
+ /* fallthrough */
+ case INPUT_KEYBOARD:
status = send_hardware_message( 0, &input, SEND_HWMSG_INJECTED );
+ break;
+#ifdef _WIN64
+ case INPUT_HARDWARE:
+ SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+ return 0;
+#endif
}
- else status = send_hardware_message( 0, &inputs[i], SEND_HWMSG_INJECTED );
if (status)
{
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index f48807a27a0..564ab2e1ba0 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -4286,13 +4286,12 @@ static void test_SendInput(void)
SetLastError( 0xdeadbeef );
res = SendInput( 16, input, sizeof(*input) );
#ifdef _WIN64
- todo_wine
ok( res == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "SendInput returned %u, error %#x\n", res, GetLastError() );
#else
ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() );
#endif
while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg);
- todo_wine ok( !res, "SendInput triggered unexpected message %#x\n", msg.message );
+ ok( !res, "SendInput triggered unexpected message %#x\n", msg.message );
empty_message_queue();
memset( input, 0, sizeof(input) );
@@ -4306,27 +4305,27 @@ static void test_SendInput(void)
SetLastError( 0xdeadbeef );
res = SendInput( 16, input, sizeof(*input) );
#ifdef _WIN64
- todo_wine ok( res == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "SendInput returned %u, error %#x\n", res, GetLastError() );
+ ok( res == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED, "SendInput returned %u, error %#x\n", res, GetLastError() );
while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg);
- todo_wine ok( !res, "SendInput triggered unexpected message %#x\n", msg.message );
+ ok( !res, "SendInput triggered unexpected message %#x\n", msg.message );
empty_message_queue();
#else
ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() );
while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg);
ok( !!res, "SendInput did not trigger any message\n" );
- todo_wine ok( msg.message == WM_KEYDOWN, "SendInput triggered unexpected message %#x\n", msg.message );
+ ok( msg.message == WM_KEYDOWN, "SendInput triggered unexpected message %#x\n", msg.message );
while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg);
ok( !!res, "SendInput did not trigger any message\n" );
- todo_wine ok( msg.message == WM_KEYUP, "SendInput triggered unexpected message %#x\n", msg.message );
+ ok( msg.message == WM_KEYUP, "SendInput triggered unexpected message %#x\n", msg.message );
empty_message_queue();
#endif
for (i = 0; i < ARRAY_SIZE(input); ++i) input[i].type = INPUT_HARDWARE + 1;
SetLastError( 0xdeadbeef );
res = SendInput( 16, input, sizeof(*input) );
- todo_wine ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() );
+ ok( res == 16 && GetLastError() == 0xdeadbeef, "SendInput returned %u, error %#x\n", res, GetLastError() );
while ((res = wait_for_message(&msg)) && msg.message == WM_TIMER) DispatchMessageA(&msg);
- todo_wine ok( !res, "SendInput triggered unexpected message %#x\n", msg.message );
+ ok( !res, "SendInput triggered unexpected message %#x\n", msg.message );
empty_message_queue();
trace( "done\n" );
--
2.30.2

View File

@ -1,64 +0,0 @@
From eee5ecbed5c813be03d4b540675f1c4792101567 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 11 Nov 2019 18:35:18 +0100
Subject: [PATCH] server: Make it possible to queue rawinput message on all
desktops.
---
server/queue.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/server/queue.c b/server/queue.c
index f5d19031485..59c6cbb6921 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1658,8 +1658,8 @@ static int queue_rawinput_message( struct process* process, void *arg )
{
const struct rawinput_message* raw_msg = arg;
const struct rawinput_device *device = NULL;
- struct desktop *target_desktop = NULL;
- struct thread *target_thread = NULL;
+ struct desktop *target_desktop = NULL, *desktop = NULL;
+ struct thread *target_thread = NULL, *foreground = NULL;
struct message *msg;
struct hardware_msg_data *msg_data;
int wparam = RIM_INPUT;
@@ -1670,12 +1670,18 @@ static int queue_rawinput_message( struct process* process, void *arg )
device = process->rawinput_kbd;
if (!device) return 0;
- if (process != raw_msg->foreground->process)
+ if (raw_msg->desktop) desktop = (struct desktop *)grab_object( raw_msg->desktop );
+ else if (!(desktop = get_desktop_obj( process, process->desktop, 0 ))) goto done;
+
+ if (raw_msg->foreground) foreground = (struct thread *)grab_object( raw_msg->foreground );
+ else if (!(foreground = get_foreground_thread( desktop, 0 ))) goto done;
+
+ if (process != foreground->process)
{
if (!(device->flags & RIDEV_INPUTSINK)) goto done;
if (!(target_thread = get_window_thread( device->target ))) goto done;
if (!(target_desktop = get_thread_desktop( target_thread, 0 ))) goto done;
- if (target_desktop != raw_msg->desktop) goto done;
+ if (target_desktop != desktop) goto done;
wparam = RIM_INPUTSINK;
}
@@ -1692,11 +1698,13 @@ static int queue_rawinput_message( struct process* process, void *arg )
if (raw_msg->extra_len && raw_msg->extra)
memcpy( msg_data + 1, raw_msg->extra, raw_msg->extra_len );
- queue_hardware_message( raw_msg->desktop, msg, 1 );
+ queue_hardware_message( desktop, msg, 1 );
done:
if (target_thread) release_object( target_thread );
if (target_desktop) release_object( target_desktop );
+ if (foreground) release_object( foreground );
+ if (desktop) release_object( desktop );
return 0;
}
--
2.27.0

View File

@ -1,51 +1,94 @@
From c74a22af02a816e81bf84b2f80fcd05582e01187 Mon Sep 17 00:00:00 2001
From 1d4f802b393ca552ec262f359794277c9ecf2c7f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 26 Aug 2019 15:20:32 +0200
Subject: [PATCH] user32: Add __wine_send_input flags to hint raw input
translation.
Date: Wed, 7 Apr 2021 14:52:00 +0200
Subject: [PATCH] user32: Add RAWINPUT parameter to __wine_send_input.
And send_hardware_message.
This makes it possible to use __wine_send_input to send extended input
data, such as HID device notifications and WM_INPUT messages carrying
HID reports.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506
---
dlls/user32/input.c | 4 ++--
dlls/user32/input.c | 6 +++---
dlls/user32/message.c | 2 +-
dlls/user32/user32.spec | 2 +-
dlls/user32/user_private.h | 2 +-
dlls/wineandroid.drv/keyboard.c | 2 +-
dlls/wineandroid.drv/window.c | 4 ++--
dlls/winemac.drv/ime.c | 5 +++--
dlls/winemac.drv/ime.c | 4 ++--
dlls/winemac.drv/keyboard.c | 2 +-
dlls/winemac.drv/mouse.c | 2 +-
dlls/winex11.drv/keyboard.c | 2 +-
dlls/winex11.drv/mouse.c | 8 ++++----
include/winuser.h | 2 +-
10 files changed, 17 insertions(+), 16 deletions(-)
12 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index f0b95c7fc6c..150b7de9704 100644
index e97264960ea..3fc818a2510 100644
--- a/dlls/user32/input.c
+++ b/dlls/user32/input.c
@@ -123,9 +123,9 @@ BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret )
@@ -119,9 +119,9 @@ BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret )
*
* Internal SendInput function to allow the graphics driver to inject real events.
*/
-BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input )
+BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input, UINT flags )
+BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input, const RAWINPUT *rawinput )
{
- NTSTATUS status = send_hardware_message( hwnd, input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
+ NTSTATUS status = send_hardware_message( hwnd, input, flags );
- NTSTATUS status = send_hardware_message( hwnd, input, 0 );
+ NTSTATUS status = send_hardware_message( hwnd, input, rawinput, 0 );
if (status) SetLastError( RtlNtStatusToDosError(status) );
return !status;
}
@@ -210,7 +210,7 @@ UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size )
update_mouse_coords( &input );
/* fallthrough */
case INPUT_KEYBOARD:
- status = send_hardware_message( 0, &input, SEND_HWMSG_INJECTED );
+ status = send_hardware_message( 0, &input, NULL, SEND_HWMSG_INJECTED );
break;
#ifdef _WIN64
case INPUT_HARDWARE:
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index def59998a52..f87ef9fb3af 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -3227,7 +3227,7 @@ static BOOL send_message( struct send_message_info *info, DWORD_PTR *res_ptr, BO
/***********************************************************************
* send_hardware_message
*/
-NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags )
+NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *rawinput, UINT flags )
{
struct user_key_state_info *key_state_info = get_user_thread_info()->key_state;
struct send_message_info info;
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index d2a14879714..6ffc7d44096 100644
index 4ef75247d71..190ee74fd6c 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -833,5 +833,5 @@
@@ -834,5 +834,5 @@
# All functions must be prefixed with '__wine_' (for internal functions)
# or 'wine_' (for user-visible functions) to avoid namespace conflicts.
#
-@ cdecl __wine_send_input(long ptr)
+@ cdecl __wine_send_input(long ptr long)
+@ cdecl __wine_send_input(long ptr ptr)
@ cdecl __wine_set_pixel_format(long long)
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index 7761a1ceb4f..dfd52421e66 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -263,7 +263,7 @@ extern RECT get_virtual_screen_rect(void) DECLSPEC_HIDDEN;
extern LRESULT call_current_hook( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN;
extern DWORD get_input_codepage( void ) DECLSPEC_HIDDEN;
extern BOOL map_wparam_AtoW( UINT message, WPARAM *wparam, enum wm_char_mapping mapping ) DECLSPEC_HIDDEN;
-extern NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags ) DECLSPEC_HIDDEN;
+extern NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *rawinput, UINT flags ) DECLSPEC_HIDDEN;
extern LRESULT MSG_SendInternalMessageTimeout( DWORD dest_pid, DWORD dest_tid,
UINT msg, WPARAM wparam, LPARAM lparam,
UINT flags, UINT timeout, PDWORD_PTR res_ptr ) DECLSPEC_HIDDEN;
diff --git a/dlls/wineandroid.drv/keyboard.c b/dlls/wineandroid.drv/keyboard.c
index a0f3257f74b..1af8a98f1f9 100644
index 1c8a1e4f68f..0a6ede0ec5f 100644
--- a/dlls/wineandroid.drv/keyboard.c
+++ b/dlls/wineandroid.drv/keyboard.c
@@ -680,7 +680,7 @@ static void send_keyboard_input( HWND hwnd, WORD vkey, WORD scan, DWORD flags )
@ -53,12 +96,12 @@ index a0f3257f74b..1af8a98f1f9 100644
input.u.ki.dwExtraInfo = 0;
- __wine_send_input( hwnd, &input );
+ __wine_send_input( hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
+ __wine_send_input( hwnd, &input, NULL );
}
/***********************************************************************
diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c
index eb05aaf2832..c1e7b000a8f 100644
index 79bc471a984..1cb1bbbadc9 100644
--- a/dlls/wineandroid.drv/window.c
+++ b/dlls/wineandroid.drv/window.c
@@ -521,7 +521,7 @@ static int process_events( DWORD mask )
@ -66,7 +109,7 @@ index eb05aaf2832..c1e7b000a8f 100644
SERVER_END_REQ;
}
- __wine_send_input( capture ? capture : event->data.motion.hwnd, &event->data.motion.input );
+ __wine_send_input( capture ? capture : event->data.motion.hwnd, &event->data.motion.input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
+ __wine_send_input( capture ? capture : event->data.motion.hwnd, &event->data.motion.input, NULL );
}
break;
@ -75,37 +118,29 @@ index eb05aaf2832..c1e7b000a8f 100644
event->data.kbd.input.u.ki.wScan );
update_keyboard_lock_state( event->data.kbd.input.u.ki.wVk, event->data.kbd.lock_state );
- __wine_send_input( 0, &event->data.kbd.input );
+ __wine_send_input( 0, &event->data.kbd.input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
+ __wine_send_input( 0, &event->data.kbd.input, NULL );
break;
default:
diff --git a/dlls/winemac.drv/ime.c b/dlls/winemac.drv/ime.c
index dabe6654f98..3593374a613 100644
index dabe6654f98..f2368c10743 100644
--- a/dlls/winemac.drv/ime.c
+++ b/dlls/winemac.drv/ime.c
@@ -42,6 +42,7 @@
#include "winuser.h"
#include "imm.h"
#include "ddk/imm.h"
+#include "wine/server.h"
WINE_DEFAULT_DEBUG_CHANNEL(imm);
@@ -1427,10 +1428,10 @@ void macdrv_im_set_text(const macdrv_event *event)
@@ -1427,10 +1427,10 @@ void macdrv_im_set_text(const macdrv_event *event)
{
input.ki.wScan = chars[i];
input.ki.dwFlags = KEYEVENTF_UNICODE;
- __wine_send_input(hwnd, &input);
+ __wine_send_input(hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW);
+ __wine_send_input(hwnd, &input, NULL);
input.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
- __wine_send_input(hwnd, &input);
+ __wine_send_input(hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW);
+ __wine_send_input(hwnd, &input, NULL);
}
}
diff --git a/dlls/winemac.drv/keyboard.c b/dlls/winemac.drv/keyboard.c
index bb408cb20c5..41919baafc7 100644
index 1b74300e93a..1ea15f59341 100644
--- a/dlls/winemac.drv/keyboard.c
+++ b/dlls/winemac.drv/keyboard.c
@@ -929,7 +929,7 @@ static void macdrv_send_keyboard_input(HWND hwnd, WORD vkey, WORD scan, DWORD fl
@ -113,12 +148,12 @@ index bb408cb20c5..41919baafc7 100644
input.ki.dwExtraInfo = 0;
- __wine_send_input(hwnd, &input);
+ __wine_send_input(hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW);
+ __wine_send_input(hwnd, &input, NULL);
}
diff --git a/dlls/winemac.drv/mouse.c b/dlls/winemac.drv/mouse.c
index dd6443fe1ba..91cafdf1362 100644
index dd6443fe1ba..d2278ae0e4c 100644
--- a/dlls/winemac.drv/mouse.c
+++ b/dlls/winemac.drv/mouse.c
@@ -165,7 +165,7 @@ static void send_mouse_input(HWND hwnd, macdrv_window cocoa_window, UINT flags,
@ -126,12 +161,12 @@ index dd6443fe1ba..91cafdf1362 100644
input.mi.dwExtraInfo = 0;
- __wine_send_input(top_level_hwnd, &input);
+ __wine_send_input(top_level_hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW);
+ __wine_send_input(top_level_hwnd, &input, NULL);
}
diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c
index 48da12c0292..2a3bed787ab 100644
index 35a801fc895..01620c5e4a4 100644
--- a/dlls/winex11.drv/keyboard.c
+++ b/dlls/winex11.drv/keyboard.c
@@ -1148,7 +1148,7 @@ static void X11DRV_send_keyboard_input( HWND hwnd, WORD vkey, WORD scan, DWORD f
@ -139,52 +174,52 @@ index 48da12c0292..2a3bed787ab 100644
input.u.ki.dwExtraInfo = 0;
- __wine_send_input( hwnd, &input );
+ __wine_send_input( hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
+ __wine_send_input( hwnd, &input, NULL );
}
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index 7f11ba86e49..aaa34d8ff0f 100644
index 94dece652b6..42bac332664 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -657,7 +657,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU
@@ -659,7 +659,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU
sync_window_cursor( window );
last_cursor_change = input->u.mi.time;
}
input->u.mi.dx += clip_rect.left;
input->u.mi.dy += clip_rect.top;
- __wine_send_input( hwnd, input );
+ __wine_send_input( hwnd, input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
+ __wine_send_input( hwnd, input, NULL );
return;
}
@@ -697,7 +697,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU
@@ -699,7 +699,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU
SERVER_END_REQ;
}
- __wine_send_input( hwnd, input );
+ __wine_send_input( hwnd, input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
+ __wine_send_input( hwnd, input, NULL );
}
#ifdef SONAME_LIBXCURSOR
@@ -1643,7 +1643,7 @@ void move_resize_window( HWND hwnd, int dir )
@@ -1669,7 +1669,7 @@ void move_resize_window( HWND hwnd, int dir )
input.u.mi.dwFlags = button_up_flags[button - 1] | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
input.u.mi.time = GetTickCount();
input.u.mi.dwExtraInfo = 0;
- __wine_send_input( hwnd, &input );
+ __wine_send_input( hwnd, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
+ __wine_send_input( hwnd, &input, NULL );
}
while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ))
@@ -1882,7 +1882,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
@@ -1900,7 +1900,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy );
input.type = INPUT_MOUSE;
- __wine_send_input( 0, &input );
+ __wine_send_input( 0, &input, SEND_HWMSG_RAWINPUT|SEND_HWMSG_WINDOW );
+ __wine_send_input( 0, &input, NULL );
return TRUE;
}
diff --git a/include/winuser.h b/include/winuser.h
index 311b1481be4..4bc18a63e31 100644
index 53661f6c788..0b1571c0a95 100644
--- a/include/winuser.h
+++ b/include/winuser.h
@@ -4406,7 +4406,7 @@ static inline BOOL WINAPI SetRectEmpty(LPRECT rect)
@ -192,10 +227,10 @@ index 311b1481be4..4bc18a63e31 100644
#ifdef __WINESRC__
-WINUSERAPI BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input );
+WINUSERAPI BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input, UINT flags );
+WINUSERAPI BOOL CDECL __wine_send_input( HWND hwnd, const INPUT *input, const RAWINPUT *rawinput );
#endif
#ifdef __cplusplus
--
2.27.0
2.30.2

View File

@ -0,0 +1,69 @@
From 1da5b77304f9ef71340692a9d3d6e95526101ea6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 22 Mar 2021 18:41:55 +0100
Subject: [PATCH] hidclass.sys: Assign rawinput device handle in
HID_LinkDevice.
The handles are just numeric values and not real object handles, they
are used in the hDevice field of the RAWINPUTHEADER struct.
They will also be used as an HID rawinput device array index on the
server side.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506
---
dlls/hidclass.sys/device.c | 17 +++++++++++++++++
dlls/hidclass.sys/hid.h | 1 +
2 files changed, 18 insertions(+)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c
index fc1dfd07db1..9a3c92b3576 100644
--- a/dlls/hidclass.sys/device.c
+++ b/dlls/hidclass.sys/device.c
@@ -71,6 +71,17 @@ NTSTATUS HID_CreateDevice(DEVICE_OBJECT *native_device, HID_MINIDRIVER_REGISTRAT
return STATUS_SUCCESS;
}
+/* user32 reserves 1 & 2 for winemouse and winekeyboard,
+ * keep this in sync with user_private.h */
+#define WINE_MOUSE_HANDLE 1
+#define WINE_KEYBOARD_HANDLE 2
+
+static UINT32 alloc_rawinput_handle(void)
+{
+ static LONG counter = WINE_KEYBOARD_HANDLE + 1;
+ return InterlockedIncrement(&counter);
+}
+
NTSTATUS HID_LinkDevice(DEVICE_OBJECT *device)
{
WCHAR device_instance_id[MAX_DEVICE_ID_LEN];
@@ -125,7 +136,13 @@ NTSTATUS HID_LinkDevice(DEVICE_OBJECT *device)
{
if (!IoRegisterDeviceInterface(device, &GUID_DEVINTERFACE_MOUSE, NULL, &ext->mouse_link_name))
ext->is_mouse = TRUE;
+ ext->rawinput_handle = WINE_MOUSE_HANDLE;
}
+ else if (ext->preparseData->caps.UsagePage == HID_USAGE_PAGE_GENERIC
+ && ext->preparseData->caps.Usage == HID_USAGE_GENERIC_KEYBOARD)
+ ext->rawinput_handle = WINE_KEYBOARD_HANDLE;
+ else
+ ext->rawinput_handle = alloc_rawinput_handle();
return STATUS_SUCCESS;
diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h
index 889b8c625c0..41f3766a535 100644
--- a/dlls/hidclass.sys/hid.h
+++ b/dlls/hidclass.sys/hid.h
@@ -51,6 +51,7 @@ typedef struct _BASE_DEVICE_EXTENSION {
struct ReportRingBuffer *ring_buffer;
HANDLE halt_event;
HANDLE thread;
+ UINT32 rawinput_handle;
KSPIN_LOCK irp_queue_lock;
LIST_ENTRY irp_queue;
--
2.30.2

View File

@ -1,426 +0,0 @@
From 3d61d04751da0d7267d83ddc374e0f7be550348e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 11 Nov 2019 18:35:18 +0100
Subject: [PATCH] server: Add HID input message type to send_hardware_message
request.
---
dlls/user32/message.c | 4 ++-
dlls/user32/rawinput.c | 60 ++++++++++++++++++++++++++++++++++++--
dlls/user32/user_private.h | 2 ++
server/protocol.def | 26 +++++++++++++++--
server/queue.c | 60 ++++++++++++++++++++++++++++++++------
server/trace.c | 10 +++++--
6 files changed, 144 insertions(+), 18 deletions(-)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index f7ce262f90d..01d1a0eed97 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -3240,10 +3240,10 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags )
{
req->win = wine_server_user_handle( hwnd );
req->flags = flags;
- req->input.type = input->type;
switch (input->type)
{
case INPUT_MOUSE:
+ req->input.type = HW_INPUT_MOUSE;
req->input.mouse.x = input->u.mi.dx;
req->input.mouse.y = input->u.mi.dy;
req->input.mouse.data = input->u.mi.mouseData;
@@ -3252,6 +3252,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags )
req->input.mouse.info = input->u.mi.dwExtraInfo;
break;
case INPUT_KEYBOARD:
+ req->input.type = HW_INPUT_KEYBOARD;
req->input.kbd.vkey = input->u.ki.wVk;
req->input.kbd.scan = input->u.ki.wScan;
req->input.kbd.flags = input->u.ki.dwFlags;
@@ -3259,6 +3260,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags )
req->input.kbd.info = input->u.ki.dwExtraInfo;
break;
case INPUT_HARDWARE:
+ req->input.type = HW_INPUT_HARDWARE;
req->input.hw.msg = input->u.hi.uMsg;
req->input.hw.lparam = MAKELONG( input->u.hi.wParamL, input->u.hi.wParamH );
break;
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c
index ba11a121bc5..a6327b06422 100644
--- a/dlls/user32/rawinput.c
+++ b/dlls/user32/rawinput.c
@@ -46,6 +46,7 @@ struct device
{
WCHAR *path;
HANDLE file;
+ HANDLE handle;
RID_DEVICE_INFO info;
PHIDP_PREPARSED_DATA data;
};
@@ -62,6 +63,8 @@ static CRITICAL_SECTION_DEBUG rawinput_devices_cs_debug =
};
static CRITICAL_SECTION rawinput_devices_cs = { &rawinput_devices_cs_debug, -1, 0, 0, 0, 0 };
+extern DWORD WINAPI GetFinalPathNameByHandleW(HANDLE file, LPWSTR path, DWORD charcount, DWORD flags);
+
static BOOL array_reserve(void **elements, unsigned int *capacity, unsigned int count, unsigned int size)
{
unsigned int new_capacity, max_capacity;
@@ -143,10 +146,43 @@ static struct device *add_device(HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface)
device->path = path;
device->file = file;
device->info.cbSize = sizeof(RID_DEVICE_INFO);
+ device->handle = INVALID_HANDLE_VALUE;
return device;
}
+HANDLE rawinput_handle_from_device_handle(HANDLE device)
+{
+ WCHAR buffer[sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH + 1];
+ OBJECT_NAME_INFORMATION *info = (OBJECT_NAME_INFORMATION*)&buffer;
+ ULONG dummy;
+ unsigned int i;
+
+ for (i = 0; i < rawinput_devices_count; ++i)
+ {
+ if (rawinput_devices[i].handle == device)
+ return &rawinput_devices[i];
+ }
+
+ if (NtQueryObject( device, ObjectNameInformation, &buffer, sizeof(buffer) - sizeof(WCHAR), &dummy ) || !info->Name.Buffer)
+ return NULL;
+
+ /* replace \??\ with \\?\ to match rawinput_devices paths */
+ if (info->Name.Length > 1 && info->Name.Buffer[0] == '\\' && info->Name.Buffer[1] == '?')
+ info->Name.Buffer[1] = '\\';
+
+ for (i = 0; i < rawinput_devices_count; ++i)
+ {
+ if (!wcscmp(rawinput_devices[i].path, info->Name.Buffer))
+ {
+ rawinput_devices[i].handle = device;
+ return &rawinput_devices[i];
+ }
+ }
+
+ return NULL;
+}
+
static void find_devices(void)
{
static ULONGLONG last_check;
@@ -326,6 +362,22 @@ BOOL rawinput_from_hardware_message(RAWINPUT *rawinput, const struct hardware_ms
rawinput->data.keyboard.Message = msg_data->rawinput.kbd.message;
rawinput->data.keyboard.ExtraInformation = msg_data->info;
}
+ else if (msg_data->rawinput.type == RIM_TYPEHID)
+ {
+ if (sizeof(*rawinput) + msg_data->rawinput.hid.length > RAWINPUT_BUFFER_SIZE)
+ {
+ ERR("unexpectedly large hardware message dropped\n");
+ return FALSE;
+ }
+
+ rawinput->header.dwSize = FIELD_OFFSET(RAWINPUT, data.hid.bRawData) + msg_data->rawinput.hid.length;
+ rawinput->header.hDevice = rawinput_handle_from_device_handle(wine_server_ptr_handle(msg_data->rawinput.hid.device));
+ rawinput->header.wParam = 0;
+
+ rawinput->data.hid.dwSizeHid = msg_data->rawinput.hid.length;
+ rawinput->data.hid.dwCount = 1;
+ memcpy(rawinput->data.hid.bRawData, msg_data + 1, msg_data->rawinput.hid.length);
+ }
else
{
FIXME("Unhandled rawinput type %#x.\n", msg_data->rawinput.type);
@@ -524,7 +576,7 @@ UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(RAWINPUT *data, UINT *data_size,
struct hardware_msg_data *msg_data;
struct rawinput_thread_data *thread_data;
RAWINPUT *rawinput;
- UINT count = 0, rawinput_size, next_size, overhead;
+ UINT count = 0, rawinput_size, msg_size, next_size, overhead;
BOOL is_wow64;
int i;
@@ -584,7 +636,10 @@ UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(RAWINPUT *data, UINT *data_size,
data->header.dwSize - sizeof(RAWINPUTHEADER));
data->header.dwSize += overhead;
data = NEXTRAWINPUTBLOCK(data);
- msg_data++;
+ msg_size = sizeof(*msg_data);
+ if (msg_data->rawinput.type == RIM_TYPEHID)
+ msg_size += msg_data->rawinput.hid.length;
+ msg_data = (struct hardware_msg_data *)((char *)msg_data + msg_size);
}
if (count == 0 && next_size == 0) *data_size = 0;
@@ -657,6 +712,7 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE handle, UINT command, void *data, UINT
handle, command, data, data_size);
if (!data_size) return ~0U;
+ if (!device) return ~0U;
/* each case below must set:
* *data_size: length (meaning defined by command) of data we want to copy
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index 7761a1ceb4f..bf13e81762a 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -391,4 +391,6 @@ static inline WCHAR *heap_strdupW(const WCHAR *src)
return dst;
}
+extern HANDLE rawinput_handle_from_device_handle(HANDLE device);
+
#endif /* __WINE_USER_PRIVATE_H */
diff --git a/server/protocol.def b/server/protocol.def
index 140d94ea036..a032f9aa507 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -312,6 +312,13 @@ struct hardware_msg_data
int y; /* y coordinate */
unsigned int data; /* mouse data */
} mouse;
+ struct
+ {
+ int type; /* RIM_TYPEHID */
+ obj_handle_t device;
+ unsigned int length; /* HID report length */
+ /* followed by length bytes of HID report data */
+ } hid;
} rawinput;
};
@@ -335,7 +342,7 @@ typedef union
int type;
struct
{
- int type; /* INPUT_KEYBOARD */
+ int type; /* HW_INPUT_KEYBOARD */
unsigned short vkey; /* virtual key code */
unsigned short scan; /* scan code */
unsigned int flags; /* event flags */
@@ -344,7 +351,7 @@ typedef union
} kbd;
struct
{
- int type; /* INPUT_MOUSE */
+ int type; /* HW_INPUT_MOUSE */
int x; /* coordinates */
int y;
unsigned int data; /* mouse data */
@@ -354,11 +361,23 @@ typedef union
} mouse;
struct
{
- int type; /* INPUT_HARDWARE */
+ int type; /* HW_INPUT_HARDWARE */
unsigned int msg; /* message code */
lparam_t lparam; /* message param */
} hw;
+ struct
+ {
+ int type; /* HW_INPUT_HID */
+ obj_handle_t device;
+ unsigned char usage_page;
+ unsigned char usage;
+ unsigned int length;
+ } hid;
} hw_input_t;
+#define HW_INPUT_MOUSE 0
+#define HW_INPUT_KEYBOARD 1
+#define HW_INPUT_HARDWARE 2
+#define HW_INPUT_HID 3
typedef union
{
@@ -2044,6 +2063,7 @@ enum message_type
user_handle_t win; /* window handle */
hw_input_t input; /* input data */
unsigned int flags; /* flags (see below) */
+ VARARG(data,bytes); /* hid report data */
@REPLY
int wait; /* do we need to wait for a reply? */
int prev_x; /* previous cursor position */
diff --git a/server/queue.c b/server/queue.c
index f39cf19ecd7..1b9d66b847e 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1608,7 +1608,7 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa
struct msg_queue *queue;
struct message *msg;
timeout_t timeout = 2000 * -10000; /* FIXME: load from registry */
- int id = (input->type == INPUT_MOUSE) ? WH_MOUSE_LL : WH_KEYBOARD_LL;
+ int id = (input->type == HW_INPUT_MOUSE) ? WH_MOUSE_LL : WH_KEYBOARD_LL;
if (!(hook_thread = get_first_global_hook( id ))) return 0;
if (!(queue = hook_thread->queue)) return 0;
@@ -1626,7 +1626,7 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa
msg->data_size = hardware_msg->data_size;
msg->result = NULL;
- if (input->type == INPUT_KEYBOARD)
+ if (input->type == HW_INPUT_KEYBOARD)
{
unsigned short vkey = input->kbd.vkey;
if (input->kbd.flags & KEYEVENTF_UNICODE) vkey = VK_PACKET;
@@ -1662,6 +1662,8 @@ struct rawinput_message
struct desktop *desktop;
struct hw_msg_source source;
unsigned int time;
+ unsigned char usage_page;
+ unsigned char usage;
struct hardware_msg_data data;
const void *extra;
data_size_t extra_len;
@@ -1671,6 +1673,7 @@ struct rawinput_message
static int queue_rawinput_message( struct process* process, void *arg )
{
const struct rawinput_message* raw_msg = arg;
+ const struct rawinput_device_entry *entry;
const struct rawinput_device *device = NULL;
struct desktop *target_desktop = NULL, *desktop = NULL;
struct thread *target_thread = NULL, *foreground = NULL;
@@ -1682,6 +1685,8 @@ static int queue_rawinput_message( struct process* process, void *arg )
device = process->rawinput_mouse;
else if (raw_msg->data.rawinput.type == RIM_TYPEKEYBOARD)
device = process->rawinput_kbd;
+ else if ((entry = find_rawinput_device( process, raw_msg->usage_page, raw_msg->usage )))
+ device = &entry->device;
if (!device) return 0;
if (raw_msg->desktop) desktop = (struct desktop *)grab_object( raw_msg->desktop );
@@ -2000,6 +2005,37 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_
queue_hardware_message( desktop, msg, 1 );
}
+/* queue a hardware message for an hid event */
+static void queue_hid_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input,
+ unsigned int origin, struct msg_queue *sender, unsigned int req_flags,
+ const void *report, data_size_t report_len )
+{
+ struct hw_msg_source source = { IMDT_UNAVAILABLE, origin };
+ struct hardware_msg_data *msg_data;
+ struct rawinput_message raw_msg;
+
+ if (!(req_flags & SEND_HWMSG_RAWINPUT))
+ return;
+
+ /* send to all desktops */
+ raw_msg.foreground = NULL;
+ raw_msg.desktop = NULL;
+ raw_msg.source = source;
+ raw_msg.time = get_tick_count();
+ raw_msg.usage_page = input->hid.usage_page;
+ raw_msg.usage = input->hid.usage;
+ raw_msg.extra = report;
+ raw_msg.extra_len = report_len;
+
+ msg_data = &raw_msg.data;
+ msg_data->flags = 0;
+ msg_data->rawinput.type = RIM_TYPEHID;
+ msg_data->rawinput.hid.device = input->hid.device;
+ msg_data->rawinput.hid.length = report_len;
+
+ enum_processes( queue_rawinput_message, &raw_msg );
+}
+
/* check message filter for a hardware message */
static int check_hw_message_filter( user_handle_t win, unsigned int msg_code,
user_handle_t filter_win, unsigned int first, unsigned int last )
@@ -2505,15 +2541,18 @@ DECL_HANDLER(send_hardware_message)
switch (req->input.type)
{
- case INPUT_MOUSE:
+ case HW_INPUT_MOUSE:
reply->wait = queue_mouse_message( desktop, req->win, &req->input, origin, sender, req->flags );
break;
- case INPUT_KEYBOARD:
+ case HW_INPUT_KEYBOARD:
reply->wait = queue_keyboard_message( desktop, req->win, &req->input, origin, sender, req->flags );
break;
- case INPUT_HARDWARE:
+ case HW_INPUT_HARDWARE:
queue_custom_hardware_message( desktop, req->win, origin, &req->input );
break;
+ case HW_INPUT_HID:
+ queue_hid_message( desktop, req->win, &req->input, origin, sender, req->flags, get_req_data(), get_req_data_size() );
+ break;
default:
set_error( STATUS_INVALID_PARAMETER );
}
@@ -3295,14 +3334,17 @@ DECL_HANDLER(get_rawinput_buffer)
{
struct message *msg = LIST_ENTRY( ptr, struct message, entry );
struct hardware_msg_data *data = msg->data;
+ data_size_t msg_size = sizeof(*data);
+ if (data->rawinput.type == RIM_TYPEHID)
+ msg_size += data->rawinput.hid.length;
ptr = list_next( &input->msg_list, ptr );
if (msg->msg != WM_INPUT) continue;
next_size = req->rawinput_size;
if (size + next_size > req->buffer_size) break;
- if (cur + sizeof(*data) > buf + get_reply_max_size()) break;
- if (cur + sizeof(*data) > buf + buf_size)
+ if (cur + msg_size > buf + get_reply_max_size()) break;
+ if (cur + msg_size > buf + buf_size)
{
buf_size += buf_size / 2;
if (!(tmp = realloc( buf, buf_size )))
@@ -3314,12 +3356,12 @@ DECL_HANDLER(get_rawinput_buffer)
buf = tmp;
}
- memcpy(cur, data, sizeof(*data));
+ memcpy(cur, data, msg_size);
list_remove( &msg->entry );
free_message( msg );
size += next_size;
- cur += sizeof(*data);
+ cur += msg_size;
count++;
}
diff --git a/server/trace.c b/server/trace.c
index c6ef3fb9773..4434bb1893f 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -398,24 +398,28 @@ static void dump_hw_input( const char *prefix, const hw_input_t *input )
{
switch (input->type)
{
- case INPUT_MOUSE:
+ case HW_INPUT_MOUSE:
fprintf( stderr, "%s{type=MOUSE,x=%d,y=%d,data=%08x,flags=%08x,time=%u",
prefix, input->mouse.x, input->mouse.y, input->mouse.data, input->mouse.flags,
input->mouse.time );
dump_uint64( ",info=", &input->mouse.info );
fputc( '}', stderr );
break;
- case INPUT_KEYBOARD:
+ case HW_INPUT_KEYBOARD:
fprintf( stderr, "%s{type=KEYBOARD,vkey=%04hx,scan=%04hx,flags=%08x,time=%u",
prefix, input->kbd.vkey, input->kbd.scan, input->kbd.flags, input->kbd.time );
dump_uint64( ",info=", &input->kbd.info );
fputc( '}', stderr );
break;
- case INPUT_HARDWARE:
+ case HW_INPUT_HARDWARE:
fprintf( stderr, "%s{type=HARDWARE,msg=%04x", prefix, input->hw.msg );
dump_uint64( ",lparam=", &input->hw.lparam );
fputc( '}', stderr );
break;
+ case HW_INPUT_HID:
+ fprintf( stderr, "%s{type=HID,device=%04x,usage_page=%02x,usage=%02x,length=%04x}",
+ prefix, input->hid.device, input->hid.usage_page, input->hid.usage, input->hid.length );
+ break;
default:
fprintf( stderr, "%s{type=%04x}", prefix, input->type );
break;
--
2.20.1

View File

@ -1,139 +0,0 @@
From 8f7a0c92c370cb4bf1ee6e6d7c51a3d90fe4cd48 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Wed, 18 Sep 2019 21:04:25 +0200
Subject: [PATCH] hidclass.sys: Send input message to server when HID report is
received.
---
dlls/hidclass.sys/device.c | 30 ++++++++++++++++++++++++++++++
dlls/hidclass.sys/hid.h | 1 +
dlls/hidclass.sys/pnp.c | 16 ++++++++++++++++
3 files changed, 47 insertions(+)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c
index 0e905c8322f..369d847e3c1 100644
--- a/dlls/hidclass.sys/device.c
+++ b/dlls/hidclass.sys/device.c
@@ -26,9 +26,11 @@
#include "winuser.h"
#include "setupapi.h"
+#include "wine/server.h"
#include "wine/debug.h"
#include "ddk/hidsdi.h"
#include "ddk/hidtypes.h"
+#include "ddk/ntifs.h"
#include "ddk/wdm.h"
#include "initguid.h"
@@ -123,6 +125,8 @@ NTSTATUS HID_LinkDevice(DEVICE_OBJECT *device)
return status;
}
+ ext->link_handle = INVALID_HANDLE_VALUE;
+
/* FIXME: This should probably be done in mouhid.sys. */
if (ext->preparseData->caps.UsagePage == HID_USAGE_PAGE_GENERIC
&& ext->preparseData->caps.Usage == HID_USAGE_GENERIC_MOUSE)
@@ -207,6 +211,8 @@ void HID_DeleteDevice(DEVICE_OBJECT *device)
IoCompleteRequest(irp, IO_NO_INCREMENT);
}
+ CloseHandle(ext->link_handle);
+
TRACE("Delete device(%p) %s\n", device, debugstr_w(ext->device_name));
HeapFree(GetProcessHeap(), 0, ext->device_name);
RtlFreeUnicodeString(&ext->link_name);
@@ -241,6 +247,28 @@ static NTSTATUS copy_packet_into_buffer(HID_XFER_PACKET *packet, BYTE* buffer, U
return STATUS_BUFFER_OVERFLOW;
}
+static void HID_Device_sendRawInput(DEVICE_OBJECT *device, HID_XFER_PACKET *packet)
+{
+ BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
+
+ if (ext->link_handle == INVALID_HANDLE_VALUE)
+ return;
+
+ SERVER_START_REQ(send_hardware_message)
+ {
+ req->win = 0;
+ req->flags = SEND_HWMSG_RAWINPUT;
+ req->input.type = HW_INPUT_HID;
+ req->input.hid.device = wine_server_obj_handle(ext->link_handle);
+ req->input.hid.usage_page = ext->preparseData->caps.UsagePage;
+ req->input.hid.usage = ext->preparseData->caps.Usage;
+ req->input.hid.length = packet->reportBufferLen;
+ wine_server_add_data(req, packet->reportBuffer, packet->reportBufferLen);
+ wine_server_call(req);
+ }
+ SERVER_END_REQ;
+}
+
static void HID_Device_processQueue(DEVICE_OBJECT *device)
{
IRP *irp;
@@ -324,6 +352,7 @@ static DWORD CALLBACK hid_device_thread(void *args)
if (irp->IoStatus.u.Status == STATUS_SUCCESS)
{
RingBuffer_Write(ext->ring_buffer, packet);
+ HID_Device_sendRawInput(device, packet);
HID_Device_processQueue(device);
}
@@ -370,6 +399,7 @@ static DWORD CALLBACK hid_device_thread(void *args)
else
packet->reportId = 0;
RingBuffer_Write(ext->ring_buffer, packet);
+ HID_Device_sendRawInput(device, packet);
HID_Device_processQueue(device);
}
diff --git a/dlls/hidclass.sys/hid.h b/dlls/hidclass.sys/hid.h
index 36d13c009d7..f12e04d7898 100644
--- a/dlls/hidclass.sys/hid.h
+++ b/dlls/hidclass.sys/hid.h
@@ -46,6 +46,7 @@ typedef struct _BASE_DEVICE_EXTENSION {
ULONG poll_interval;
WCHAR *device_name;
UNICODE_STRING link_name;
+ HANDLE link_handle;
WCHAR device_id[MAX_DEVICE_ID_LEN];
WCHAR instance_id[MAX_DEVICE_ID_LEN];
struct ReportRingBuffer *ring_buffer;
diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c
index 1c130e8dd80..b84a358dba4 100644
--- a/dlls/hidclass.sys/pnp.c
+++ b/dlls/hidclass.sys/pnp.c
@@ -299,12 +299,28 @@ NTSTATUS WINAPI HID_PNP_Dispatch(DEVICE_OBJECT *device, IRP *irp)
case IRP_MN_START_DEVICE:
{
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
+ OBJECT_ATTRIBUTES attr;
rc = minidriver->PNPDispatch(device, irp);
IoSetDeviceInterfaceState(&ext->link_name, TRUE);
if (ext->is_mouse)
IoSetDeviceInterfaceState(&ext->mouse_link_name, TRUE);
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = 0;
+ attr.Attributes = OBJ_CASE_INSENSITIVE;
+ attr.ObjectName = &ext->link_name;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+ NtOpenSymbolicLinkObject(&ext->link_handle, SYMBOLIC_LINK_QUERY, &attr);
+ ext->link_handle = ConvertToGlobalHandle(ext->link_handle);
+
+ if (ext->link_handle == INVALID_HANDLE_VALUE)
+ ERR("Failed to open link %s, error %u.\n", debugstr_w(ext->link_name.Buffer), GetLastError());
+ else
+ TRACE("Opened link handle: %p for %s\n", ext->link_handle, debugstr_w(ext->link_name.Buffer));
+
return rc;
}
case IRP_MN_REMOVE_DEVICE:
--
2.27.0

View File

@ -0,0 +1,118 @@
From 4b24ceb11c3b77ecd1e00d7145be370f7192bbbb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Fri, 19 Mar 2021 14:16:16 +0100
Subject: [PATCH] hidclass.sys: Use __wine_send_input to send device
notifications.
This currently does nothing, because winedevice.exe isn't associated
with any desktop, and the INPUT_HARDWARE messages are dropped.
In this specific case, when INPUT type is INPUT_HARDWARE and hi.uMsg is
WM_INPUT_DEVICE_CHANGE, the RAWINPUT structure usage is a non-standard
extension for Wine internal usage:
* header.wParam contains the message GIDC_ARRIVAL / GIDC_REMOVAL wparam,
* hid.bRawData contains two bytes, which are the HID device UsagePage
and Usage bytes, instead of a real HID report.
This will let us use the same entry point and structures to send device
notifications as for the HID reports in the future (which will be sent
with INPUT_HARDWARE type / WM_INPUT uMsg instead).
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506
---
dlls/hidclass.sys/Makefile.in | 2 +-
dlls/hidclass.sys/pnp.c | 36 +++++++++++++++++++++++++++++++++++
2 files changed, 37 insertions(+), 1 deletion(-)
diff --git a/dlls/hidclass.sys/Makefile.in b/dlls/hidclass.sys/Makefile.in
index be4af747853..2f9f30f8bef 100644
--- a/dlls/hidclass.sys/Makefile.in
+++ b/dlls/hidclass.sys/Makefile.in
@@ -1,6 +1,6 @@
MODULE = hidclass.sys
IMPORTLIB = hidclass
-IMPORTS = hal ntoskrnl
+IMPORTS = hal ntoskrnl user32
DELAYIMPORTS = setupapi hid
EXTRADLLFLAGS = -mno-cygwin
diff --git a/dlls/hidclass.sys/pnp.c b/dlls/hidclass.sys/pnp.c
index a499aec93bb..8e539dfe6b7 100644
--- a/dlls/hidclass.sys/pnp.c
+++ b/dlls/hidclass.sys/pnp.c
@@ -25,6 +25,7 @@
#include "ddk/hidtypes.h"
#include "ddk/wdm.h"
#include "regstr.h"
+#include "winuser.h"
#include "wine/debug.h"
#include "wine/list.h"
@@ -69,6 +70,9 @@ static NTSTATUS get_device_id(DEVICE_OBJECT *device, BUS_QUERY_ID_TYPE type, WCH
return status;
}
+/* make sure bRawData can hold two bytes without requiring additional allocation */
+C_ASSERT(offsetof(RAWINPUT, data.hid.bRawData[2]) < sizeof(RAWINPUT));
+
NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
{
WCHAR device_id[MAX_DEVICE_ID_LEN], instance_id[MAX_DEVICE_ID_LEN];
@@ -79,6 +83,8 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
BASE_DEVICE_EXTENSION *ext = NULL;
HID_DESCRIPTOR descriptor;
BYTE *reportDescriptor;
+ RAWINPUT rawinput;
+ INPUT input;
INT i;
if ((status = get_device_id(PDO, BusQueryDeviceID, device_id)))
@@ -187,6 +193,21 @@ NTSTATUS WINAPI PNP_AddDevice(DRIVER_OBJECT *driver, DEVICE_OBJECT *PDO)
HID_StartDeviceThread(device);
+ rawinput.header.dwType = RIM_TYPEHID;
+ rawinput.header.dwSize = offsetof(RAWINPUT, data.hid.bRawData[2]);
+ rawinput.header.hDevice = ULongToHandle(ext->rawinput_handle);
+ rawinput.header.wParam = GIDC_ARRIVAL;
+ rawinput.data.hid.dwCount = 1;
+ rawinput.data.hid.dwSizeHid = 2;
+ rawinput.data.hid.bRawData[0] = ext->preparseData->caps.UsagePage;
+ rawinput.data.hid.bRawData[1] = ext->preparseData->caps.Usage;
+
+ input.type = INPUT_HARDWARE;
+ input.u.hi.uMsg = WM_INPUT_DEVICE_CHANGE;
+ input.u.hi.wParamH = (WORD)(rawinput.header.dwSize >> 16);
+ input.u.hi.wParamL = (WORD)(rawinput.header.dwSize >> 0);
+ __wine_send_input(0, &input, &rawinput);
+
return STATUS_SUCCESS;
}
@@ -194,6 +215,21 @@ static NTSTATUS remove_device(minidriver *minidriver, DEVICE_OBJECT *device, IRP
{
BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
NTSTATUS rc = STATUS_NOT_SUPPORTED;
+ RAWINPUT rawinput;
+ INPUT input;
+
+ rawinput.header.dwType = RIM_TYPEHID;
+ rawinput.header.dwSize = offsetof(RAWINPUT, data.hid.bRawData[0]);
+ rawinput.header.hDevice = ULongToHandle(ext->rawinput_handle);
+ rawinput.header.wParam = GIDC_REMOVAL;
+ rawinput.data.hid.dwCount = 0;
+ rawinput.data.hid.dwSizeHid = 0;
+
+ input.type = INPUT_HARDWARE;
+ input.u.hi.uMsg = WM_INPUT_DEVICE_CHANGE;
+ input.u.hi.wParamH = (WORD)(rawinput.header.dwSize >> 16);
+ input.u.hi.wParamL = (WORD)(rawinput.header.dwSize >> 0);
+ __wine_send_input(0, &input, &rawinput);
rc = IoSetDeviceInterfaceState(&ext->link_name, FALSE);
if (rc)
--
2.30.2

View File

@ -0,0 +1,140 @@
From 84aab96026febc4d222733b5ecc2919047ac549b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 22 Mar 2021 22:46:36 +0100
Subject: [PATCH] server: Implement desktop broadcast in
queue_rawinput_message.
HID rawinput hardware messages will be sent from winedevice.exe, which
is not attached to any desktop. We need to broadcast the messages to all
desktops in that case.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506
---
server/queue.c | 45 +++++++++++++++++++++++++++++++--------------
1 file changed, 31 insertions(+), 14 deletions(-)
diff --git a/server/queue.c b/server/queue.c
index b026c03e13d..ca2f898492b 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1670,8 +1670,8 @@ static int queue_rawinput_message( struct process* process, void *arg )
{
const struct rawinput_message* raw_msg = arg;
const struct rawinput_device *device = NULL;
- struct desktop *target_desktop = NULL;
- struct thread *target_thread = NULL;
+ struct desktop *target_desktop = NULL, *desktop = NULL;
+ struct thread *target_thread = NULL, *foreground = NULL;
struct message *msg;
int wparam = RIM_INPUT;
@@ -1681,12 +1681,18 @@ static int queue_rawinput_message( struct process* process, void *arg )
device = process->rawinput_kbd;
if (!device) return 0;
- if (process != raw_msg->foreground->process)
+ if (raw_msg->desktop) desktop = (struct desktop *)grab_object( raw_msg->desktop );
+ else if (!(desktop = get_desktop_obj( process, process->desktop, 0 ))) goto done;
+
+ if (raw_msg->foreground) foreground = (struct thread *)grab_object( raw_msg->foreground );
+ else if (!(foreground = get_foreground_thread( desktop, 0 ))) goto done;
+
+ if (process != foreground->process)
{
if (!(device->flags & RIDEV_INPUTSINK)) goto done;
if (!(target_thread = get_window_thread( device->target ))) goto done;
if (!(target_desktop = get_thread_desktop( target_thread, 0 ))) goto done;
- if (target_desktop != raw_msg->desktop) goto done;
+ if (target_desktop != desktop) goto done;
wparam = RIM_INPUTSINK;
}
@@ -1699,11 +1705,13 @@ static int queue_rawinput_message( struct process* process, void *arg )
msg->lparam = 0;
memcpy( msg->data, &raw_msg->data, sizeof(raw_msg->data) );
- queue_hardware_message( raw_msg->desktop, msg, 1 );
+ queue_hardware_message( desktop, msg, 1 );
done:
if (target_thread) release_object( target_thread );
if (target_desktop) release_object( target_desktop );
+ if (foreground) release_object( foreground );
+ if (desktop) release_object( desktop );
return 0;
}
@@ -1961,6 +1969,7 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_
struct hw_msg_source source = { IMDT_UNAVAILABLE, origin };
struct message *msg;
+ if (!desktop) return;
if (!(msg = alloc_hardware_message( 0, source, get_tick_count() ))) return;
msg->win = get_user_full_handle( win );
@@ -2455,15 +2464,14 @@ DECL_HANDLER(send_message)
DECL_HANDLER(send_hardware_message)
{
struct thread *thread = NULL;
- struct desktop *desktop;
+ struct desktop *desktop = get_thread_desktop( current, 0 );
unsigned int origin = (req->flags & SEND_HWMSG_INJECTED ? IMO_INJECTED : IMO_HARDWARE);
struct msg_queue *sender = get_current_queue();
data_size_t size = min( 256, get_reply_max_size() );
- if (!(desktop = get_thread_desktop( current, 0 ))) return;
-
if (req->win)
{
+ if (!desktop) return;
if (!(thread = get_window_thread( req->win ))) return;
if (desktop != thread->queue->input->desktop)
{
@@ -2473,18 +2481,24 @@ DECL_HANDLER(send_hardware_message)
}
}
- reply->prev_x = desktop->cursor.x;
- reply->prev_y = desktop->cursor.y;
+ if (desktop)
+ {
+ reply->prev_x = desktop->cursor.x;
+ reply->prev_y = desktop->cursor.y;
+ }
switch (req->input.type)
{
case INPUT_MOUSE:
+ if (!desktop) return;
reply->wait = queue_mouse_message( desktop, req->win, &req->input, origin, sender );
break;
case INPUT_KEYBOARD:
+ if (!desktop) return;
reply->wait = queue_keyboard_message( desktop, req->win, &req->input, origin, sender );
break;
case INPUT_HARDWARE:
+ if (!desktop) set_error( STATUS_SUCCESS );
queue_custom_hardware_message( desktop, req->win, origin, &req->input );
break;
default:
@@ -2492,10 +2506,13 @@ DECL_HANDLER(send_hardware_message)
}
if (thread) release_object( thread );
- reply->new_x = desktop->cursor.x;
- reply->new_y = desktop->cursor.y;
- set_reply_data( desktop->keystate, size );
- release_object( desktop );
+ if (desktop)
+ {
+ reply->new_x = desktop->cursor.x;
+ reply->new_y = desktop->cursor.y;
+ set_reply_data( desktop->keystate, size );
+ release_object( desktop );
+ }
}
/* post a quit message to the current queue */
--
2.30.2

View File

@ -0,0 +1,123 @@
From 281b7628ea550071eab3b0c933b02ff67a3b215d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 22 Mar 2021 17:55:50 +0100
Subject: [PATCH] server: Add rawinput union to hw_input_t / INPUT_HARDWARE.
When msg is WM_INPUT_DEVICE_CHANGE.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506
---
server/protocol.def | 42 ++++++++++++++++++++++++------------------
server/trace.c | 23 +++++++++++++++++++++++
2 files changed, 47 insertions(+), 18 deletions(-)
diff --git a/server/protocol.def b/server/protocol.def
index 617818f622d..9539169f1ff 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -289,30 +289,32 @@ struct hw_msg_source
unsigned int origin; /* source origin (IMO_* values) */
};
+union rawinput
+{
+ int type;
+ struct
+ {
+ int type; /* RIM_TYPEKEYBOARD */
+ unsigned int message; /* message generated by this rawinput event */
+ unsigned short vkey; /* virtual key code */
+ unsigned short scan; /* scan code */
+ } kbd;
+ struct
+ {
+ int type; /* RIM_TYPEMOUSE */
+ int x; /* x coordinate */
+ int y; /* y coordinate */
+ unsigned int data; /* mouse data */
+ } mouse;
+};
+
struct hardware_msg_data
{
lparam_t info; /* extra info */
unsigned int hw_id; /* unique id */
unsigned int flags; /* hook flags */
struct hw_msg_source source; /* message source */
- union
- {
- int type;
- struct
- {
- int type; /* RIM_TYPEKEYBOARD */
- unsigned int message; /* message generated by this rawinput event */
- unsigned short vkey; /* virtual key code */
- unsigned short scan; /* scan code */
- } kbd;
- struct
- {
- int type; /* RIM_TYPEMOUSE */
- int x; /* x coordinate */
- int y; /* y coordinate */
- unsigned int data; /* mouse data */
- } mouse;
- } rawinput;
+ union rawinput rawinput; /* rawinput message data */
};
struct callback_msg_data
@@ -357,6 +359,10 @@ typedef union
int type; /* INPUT_HARDWARE */
unsigned int msg; /* message code */
lparam_t lparam; /* message param */
+ union
+ {
+ union rawinput rawinput; /* WM_INPUT_DEVICE_CHANGE msg */
+ } data;
} hw;
} hw_input_t;
diff --git a/server/trace.c b/server/trace.c
index 44bc8d8ee6f..ce21ae4fe4f 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -409,6 +409,24 @@ static void dump_irp_params( const char *prefix, const irp_params_t *data )
}
}
+static void dump_rawinput( const char *prefix, const union rawinput *rawinput )
+{
+ switch (rawinput->type)
+ {
+ case RIM_TYPEMOUSE:
+ fprintf( stderr, "%s{type=MOUSE,x=%d,y=%d,data=%08x}", prefix, rawinput->mouse.x,
+ rawinput->mouse.y, rawinput->mouse.data );
+ break;
+ case RIM_TYPEKEYBOARD:
+ fprintf( stderr, "%s{type=KEYBOARD,message=%04x,vkey=%04hx,scan=%04hx}", prefix,
+ rawinput->kbd.message, rawinput->kbd.vkey, rawinput->kbd.scan );
+ break;
+ default:
+ fprintf( stderr, "%s{type=%04x}", prefix, rawinput->type );
+ break;
+ }
+}
+
static void dump_hw_input( const char *prefix, const hw_input_t *input )
{
switch (input->type)
@@ -429,6 +447,11 @@ static void dump_hw_input( const char *prefix, const hw_input_t *input )
case INPUT_HARDWARE:
fprintf( stderr, "%s{type=HARDWARE,msg=%04x", prefix, input->hw.msg );
dump_uint64( ",lparam=", &input->hw.lparam );
+ switch (input->hw.msg)
+ {
+ case WM_INPUT_DEVICE_CHANGE:
+ dump_rawinput( ",rawinput=", &input->hw.data.rawinput );
+ }
fputc( '}', stderr );
break;
default:
--
2.30.2

View File

@ -0,0 +1,96 @@
From 6b794622488eb83f6ede9d62a14f413660a2623a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 22 Mar 2021 18:28:38 +0100
Subject: [PATCH] server: Add RIM_TYPEHID type / hid member to rawinput union.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506
---
server/protocol.def | 8 ++++++++
server/trace.c | 38 ++++++++++++++++++++++----------------
2 files changed, 30 insertions(+), 16 deletions(-)
diff --git a/server/protocol.def b/server/protocol.def
index 9539169f1ff..f97b966719c 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -306,6 +306,14 @@ union rawinput
int y; /* y coordinate */
unsigned int data; /* mouse data */
} mouse;
+ struct
+ {
+ int type; /* RIM_TYPEHID */
+ unsigned int device; /* rawinput device index */
+ unsigned int param; /* rawinput message param */
+ unsigned int length; /* HID report length */
+ /* followed by length bytes of HID report data */
+ } hid;
};
struct hardware_msg_data
diff --git a/server/trace.c b/server/trace.c
index ce21ae4fe4f..3d24cec0133 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -409,6 +409,22 @@ static void dump_irp_params( const char *prefix, const irp_params_t *data )
}
}
+static void dump_varargs_bytes( const char *prefix, data_size_t size )
+{
+ const unsigned char *data = cur_data;
+ data_size_t len = min( 1024, size );
+
+ fprintf( stderr, "%s{", prefix );
+ while (len > 0)
+ {
+ fprintf( stderr, "%02x", *data++ );
+ if (--len) fputc( ',', stderr );
+ }
+ if (size > 1024) fprintf( stderr, "...(total %u)", size );
+ fputc( '}', stderr );
+ remove_data( size );
+}
+
static void dump_rawinput( const char *prefix, const union rawinput *rawinput )
{
switch (rawinput->type)
@@ -421,6 +437,12 @@ static void dump_rawinput( const char *prefix, const union rawinput *rawinput )
fprintf( stderr, "%s{type=KEYBOARD,message=%04x,vkey=%04hx,scan=%04hx}", prefix,
rawinput->kbd.message, rawinput->kbd.vkey, rawinput->kbd.scan );
break;
+ case RIM_TYPEHID:
+ fprintf( stderr, "%s{type=HID,device=%04x,param=%04x,length=%u", prefix,
+ rawinput->hid.device, rawinput->hid.param, rawinput->hid.length );
+ dump_varargs_bytes( ",report=", rawinput->hid.length );
+ fputc( '}', stderr );
+ break;
default:
fprintf( stderr, "%s{type=%04x}", prefix, rawinput->type );
break;
@@ -580,22 +602,6 @@ static void dump_varargs_user_handles( const char *prefix, data_size_t size )
remove_data( size );
}
-static void dump_varargs_bytes( const char *prefix, data_size_t size )
-{
- const unsigned char *data = cur_data;
- data_size_t len = min( 1024, size );
-
- fprintf( stderr,"%s{", prefix );
- while (len > 0)
- {
- fprintf( stderr, "%02x", *data++ );
- if (--len) fputc( ',', stderr );
- }
- if (size > 1024) fprintf( stderr, "...(total %u)", size );
- fputc( '}', stderr );
- remove_data( size );
-}
-
static void dump_varargs_string( const char *prefix, data_size_t size )
{
fprintf( stderr, "%s\"%.*s\"", prefix, (int)size, (const char *)cur_data );
--
2.30.2

View File

@ -0,0 +1,47 @@
From dcd1d9ab1462b49093465e3e4117419b63778799 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 22 Mar 2021 18:11:27 +0100
Subject: [PATCH] user32: Send WM_INPUT_DEVICE_CHANGE / RAWINPUT to the server.
Expect INPUT/INPUT_HARDWARE to be followed with RAWINPUT, when uMsg is
WM_INPUT_DEVICE_CHANGE. This is for internal __wine_send_input calls
only, as we ignore INPUT_HARDWARE in SendInput.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506
---
dlls/user32/message.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index f87ef9fb3af..f11aaa4144d 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -3267,6 +3267,25 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r
case INPUT_HARDWARE:
req->input.hw.msg = input->u.hi.uMsg;
req->input.hw.lparam = MAKELONG( input->u.hi.wParamL, input->u.hi.wParamH );
+ switch (input->u.hi.uMsg)
+ {
+ case WM_INPUT_DEVICE_CHANGE:
+ req->input.hw.data.rawinput.type = rawinput->header.dwType;
+ switch (rawinput->header.dwType)
+ {
+ case RIM_TYPEHID:
+ assert( rawinput->data.hid.dwCount <= 1 );
+ req->input.hw.data.rawinput.hid.device = HandleToUlong( rawinput->header.hDevice );
+ req->input.hw.data.rawinput.hid.param = rawinput->header.wParam;
+ req->input.hw.data.rawinput.hid.length = rawinput->data.hid.dwSizeHid;
+ if (rawinput->data.hid.dwSizeHid)
+ wine_server_add_data( req, rawinput->data.hid.bRawData, rawinput->data.hid.dwSizeHid );
+ break;
+ default:
+ assert( 0 );
+ break;
+ }
+ }
break;
}
if (key_state_info) wine_server_set_reply( req, key_state_info->state,
--
2.30.2

View File

@ -0,0 +1,83 @@
From cb2f3ed7057e769dda746b65464b364edb447c32 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Wed, 7 Apr 2021 12:17:09 +0200
Subject: [PATCH] server: Track known HID rawinput devices on addition and
removal.
To track their usage page and usage bytes.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506
---
server/queue.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/server/queue.c b/server/queue.c
index ca2f898492b..033e4e30b66 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1656,6 +1656,42 @@ static struct thread *get_foreground_thread( struct desktop *desktop, user_handl
return NULL;
}
+static struct rawinput_device *hid_rawinput_devices;
+static unsigned int hid_rawinput_device_count;
+
+static void insert_hid_rawinput_device( unsigned int index, const char *data, unsigned int data_len )
+{
+ unsigned int new_count;
+
+ if (data_len < 2) return;
+
+ if (!hid_rawinput_device_count)
+ {
+ hid_rawinput_device_count = 64;
+ while (hid_rawinput_device_count < index) hid_rawinput_device_count *= 2;
+ hid_rawinput_devices = mem_alloc( hid_rawinput_device_count * sizeof(*hid_rawinput_devices) );
+ memset( hid_rawinput_devices, 0, hid_rawinput_device_count * sizeof(*hid_rawinput_devices) );
+ }
+ else if (hid_rawinput_device_count < index)
+ {
+ new_count = hid_rawinput_device_count;
+ while (new_count < index) new_count *= 2;
+ hid_rawinput_devices = realloc( hid_rawinput_devices, new_count * sizeof(*hid_rawinput_devices) );
+ memset( hid_rawinput_devices + hid_rawinput_device_count, 0, (new_count - hid_rawinput_device_count) * sizeof(*hid_rawinput_devices) );
+ hid_rawinput_device_count = new_count;
+ }
+
+ hid_rawinput_devices[index].usage_page = data[0];
+ hid_rawinput_devices[index].usage = data[1];
+}
+
+static void remove_hid_rawinput_device( unsigned int index )
+{
+ if (hid_rawinput_device_count < index) return;
+ hid_rawinput_devices[index].usage_page = 0;
+ hid_rawinput_devices[index].usage = 0;
+}
+
struct rawinput_message
{
struct thread *foreground;
@@ -1969,6 +2005,19 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_
struct hw_msg_source source = { IMDT_UNAVAILABLE, origin };
struct message *msg;
+ switch (input->hw.msg)
+ {
+ case WM_INPUT_DEVICE_CHANGE:
+ if (input->hw.data.rawinput.type == RIM_TYPEHID &&
+ input->hw.data.rawinput.hid.param == GIDC_ARRIVAL)
+ insert_hid_rawinput_device( input->hw.data.rawinput.hid.device, get_req_data(), get_req_data_size() );
+
+ if (input->hw.data.rawinput.type == RIM_TYPEHID &&
+ input->hw.data.rawinput.hid.param == GIDC_REMOVAL)
+ remove_hid_rawinput_device( input->hw.data.rawinput.hid.device );
+ return;
+ }
+
if (!desktop) return;
if (!(msg = alloc_hardware_message( 0, source, get_tick_count() ))) return;
--
2.30.2

View File

@ -1,19 +1,21 @@
From 1851c55f41d14e03c927b0e5220f9c00b1d05f6e Mon Sep 17 00:00:00 2001
From 3c71ae18955c39a1e85532175de76068597010d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 12 Sep 2019 14:14:08 +0200
Date: Wed, 10 Feb 2021 13:23:31 +0100
Subject: [PATCH] server: Add process argument to find_rawinput_device.
We need to be able to iterate all registered rawinput devices for
foreign processes, not only the current one.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506
---
server/queue.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/server/queue.c b/server/queue.c
index 46ace52f004..810612c5167 100644
index 033e4e30b66..e71d9207e1a 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1490,11 +1490,11 @@ static user_handle_t find_hardware_message_window( struct desktop *desktop, stru
@@ -1489,11 +1489,11 @@ static user_handle_t find_hardware_message_window( struct desktop *desktop, stru
return win;
}
@ -27,7 +29,7 @@ index 46ace52f004..810612c5167 100644
{
if (e->device.usage_page != usage_page || e->device.usage != usage) continue;
return e;
@@ -1507,7 +1507,7 @@ static void update_rawinput_device(const struct rawinput_device *device)
@@ -1506,7 +1506,7 @@ static void update_rawinput_device(const struct rawinput_device *device)
{
struct rawinput_device_entry *e;
@ -36,7 +38,7 @@ index 46ace52f004..810612c5167 100644
{
if (!(e = mem_alloc( sizeof(*e) ))) return;
list_add_tail( &current->process->rawinput_devices, &e->entry );
@@ -3286,9 +3286,9 @@ DECL_HANDLER(update_rawinput_devices)
@@ -3362,9 +3362,9 @@ DECL_HANDLER(update_rawinput_devices)
update_rawinput_device(&devices[i]);
}
@ -49,5 +51,5 @@ index 46ace52f004..810612c5167 100644
}
--
2.27.0
2.30.2

View File

@ -0,0 +1,225 @@
From aec62828c1b4daee79e452e749eb215deb40425a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Wed, 7 Apr 2021 12:17:40 +0200
Subject: [PATCH] server: Implement WM_INPUT_DEVICE_CHANGE message dispatch.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506
---
dlls/user32/message.c | 13 +++++++----
dlls/user32/rawinput.c | 2 +-
server/queue.c | 53 +++++++++++++++++++++++++++++++++++++-----
3 files changed, 56 insertions(+), 12 deletions(-)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index f11aaa4144d..54fcdc4588c 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -2288,11 +2288,14 @@ static void accept_hardware_message( UINT hw_id )
static BOOL process_rawinput_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data )
{
struct rawinput_thread_data *thread_data = rawinput_thread_data();
- if (!rawinput_from_hardware_message( thread_data->buffer, msg_data ))
- return FALSE;
- thread_data->hw_id = hw_id;
- msg->lParam = (LPARAM)hw_id;
+ if (msg->message == WM_INPUT)
+ {
+ if (!rawinput_from_hardware_message( thread_data->buffer, msg_data )) return FALSE;
+ thread_data->hw_id = hw_id;
+ msg->lParam = (LPARAM)hw_id;
+ }
+
msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt );
return TRUE;
}
@@ -2612,7 +2615,7 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar
/* hardware messages are always in physical coords */
context = SetThreadDpiAwarenessContext( DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE );
- if (msg->message == WM_INPUT)
+ if (msg->message == WM_INPUT || msg->message == WM_INPUT_DEVICE_CHANGE)
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 );
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c
index ba11a121bc5..99481ffae3d 100644
--- a/dlls/user32/rawinput.c
+++ b/dlls/user32/rawinput.c
@@ -428,7 +428,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH RegisterRawInputDevices(RAWINPUTDEVICE *devices, U
TRACE("device %u: page %#x, usage %#x, flags %#x, target %p.\n",
i, devices[i].usUsagePage, devices[i].usUsage,
devices[i].dwFlags, devices[i].hwndTarget);
- if (devices[i].dwFlags & ~(RIDEV_REMOVE|RIDEV_NOLEGACY|RIDEV_INPUTSINK))
+ if (devices[i].dwFlags & ~(RIDEV_REMOVE|RIDEV_NOLEGACY|RIDEV_INPUTSINK|RIDEV_DEVNOTIFY))
FIXME("Unhandled flags %#x for device %u.\n", devices[i].dwFlags, i);
d[i].usage_page = devices[i].usUsagePage;
diff --git a/server/queue.c b/server/queue.c
index e71d9207e1a..9fe009b5cfe 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1464,7 +1464,7 @@ static user_handle_t find_hardware_message_window( struct desktop *desktop, stru
*thread = NULL;
*msg_code = msg->msg;
- if (msg->msg == WM_INPUT)
+ if (msg->msg == WM_INPUT || msg->msg == WM_INPUT_DEVICE_CHANGE)
{
if (!(win = msg->win) && input) win = input->focus;
}
@@ -1553,7 +1553,7 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg
if (msg->wparam == VK_SHIFT || msg->wparam == VK_LSHIFT || msg->wparam == VK_RSHIFT)
msg->lparam &= ~(KF_EXTENDED << 16);
}
- else if (msg->msg != WM_INPUT)
+ else if (msg->msg != WM_INPUT && msg->msg != WM_INPUT_DEVICE_CHANGE)
{
if (msg->msg == WM_MOUSEMOVE)
{
@@ -1651,7 +1651,7 @@ static int send_hook_ll_message( struct desktop *desktop, struct message *hardwa
static struct thread *get_foreground_thread( struct desktop *desktop, user_handle_t window )
{
/* if desktop has no foreground process, assume the receiving window is */
- if (desktop->foreground_input) return get_window_thread( desktop->foreground_input->focus );
+ if (desktop && desktop->foreground_input) return get_window_thread( desktop->foreground_input->focus );
if (window) return get_window_thread( window );
return NULL;
}
@@ -1692,12 +1692,23 @@ static void remove_hid_rawinput_device( unsigned int index )
hid_rawinput_devices[index].usage = 0;
}
+static struct rawinput_device_entry *find_hid_rawinput_device( struct process *process, const union rawinput *rawinput )
+{
+ unsigned int index;
+ if (rawinput->type != RIM_TYPEHID) return NULL;
+ if (!(index = rawinput->hid.device)) return NULL;
+ if (hid_rawinput_device_count < index) return NULL;
+ if (!hid_rawinput_devices[index].usage_page) return NULL;
+ return find_rawinput_device( process, hid_rawinput_devices[index].usage_page, hid_rawinput_devices[index].usage );
+}
+
struct rawinput_message
{
struct thread *foreground;
struct desktop *desktop;
struct hw_msg_source source;
unsigned int time;
+ unsigned int message;
struct hardware_msg_data data;
};
@@ -1705,6 +1716,7 @@ struct rawinput_message
static int queue_rawinput_message( struct process* process, void *arg )
{
const struct rawinput_message* raw_msg = arg;
+ const struct rawinput_device_entry *entry;
const struct rawinput_device *device = NULL;
struct desktop *target_desktop = NULL, *desktop = NULL;
struct thread *target_thread = NULL, *foreground = NULL;
@@ -1715,8 +1727,12 @@ static int queue_rawinput_message( struct process* process, void *arg )
device = process->rawinput_mouse;
else if (raw_msg->data.rawinput.type == RIM_TYPEKEYBOARD)
device = process->rawinput_kbd;
+ else if ((entry = find_hid_rawinput_device( process, &raw_msg->data.rawinput )))
+ device = &entry->device;
if (!device) return 0;
+ if (raw_msg->message == WM_INPUT_DEVICE_CHANGE && !(device->flags & RIDEV_DEVNOTIFY)) return 0;
+
if (raw_msg->desktop) desktop = (struct desktop *)grab_object( raw_msg->desktop );
else if (!(desktop = get_desktop_obj( process, process->desktop, 0 ))) goto done;
@@ -1725,7 +1741,7 @@ static int queue_rawinput_message( struct process* process, void *arg )
if (process != foreground->process)
{
- if (!(device->flags & RIDEV_INPUTSINK)) goto done;
+ if (raw_msg->message == WM_INPUT && !(device->flags & RIDEV_INPUTSINK)) goto done;
if (!(target_thread = get_window_thread( device->target ))) goto done;
if (!(target_desktop = get_thread_desktop( target_thread, 0 ))) goto done;
if (target_desktop != desktop) goto done;
@@ -1736,11 +1752,17 @@ static int queue_rawinput_message( struct process* process, void *arg )
goto done;
msg->win = device->target;
- msg->msg = WM_INPUT;
+ msg->msg = raw_msg->message;
msg->wparam = wparam;
msg->lparam = 0;
memcpy( msg->data, &raw_msg->data, sizeof(raw_msg->data) );
+ if (raw_msg->message == WM_INPUT_DEVICE_CHANGE && raw_msg->data.rawinput.type == RIM_TYPEHID)
+ {
+ msg->wparam = raw_msg->data.rawinput.hid.param;
+ msg->lparam = raw_msg->data.rawinput.hid.device;
+ }
+
queue_hardware_message( desktop, msg, 1 );
done:
@@ -1814,6 +1836,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
raw_msg.desktop = desktop;
raw_msg.source = source;
raw_msg.time = time;
+ raw_msg.message = WM_INPUT;
msg_data = &raw_msg.data;
msg_data->info = input->mouse.info;
@@ -1948,6 +1971,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
raw_msg.desktop = desktop;
raw_msg.source = source;
raw_msg.time = time;
+ raw_msg.message = WM_INPUT;
msg_data = &raw_msg.data;
msg_data->info = input->kbd.info;
@@ -2003,18 +2027,35 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_
unsigned int origin, const hw_input_t *input )
{
struct hw_msg_source source = { IMDT_UNAVAILABLE, origin };
+ struct hardware_msg_data *msg_data;
+ struct rawinput_message raw_msg;
struct message *msg;
switch (input->hw.msg)
{
case WM_INPUT_DEVICE_CHANGE:
+ raw_msg.foreground = get_foreground_thread( desktop, win );
+ raw_msg.desktop = desktop;
+ raw_msg.source = source;
+ raw_msg.time = get_tick_count();
+ raw_msg.message = input->hw.msg;
+
+ msg_data = &raw_msg.data;
+ msg_data->info = 0;
+ msg_data->flags = 0;
+ msg_data->rawinput = input->hw.data.rawinput;
+
if (input->hw.data.rawinput.type == RIM_TYPEHID &&
input->hw.data.rawinput.hid.param == GIDC_ARRIVAL)
insert_hid_rawinput_device( input->hw.data.rawinput.hid.device, get_req_data(), get_req_data_size() );
+ enum_processes( queue_rawinput_message, &raw_msg );
+
if (input->hw.data.rawinput.type == RIM_TYPEHID &&
input->hw.data.rawinput.hid.param == GIDC_REMOVAL)
remove_hid_rawinput_device( input->hw.data.rawinput.hid.device );
+
+ if (raw_msg.foreground) release_object( raw_msg.foreground );
return;
}
@@ -2151,7 +2192,7 @@ static int get_hardware_message( struct thread *thread, unsigned int hw_id, user
data->hw_id = msg->unique_id;
set_reply_data( msg->data, msg->data_size );
- if (msg->msg == WM_INPUT && (flags & PM_REMOVE))
+ if ((msg->msg == WM_INPUT || msg->msg == WM_INPUT_DEVICE_CHANGE) && (flags & PM_REMOVE))
release_hardware_message( current->queue, data->hw_id );
return 1;
}
--
2.30.2

View File

@ -0,0 +1,73 @@
From 7819fe251e3f12eda8ee615aa735b1870a49e3b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Fri, 5 Mar 2021 10:41:20 +0100
Subject: [PATCH] hidclass.sys: Send rawinput messages with HID report.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506
---
dlls/hidclass.sys/device.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/dlls/hidclass.sys/device.c b/dlls/hidclass.sys/device.c
index 9a3c92b3576..551816aa4fe 100644
--- a/dlls/hidclass.sys/device.c
+++ b/dlls/hidclass.sys/device.c
@@ -254,6 +254,39 @@ static NTSTATUS copy_packet_into_buffer(HID_XFER_PACKET *packet, BYTE* buffer, U
return STATUS_BUFFER_OVERFLOW;
}
+static void HID_Device_sendRawInput(DEVICE_OBJECT *device, HID_XFER_PACKET *packet)
+{
+ BASE_DEVICE_EXTENSION *ext = device->DeviceExtension;
+ RAWINPUT *rawinput;
+ UCHAR *report, id;
+ ULONG data_size;
+ INPUT input;
+
+ data_size = offsetof(RAWINPUT, data.hid.bRawData) + packet->reportBufferLen;
+ if (!(id = ext->preparseData->reports[0].reportID)) data_size += 1;
+
+ rawinput = HeapAlloc(GetProcessHeap(), 0, data_size);
+
+ rawinput->header.dwType = RIM_TYPEHID;
+ rawinput->header.dwSize = data_size;
+ rawinput->header.hDevice = ULongToHandle(ext->rawinput_handle);
+ rawinput->header.wParam = RIM_INPUT;
+ rawinput->data.hid.dwCount = 1;
+ rawinput->data.hid.dwSizeHid = data_size - offsetof(RAWINPUT, data.hid.bRawData);
+
+ report = rawinput->data.hid.bRawData;
+ if (!id) *report++ = 0;
+ memcpy(report, packet->reportBuffer, packet->reportBufferLen);
+
+ input.type = INPUT_HARDWARE;
+ input.u.hi.uMsg = WM_INPUT;
+ input.u.hi.wParamH = (WORD)(rawinput->header.dwSize >> 16);
+ input.u.hi.wParamL = (WORD)(rawinput->header.dwSize >> 0);
+ __wine_send_input(0, &input, rawinput);
+
+ HeapFree(GetProcessHeap(), 0, rawinput);
+}
+
static void HID_Device_processQueue(DEVICE_OBJECT *device)
{
IRP *irp;
@@ -337,6 +370,7 @@ static DWORD CALLBACK hid_device_thread(void *args)
if (irp->IoStatus.u.Status == STATUS_SUCCESS)
{
RingBuffer_Write(ext->ring_buffer, packet);
+ HID_Device_sendRawInput(device, packet);
HID_Device_processQueue(device);
}
@@ -383,6 +417,7 @@ static DWORD CALLBACK hid_device_thread(void *args)
else
packet->reportId = 0;
RingBuffer_Write(ext->ring_buffer, packet);
+ HID_Device_sendRawInput(device, packet);
HID_Device_processQueue(device);
}
--
2.30.2

View File

@ -1,19 +1,21 @@
From ea854d200d2fb243dc898a1ef4e2a1a6f127a329 Mon Sep 17 00:00:00 2001
From 9b9134b94879a1e501d0337cdf6f607ebe2ff84f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 19 Sep 2019 09:20:44 +0200
Subject: [PATCH] server: Allow extra data for hardware_msg_data message.
Date: Tue, 23 Mar 2021 10:11:07 +0100
Subject: [PATCH] server: Add extra data to hardware_msg_data.
The RIM_TYPEHID messages will have to carry the variable length HID
report.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506
---
server/queue.c | 31 +++++++++++++++++++++----------
1 file changed, 21 insertions(+), 10 deletions(-)
server/queue.c | 33 +++++++++++++++++++++++----------
1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/server/queue.c b/server/queue.c
index 810612c5167..f5d19031485 100644
index 9fe009b5cfe..248157ca7da 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -343,13 +343,13 @@ static int assign_thread_input( struct thread *thread, struct thread_input *new_
@@ -348,13 +348,13 @@ static int assign_thread_input( struct thread *thread, struct thread_input *new_
/* allocate a hardware message and its data */
static struct message *alloc_hardware_message( lparam_t info, struct hw_msg_source source,
@ -29,7 +31,7 @@ index 810612c5167..f5d19031485 100644
{
free( msg );
return NULL;
@@ -358,9 +358,9 @@ static struct message *alloc_hardware_message( lparam_t info, struct hw_msg_sour
@@ -363,9 +363,9 @@ static struct message *alloc_hardware_message( lparam_t info, struct hw_msg_sour
msg->type = MSG_HARDWARE;
msg->time = time;
msg->data = msg_data;
@ -41,7 +43,7 @@ index 810612c5167..f5d19031485 100644
msg_data->info = info;
msg_data->source = source;
return msg;
@@ -393,7 +393,7 @@ static void set_cursor_pos( struct desktop *desktop, int x, int y )
@@ -398,7 +398,7 @@ static void set_cursor_pos( struct desktop *desktop, int x, int y )
return;
}
@ -50,24 +52,24 @@ index 810612c5167..f5d19031485 100644
msg->msg = WM_MOUSEMOVE;
msg->x = x;
@@ -1649,6 +1649,8 @@ struct rawinput_message
struct hw_msg_source source;
@@ -1710,6 +1710,8 @@ struct rawinput_message
unsigned int time;
unsigned int message;
struct hardware_msg_data data;
+ const void *extra;
+ data_size_t extra_len;
};
/* check if process is supposed to receive a WM_INPUT message and eventually queue it */
@@ -1659,6 +1661,7 @@ static int queue_rawinput_message( struct process* process, void *arg )
struct desktop *target_desktop = NULL;
struct thread *target_thread = NULL;
@@ -1721,6 +1723,7 @@ static int queue_rawinput_message( struct process* process, void *arg )
struct desktop *target_desktop = NULL, *desktop = NULL;
struct thread *target_thread = NULL, *foreground = NULL;
struct message *msg;
+ struct hardware_msg_data *msg_data;
int wparam = RIM_INPUT;
if (raw_msg->data.rawinput.type == RIM_TYPEMOUSE)
@@ -1676,14 +1679,18 @@ static int queue_rawinput_message( struct process* process, void *arg )
@@ -1748,14 +1751,18 @@ static int queue_rawinput_message( struct process* process, void *arg )
wparam = RIM_INPUTSINK;
}
@ -77,7 +79,7 @@ index 810612c5167..f5d19031485 100644
+ msg_data = msg->data;
msg->win = device->target;
msg->msg = WM_INPUT;
msg->msg = raw_msg->message;
msg->wparam = wparam;
msg->lparam = 0;
- memcpy( msg->data, &raw_msg->data, sizeof(raw_msg->data) );
@ -86,18 +88,18 @@ index 810612c5167..f5d19031485 100644
+ if (raw_msg->extra_len && raw_msg->extra)
+ memcpy( msg_data + 1, raw_msg->extra, raw_msg->extra_len );
queue_hardware_message( raw_msg->desktop, msg, 1 );
@@ -1756,6 +1763,8 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
raw_msg.desktop = desktop;
if (raw_msg->message == WM_INPUT_DEVICE_CHANGE && raw_msg->data.rawinput.type == RIM_TYPEHID)
{
@@ -1837,6 +1844,8 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
raw_msg.source = source;
raw_msg.time = time;
raw_msg.message = WM_INPUT;
+ raw_msg.extra = NULL;
+ raw_msg.extra_len = 0;
msg_data = &raw_msg.data;
msg_data->info = input->mouse.info;
@@ -1785,7 +1794,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
@@ -1862,7 +1871,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons
if (!(flags & (1 << i))) continue;
flags &= ~(1 << i);
@ -106,33 +108,42 @@ index 810612c5167..f5d19031485 100644
msg_data = msg->data;
msg->win = get_user_full_handle( win );
@@ -1894,6 +1903,8 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
raw_msg.desktop = desktop;
@@ -1972,6 +1981,8 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
raw_msg.source = source;
raw_msg.time = time;
raw_msg.message = WM_INPUT;
+ raw_msg.extra = NULL;
+ raw_msg.extra_len = 0;
msg_data = &raw_msg.data;
msg_data->info = input->kbd.info;
@@ -1917,7 +1928,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
if (!(req_flags & SEND_HWMSG_WINDOW))
@@ -1991,7 +2002,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
return 0;
}
- if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0;
+ if (!(msg = alloc_hardware_message( input->kbd.info, source, time, 0 ))) return 0;
msg_data = msg->data;
msg->win = get_user_full_handle( win );
@@ -1955,7 +1966,7 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_
struct hw_msg_source source = { IMDT_UNAVAILABLE, origin };
struct message *msg;
@@ -2039,6 +2050,8 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_
raw_msg.source = source;
raw_msg.time = get_tick_count();
raw_msg.message = input->hw.msg;
+ raw_msg.extra = NULL;
+ raw_msg.extra_len = 0;
msg_data = &raw_msg.data;
msg_data->info = 0;
@@ -2060,7 +2073,7 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_
}
if (!desktop) return;
- if (!(msg = alloc_hardware_message( 0, source, get_tick_count() ))) return;
+ if (!(msg = alloc_hardware_message( 0, source, get_tick_count(), 0 ))) return;
msg->win = get_user_full_handle( win );
msg->msg = input->hw.msg;
--
2.27.0
2.30.2

View File

@ -0,0 +1,185 @@
From d394cc092108c710ad2cccbcec1919a084037910 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 23 Mar 2021 10:42:07 +0100
Subject: [PATCH] server: Implement WM_INPUT / RIM_TYPEHID message dispatch.
The messages are of variable size and carry the corresponding HID report
data after each RAWINPUT struct.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50506
---
dlls/user32/message.c | 1 +
dlls/user32/rawinput.c | 23 +++++++++++++++++++++--
server/protocol.def | 2 +-
server/queue.c | 25 ++++++++++++++++++-------
server/trace.c | 1 +
5 files changed, 42 insertions(+), 10 deletions(-)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index 54fcdc4588c..f986b71953a 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -3272,6 +3272,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r
req->input.hw.lparam = MAKELONG( input->u.hi.wParamL, input->u.hi.wParamH );
switch (input->u.hi.uMsg)
{
+ case WM_INPUT:
case WM_INPUT_DEVICE_CHANGE:
req->input.hw.data.rawinput.type = rawinput->header.dwType;
switch (rawinput->header.dwType)
diff --git a/dlls/user32/rawinput.c b/dlls/user32/rawinput.c
index 99481ffae3d..c69393d9ed2 100644
--- a/dlls/user32/rawinput.c
+++ b/dlls/user32/rawinput.c
@@ -326,6 +326,22 @@ BOOL rawinput_from_hardware_message(RAWINPUT *rawinput, const struct hardware_ms
rawinput->data.keyboard.Message = msg_data->rawinput.kbd.message;
rawinput->data.keyboard.ExtraInformation = msg_data->info;
}
+ else if (msg_data->rawinput.type == RIM_TYPEHID)
+ {
+ if (sizeof(*rawinput) + msg_data->rawinput.hid.length > RAWINPUT_BUFFER_SIZE)
+ {
+ ERR( "unexpectedly large hardware message dropped\n" );
+ return FALSE;
+ }
+
+ rawinput->header.dwSize = FIELD_OFFSET( RAWINPUT, data.hid.bRawData ) + msg_data->rawinput.hid.length;
+ rawinput->header.hDevice = ULongToHandle( msg_data->rawinput.hid.device );
+ rawinput->header.wParam = 0;
+
+ rawinput->data.hid.dwSizeHid = msg_data->rawinput.hid.length;
+ rawinput->data.hid.dwCount = 1;
+ memcpy( rawinput->data.hid.bRawData, msg_data + 1, msg_data->rawinput.hid.length );
+ }
else
{
FIXME("Unhandled rawinput type %#x.\n", msg_data->rawinput.type);
@@ -524,7 +540,7 @@ UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(RAWINPUT *data, UINT *data_size,
struct hardware_msg_data *msg_data;
struct rawinput_thread_data *thread_data;
RAWINPUT *rawinput;
- UINT count = 0, rawinput_size, next_size, overhead;
+ UINT count = 0, rawinput_size, msg_size, next_size, overhead;
BOOL is_wow64;
int i;
@@ -584,7 +600,9 @@ UINT WINAPI DECLSPEC_HOTPATCH GetRawInputBuffer(RAWINPUT *data, UINT *data_size,
data->header.dwSize - sizeof(RAWINPUTHEADER));
data->header.dwSize += overhead;
data = NEXTRAWINPUTBLOCK(data);
- msg_data++;
+ msg_size = sizeof(*msg_data);
+ if (msg_data->rawinput.type == RIM_TYPEHID) msg_size += msg_data->rawinput.hid.length;
+ msg_data = (struct hardware_msg_data *)((char *)msg_data + msg_size);
}
if (count == 0 && next_size == 0) *data_size = 0;
@@ -657,6 +675,7 @@ UINT WINAPI GetRawInputDeviceInfoW(HANDLE handle, UINT command, void *data, UINT
handle, command, data, data_size);
if (!data_size) return ~0U;
+ if (!device) return ~0U;
/* each case below must set:
* *data_size: length (meaning defined by command) of data we want to copy
diff --git a/server/protocol.def b/server/protocol.def
index f97b966719c..829216b58c1 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -369,7 +369,7 @@ typedef union
lparam_t lparam; /* message param */
union
{
- union rawinput rawinput; /* WM_INPUT_DEVICE_CHANGE msg */
+ union rawinput rawinput; /* WM_INPUT and WM_INPUT_DEVICE_CHANGE msg */
} data;
} hw;
} hw_input_t;
diff --git a/server/queue.c b/server/queue.c
index 248157ca7da..a411d0af8d2 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -2044,6 +2044,7 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_
switch (input->hw.msg)
{
+ case WM_INPUT:
case WM_INPUT_DEVICE_CHANGE:
raw_msg.foreground = get_foreground_thread( desktop, win );
raw_msg.desktop = desktop;
@@ -2053,18 +2054,26 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_
raw_msg.extra = NULL;
raw_msg.extra_len = 0;
+ if (input->hw.msg == WM_INPUT)
+ {
+ raw_msg.extra = get_req_data();
+ raw_msg.extra_len = get_req_data_size();
+ }
+
msg_data = &raw_msg.data;
msg_data->info = 0;
msg_data->flags = 0;
msg_data->rawinput = input->hw.data.rawinput;
- if (input->hw.data.rawinput.type == RIM_TYPEHID &&
+ if (input->hw.msg == WM_INPUT_DEVICE_CHANGE &&
+ input->hw.data.rawinput.type == RIM_TYPEHID &&
input->hw.data.rawinput.hid.param == GIDC_ARRIVAL)
insert_hid_rawinput_device( input->hw.data.rawinput.hid.device, get_req_data(), get_req_data_size() );
enum_processes( queue_rawinput_message, &raw_msg );
- if (input->hw.data.rawinput.type == RIM_TYPEHID &&
+ if (input->hw.msg == WM_INPUT_DEVICE_CHANGE &&
+ input->hw.data.rawinput.type == RIM_TYPEHID &&
input->hw.data.rawinput.hid.param == GIDC_REMOVAL)
remove_hid_rawinput_device( input->hw.data.rawinput.hid.device );
@@ -3371,16 +3380,18 @@ DECL_HANDLER(get_rawinput_buffer)
{
struct message *msg = LIST_ENTRY( ptr, struct message, entry );
struct hardware_msg_data *data = msg->data;
+ data_size_t hid_size = data->rawinput.type != RIM_TYPEHID ? 0 : data->rawinput.hid.length;
+ data_size_t data_size = sizeof(*data) + hid_size;
ptr = list_next( &input->msg_list, ptr );
if (msg->msg != WM_INPUT) continue;
- next_size = req->rawinput_size;
+ next_size = req->rawinput_size + hid_size;
if (size + next_size > req->buffer_size) break;
- if (cur + sizeof(*data) > buf + get_reply_max_size()) break;
- if (cur + sizeof(*data) > buf + buf_size)
+ if (cur + data_size > buf + get_reply_max_size()) break;
+ if (cur + data_size > buf + buf_size)
{
- buf_size += buf_size / 2;
+ buf_size += buf_size / 2 + hid_size;
if (!(tmp = realloc( buf, buf_size )))
{
set_error( STATUS_NO_MEMORY );
@@ -3390,7 +3401,7 @@ DECL_HANDLER(get_rawinput_buffer)
buf = tmp;
}
- memcpy(cur, data, sizeof(*data));
+ memcpy( cur, data, data_size );
list_remove( &msg->entry );
free_message( msg );
diff --git a/server/trace.c b/server/trace.c
index 3d24cec0133..f50a0367683 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -471,6 +471,7 @@ static void dump_hw_input( const char *prefix, const hw_input_t *input )
dump_uint64( ",lparam=", &input->hw.lparam );
switch (input->hw.msg)
{
+ case WM_INPUT:
case WM_INPUT_DEVICE_CHANGE:
dump_rawinput( ",rawinput=", &input->hw.data.rawinput );
}
--
2.30.2

View File

@ -0,0 +1,124 @@
From 2e8dd5065ba659d6f5f5c5bedadbec4e06a98a6a Mon Sep 17 00:00:00 2001
From: Arkadiusz Hiler <ahiler@codeweavers.com>
Date: Tue, 23 Feb 2021 14:41:58 +0200
Subject: [PATCH] ntoskrnl: Implement IoSetDevicePropertyData().
---
dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 1 +
dlls/ntoskrnl.exe/pnp.c | 51 +++++++++++++++++++++++++++++
include/ddk/wdm.h | 4 +++
3 files changed, 56 insertions(+)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
index 2e5e2e6e11b..4eb08faec2e 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
+++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec
@@ -465,6 +465,7 @@
@ stdcall IoReuseIrp(ptr long)
@ stub IoSetCompletionRoutineEx
@ stdcall IoSetDeviceInterfaceState(ptr long)
+@ stdcall IoSetDevicePropertyData(ptr ptr long long long long ptr)
@ stub IoSetDeviceToVerify
@ stub IoSetFileOrigin
@ stub IoSetHardErrorOrVerifyDevice
diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c
index 7994a8b85b9..0d5d0d721d4 100644
--- a/dlls/ntoskrnl.exe/pnp.c
+++ b/dlls/ntoskrnl.exe/pnp.c
@@ -38,6 +38,12 @@ DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
+static inline const char *debugstr_propkey( const DEVPROPKEY *id )
+{
+ if (!id) return "(null)";
+ return wine_dbg_sprintf( "{%s,%04x}", wine_dbgstr_guid( &id->fmtid ), id->pid );
+}
+
#define MAX_SERVICE_NAME 260
struct device_interface
@@ -770,6 +776,51 @@ NTSTATUS WINAPI IoSetDeviceInterfaceState( UNICODE_STRING *name, BOOLEAN enable
return ret;
}
+/***********************************************************************
+ * IoSetDevicePropertyData (NTOSKRNL.EXE.@)
+ */
+NTSTATUS WINAPI IoSetDevicePropertyData( DEVICE_OBJECT *device, const DEVPROPKEY *property_key, LCID lcid,
+ ULONG flags, DEVPROPTYPE type, ULONG size, void *data )
+{
+ SP_DEVINFO_DATA sp_device = {sizeof(sp_device)};
+ WCHAR device_instance_id[MAX_DEVICE_ID_LEN];
+ NTSTATUS status;
+ HDEVINFO set;
+
+ TRACE( "device %p, property_key %s, lcid %#x, flags %#x, type %#x, size %u, data %p.\n",
+ device, debugstr_propkey(property_key), lcid, flags, type, size, data );
+
+ /* flags is always treated as PLUGPLAY_PROPERTY_PERSISTENT starting with Win 8 / 2012 */
+
+ if (lcid != LOCALE_NEUTRAL) FIXME( "only LOCALE_NEUTRAL is supported\n" );
+
+ if ((status = get_device_instance_id( device, device_instance_id ))) return status;
+
+ if ((set = SetupDiCreateDeviceInfoList( &GUID_NULL, NULL )) == INVALID_HANDLE_VALUE)
+ {
+ ERR( "Failed to create device list, error %#x.\n", GetLastError() );
+ return GetLastError();
+ }
+
+ if (!SetupDiOpenDeviceInfoW( set, device_instance_id, NULL, 0, &sp_device ))
+ {
+ ERR( "Failed to open device, error %#x.\n", GetLastError() );
+ SetupDiDestroyDeviceInfoList( set );
+ return GetLastError();
+ }
+
+ if (!SetupDiSetDevicePropertyW( set, &sp_device, property_key, type, data, size, 0 ))
+ {
+ ERR( "Failed to set property, error %#x.\n", GetLastError() );
+ SetupDiDestroyDeviceInfoList( set );
+ return GetLastError();
+ }
+
+ SetupDiDestroyDeviceInfoList( set );
+
+ return STATUS_SUCCESS;
+}
+
/***********************************************************************
* IoRegisterDeviceInterface (NTOSKRNL.EXE.@)
*/
diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h
index 3b9af7d52b2..3d0f810c2f0 100644
--- a/include/ddk/wdm.h
+++ b/include/ddk/wdm.h
@@ -21,6 +21,7 @@
#define _NTDDK_
#include <ntstatus.h>
+#include <devpropdef.h>
#ifdef _WIN64
#define POINTER_ALIGNMENT DECLSPEC_ALIGN(8)
@@ -1677,6 +1678,8 @@ void WINAPI ExReleaseResourceForThreadLite(ERESOURCE*,ERESOURCE_THREAD);
ULONG WINAPI ExSetTimerResolution(ULONG,BOOLEAN);
void WINAPI ExUnregisterCallback(void*);
+#define PLUGPLAY_PROPERTY_PERSISTENT 0x0001
+
void WINAPI IoAcquireCancelSpinLock(KIRQL*);
NTSTATUS WINAPI IoAcquireRemoveLockEx(IO_REMOVE_LOCK*,void*,const char*,ULONG, ULONG);
NTSTATUS WINAPI IoAllocateDriverObjectExtension(PDRIVER_OBJECT,PVOID,ULONG,PVOID*);
@@ -1724,6 +1727,7 @@ void WINAPI IoReleaseRemoveLockAndWaitEx(IO_REMOVE_LOCK*,void*,ULONG);
void WINAPI IoReleaseRemoveLockEx(IO_REMOVE_LOCK*,void*,ULONG);
void WINAPI IoReuseIrp(IRP*,NTSTATUS);
NTSTATUS WINAPI IoSetDeviceInterfaceState(UNICODE_STRING*,BOOLEAN);
+NTSTATUS WINAPI IoSetDevicePropertyData(DEVICE_OBJECT*,const DEVPROPKEY*,LCID,ULONG,DEVPROPTYPE,ULONG,void*);
NTSTATUS WINAPI IoWMIRegistrationControl(PDEVICE_OBJECT,ULONG);
void FASTCALL KeAcquireInStackQueuedSpinLockAtDpcLevel(KSPIN_LOCK*,KLOCK_QUEUE_HANDLE*);
--
2.30.2

Some files were not shown because too many files have changed in this diff Show More