-- v6: server: Dispatch rawinput messages using the rawinput process list. server: Keep a list of processes that can receive rawinput messages. server: Keep a list of threads connected to each desktop. server: Send hardware input to the visible input desktop. server: Keep track of the winstation input desktop. win32u: Introduce new NtUserSwitchDesktop syscall stub.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/user32.spec | 2 +- dlls/user32/win.c | 12 ----- dlls/win32u/main.c | 5 ++ dlls/win32u/win32syscalls.h | 98 +++++++++++++++++++------------------ dlls/win32u/win32u.spec | 2 +- dlls/win32u/winstation.c | 6 +++ dlls/wow64win/user.c | 7 +++ include/ntuser.h | 1 + 8 files changed, 71 insertions(+), 62 deletions(-)
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec index 042730845f1..14246b3e3e0 100644 --- a/dlls/user32/user32.spec +++ b/dlls/user32/user32.spec @@ -758,7 +758,7 @@ # @ stub SoftModalMessageBox @ stdcall SubtractRect(ptr ptr ptr) @ stdcall SwapMouseButton(long) -@ stdcall SwitchDesktop(long) +@ stdcall SwitchDesktop(long) NtUserSwitchDesktop @ stdcall SwitchToThisWindow(long long) # @ stub SysErrorBox @ stdcall SystemParametersInfoA(long long ptr long) diff --git a/dlls/user32/win.c b/dlls/user32/win.c index b8c04047333..f241d1371f3 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -1571,18 +1571,6 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetWindowInfo( HWND hwnd, WINDOWINFO *info ) return NtUserGetWindowInfo( hwnd, info ); }
-/****************************************************************************** - * SwitchDesktop (USER32.@) - * - * NOTES: Sets the current input or interactive desktop. - */ -BOOL WINAPI SwitchDesktop( HDESK hDesktop) -{ - FIXME("(hwnd %p) stub!\n", hDesktop); - return TRUE; -} - - /***************************************************************************** * UpdateLayeredWindowIndirect (USER32.@) */ diff --git a/dlls/win32u/main.c b/dlls/win32u/main.c index 3f910c214ed..ed0abafe223 100644 --- a/dlls/win32u/main.c +++ b/dlls/win32u/main.c @@ -2034,6 +2034,11 @@ BOOL SYSCALL_API NtUserShowWindowAsync( HWND hwnd, INT cmd ) __ASM_SYSCALL_FUNC( __id_NtUserShowWindowAsync ); }
+BOOL SYSCALL_API NtUserSwitchDesktop( HDESK handle ) +{ + __ASM_SYSCALL_FUNC( __id_NtUserSwitchDesktop ); +} + BOOL SYSCALL_API NtUserSystemParametersInfo( UINT action, UINT val, void *ptr, UINT winini ) { __ASM_SYSCALL_FUNC( __id_NtUserSystemParametersInfo ); diff --git a/dlls/win32u/win32syscalls.h b/dlls/win32u/win32syscalls.h index c8a5ee9367b..da0ba39f771 100644 --- a/dlls/win32u/win32syscalls.h +++ b/dlls/win32u/win32syscalls.h @@ -379,30 +379,31 @@ SYSCALL_ENTRY( 0x0177, NtUserShowScrollBar, 12 ) \ SYSCALL_ENTRY( 0x0178, NtUserShowWindow, 8 ) \ SYSCALL_ENTRY( 0x0179, NtUserShowWindowAsync, 8 ) \ - SYSCALL_ENTRY( 0x017a, NtUserSystemParametersInfo, 16 ) \ - SYSCALL_ENTRY( 0x017b, NtUserSystemParametersInfoForDpi, 20 ) \ - SYSCALL_ENTRY( 0x017c, NtUserThunkedMenuInfo, 8 ) \ - SYSCALL_ENTRY( 0x017d, NtUserThunkedMenuItemInfo, 24 ) \ - SYSCALL_ENTRY( 0x017e, NtUserToUnicodeEx, 28 ) \ - SYSCALL_ENTRY( 0x017f, NtUserTrackMouseEvent, 4 ) \ - SYSCALL_ENTRY( 0x0180, NtUserTrackPopupMenuEx, 24 ) \ - SYSCALL_ENTRY( 0x0181, NtUserTranslateAccelerator, 12 ) \ - SYSCALL_ENTRY( 0x0182, NtUserTranslateMessage, 8 ) \ - SYSCALL_ENTRY( 0x0183, NtUserUnhookWinEvent, 4 ) \ - SYSCALL_ENTRY( 0x0184, NtUserUnhookWindowsHookEx, 4 ) \ - SYSCALL_ENTRY( 0x0185, NtUserUnregisterClass, 12 ) \ - SYSCALL_ENTRY( 0x0186, NtUserUnregisterHotKey, 8 ) \ - SYSCALL_ENTRY( 0x0187, NtUserUpdateInputContext, 12 ) \ - SYSCALL_ENTRY( 0x0188, NtUserUpdateLayeredWindow, 40 ) \ - SYSCALL_ENTRY( 0x0189, NtUserValidateRect, 8 ) \ - SYSCALL_ENTRY( 0x018a, NtUserVkKeyScanEx, 8 ) \ - SYSCALL_ENTRY( 0x018b, NtUserWaitForInputIdle, 12 ) \ - SYSCALL_ENTRY( 0x018c, NtUserWaitMessage, 0 ) \ - SYSCALL_ENTRY( 0x018d, NtUserWindowFromDC, 4 ) \ - SYSCALL_ENTRY( 0x018e, NtUserWindowFromPoint, 8 ) \ - SYSCALL_ENTRY( 0x018f, __wine_get_file_outline_text_metric, 16 ) \ - SYSCALL_ENTRY( 0x0190, __wine_get_icm_profile, 16 ) \ - SYSCALL_ENTRY( 0x0191, __wine_send_input, 12 ) + SYSCALL_ENTRY( 0x017a, NtUserSwitchDesktop, 4 ) \ + SYSCALL_ENTRY( 0x017b, NtUserSystemParametersInfo, 16 ) \ + SYSCALL_ENTRY( 0x017c, NtUserSystemParametersInfoForDpi, 20 ) \ + SYSCALL_ENTRY( 0x017d, NtUserThunkedMenuInfo, 8 ) \ + SYSCALL_ENTRY( 0x017e, NtUserThunkedMenuItemInfo, 24 ) \ + SYSCALL_ENTRY( 0x017f, NtUserToUnicodeEx, 28 ) \ + SYSCALL_ENTRY( 0x0180, NtUserTrackMouseEvent, 4 ) \ + SYSCALL_ENTRY( 0x0181, NtUserTrackPopupMenuEx, 24 ) \ + SYSCALL_ENTRY( 0x0182, NtUserTranslateAccelerator, 12 ) \ + SYSCALL_ENTRY( 0x0183, NtUserTranslateMessage, 8 ) \ + SYSCALL_ENTRY( 0x0184, NtUserUnhookWinEvent, 4 ) \ + SYSCALL_ENTRY( 0x0185, NtUserUnhookWindowsHookEx, 4 ) \ + SYSCALL_ENTRY( 0x0186, NtUserUnregisterClass, 12 ) \ + SYSCALL_ENTRY( 0x0187, NtUserUnregisterHotKey, 8 ) \ + SYSCALL_ENTRY( 0x0188, NtUserUpdateInputContext, 12 ) \ + SYSCALL_ENTRY( 0x0189, NtUserUpdateLayeredWindow, 40 ) \ + SYSCALL_ENTRY( 0x018a, NtUserValidateRect, 8 ) \ + SYSCALL_ENTRY( 0x018b, NtUserVkKeyScanEx, 8 ) \ + SYSCALL_ENTRY( 0x018c, NtUserWaitForInputIdle, 12 ) \ + SYSCALL_ENTRY( 0x018d, NtUserWaitMessage, 0 ) \ + SYSCALL_ENTRY( 0x018e, NtUserWindowFromDC, 4 ) \ + SYSCALL_ENTRY( 0x018f, NtUserWindowFromPoint, 8 ) \ + SYSCALL_ENTRY( 0x0190, __wine_get_file_outline_text_metric, 16 ) \ + SYSCALL_ENTRY( 0x0191, __wine_get_icm_profile, 16 ) \ + SYSCALL_ENTRY( 0x0192, __wine_send_input, 12 )
#define ALL_SYSCALLS64 \ SYSCALL_ENTRY( 0x0000, NtGdiAbortDoc, 8 ) \ @@ -783,27 +784,28 @@ SYSCALL_ENTRY( 0x0177, NtUserShowScrollBar, 24 ) \ SYSCALL_ENTRY( 0x0178, NtUserShowWindow, 16 ) \ SYSCALL_ENTRY( 0x0179, NtUserShowWindowAsync, 16 ) \ - SYSCALL_ENTRY( 0x017a, NtUserSystemParametersInfo, 32 ) \ - SYSCALL_ENTRY( 0x017b, NtUserSystemParametersInfoForDpi, 40 ) \ - SYSCALL_ENTRY( 0x017c, NtUserThunkedMenuInfo, 16 ) \ - SYSCALL_ENTRY( 0x017d, NtUserThunkedMenuItemInfo, 48 ) \ - SYSCALL_ENTRY( 0x017e, NtUserToUnicodeEx, 56 ) \ - SYSCALL_ENTRY( 0x017f, NtUserTrackMouseEvent, 8 ) \ - SYSCALL_ENTRY( 0x0180, NtUserTrackPopupMenuEx, 48 ) \ - SYSCALL_ENTRY( 0x0181, NtUserTranslateAccelerator, 24 ) \ - SYSCALL_ENTRY( 0x0182, NtUserTranslateMessage, 16 ) \ - SYSCALL_ENTRY( 0x0183, NtUserUnhookWinEvent, 8 ) \ - SYSCALL_ENTRY( 0x0184, NtUserUnhookWindowsHookEx, 8 ) \ - SYSCALL_ENTRY( 0x0185, NtUserUnregisterClass, 24 ) \ - SYSCALL_ENTRY( 0x0186, NtUserUnregisterHotKey, 16 ) \ - SYSCALL_ENTRY( 0x0187, NtUserUpdateInputContext, 24 ) \ - SYSCALL_ENTRY( 0x0188, NtUserUpdateLayeredWindow, 80 ) \ - SYSCALL_ENTRY( 0x0189, NtUserValidateRect, 16 ) \ - SYSCALL_ENTRY( 0x018a, NtUserVkKeyScanEx, 16 ) \ - SYSCALL_ENTRY( 0x018b, NtUserWaitForInputIdle, 24 ) \ - SYSCALL_ENTRY( 0x018c, NtUserWaitMessage, 0 ) \ - SYSCALL_ENTRY( 0x018d, NtUserWindowFromDC, 8 ) \ - SYSCALL_ENTRY( 0x018e, NtUserWindowFromPoint, 16 ) \ - SYSCALL_ENTRY( 0x018f, __wine_get_file_outline_text_metric, 32 ) \ - SYSCALL_ENTRY( 0x0190, __wine_get_icm_profile, 32 ) \ - SYSCALL_ENTRY( 0x0191, __wine_send_input, 24 ) + SYSCALL_ENTRY( 0x017a, NtUserSwitchDesktop, 8 ) \ + SYSCALL_ENTRY( 0x017b, NtUserSystemParametersInfo, 32 ) \ + SYSCALL_ENTRY( 0x017c, NtUserSystemParametersInfoForDpi, 40 ) \ + SYSCALL_ENTRY( 0x017d, NtUserThunkedMenuInfo, 16 ) \ + SYSCALL_ENTRY( 0x017e, NtUserThunkedMenuItemInfo, 48 ) \ + SYSCALL_ENTRY( 0x017f, NtUserToUnicodeEx, 56 ) \ + SYSCALL_ENTRY( 0x0180, NtUserTrackMouseEvent, 8 ) \ + SYSCALL_ENTRY( 0x0181, NtUserTrackPopupMenuEx, 48 ) \ + SYSCALL_ENTRY( 0x0182, NtUserTranslateAccelerator, 24 ) \ + SYSCALL_ENTRY( 0x0183, NtUserTranslateMessage, 16 ) \ + SYSCALL_ENTRY( 0x0184, NtUserUnhookWinEvent, 8 ) \ + SYSCALL_ENTRY( 0x0185, NtUserUnhookWindowsHookEx, 8 ) \ + SYSCALL_ENTRY( 0x0186, NtUserUnregisterClass, 24 ) \ + SYSCALL_ENTRY( 0x0187, NtUserUnregisterHotKey, 16 ) \ + SYSCALL_ENTRY( 0x0188, NtUserUpdateInputContext, 24 ) \ + SYSCALL_ENTRY( 0x0189, NtUserUpdateLayeredWindow, 80 ) \ + SYSCALL_ENTRY( 0x018a, NtUserValidateRect, 16 ) \ + SYSCALL_ENTRY( 0x018b, NtUserVkKeyScanEx, 16 ) \ + SYSCALL_ENTRY( 0x018c, NtUserWaitForInputIdle, 24 ) \ + SYSCALL_ENTRY( 0x018d, NtUserWaitMessage, 0 ) \ + SYSCALL_ENTRY( 0x018e, NtUserWindowFromDC, 8 ) \ + SYSCALL_ENTRY( 0x018f, NtUserWindowFromPoint, 16 ) \ + SYSCALL_ENTRY( 0x0190, __wine_get_file_outline_text_metric, 32 ) \ + SYSCALL_ENTRY( 0x0191, __wine_get_icm_profile, 32 ) \ + SYSCALL_ENTRY( 0x0192, __wine_send_input, 24 ) diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 76a60bf1dc8..8aa241b1e7a 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -1270,7 +1270,7 @@ @ stub NtUserSlicerControl @ stub NtUserSoundSentry @ stub NtUserStopAndEndInertia -@ stub NtUserSwitchDesktop +@ stdcall -syscall NtUserSwitchDesktop(long) @ stdcall -syscall NtUserSystemParametersInfo(long long ptr long) @ stdcall -syscall NtUserSystemParametersInfoForDpi(long long ptr long long) @ stub NtUserTestForInteractiveUser diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index 9df27517a43..ef6a7f2c40f 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -293,6 +293,12 @@ HDESK WINAPI NtUserOpenInputDesktop( DWORD flags, BOOL inherit, ACCESS_MASK acce return ret; }
+BOOL WINAPI NtUserSwitchDesktop( HDESK desktop ) +{ + FIXME( "desktop %p stub!\n", desktop ); + return TRUE; +} + /*********************************************************************** * NtUserGetObjectInformation (win32u.@) */ diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index 2dd811578f5..ff3f92c81fe 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -4472,6 +4472,13 @@ NTSTATUS WINAPI wow64_NtUserShowWindowAsync( UINT *args ) return NtUserShowWindowAsync( hwnd, cmd ); }
+NTSTATUS WINAPI wow64_NtUserSwitchDesktop( UINT *args ) +{ + HDESK handle = get_handle( &args ); + + return NtUserSwitchDesktop( handle ); +} + NTSTATUS WINAPI wow64_NtUserSystemParametersInfo( UINT *args ) { UINT action = get_ulong( &args ); diff --git a/include/ntuser.h b/include/ntuser.h index 86f847b8b83..9cf23373cdc 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -784,6 +784,7 @@ W32KAPI BOOL WINAPI NtUserShowWindow( HWND hwnd, INT cmd ); W32KAPI BOOL WINAPI NtUserShowWindowAsync( HWND hwnd, INT cmd ); W32KAPI BOOL WINAPI NtUserSystemParametersInfo( UINT action, UINT val, void *ptr, UINT winini ); W32KAPI BOOL WINAPI NtUserSystemParametersInfoForDpi( UINT action, UINT val, PVOID ptr, UINT winini, UINT dpi ); +W32KAPI BOOL WINAPI NtUserSwitchDesktop( HDESK desktop ); W32KAPI BOOL WINAPI NtUserThunkedMenuInfo( HMENU menu, const MENUINFO *info ); W32KAPI UINT WINAPI NtUserThunkedMenuItemInfo( HMENU menu, UINT pos, UINT flags, UINT method, MENUITEMINFOW *info, UNICODE_STRING *str );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/tests/msg.c | 1 - dlls/user32/tests/winstation.c | 2 -- dlls/win32u/winstation.c | 10 ++++++- server/protocol.def | 6 +++++ server/user.h | 2 ++ server/winstation.c | 48 +++++++++++++++++++++++++++++++++- 6 files changed, 64 insertions(+), 5 deletions(-)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index b699aaa6ff9..8ed608c5d3b 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -9806,7 +9806,6 @@ static DWORD WINAPI run_in_temp_desktop_thread_func(LPVOID param) curr_desktop_name, sizeof(curr_desktop_name), &length ); ok_(file, line)( result, "GetUserObjectInformationA(post_inp_desktop=%p) error %lu [rl = %lu]\n", post_inp_desktop, GetLastError(), length ); - todo_wine ok_(file, line)( strcmp( curr_desktop_name, temp_desktop_name ) == 0, "different desktop name: %s != %s (no switch or concurrent WineTest run?)\n", debugstr_a( curr_desktop_name ), debugstr_a( temp_desktop_name ) ); diff --git a/dlls/user32/tests/winstation.c b/dlls/user32/tests/winstation.c index 805bf57ec6f..11ad7685e97 100644 --- a/dlls/user32/tests/winstation.c +++ b/dlls/user32/tests/winstation.c @@ -693,7 +693,6 @@ static void test_inputdesktop(void) memset(name, 0, sizeof(name)); ret = GetUserObjectInformationA(input_desk, UOI_NAME, name, 1024, NULL); ok(ret, "GetUserObjectInformation failed!\n"); - todo_wine ok(!strcmp(name, "new_desk"), "unexpected desktop %s\n", name); ret = CloseDesktop(input_desk); ok(ret, "CloseDesktop failed!\n"); @@ -798,7 +797,6 @@ static void test_inputdesktop2(void) ok(hdesk != NULL, "OpenDesktop failed!\n"); SetLastError(0xdeadbeef); ret = SwitchDesktop(hdesk); - todo_wine ok(!ret, "Switch to desktop belong to non default winstation should fail!\n"); todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED || broken(GetLastError() == 0xdeadbeef), "last error %08lx\n", GetLastError()); diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index ef6a7f2c40f..6ddd5411f94 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -295,7 +295,15 @@ HDESK WINAPI NtUserOpenInputDesktop( DWORD flags, BOOL inherit, ACCESS_MASK acce
BOOL WINAPI NtUserSwitchDesktop( HDESK desktop ) { - FIXME( "desktop %p stub!\n", desktop ); + TRACE( "desktop %p\n", desktop ); + + SERVER_START_REQ( set_input_desktop ) + { + req->handle = wine_server_obj_handle( desktop ); + if (wine_server_call_err( req )) return FALSE; + } + SERVER_END_REQ; + return TRUE; }
diff --git a/server/protocol.def b/server/protocol.def index 8b51618ebe0..fa78e0487f8 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2769,6 +2769,12 @@ enum coords_relative @END
+/* Changes the current input desktop */ +@REQ(set_input_desktop) + obj_handle_t handle; /* handle to the desktop */ +@END + + /* Close a desktop */ @REQ(close_desktop) obj_handle_t handle; /* handle to the desktop */ diff --git a/server/user.h b/server/user.h index bc58c93200d..56b0eb685f0 100644 --- a/server/user.h +++ b/server/user.h @@ -48,6 +48,7 @@ struct winstation unsigned int flags; /* winstation flags */ struct list entry; /* entry in global winstation list */ struct list desktops; /* list of desktops of this winstation */ + struct desktop *input_desktop; /* desktop receiving user input */ struct clipboard *clipboard; /* clipboard information */ struct atom_table *atom_table; /* global atom table */ struct namespace *desktop_names; /* namespace for desktops of this winstation */ @@ -67,6 +68,7 @@ struct desktop struct object obj; /* object header */ unsigned int flags; /* desktop flags */ struct winstation *winstation; /* winstation this desktop belongs to */ + timeout_t input_time; /* last time this desktop had the input */ struct list entry; /* entry in winstation list of desktops */ struct window *top_window; /* desktop window for this desktop */ struct window *msg_window; /* HWND_MESSAGE top window */ diff --git a/server/winstation.c b/server/winstation.c index c3ea69c8a29..a23cd24261a 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -144,6 +144,7 @@ static struct winstation *create_winstation( struct object *root, const struct u { /* initialize it if it didn't already exist */ winstation->flags = flags; + winstation->input_desktop = NULL; winstation->clipboard = NULL; winstation->atom_table = NULL; list_add_tail( &winstation_list, &winstation->entry ); @@ -211,6 +212,23 @@ struct winstation *get_process_winstation( struct process *process, unsigned int access, &winstation_ops ); }
+/* retrieve the winstation current input desktop */ +static struct desktop *get_input_desktop( struct winstation *winstation ) +{ + struct desktop *desktop; + if (!(desktop = winstation->input_desktop)) return NULL; + return (struct desktop *)grab_object( desktop ); +} + +/* changes the winstation current input desktop and update its input time */ +static int set_input_desktop( struct winstation *winstation, struct desktop *new_desktop ) +{ + if (!(winstation->flags & WSF_VISIBLE)) return 0; + if (new_desktop) new_desktop->input_time = current_time; + winstation->input_desktop = new_desktop; + return 1; +} + /* retrieve a pointer to a desktop object */ struct desktop *get_desktop_obj( struct process *process, obj_handle_t handle, unsigned int access ) { @@ -300,6 +318,15 @@ static int desktop_close_handle( struct object *obj, struct process *process, ob static void desktop_destroy( struct object *obj ) { struct desktop *desktop = (struct desktop *)obj; + struct winstation *winstation = desktop->winstation; + + if (desktop == winstation->input_desktop) + { + struct desktop *other, *found = NULL; + LIST_FOR_EACH_ENTRY(other, &winstation->desktops, struct desktop, entry) + if (!found || other->input_time > found->input_time) found = other; + set_input_desktop( winstation, found ); + }
free_hotkeys( desktop, 0 ); if (desktop->top_window) free_window_handle( desktop->top_window ); @@ -561,6 +588,7 @@ DECL_HANDLER(create_desktop) { if ((desktop = create_desktop( &name, req->attributes, req->flags, winstation ))) { + if (!winstation->input_desktop) set_input_desktop( winstation, desktop ); reply->handle = alloc_handle( current->process, desktop, req->access, req->attributes ); release_object( desktop ); } @@ -608,7 +636,7 @@ DECL_HANDLER(open_input_desktop) return; }
- if ((desktop = get_desktop_obj( current->process, current->process->desktop, 0 ))) + if ((desktop = get_input_desktop( winstation ))) { reply->handle = alloc_handle( current->process, desktop, req->access, req->attributes ); release_object( desktop ); @@ -616,6 +644,24 @@ DECL_HANDLER(open_input_desktop) release_object( winstation ); }
+/* changes the current input desktop */ +DECL_HANDLER(set_input_desktop) +{ + /* FIXME: check access rights */ + struct winstation *winstation; + struct desktop *desktop; + + if (!(winstation = get_process_winstation( current->process, 0 ))) return; + + if ((desktop = (struct desktop *)get_handle_obj( current->process, req->handle, 0, &desktop_ops ))) + { + if (!set_input_desktop( winstation, desktop )) set_error( STATUS_ILLEGAL_FUNCTION ); + release_object( desktop ); + } + + release_object( winstation ); +} + /* close a desktop */ DECL_HANDLER(close_desktop) {
From: Rémi Bernon rbernon@codeweavers.com
When hwnd is specified, it is because it received a direct host input, so switch the input desktop to match the one that is receiving it.
We don't validate that the sending thread uses the same desktop as the target window: it may not even be the case for drivers with a separate thread that listens on input events. --- dlls/user32/tests/winstation.c | 6 ++--- server/queue.c | 40 ++++++++++++++++++++++++---------- server/user.h | 3 +++ server/winstation.c | 13 +++++++++-- 4 files changed, 44 insertions(+), 18 deletions(-)
diff --git a/dlls/user32/tests/winstation.c b/dlls/user32/tests/winstation.c index 11ad7685e97..bcbb55ee918 100644 --- a/dlls/user32/tests/winstation.c +++ b/dlls/user32/tests/winstation.c @@ -652,9 +652,8 @@ static void test_inputdesktop(void) win_skip("Skip tests on NT4\n"); return; } - todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "unexpected last error %08lx\n", GetLastError()); - ok(ret == 1 || broken(ret == 0) /* Win64 */, "unexpected return count %ld\n", ret); + ok(ret == 0 || broken(ret == 1) /* Win32 */, "unexpected return count %ld\n", ret);
/* Set thread desktop back to the old thread desktop, SendInput should success. */ ret = SetThreadDesktop(old_thread_desk); @@ -699,9 +698,8 @@ static void test_inputdesktop(void)
SetLastError(0xdeadbeef); ret = SendInput(1, inputs, sizeof(INPUT)); - todo_wine ok(GetLastError() == ERROR_ACCESS_DENIED, "unexpected last error %08lx\n", GetLastError()); - ok(ret == 1 || broken(ret == 0) /* Win64 */, "unexpected return count %ld\n", ret); + ok(ret == 0 || broken(ret == 1) /* Win32 */, "unexpected return count %ld\n", ret);
/* Set thread desktop to the new desktop, SendInput should success. */ ret = SetThreadDesktop(new_desk); diff --git a/server/queue.c b/server/queue.c index 6f38227aa84..dbd83c43217 100644 --- a/server/queue.c +++ b/server/queue.c @@ -2598,6 +2598,28 @@ void free_hotkeys( struct desktop *desktop, user_handle_t window ) } }
+/* retrieve the desktop which should receive some hardware input event */ +static struct desktop *get_hardware_input_desktop( user_handle_t win ) +{ + struct winstation *winstation; + struct desktop *desktop; + struct thread *thread; + + if (!win || !(thread = get_window_thread( win ))) + { + if (!(winstation = get_visible_winstation())) return NULL; + return get_input_desktop( winstation ); + } + else + { + /* if window is specified, use its desktop to make it the input desktop */ + desktop = (struct desktop *)grab_object( thread->queue->input->desktop ); + release_object( thread ); + } + + return desktop; +} +
/* check if the thread owning the window is hung */ DECL_HANDLER(is_window_hung) @@ -2767,22 +2789,17 @@ DECL_HANDLER(send_message) /* send a hardware message to a thread queue */ DECL_HANDLER(send_hardware_message) { - struct thread *thread = NULL; struct desktop *desktop; unsigned int origin = (req->flags & SEND_HWMSG_INJECTED ? IMO_INJECTED : IMO_HARDWARE); struct msg_queue *sender = get_current_queue();
- if (!(desktop = get_thread_desktop( current, 0 ))) return; - - if (req->win) + if (!(desktop = get_hardware_input_desktop( req->win ))) return; + if ((origin == IMO_INJECTED && desktop != current->queue->input->desktop) || + !set_input_desktop( desktop->winstation, desktop )) { - if (!(thread = get_window_thread( req->win ))) return; - if (desktop != thread->queue->input->desktop) - { - /* don't allow queuing events to a different desktop */ - release_object( desktop ); - return; - } + release_object( desktop ); + set_error( STATUS_ACCESS_DENIED ); + return; }
reply->prev_x = desktop->cursor.x; @@ -2802,7 +2819,6 @@ DECL_HANDLER(send_hardware_message) default: set_error( STATUS_INVALID_PARAMETER ); } - if (thread) release_object( thread );
reply->new_x = desktop->cursor.x; reply->new_y = desktop->cursor.y; diff --git a/server/user.h b/server/user.h index 56b0eb685f0..1acd0638520 100644 --- a/server/user.h +++ b/server/user.h @@ -186,6 +186,9 @@ extern client_ptr_t get_class_client_ptr( struct window_class *class );
/* windows station functions */
+extern struct winstation *get_visible_winstation(void); +extern struct desktop *get_input_desktop( struct winstation *winstation ); +extern int set_input_desktop( struct winstation *winstation, struct desktop *new_desktop ); extern struct desktop *get_desktop_obj( struct process *process, obj_handle_t handle, unsigned int access ); extern struct winstation *get_process_winstation( struct process *process, unsigned int access ); extern struct desktop *get_thread_desktop( struct thread *thread, unsigned int access ); diff --git a/server/winstation.c b/server/winstation.c index a23cd24261a..00afe0119ff 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -212,8 +212,17 @@ struct winstation *get_process_winstation( struct process *process, unsigned int access, &winstation_ops ); }
+/* retrieve the visible winstation */ +struct winstation *get_visible_winstation(void) +{ + struct winstation *winstation; + LIST_FOR_EACH_ENTRY( winstation, &winstation_list, struct winstation, entry ) + if (winstation->flags & WSF_VISIBLE) return winstation; + return NULL; +} + /* retrieve the winstation current input desktop */ -static struct desktop *get_input_desktop( struct winstation *winstation ) +struct desktop *get_input_desktop( struct winstation *winstation ) { struct desktop *desktop; if (!(desktop = winstation->input_desktop)) return NULL; @@ -221,7 +230,7 @@ static struct desktop *get_input_desktop( struct winstation *winstation ) }
/* changes the winstation current input desktop and update its input time */ -static int set_input_desktop( struct winstation *winstation, struct desktop *new_desktop ) +int set_input_desktop( struct winstation *winstation, struct desktop *new_desktop ) { if (!(winstation->flags & WSF_VISIBLE)) return 0; if (new_desktop) new_desktop->input_time = current_time;
From: Rémi Bernon rbernon@codeweavers.com
--- server/thread.h | 1 + server/user.h | 1 + server/winstation.c | 53 ++++++++++++++++++++++++++------------------- 3 files changed, 33 insertions(+), 22 deletions(-)
diff --git a/server/thread.h b/server/thread.h index 8dcf966a90a..766ed78a72f 100644 --- a/server/thread.h +++ b/server/thread.h @@ -51,6 +51,7 @@ struct thread struct object obj; /* object header */ struct list entry; /* entry in system-wide thread list */ struct list proc_entry; /* entry in per-process thread list */ + struct list desktop_entry; /* entry in per-desktop thread list */ struct process *process; thread_id_t id; /* thread id */ struct list mutex_list; /* list of currently owned mutexes */ diff --git a/server/user.h b/server/user.h index 1acd0638520..c3ca90d5a77 100644 --- a/server/user.h +++ b/server/user.h @@ -70,6 +70,7 @@ struct desktop struct winstation *winstation; /* winstation this desktop belongs to */ timeout_t input_time; /* last time this desktop had the input */ struct list entry; /* entry in winstation list of desktops */ + struct list threads; /* list of threads connected to this desktop */ struct window *top_window; /* desktop window for this desktop */ struct window *msg_window; /* HWND_MESSAGE top window */ struct hook_table *global_hooks; /* table of global hooks on this desktop */ diff --git a/server/winstation.c b/server/winstation.c index 00afe0119ff..f6fe5fd9e57 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -273,6 +273,7 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned desktop->close_timeout = NULL; desktop->foreground_input = NULL; desktop->users = 0; + list_init( &desktop->threads ); memset( &desktop->cursor, 0, sizeof(desktop->cursor) ); memset( desktop->keystate, 0, sizeof(desktop->keystate) ); list_add_tail( &winstation->desktops, &desktop->entry ); @@ -362,26 +363,37 @@ static void close_desktop_timeout( void *private ) }
/* add a user of the desktop and cancel the close timeout */ -static void add_desktop_user( struct desktop *desktop ) +static void add_desktop_thread( struct desktop *desktop, struct thread *thread ) { - desktop->users++; - if (desktop->close_timeout) + list_add_tail( &desktop->threads, &thread->desktop_entry ); + + if (!thread->process->is_system) { - remove_timeout_user( desktop->close_timeout ); - desktop->close_timeout = NULL; + desktop->users++; + if (desktop->close_timeout) + { + remove_timeout_user( desktop->close_timeout ); + desktop->close_timeout = NULL; + } } }
/* remove a user of the desktop and start the close timeout if necessary */ -static void remove_desktop_user( struct desktop *desktop ) +static void remove_desktop_thread( struct desktop *desktop, struct thread *thread ) { struct process *process; - assert( desktop->users > 0 ); - desktop->users--;
- /* if we have one remaining user, it has to be the manager of the desktop window */ - if ((process = get_top_window_owner( desktop )) && desktop->users == process->running_threads && !desktop->close_timeout) - desktop->close_timeout = add_timeout_user( -TICKS_PER_SEC, close_desktop_timeout, desktop ); + list_remove( &thread->desktop_entry ); + + if (!thread->process->is_system) + { + assert( desktop->users > 0 ); + desktop->users--; + + /* if we have one remaining user, it has to be the manager of the desktop window */ + if ((process = get_top_window_owner( desktop )) && desktop->users == process->running_threads && !desktop->close_timeout) + desktop->close_timeout = add_timeout_user( -TICKS_PER_SEC, close_desktop_timeout, desktop ); + } }
/* set the thread default desktop handle */ @@ -390,7 +402,7 @@ void set_thread_default_desktop( struct thread *thread, struct desktop *desktop, if (thread->desktop) return; /* nothing to do */
thread->desktop = handle; - if (!thread->process->is_system) add_desktop_user( desktop ); + add_desktop_thread( desktop, thread ); }
/* set the process default desktop handle */ @@ -500,14 +512,11 @@ void release_thread_desktop( struct thread *thread, int close )
if (!(handle = thread->desktop)) return;
- if (!thread->process->is_system) + if (!(desktop = get_desktop_obj( thread->process, handle, 0 ))) clear_error(); /* ignore errors */ + else { - if (!(desktop = get_desktop_obj( thread->process, handle, 0 ))) clear_error(); /* ignore errors */ - else - { - remove_desktop_user( desktop ); - release_object( desktop ); - } + remove_desktop_thread( desktop, thread ); + release_object( desktop ); }
if (close) @@ -730,10 +739,10 @@ DECL_HANDLER(set_thread_desktop) else { current->desktop = req->handle; /* FIXME: should we close the old one? */ - if (!current->process->is_system && old_desktop != new_desktop) + if (old_desktop != new_desktop) { - add_desktop_user( new_desktop ); - if (old_desktop) remove_desktop_user( old_desktop ); + if (old_desktop) remove_desktop_thread( old_desktop, current ); + add_desktop_thread( new_desktop, current ); } }
From: Rémi Bernon rbernon@codeweavers.com
--- server/process.c | 2 ++ server/process.h | 1 + server/queue.c | 24 ++++++++++++++++++++++++ server/user.h | 1 + server/winstation.c | 30 +++++++++++++++++++++++++++++- 5 files changed, 57 insertions(+), 1 deletion(-)
diff --git a/server/process.c b/server/process.c index b6c21d15752..bc6636dbe8b 100644 --- a/server/process.c +++ b/server/process.c @@ -684,6 +684,7 @@ struct process *create_process( int fd, struct process *parent, unsigned int fla process->rawinput_mouse = NULL; process->rawinput_kbd = NULL; memset( &process->image_info, 0, sizeof(process->image_info) ); + list_init( &process->rawinput_entry ); list_init( &process->kernel_object ); list_init( &process->thread_list ); list_init( &process->locks ); @@ -784,6 +785,7 @@ static void process_destroy( struct object *obj ) if (process->idle_event) release_object( process->idle_event ); if (process->id) free_ptid( process->id ); if (process->token) release_object( process->token ); + list_remove( &process->rawinput_entry ); free( process->rawinput_devices ); free( process->dir_cache ); free( process->image ); diff --git a/server/process.h b/server/process.h index 97e0d455ece..1e73e9d47dc 100644 --- a/server/process.h +++ b/server/process.h @@ -83,6 +83,7 @@ struct process unsigned int rawinput_device_count; /* number of registered rawinput devices */ const struct rawinput_device *rawinput_mouse; /* rawinput mouse device, if any */ const struct rawinput_device *rawinput_kbd; /* rawinput keyboard device, if any */ + struct list rawinput_entry; /* entry in the rawinput process list */ struct list kernel_object; /* list of kernel object pointers */ pe_image_info_t image_info; /* main exe image info */ }; diff --git a/server/queue.c b/server/queue.c index dbd83c43217..041df36331e 100644 --- a/server/queue.c +++ b/server/queue.c @@ -50,6 +50,8 @@ enum message_kind { SEND_MESSAGE, POST_MESSAGE }; #define NB_MSG_KINDS (POST_MESSAGE+1)
+/* list of processes registered for rawinput in the input desktop */ +static struct list rawinput_processes = LIST_INIT(rawinput_processes);
struct message_result { @@ -2620,6 +2622,14 @@ static struct desktop *get_hardware_input_desktop( user_handle_t win ) return desktop; }
+/* enable or disable rawinput for a given process */ +void set_rawinput_process( struct process *process, int enable ) +{ + list_remove( &process->rawinput_entry ); /* remove it first, it might already be in the list */ + if (!process->rawinput_device_count || !enable) list_init( &process->rawinput_entry ); + else list_add_tail( &rawinput_processes, &process->rawinput_entry ); +} +
/* check if the thread owning the window is hung */ DECL_HANDLER(is_window_hung) @@ -3639,12 +3649,15 @@ DECL_HANDLER(update_rawinput_devices) unsigned int device_count = get_req_data_size() / sizeof (*devices); size_t size = device_count * sizeof(*devices); struct process *process = current->process; + struct winstation *winstation; + struct desktop *desktop;
if (!size) { process->rawinput_device_count = 0; process->rawinput_mouse = NULL; process->rawinput_kbd = NULL; + set_rawinput_process( process, 0 ); return; }
@@ -3659,4 +3672,15 @@ DECL_HANDLER(update_rawinput_devices)
process->rawinput_mouse = find_rawinput_device( process, MAKELONG(HID_USAGE_GENERIC_MOUSE, HID_USAGE_PAGE_GENERIC) ); process->rawinput_kbd = find_rawinput_device( process, MAKELONG(HID_USAGE_GENERIC_KEYBOARD, HID_USAGE_PAGE_GENERIC) ); + + if ((winstation = get_visible_winstation()) && (desktop = get_input_desktop( winstation ))) + { + struct thread *thread; + + /* one of the process thread might be connected to the input desktop, update the full list */ + LIST_FOR_EACH_ENTRY( thread, &desktop->threads, struct thread, desktop_entry ) + set_rawinput_process( thread->process, 1 ); + + release_object( desktop ); + } } diff --git a/server/user.h b/server/user.h index c3ca90d5a77..b4cf618f87e 100644 --- a/server/user.h +++ b/server/user.h @@ -125,6 +125,7 @@ extern void post_win_event( struct thread *thread, unsigned int event, const WCHAR *module, data_size_t module_size, user_handle_t handle ); extern void free_hotkeys( struct desktop *desktop, user_handle_t window ); +extern void set_rawinput_process( struct process *process, int enable );
/* region functions */
diff --git a/server/winstation.c b/server/winstation.c index f6fe5fd9e57..373a1f7ba92 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -232,9 +232,27 @@ struct desktop *get_input_desktop( struct winstation *winstation ) /* changes the winstation current input desktop and update its input time */ int set_input_desktop( struct winstation *winstation, struct desktop *new_desktop ) { + struct desktop *old_desktop = winstation->input_desktop; + struct thread *thread; + if (!(winstation->flags & WSF_VISIBLE)) return 0; if (new_desktop) new_desktop->input_time = current_time; - winstation->input_desktop = new_desktop; + if (old_desktop == new_desktop) return 1; + + if (old_desktop) + { + /* disconnect every process of the old input desktop from rawinput */ + LIST_FOR_EACH_ENTRY( thread, &old_desktop->threads, struct thread, desktop_entry ) + set_rawinput_process( thread->process, 0 ); + } + + if ((winstation->input_desktop = new_desktop)) + { + /* connect every process of the new input desktop to rawinput */ + LIST_FOR_EACH_ENTRY( thread, &new_desktop->threads, struct thread, desktop_entry ) + set_rawinput_process( thread->process, 1 ); + } + return 1; }
@@ -376,6 +394,9 @@ static void add_desktop_thread( struct desktop *desktop, struct thread *thread ) desktop->close_timeout = NULL; } } + + /* if thread process is now connected to the input desktop, let it receive rawinput */ + if (desktop == desktop->winstation->input_desktop) set_rawinput_process( thread->process, 1 ); }
/* remove a user of the desktop and start the close timeout if necessary */ @@ -394,6 +415,13 @@ static void remove_desktop_thread( struct desktop *desktop, struct thread *threa if ((process = get_top_window_owner( desktop )) && desktop->users == process->running_threads && !desktop->close_timeout) desktop->close_timeout = add_timeout_user( -TICKS_PER_SEC, close_desktop_timeout, desktop ); } + + if (desktop == desktop->winstation->input_desktop) + { + /* thread process might still be connected the input desktop through another thread, update the full list */ + LIST_FOR_EACH_ENTRY( thread, &desktop->threads, struct thread, desktop_entry ) + set_rawinput_process( thread->process, 1 ); + } }
/* set the thread default desktop handle */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/tests/joystick8.c | 9 ----- server/queue.c | 75 +++++++++++++++-------------------- 2 files changed, 31 insertions(+), 53 deletions(-)
diff --git a/dlls/dinput/tests/joystick8.c b/dlls/dinput/tests/joystick8.c index 428fc59c1af..be6f432808f 100644 --- a/dlls/dinput/tests/joystick8.c +++ b/dlls/dinput/tests/joystick8.c @@ -5756,23 +5756,16 @@ static DWORD WINAPI test_rawinput_desktop_thread( void *args ) rawbuffer_size = sizeof(rawbuffer); memset( rawbuffer, 0, sizeof(rawbuffer) ); res = msg_wait_for_events( 1, &rawinput_event, 100 ); - todo_wine_if( params->input ) ok( res == 0, "WaitForSingleObject returned %#lx\n", res ); - todo_wine_if( params->input ) ok( rawinput_calls == 1, "got %u WM_INPUT messages\n", rawinput_calls );
rawinput = (RAWINPUT *)rawbuffer; - todo_wine_if( params->input ) ok( rawinput->header.dwType == RIM_TYPEHID, "got dwType %lu\n", rawinput->header.dwType ); - todo_wine_if( params->input ) ok( rawinput->header.dwSize == offsetof(RAWINPUT, data.hid.bRawData[desc.caps.InputReportByteLength * rawinput->data.hid.dwCount]), "got header.dwSize %lu\n", rawinput->header.dwSize ); - todo_wine_if( params->input ) ok( rawinput->header.hDevice != 0, "got hDevice %p\n", rawinput->header.hDevice ); ok( rawinput->header.wParam == 0, "got wParam %#Ix\n", rawinput->header.wParam ); - todo_wine_if( params->input ) ok( rawinput->data.hid.dwSizeHid == desc.caps.InputReportByteLength, "got dwSizeHid %lu\n", rawinput->data.hid.dwSizeHid ); - todo_wine_if( params->input ) ok( rawinput->data.hid.dwCount >= 1, "got dwCount %lu\n", rawinput->data.hid.dwCount );
@@ -5878,9 +5871,7 @@ static void test_rawinput_desktop( const char *path, BOOL input ) } else { - todo_wine ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#lx\n", res ); - todo_wine ok( rawinput_calls == 0, "got %u WM_INPUT messages\n", rawinput_calls ); }
diff --git a/server/queue.c b/server/queue.c index 041df36331e..4373bd71254 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1896,7 +1896,6 @@ static void rawhid_init( struct rawinput *rawinput, RAWHID *hid, const hw_input_ struct rawinput_message { struct thread *foreground; - struct desktop *desktop; struct hw_msg_source source; unsigned int time; unsigned int message; @@ -1912,12 +1911,10 @@ struct rawinput_message };
/* check if process is supposed to receive a WM_INPUT message and eventually queue it */ -static int queue_rawinput_message( struct process* process, void *arg ) +static void queue_rawinput_message( struct desktop *desktop, struct process *process, void *args ) { - const struct rawinput_message *raw_msg = arg; - const struct rawinput_device *device = NULL; - struct desktop *target_desktop = NULL, *desktop = NULL; - struct thread *target_thread = NULL, *foreground = NULL; + const struct rawinput_message *raw_msg = args; + const struct rawinput_device *device; struct hardware_msg_data *msg_data; struct message *msg; data_size_t report_size = 0, data_size = 0; @@ -1942,26 +1939,16 @@ static int queue_rawinput_message( struct process* process, void *arg ) data_size = offsetof(RAWHID, bRawData[0]); report_size = raw_msg->data.hid.dwCount * raw_msg->data.hid.dwSizeHid; } - 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; + if (!device) return;
- 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 (raw_msg->message == WM_INPUT_DEVICE_CHANGE && !(device->flags & RIDEV_DEVNOTIFY)) return; + if (process != raw_msg->foreground->process) { - 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; + if (raw_msg->message == WM_INPUT && !(device->flags & RIDEV_INPUTSINK)) return; wparam = RIM_INPUTSINK; }
- if (!(msg = alloc_hardware_message( info, raw_msg->source, raw_msg->time, data_size + report_size ))) goto done; + if (!(msg = alloc_hardware_message( info, raw_msg->source, raw_msg->time, data_size + report_size ))) return; msg->win = device->target; msg->msg = raw_msg->message; msg->wparam = wparam; @@ -1980,13 +1967,14 @@ static int queue_rawinput_message( struct process* process, void *arg ) }
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; +static void dispatch_rawinput_message( struct desktop *desktop, struct rawinput_message *raw_msg ) +{ + struct process *process; + + LIST_FOR_EACH_ENTRY( process, &rawinput_processes, struct process, rawinput_entry ) + queue_rawinput_message( desktop, process, raw_msg ); }
/* queue a hardware message for a mouse event */ @@ -2050,7 +2038,6 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons { memset( &raw_msg, 0, sizeof(raw_msg) ); raw_msg.foreground = foreground; - raw_msg.desktop = desktop; raw_msg.source = source; raw_msg.time = time; raw_msg.message = WM_INPUT; @@ -2058,7 +2045,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons rawmouse_init( &raw_msg.rawinput, &raw_msg.data.mouse, x - desktop->cursor.x, y - desktop->cursor.y, raw_msg.flags, input->mouse.data, input->mouse.info );
- enum_processes( queue_rawinput_message, &raw_msg ); + dispatch_rawinput_message( desktop, &raw_msg ); release_object( foreground ); }
@@ -2105,7 +2092,6 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c struct hw_msg_source source = { IMDT_KEYBOARD, origin }; const struct rawinput_device *device; struct hardware_msg_data *msg_data; - struct rawinput_message raw_msg; struct message *msg; struct thread *foreground; unsigned char vkey = input->kbd.vkey; @@ -2180,9 +2166,8 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
if ((foreground = get_foreground_thread( desktop, win ))) { - memset( &raw_msg, 0, sizeof(raw_msg) ); + struct rawinput_message raw_msg = {0}; raw_msg.foreground = foreground; - raw_msg.desktop = desktop; raw_msg.source = source; raw_msg.time = time; raw_msg.message = WM_INPUT; @@ -2190,7 +2175,7 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c rawkeyboard_init( &raw_msg.rawinput, &raw_msg.data.keyboard, input->kbd.scan, vkey, raw_msg.flags, message_code, input->kbd.info );
- enum_processes( queue_rawinput_message, &raw_msg ); + dispatch_rawinput_message( desktop, &raw_msg ); release_object( foreground ); }
@@ -2236,26 +2221,28 @@ 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 rawinput_message raw_msg; + struct thread *foreground; struct message *msg;
switch (input->hw.msg) { case WM_INPUT: case WM_INPUT_DEVICE_CHANGE: - memset( &raw_msg, 0, sizeof(raw_msg) ); - raw_msg.source = source; - raw_msg.time = get_tick_count(); - raw_msg.message = input->hw.msg; - raw_msg.hid_report = get_req_data(); if (input->hw.hid.length * input->hw.hid.count != get_req_data_size()) - { set_error( STATUS_INVALID_PARAMETER ); - return; + else if ((foreground = get_foreground_thread( desktop, win ))) + { + struct rawinput_message raw_msg = {0}; + raw_msg.foreground = foreground; + raw_msg.source = source; + raw_msg.time = get_tick_count(); + raw_msg.message = input->hw.msg; + raw_msg.hid_report = get_req_data(); + rawhid_init( &raw_msg.rawinput, &raw_msg.data.hid, input ); + + dispatch_rawinput_message( desktop, &raw_msg ); + release_object( foreground ); } - rawhid_init( &raw_msg.rawinput, &raw_msg.data.hid, input ); - - enum_processes( queue_rawinput_message, &raw_msg ); return; }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=143409
Your paranoid android.
=== debian11 (32 bit ar:MA report) ===
user32: msg.c:12239: Test failed: MOUSE_LL hook other thread: 0: the msg sequence is not complete: expected hook 0200 - actual msg 0000 msg.c:12246: Test failed: MOUSE_LL hook same thread: 0: the msg sequence is not complete: expected hook 0200 - actual msg 0000
v6: Rebase, drop the now unnecessary tests workaround, keep a list of rawinput processes instead of re-creating it on every message.
Test failures don't seem related, oleaut32 on Linux, some spurious failures on Windows.