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;