Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
The first two patches are just about testing and fixing the standard
SendInput behavior regarding its parameters.
Then, the idea introduced here is to use a custom struct for hardware
input, so we can then add more data for the HID reports, and send
WM_INPUT messages using SendInput.
It looks like that INPUT struct already has a INPUT_HARDWARE type, which
we could also re-use for such non-mouse and non-keyboard input, but it
doesn't seem to do anything on Windows. It always returns 0 and sets
last error to ERROR_CALL_NOT_IMPLEMENTED.
Alternatively, this could be implemented by changing __wine_send_input
to accept the extended structure, but this way will make it possible to
drop this custom entry point completely, which may be interesting.
dlls/user32/input.c | 18 +++++++++++
dlls/user32/tests/input.c | 63 +++++++++++++++++++++++++++++++++++++++
2 files changed, 81 insertions(+)
diff --git a/dlls/user32/input.c b/dlls/user32/input.c
index e06f8b4413e..e9a74f177b9 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 9d75daa0bd5..57bae6cdcad 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -4118,6 +4118,68 @@ static void test_UnregisterDeviceNotification(void)
ok(ret == FALSE, "Unregistering NULL Device Notification returned: %d\n", ret);
}
+static void test_SendInput(void)
+{
+ INPUT input[16];
+ UINT res, i;
+ HWND hwnd;
+
+ 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, "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();
+
+ trace("done\n");
+ DestroyWindow(hwnd);
+}
+
START_TEST(input)
{
char **argv;
@@ -4140,6 +4202,7 @@ START_TEST(input)
return;
}
+ test_SendInput();
test_Input_blackbox();
test_Input_whitebox();
test_Input_unicode();
--
2.30.0