From: Paul Gofman pgofman@codeweavers.com
--- dlls/win32u/input.c | 13 ++++++++++++- server/protocol.def | 2 ++ server/queue.c | 6 ++++++ server/winstation.c | 1 + 4 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index c7ba334f1c0..c718bd1cbbc 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -1019,16 +1019,27 @@ SHORT WINAPI NtUserGetKeyState( INT vkey ) { struct object_lock lock = OBJECT_LOCK_INIT; const input_shm_t *input_shm; + UINT64 keystate_serial = 0; BOOL ret = FALSE; SHORT retval = 0; NTSTATUS status;
while ((status = get_shared_input( GetCurrentThreadId(), &lock, &input_shm )) == STATUS_PENDING) { - ret = !!input_shm->keystate_lock; /* needs a request for sync_input_keystate */ + ret = !!input_shm->keystate_lock; /* needs a request for sync_input_keystate if desktop keystate differs. */ + keystate_serial = input_shm->keystate_serial; retval = (signed char)(input_shm->keystate[vkey & 0xff] & 0x81); }
+ if (!ret) + { + struct object_lock lock = OBJECT_LOCK_INIT; + const desktop_shm_t *desktop_shm; + + while ((status = get_shared_desktop( &lock, &desktop_shm )) == STATUS_PENDING) + ret = keystate_serial == desktop_shm->keystate_serial; + } + if (!ret) SERVER_START_REQ( get_key_state ) { req->key = vkey; diff --git a/server/protocol.def b/server/protocol.def index ecc20a8e2d0..1112d09f3d6 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -985,6 +985,7 @@ typedef volatile struct struct shared_cursor cursor; /* global cursor information */ unsigned char keystate[256]; /* asynchronous key state */ unsigned __int64 monitor_serial; /* winstation monitor update counter */ + unsigned __int64 keystate_serial; /* keystate update counter */ } desktop_shm_t;
typedef volatile struct @@ -1010,6 +1011,7 @@ typedef volatile struct int cursor_count; /* cursor show count */ unsigned char keystate[256]; /* key state */ int keystate_lock; /* keystate is locked */ + unsigned __int64 keystate_serial; /* keystate update counter at last sync */ } input_shm_t;
typedef volatile struct diff --git a/server/queue.c b/server/queue.c index f42d8f57446..c3d80ed7f2d 100644 --- a/server/queue.c +++ b/server/queue.c @@ -283,6 +283,7 @@ static struct thread_input *create_thread_input( struct thread *thread ) shared->cursor_count = 0; memset( (void *)shared->keystate, 0, sizeof(shared->keystate) ); shared->keystate_lock = 0; + shared->keystate_serial = 1; } SHARED_WRITE_END; } @@ -379,6 +380,7 @@ static void sync_input_keystate( struct thread_input *input ) if (input->desktop_keystate[i] == desktop_shm->keystate[i]) continue; shared->keystate[i] = input->desktop_keystate[i] = desktop_shm->keystate[i]; } + shared->keystate_serial = desktop_shm->keystate_serial; } SHARED_WRITE_END; } @@ -1525,6 +1527,7 @@ int attach_thread_input( struct thread *thread_from, struct thread *thread_to ) SHARED_WRITE_BEGIN( input_shm, input_shm_t ) { memset( (void *)shared->keystate, 0, sizeof(shared->keystate) ); + shared->keystate_serial = 1; } SHARED_WRITE_END; } @@ -1790,6 +1793,7 @@ static void update_desktop_key_state( struct desktop *desktop, unsigned int msg, SHARED_WRITE_BEGIN( desktop->shared, desktop_shm_t ) { update_key_state( shared->keystate, msg, wparam, 1 ); + ++shared->keystate_serial; } SHARED_WRITE_END; } @@ -3801,6 +3805,7 @@ DECL_HANDLER(get_key_state) { reply->state = shared->keystate[req->key & 0xff]; shared->keystate[req->key & 0xff] &= ~0x40; + ++shared->keystate_serial; } SHARED_WRITE_END; release_object( desktop ); @@ -3838,6 +3843,7 @@ DECL_HANDLER(set_key_state) SHARED_WRITE_BEGIN( desktop->shared, desktop_shm_t ) { memcpy( (void *)shared->keystate, get_req_data(), size ); + ++shared->keystate_serial; } SHARED_WRITE_END; release_object( desktop ); diff --git a/server/winstation.c b/server/winstation.c index bb5596f9a03..bfcd4a53613 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -325,6 +325,7 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned shared->cursor.clip.right = 0; shared->cursor.clip.bottom = 0; memset( (void *)shared->keystate, 0, sizeof(shared->keystate) ); + shared->keystate_serial = 1; shared->monitor_serial = winstation->monitor_serial; } SHARED_WRITE_END;