diff --git a/reactos/subsystems/win32/win32k/include/hotkey.h b/reactos/subsystems/win32/win32k/include/hotkey.h index c5e514bf9e2..a1dbd5cc34e 100644 --- a/reactos/subsystems/win32/win32k/include/hotkey.h +++ b/reactos/subsystems/win32/win32k/include/hotkey.h @@ -14,16 +14,11 @@ typedef struct _HOT_KEY_ITEM INIT_FUNCTION NTSTATUS NTAPI InitHotkeyImpl(VOID); -BOOL FASTCALL -GetHotKey (UINT fsModifiers, - UINT vk, - struct _ETHREAD **Thread, - HWND *hWnd, - int *id); - +PHOT_KEY_ITEM FASTCALL IsHotKey(UINT fsModifiers, WORD wVk); VOID FASTCALL UnregisterWindowHotKeys(PWND Window); VOID FASTCALL UnregisterThreadHotKeys(struct _ETHREAD *Thread); +BOOL NTAPI xxxDoHotKeyStuff(WORD wVk, BOOL bIsDown); UINT FASTCALL DefWndGetHotKey(HWND hwnd); -INT FASTCALL DefWndSetHotKey( PWND pWnd, WPARAM wParam); +INT FASTCALL DefWndSetHotKey(PWND pWnd, WPARAM wParam); /* EOF */ diff --git a/reactos/subsystems/win32/win32k/include/input.h b/reactos/subsystems/win32/win32k/include/input.h index 9eac220ffb8..fb9c04dbce1 100644 --- a/reactos/subsystems/win32/win32k/include/input.h +++ b/reactos/subsystems/win32/win32k/include/input.h @@ -51,9 +51,21 @@ BOOL UserInitDefaultKeyboardLayout(VOID); PKBL UserHklToKbl(HKL hKl); BOOL FASTCALL UserAttachThreadInput(PTHREADINFO,PTHREADINFO,BOOL); VOID FASTCALL DoTheScreenSaver(VOID); -#define ThreadHasInputAccess(W32Thread) \ - (TRUE) +#define ThreadHasInputAccess(W32Thread) (TRUE) extern HANDLE ghKeyboardDevice; extern PTHREADINFO ptiRawInput; -extern BYTE gafAsyncKeyState[0x100]; +extern BYTE gafAsyncKeyState[256 * 2 / 8]; // 2 bits per key + +#define GET_KS_BYTE(vk) ((vk) * 2 / 8) +#define GET_KS_DOWN_BIT(vk) (1 << (((vk) % 4)*2)) +#define GET_KS_LOCK_BIT(vk) (1 << (((vk) % 4)*2 + 1)) +#define IS_KEY_DOWN(ks, vk) (((ks)[GET_KS_BYTE(vk)] & GET_KS_DOWN_BIT(vk)) ? TRUE : FALSE) +#define IS_KEY_LOCKED(ks, vk) (((ks)[GET_KS_BYTE(vk)] & GET_KS_LOCK_BIT(vk)) ? TRUE : FALSE) +#define SET_KEY_DOWN(ks, vk, down) (ks)[GET_KS_BYTE(vk)] = ((down) ? \ + ((ks)[GET_KS_BYTE(vk)] | GET_KS_DOWN_BIT(vk)) : \ + ((ks)[GET_KS_BYTE(vk)] & ~GET_KS_DOWN_BIT(vk))) +#define SET_KEY_LOCKED(ks, vk, down) (ks)[GET_KS_BYTE(vk)] = ((down) ? \ + ((ks)[GET_KS_BYTE(vk)] | GET_KS_LOCK_BIT(vk)) : \ + ((ks)[GET_KS_BYTE(vk)] & ~GET_KS_LOCK_BIT(vk))) + diff --git a/reactos/subsystems/win32/win32k/include/msgqueue.h b/reactos/subsystems/win32/win32k/include/msgqueue.h index fac3131a9b0..073e402a412 100644 --- a/reactos/subsystems/win32/win32k/include/msgqueue.h +++ b/reactos/subsystems/win32/win32k/include/msgqueue.h @@ -106,7 +106,8 @@ typedef struct _USER_MESSAGE_QUEUE LPARAM ExtraInfo; /* state of each key */ - UCHAR KeyState[256]; + BYTE afKeyRecentDown[256 / 8]; // 1 bit per key + BYTE afKeyState[256 * 2 / 8]; // 2 bits per key /* showing cursor counter (value>=0 - cursor visible, value<0 - cursor hidden) */ INT ShowingCursor; @@ -220,7 +221,6 @@ co_MsqSendMessageAsync(PTHREADINFO ptiReceiver, LRESULT FASTCALL IntDispatchMessage(MSG* Msg); BOOL FASTCALL IntTranslateKbdMessage(LPMSG lpMsg, UINT flags); -VOID FASTCALL co_MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL bInjected); VOID FASTCALL MsqPostHotKeyMessage(PVOID Thread, HWND hWnd, WPARAM wParam, LPARAM lParam); VOID FASTCALL co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook); BOOL FASTCALL MsqIsClkLck(LPMSG Msg, BOOL Remove); diff --git a/reactos/subsystems/win32/win32k/ntuser/hotkey.c b/reactos/subsystems/win32/win32k/ntuser/hotkey.c index 120aa7801b1..8c17fdce2e3 100644 --- a/reactos/subsystems/win32/win32k/ntuser/hotkey.c +++ b/reactos/subsystems/win32/win32k/ntuser/hotkey.c @@ -42,34 +42,31 @@ CleanupHotKeys(VOID) } #endif -BOOL FASTCALL -GetHotKey (UINT fsModifiers, - UINT vk, - struct _ETHREAD **Thread, - HWND *hWnd, - int *id) +/* + * IntGetModifiers + * + * Returns a value that indicates if the key is a modifier key, and + * which one. + */ +static +UINT FASTCALL +IntGetModifiers(PBYTE pKeyState) { - PHOT_KEY_ITEM HotKeyItem; + UINT fModifiers = 0; + + if (IS_KEY_DOWN(pKeyState, VK_SHIFT)) + fModifiers |= MOD_SHIFT; - LIST_FOR_EACH(HotKeyItem, &gHotkeyList, HOT_KEY_ITEM, ListEntry) - { - if (HotKeyItem->fsModifiers == fsModifiers && - HotKeyItem->vk == vk) - { - if (Thread != NULL) - *Thread = HotKeyItem->Thread; + if (IS_KEY_DOWN(pKeyState, VK_CONTROL)) + fModifiers |= MOD_CONTROL; - if (hWnd != NULL) - *hWnd = HotKeyItem->hWnd; + if (IS_KEY_DOWN(pKeyState, VK_MENU)) + fModifiers |= MOD_ALT; - if (id != NULL) - *id = HotKeyItem->id; + if (IS_KEY_DOWN(pKeyState, VK_LWIN) || IS_KEY_DOWN(pKeyState, VK_RWIN)) + fModifiers |= MOD_WIN; - return TRUE; - } - } - - return FALSE; + return fModifiers; } VOID FASTCALL @@ -85,7 +82,6 @@ UnregisterWindowHotKeys(PWND Window) ExFreePool (HotKeyItem); } } - } VOID FASTCALL @@ -104,23 +100,79 @@ UnregisterThreadHotKeys(struct _ETHREAD *Thread) } -static -BOOL FASTCALL -IsHotKey (UINT fsModifiers, UINT vk) +PHOT_KEY_ITEM FASTCALL +IsHotKey(UINT fsModifiers, WORD wVk) { - PHOT_KEY_ITEM HotKeyItem; + PHOT_KEY_ITEM pHotKeyItem; - LIST_FOR_EACH(HotKeyItem, &gHotkeyList, HOT_KEY_ITEM, ListEntry) + LIST_FOR_EACH(pHotKeyItem, &gHotkeyList, HOT_KEY_ITEM, ListEntry) { - if (HotKeyItem->fsModifiers == fsModifiers && HotKeyItem->vk == vk) + if (pHotKeyItem->fsModifiers == fsModifiers && pHotKeyItem->vk == wVk) { - return TRUE; + return pHotKeyItem; } } - return FALSE; + return NULL; } +/* + * IntKeyboardSendWinKeyMsg + * + * Sends syscommand to shell, when WIN key is pressed + */ +static +VOID NTAPI +IntKeyboardSendWinKeyMsg() +{ + PWND pWnd; + MSG Msg; + + if (!(pWnd = UserGetWindowObject(InputWindowStation->ShellWindow))) + { + ERR("Couldn't find window to send Windows key message!\n"); + return; + } + + Msg.hwnd = InputWindowStation->ShellWindow; + Msg.message = WM_SYSCOMMAND; + Msg.wParam = SC_TASKLIST; + Msg.lParam = 0; + + /* The QS_HOTKEY is just a guess */ + MsqPostMessage(pWnd->head.pti->MessageQueue, &Msg, FALSE, QS_HOTKEY); +} + +BOOL NTAPI +xxxDoHotKeyStuff(WORD wVk, BOOL bIsDown) +{ + UINT fModifiers; + PHOT_KEY_ITEM pHotKey; + + /* Check if it is a hotkey */ + fModifiers = IntGetModifiers(gafAsyncKeyState); + pHotKey = IsHotKey(fModifiers, wVk); + if (pHotKey) + { + if (bIsDown) + { + TRACE("Hot key pressed (hWnd %lx, id %d)\n", pHotKey->hWnd, pHotKey->id); + MsqPostHotKeyMessage(pHotKey->Thread, + pHotKey->hWnd, + (WPARAM)pHotKey->id, + MAKELPARAM((WORD)fModifiers, wVk)); + } + + return TRUE; /* Don't send any message */ + } + + if ((wVk == VK_LWIN || wVk == VK_RWIN) && fModifiers == 0) + IntKeyboardSendWinKeyMsg(); + + return FALSE; +} + + // // Get/SetHotKey message support. // @@ -258,12 +310,12 @@ NtUserRegisterHotKey(HWND hWnd, } /* Check for existing hotkey */ - if (IsHotKey (fsModifiers, vk)) + if (IsHotKey(fsModifiers, vk)) { RETURN( FALSE); } - HotKeyItem = ExAllocatePoolWithTag (PagedPool, sizeof(HOT_KEY_ITEM), USERTAG_HOTKEY); + HotKeyItem = ExAllocatePoolWithTag(PagedPool, sizeof(HOT_KEY_ITEM), USERTAG_HOTKEY); if (HotKeyItem == NULL) { RETURN( FALSE); diff --git a/reactos/subsystems/win32/win32k/ntuser/input.c b/reactos/subsystems/win32/win32k/ntuser/input.c index 1f5721916f6..3edba68d6a6 100644 --- a/reactos/subsystems/win32/win32k/ntuser/input.c +++ b/reactos/subsystems/win32/win32k/ntuser/input.c @@ -683,12 +683,12 @@ IntMouseInput(MOUSEINPUT *mi, BOOL Injected) Msg.lParam = MAKELPARAM(MousePos.x, MousePos.y); Msg.pt = MousePos; - if (gafAsyncKeyState[VK_SHIFT] & KS_DOWN_BIT) + if (IS_KEY_DOWN(gafAsyncKeyState, VK_SHIFT)) { Msg.wParam |= MK_SHIFT; } - if (gafAsyncKeyState[VK_CONTROL] & KS_DOWN_BIT) + if (IS_KEY_DOWN(gafAsyncKeyState, VK_CONTROL)) { Msg.wParam |= MK_CONTROL; } @@ -699,7 +699,7 @@ IntMouseInput(MOUSEINPUT *mi, BOOL Injected) } if(mi->dwFlags & MOUSEEVENTF_LEFTDOWN) { - gafAsyncKeyState[VK_LBUTTON] |= KS_DOWN_BIT; + SET_KEY_DOWN(gafAsyncKeyState, VK_LBUTTON, TRUE); Msg.message = SwapBtnMsg[0][SwapButtons]; CurInfo->ButtonsDown |= SwapBtn[SwapButtons]; Msg.wParam |= CurInfo->ButtonsDown; @@ -707,7 +707,7 @@ IntMouseInput(MOUSEINPUT *mi, BOOL Injected) } else if(mi->dwFlags & MOUSEEVENTF_LEFTUP) { - gafAsyncKeyState[VK_LBUTTON] &= ~KS_DOWN_BIT; + SET_KEY_DOWN(gafAsyncKeyState, VK_LBUTTON, FALSE); Msg.message = SwapBtnMsg[1][SwapButtons]; CurInfo->ButtonsDown &= ~SwapBtn[SwapButtons]; Msg.wParam |= CurInfo->ButtonsDown; @@ -715,7 +715,7 @@ IntMouseInput(MOUSEINPUT *mi, BOOL Injected) } if(mi->dwFlags & MOUSEEVENTF_MIDDLEDOWN) { - gafAsyncKeyState[VK_MBUTTON] |= KS_DOWN_BIT; + SET_KEY_DOWN(gafAsyncKeyState, VK_MBUTTON, TRUE); Msg.message = WM_MBUTTONDOWN; CurInfo->ButtonsDown |= MK_MBUTTON; Msg.wParam |= CurInfo->ButtonsDown; @@ -723,7 +723,7 @@ IntMouseInput(MOUSEINPUT *mi, BOOL Injected) } else if(mi->dwFlags & MOUSEEVENTF_MIDDLEUP) { - gafAsyncKeyState[VK_MBUTTON] &= ~KS_DOWN_BIT; + SET_KEY_DOWN(gafAsyncKeyState, VK_MBUTTON, FALSE); Msg.message = WM_MBUTTONUP; CurInfo->ButtonsDown &= ~MK_MBUTTON; Msg.wParam |= CurInfo->ButtonsDown; @@ -731,7 +731,7 @@ IntMouseInput(MOUSEINPUT *mi, BOOL Injected) } if(mi->dwFlags & MOUSEEVENTF_RIGHTDOWN) { - gafAsyncKeyState[VK_RBUTTON] |= KS_DOWN_BIT; + SET_KEY_DOWN(gafAsyncKeyState, VK_RBUTTON, TRUE); Msg.message = SwapBtnMsg[0][!SwapButtons]; CurInfo->ButtonsDown |= SwapBtn[!SwapButtons]; Msg.wParam |= CurInfo->ButtonsDown; @@ -739,7 +739,7 @@ IntMouseInput(MOUSEINPUT *mi, BOOL Injected) } else if(mi->dwFlags & MOUSEEVENTF_RIGHTUP) { - gafAsyncKeyState[VK_RBUTTON] &= ~KS_DOWN_BIT; + SET_KEY_DOWN(gafAsyncKeyState, VK_RBUTTON, FALSE); Msg.message = SwapBtnMsg[1][!SwapButtons]; CurInfo->ButtonsDown &= ~SwapBtn[!SwapButtons]; Msg.wParam |= CurInfo->ButtonsDown; @@ -758,14 +758,14 @@ IntMouseInput(MOUSEINPUT *mi, BOOL Injected) Msg.message = WM_XBUTTONDOWN; if(mi->mouseData & XBUTTON1) { - gafAsyncKeyState[VK_XBUTTON1] |= KS_DOWN_BIT; + SET_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON1, TRUE); CurInfo->ButtonsDown |= MK_XBUTTON1; Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1); co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); } if(mi->mouseData & XBUTTON2) { - gafAsyncKeyState[VK_XBUTTON2] |= KS_DOWN_BIT; + SET_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON2, TRUE); CurInfo->ButtonsDown |= MK_XBUTTON2; Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2); co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); @@ -776,14 +776,14 @@ IntMouseInput(MOUSEINPUT *mi, BOOL Injected) Msg.message = WM_XBUTTONUP; if(mi->mouseData & XBUTTON1) { - gafAsyncKeyState[VK_XBUTTON1] &= ~KS_DOWN_BIT; + SET_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON1, FALSE); CurInfo->ButtonsDown &= ~MK_XBUTTON1; Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1); co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); } if(mi->mouseData & XBUTTON2) { - gafAsyncKeyState[VK_XBUTTON2] &= ~KS_DOWN_BIT; + SET_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON2, FALSE); CurInfo->ButtonsDown &= ~MK_XBUTTON2; Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2); co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); diff --git a/reactos/subsystems/win32/win32k/ntuser/keyboard.c b/reactos/subsystems/win32/win32k/ntuser/keyboard.c index e02bccd4ade..206c27dfd4f 100644 --- a/reactos/subsystems/win32/win32k/ntuser/keyboard.c +++ b/reactos/subsystems/win32/win32k/ntuser/keyboard.c @@ -10,7 +10,8 @@ #include DBG_DEFAULT_CHANNEL(UserKbd); -BYTE gafAsyncKeyState[0x100]; +BYTE gafAsyncKeyState[256 * 2 / 8]; // 2 bits per key +BYTE gafAsyncKeyStateRecentDown[256 / 8]; // 1 bit per key static PKEYBOARD_INDICATOR_TRANSLATION gpKeyboardIndicatorTrans = NULL; /* FUNCTIONS *****************************************************************/ @@ -26,6 +27,7 @@ NTAPI InitKeyboardImpl(VOID) { RtlZeroMemory(&gafAsyncKeyState, sizeof(gafAsyncKeyState)); + RtlZeroMemory(&gafAsyncKeyStateRecentDown, sizeof(gafAsyncKeyStateRecentDown)); return STATUS_SUCCESS; } @@ -236,33 +238,6 @@ IntTranslateNumpadKey(WORD wVk) } } -/* - * IntGetModifiers - * - * Returns a value that indicates if the key is a modifier key, and - * which one. - */ -static -UINT FASTCALL -IntGetModifiers(PBYTE pKeyState) -{ - UINT fModifiers = 0; - - if (pKeyState[VK_SHIFT] & KS_DOWN_BIT) - fModifiers |= MOD_SHIFT; - - if (pKeyState[VK_CONTROL] & KS_DOWN_BIT) - fModifiers |= MOD_CONTROL; - - if (pKeyState[VK_MENU] & KS_DOWN_BIT) - fModifiers |= MOD_ALT; - - if ((pKeyState[VK_LWIN] | pKeyState[VK_RWIN]) & KS_DOWN_BIT) - fModifiers |= MOD_WIN; - - return fModifiers; -} - /* * IntGetShiftBit * @@ -295,11 +270,11 @@ IntGetModBits(PKBDTABLES pKbdTbl, PBYTE pKeyState) /* DumpKeyState( KeyState ); */ for (i = 0; pKbdTbl->pCharModifiers->pVkToBit[i].Vk; i++) - if (pKeyState[pKbdTbl->pCharModifiers->pVkToBit[i].Vk] & KS_DOWN_BIT) + if (IS_KEY_DOWN(pKeyState, pKbdTbl->pCharModifiers->pVkToBit[i].Vk)) dwModBits |= pKbdTbl->pCharModifiers->pVkToBit[i].ModBits; /* Handle Alt+Gr */ - if ((pKbdTbl->fLocaleFlags & KLLF_ALTGR) && (pKeyState[VK_RMENU] & KS_DOWN_BIT)) + if ((pKbdTbl->fLocaleFlags & KLLF_ALTGR) && IS_KEY_DOWN(pKeyState, VK_RMENU)) dwModBits |= IntGetShiftBit(pKbdTbl, VK_CONTROL); /* Don't use KBDCTRL here */ TRACE("Current Mod Bits: %lx\n", dwModBits); @@ -329,7 +304,7 @@ IntTranslateChar(WORD wVirtKey, WORD wCaplokAttr; dwModBits = pKeyState ? IntGetModBits(pKbdTbl, pKeyState) : 0; - bAltGr = pKeyState && (pKbdTbl->fLocaleFlags & KLLF_ALTGR) && (pKeyState[VK_RMENU] & KS_DOWN_BIT); + bAltGr = pKeyState && (pKbdTbl->fLocaleFlags & KLLF_ALTGR) && IS_KEY_DOWN(pKeyState, VK_RMENU); wCaplokAttr = bAltGr ? CAPLOKALTGR : CAPLOK; TRACE("TryToTranslate: %04x %x\n", wVirtKey, dwModBits); @@ -353,7 +328,7 @@ IntTranslateChar(WORD wVirtKey, /* If CapsLock is enabled for this key and locked, add SHIFT bit */ if ((pVkToVch->Attributes & wCaplokAttr) && pKeyState && - (pKeyState[VK_CAPITAL] & KS_LOCK_BIT)) + IS_KEY_LOCKED(pKeyState, VK_CAPITAL)) { /* Note: we use special value here instead of getting VK_SHIFT mod bit - it's verified */ dwVkModBits ^= KBDSHIFT; @@ -407,8 +382,8 @@ IntTranslateChar(WORD wVirtKey, /* If nothing has been found in layout, check if this is ASCII control character. Note: we could add it to layout table, but windows does not have it there */ if (wVirtKey >= 'A' && wVirtKey <= 'Z' && - (pKeyState[VK_CONTROL] & KS_DOWN_BIT) && - !(pKeyState[VK_MENU] & KS_DOWN_BIT)) + IS_KEY_DOWN(pKeyState, VK_CONTROL) && + !IS_KEY_DOWN(pKeyState, VK_MENU)) { *pwcTranslatedChar = (wVirtKey - 'A') + 1; /* ASCII control character */ *pbDead = FALSE; @@ -606,58 +581,35 @@ IntVkToChar(WORD wVk, PKBDTABLES pKbdTbl) return 0; } -#if 0 -static -VOID -DumpKeyState(PBYTE pKeyState) -{ - unsigned i; - - DbgPrint("KeyState { "); - for (i = 0; i < 0x100; i++) - { - if (pKeyState[i]) - DbgPrint("%02x(%02x) ", i, pKeyState[i]); - } - DbgPrint("};\n"); -} -#endif - /* - * IntGetAsyncKeyState + * NtUserGetAsyncKeyState * - * Gets key state from global table + * Gets key state from global bitmap */ -static -WORD FASTCALL -IntGetAsyncKeyState(DWORD dwKey) -{ - WORD dwRet = 0; - - if (dwKey < 0x100) - { - if (gafAsyncKeyState[dwKey] & KS_DOWN_BIT) - dwRet |= 0xFFFF8000; // If down, windows returns 0xFFFF8000. - if (gafAsyncKeyState[dwKey] & KS_LOCK_BIT) - dwRet |= 0x1; - } - else - { - EngSetLastError(ERROR_INVALID_PARAMETER); - } - return dwRet; -} - SHORT APIENTRY NtUserGetAsyncKeyState(INT Key) { + WORD wRet = 0; DECLARE_RETURN(SHORT); TRACE("Enter NtUserGetAsyncKeyState\n"); UserEnterExclusive(); - RETURN(IntGetAsyncKeyState(Key)); + if (Key < 0x100) + { + if (IS_KEY_DOWN(gafAsyncKeyState, Key)) + wRet |= 0x8000; // If down, windows returns 0x8000. + if (gafAsyncKeyStateRecentDown[Key / 8] & (1 << (Key % 8))) + wRet |= 0x1; + gafAsyncKeyStateRecentDown[Key / 8] &= ~(1 << (Key % 8)); + } + else + { + EngSetLastError(ERROR_INVALID_PARAMETER); + } + + RETURN(wRet); CLEANUP: TRACE("Leave NtUserGetAsyncKeyState, ret=%i\n", _ret_); @@ -665,33 +617,6 @@ CLEANUP: END_CLEANUP; } -/* - * IntKeyboardSendWinKeyMsg - * - * Sends syscommand to shell, when WIN key is pressed - */ -static -VOID NTAPI -IntKeyboardSendWinKeyMsg() -{ - PWND pWnd; - MSG Msg; - - if (!(pWnd = UserGetWindowObject(InputWindowStation->ShellWindow))) - { - ERR("Couldn't find window to send Windows key message!\n"); - return; - } - - Msg.hwnd = InputWindowStation->ShellWindow; - Msg.message = WM_SYSCOMMAND; - Msg.wParam = SC_TASKLIST; - Msg.lParam = 0; - - /* The QS_HOTKEY is just a guess */ - MsqPostMessage(pWnd->head.pti->MessageQueue, &Msg, FALSE, QS_HOTKEY); -} - /* * co_IntKeyboardSendAltKeyMsg * @@ -705,6 +630,51 @@ co_IntKeyboardSendAltKeyMsg() //co_MsqPostKeyboardMessage(WM_SYSCOMMAND,SC_KEYMENU,0); // This sends everything into a msg loop! } + +/* + * UpdateAsyncKeyState + * + * Updates gafAsyncKeyState array + */ +static +VOID NTAPI +UpdateAsyncKeyState(WORD wVk, BOOL bIsDown) +{ + if (bIsDown) + { + /* If it's first key down event, xor lock bit */ + if (!IS_KEY_DOWN(gafAsyncKeyState, wVk)) + SET_KEY_LOCKED(gafAsyncKeyState, wVk, !IS_KEY_LOCKED(gafAsyncKeyState, wVk)); + + SET_KEY_DOWN(gafAsyncKeyState, wVk, TRUE); + gafAsyncKeyStateRecentDown[wVk / 8] |= (1 << (wVk % 8)); + } + else + SET_KEY_DOWN(gafAsyncKeyState, wVk, FALSE); +} + +LRESULT +co_CallLowLevelKeyboardHook(CONST MSG *pMsg, BOOL bInjected, DWORD dwExtraInfo) +{ + KBDLLHOOKSTRUCT KbdHookData; + + KbdHookData.vkCode = pMsg->wParam; + KbdHookData.scanCode = HIWORD(pMsg->lParam) & 0xFF; + KbdHookData.flags = 0; + if (pMsg->lParam & LP_EXT_BIT) + KbdHookData.flags |= LLKHF_EXTENDED; + if (IS_KEY_DOWN(gafAsyncKeyState, VK_MENU)) + KbdHookData.flags |= LLKHF_ALTDOWN; + if (pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP) + KbdHookData.flags |= LLKHF_UP; + if (bInjected) + KbdHookData.flags |= LLKHF_INJECTED; + KbdHookData.time = pMsg->time; + KbdHookData.dwExtraInfo = dwExtraInfo; + + return co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, pMsg->message, (LPARAM) &KbdHookData); +} + /* * UserSendKeyboardInput * @@ -713,19 +683,16 @@ co_IntKeyboardSendAltKeyMsg() BOOL NTAPI UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected) { - WORD wScanCode, wVk, wSimpleVk, wVkOtherSide, wSysKey; + WORD wScanCode, wVk, wSimpleVk = 0, wVkOtherSide, wSysKey; PKBL pKbl = NULL; PKBDTABLES pKbdTbl; PUSER_MESSAGE_QUEUE pFocusQueue; struct _ETHREAD *pFocusThread; - UINT fModifiers; - BYTE PrevKeyState = 0; - HWND hWnd; - int HotkeyId; - struct _ETHREAD *Thread; LARGE_INTEGER LargeTickCount; - BOOL bExt = pKbdInput->dwFlags & KEYEVENTF_EXTENDEDKEY; - BOOL bKeyUp = pKbdInput->dwFlags & KEYEVENTF_KEYUP; + BOOL bExt = (pKbdInput->dwFlags & KEYEVENTF_EXTENDEDKEY) ? TRUE : FALSE; + BOOL bIsDown = (pKbdInput->dwFlags & KEYEVENTF_KEYUP) ? FALSE : TRUE; + BOOL bWasDown = FALSE, bPostMsg = TRUE; + MSG Msg; /* Find the target thread whose locale is in effect */ pFocusQueue = IntGetFocusMessageQueue(); @@ -758,13 +725,10 @@ UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected) } else { - if (bExt) - wScanCode |= 0xE000; - if (pKbdInput->dwFlags & KEYEVENTF_SCANCODE) { /* Don't ignore invalid scan codes */ - wVk = IntVscToVk(wScanCode, pKbdTbl); + wVk = IntVscToVk(wScanCode | (bExt ? 0xE000 : 0), pKbdTbl); if (!wVk) /* use 0xFF if vsc is invalid */ wVk = 0xFF; } @@ -776,29 +740,72 @@ UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected) wVk = IntSimplifyVk(wVk); wVk = IntFixVk(wVk, bExt); } + + /* Get virtual key without shifts (VK_(L|R)* -> VK_*) */ + wSimpleVk = IntSimplifyVk(wVk); + wVkOtherSide = IntGetVkOtherSide(wVk); + bWasDown = IS_KEY_DOWN(gafAsyncKeyState, wSimpleVk); + + if (xxxDoHotKeyStuff(wSimpleVk, bIsDown)) + bPostMsg = FALSE; + + /* Update key without shifts */ + UpdateAsyncKeyState(wSimpleVk, bIsDown || IS_KEY_DOWN(gafAsyncKeyState, wVkOtherSide)); + } + + /* If it is F10 or ALT is down and CTRL is up, it's a system key */ + wSysKey = (pKbdTbl->fLocaleFlags & KLLF_ALTGR) ? VK_LMENU : VK_MENU; + if (wVk == VK_F10 || + //uVkNoShift == VK_MENU || // FIXME: If only LALT is pressed WM_SYSKEYUP is generated instead of WM_KEYUP + (IS_KEY_DOWN(gafAsyncKeyState, wSysKey) && // FIXME + !IS_KEY_DOWN(gafAsyncKeyState, VK_CONTROL))) + { + if (bIsDown) + Msg.message = WM_SYSKEYDOWN; + else + Msg.message = WM_SYSKEYUP; + } + else + { + if (bIsDown) + Msg.message = WM_KEYDOWN; + else + Msg.message = WM_KEYUP; + } + + /* Init hwnd and lParam */ + Msg.hwnd = pFocusQueue->FocusWindow; + Msg.lParam = MAKELPARAM(1, wScanCode); + + /* If it is VK_PACKET, high word of wParam is used for wchar */ + if (!(pKbdInput->dwFlags & KEYEVENTF_UNICODE)) + { + if (bExt) + Msg.lParam |= LP_EXT_BIT; + if (IS_KEY_DOWN(gafAsyncKeyState, VK_MENU)) + Msg.lParam |= LP_CONTEXT_BIT; + if (bWasDown) + Msg.lParam |= LP_PREV_STATE_BIT; + if (!bIsDown) + Msg.lParam |= LP_TRANSITION_BIT; + } + + /* Init wParam and cursor position */ + Msg.wParam = wVk; // Note: it's simplified by msg queue + Msg.pt = gpsi->ptCursor; + + /* If time is given, use it */ + if (pKbdInput->time) + Msg.time = pKbdInput->time; + else + { + KeQueryTickCount(&LargeTickCount); + Msg.time = MsqCalculateMessageTime(&LargeTickCount); } if (!(pKbdInput->dwFlags & KEYEVENTF_UNICODE)) { - /* Get virtual key without shifts (VK_(L|R)* -> VK_*) */ - wSimpleVk = IntSimplifyVk(wVk); - wVkOtherSide = IntGetVkOtherSide(wVk); - PrevKeyState = gafAsyncKeyState[wSimpleVk]; - - /* Update global keyboard state. Begin from lock bit */ - if (!bKeyUp && !(PrevKeyState & KS_DOWN_BIT)) - gafAsyncKeyState[wVk] ^= KS_LOCK_BIT; - - /* Update down bit */ - if (bKeyUp) - gafAsyncKeyState[wVk] &= ~KS_DOWN_BIT; - else - gafAsyncKeyState[wVk] |= KS_DOWN_BIT; - - /* Update key without shifts */ - gafAsyncKeyState[wSimpleVk] = gafAsyncKeyState[wVk] | gafAsyncKeyState[wVkOtherSide]; - - if (!bKeyUp) + if (bIsDown) { /* Update keyboard LEDs */ if (!gpKeyboardIndicatorTrans) @@ -806,91 +813,34 @@ UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected) if (gpKeyboardIndicatorTrans) IntKeyboardUpdateLeds(ghKeyboardDevice, wScanCode, - gafAsyncKeyState[wSimpleVk] & KS_LOCK_BIT, + IS_KEY_LOCKED(gafAsyncKeyState, wVk), gpKeyboardIndicatorTrans); } - /* Truncate scan code */ - wScanCode &= 0x7F; - - /* Support VK_*WIN and VK_*MENU keys */ - if (bKeyUp) + /* Call hook */ + if (CallLowLevelKeyboardHook(&Msg, bInjected, pKbdInput->dwExtraInfo)) { - if (wVk == VK_LWIN || wVk == VK_RWIN) - IntKeyboardSendWinKeyMsg(); - else if(wSimpleVk == VK_MENU && !(gafAsyncKeyState[VK_CONTROL] & KS_DOWN_BIT)) - co_IntKeyboardSendAltKeyMsg(); + ERR("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n", + Msg.message, Msg.wParam, Msg.lParam); + bPostMsg = FALSE; } - /* Check if it is a hotkey */ - fModifiers = IntGetModifiers(gafAsyncKeyState); - if (GetHotKey(fModifiers, wSimpleVk, &Thread, &hWnd, &HotkeyId)) - { - if (!bKeyUp) - { - TRACE("Hot key pressed (hWnd %lx, id %d)\n", hWnd, HotkeyId); - MsqPostHotKeyMessage(Thread, - hWnd, - (WPARAM)HotkeyId, - MAKELPARAM((WORD)fModifiers, wSimpleVk)); - } + /* Update async state of not simplified vk here. + See user32_apitest:GetKeyState */ + UpdateAsyncKeyState(wVk, bIsDown); - return TRUE; /* Don't send any message */ - } + /* Support VK_*MENU keys */ + if (!bIsDown && wSimpleVk == VK_MENU && !IS_KEY_DOWN(gafAsyncKeyState, VK_CONTROL)) + co_IntKeyboardSendAltKeyMsg(); } /* If we have a focus queue, post a keyboard message */ - if (pFocusQueue) + if (pFocusQueue && bPostMsg) { - MSG Msg; - - /* If it is F10 or ALT is down and CTRL is up, it's a system key */ - wSysKey = (pKbdTbl->fLocaleFlags & KLLF_ALTGR) ? VK_LMENU : VK_MENU; - if (wVk == VK_F10 || - //uVkNoShift == VK_MENU || // FIXME: If only LALT is pressed WM_SYSKEYUP is generated instead of WM_KEYUP - ((gafAsyncKeyState[wSysKey] & KS_DOWN_BIT) && // FIXME - !(gafAsyncKeyState[VK_CONTROL] & KS_DOWN_BIT))) - { - if (bKeyUp) - Msg.message = WM_SYSKEYUP; - else - Msg.message = WM_SYSKEYDOWN; - } - else - { - if (bKeyUp) - Msg.message = WM_KEYUP; - else - Msg.message = WM_KEYDOWN; - } - Msg.hwnd = pFocusQueue->FocusWindow; - Msg.lParam = MAKELPARAM(1, wScanCode); - /* If it is VK_PACKET, high word of wParam is used for wchar */ - if (!(pKbdInput->dwFlags & KEYEVENTF_UNICODE)) - { - if (bExt) - Msg.lParam |= LP_EXT_BIT; - if (gafAsyncKeyState[VK_MENU] & KS_DOWN_BIT) - Msg.lParam |= LP_CONTEXT_BIT; - if (PrevKeyState & KS_DOWN_BIT) - Msg.lParam |= LP_PREV_STATE_BIT; - if (bKeyUp) - Msg.lParam |= LP_TRANSITION_BIT; - } - - Msg.wParam = wVk; // its "simplified" later - Msg.pt = gpsi->ptCursor; - if (pKbdInput->time) - Msg.time = pKbdInput->time; - else - { - KeQueryTickCount(&LargeTickCount); - Msg.time = MsqCalculateMessageTime(&LargeTickCount); - } - /* Post a keyboard message */ TRACE("Posting keyboard msg %u wParam 0x%x lParam 0x%x\n", Msg.message, Msg.wParam, Msg.lParam); - co_MsqPostKeyboardMessage(Msg.message, Msg.wParam, Msg.lParam, bInjected); + //co_MsqPostKeyboardMessage(Msg.message, Msg.wParam, Msg.lParam, bInjected); + MsqPostMessage(pFocusQueue, &Msg, TRUE, QS_KEY); } return TRUE; @@ -947,7 +897,7 @@ UserProcessKeyboardInput( KEYBDINPUT KbdInput; /* Support numlock */ - if ((wVk & KBDNUMPAD) && (gafAsyncKeyState[VK_NUMLOCK] & KS_LOCK_BIT)) + if ((wVk & KBDNUMPAD) && IS_KEY_LOCKED(gafAsyncKeyState, VK_NUMLOCK)) { wVk = IntTranslateNumpadKey(wVk & 0xFF); } @@ -1028,7 +978,7 @@ IntTranslateKbdMessage(LPMSG lpMsg, cch = IntToUnicodeEx(lpMsg->wParam, HIWORD(lpMsg->lParam) & 0xFF, - pti->MessageQueue->KeyState, + pti->MessageQueue->afKeyState, wch, sizeof(wch) / sizeof(wch[0]), 0, @@ -1182,31 +1132,49 @@ NtUserToUnicodeEx( UINT wScanCode, PBYTE pKeyStateUnsafe, LPWSTR pwszBuffUnsafe, - int cchBuff, + INT cchBuff, UINT wFlags, HKL dwhkl) { PTHREADINFO pti; - BYTE KeyState[0x100]; + BYTE afKeyState[256 * 2 / 8] = {0}; PWCHAR pwszBuff = NULL; - int iRet = 0; + INT i, iRet = 0; PKBL pKbl = NULL; - DECLARE_RETURN(int); + NTSTATUS Status = STATUS_SUCCESS; + DECLARE_RETURN(INT); TRACE("Enter NtUserSetKeyboardState\n"); UserEnterShared(); - /* Key up? */ + /* Return 0 if SC_KEY_UP bit is set */ if (wScanCode & SC_KEY_UP) { RETURN(0); } - if (!NT_SUCCESS(MmCopyFromCaller(KeyState, - pKeyStateUnsafe, - sizeof(KeyState)))) + _SEH2_TRY { - ERR("Couldn't copy key state from caller.\n"); + /* Probe and copy key state to smaller bitmap */ + ProbeForRead(pKeyStateUnsafe, 256 * sizeof(BYTE), 1); + for (i = 0; i < 256; ++i) + { + if (pKeyStateUnsafe[i] & KS_DOWN_BIT) + SET_KEY_DOWN(afKeyState, i, TRUE); + if (pKeyStateUnsafe[i] & KS_LOCK_BIT) + SET_KEY_LOCKED(afKeyState, i, TRUE); + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + if (!NT_SUCCESS(Status)) + { + ERR("Cannot copy key state\n"); + SetLastNtError(Status); RETURN(0); } @@ -1232,7 +1200,7 @@ NtUserToUnicodeEx( iRet = IntToUnicodeEx(wVirtKey, wScanCode, - KeyState, + afKeyState, pwszBuff, cchBuff, wFlags, @@ -1447,24 +1415,24 @@ Exit: WORD FASTCALL UserGetMouseButtonsState(VOID) { - WORD ret = 0; + WORD wRet = 0; if (gpsi->aiSysMet[SM_SWAPBUTTON]) { - if (gafAsyncKeyState[VK_RBUTTON] & KS_DOWN_BIT) ret |= MK_LBUTTON; - if (gafAsyncKeyState[VK_LBUTTON] & KS_DOWN_BIT) ret |= MK_RBUTTON; + if (IS_KEY_DOWN(gafAsyncKeyState, VK_RBUTTON)) wRet |= MK_LBUTTON; + if (IS_KEY_DOWN(gafAsyncKeyState, VK_LBUTTON)) wRet |= MK_RBUTTON; } else { - if (gafAsyncKeyState[VK_LBUTTON] & KS_DOWN_BIT) ret |= MK_LBUTTON; - if (gafAsyncKeyState[VK_RBUTTON] & KS_DOWN_BIT) ret |= MK_RBUTTON; + if (IS_KEY_DOWN(gafAsyncKeyState, VK_LBUTTON)) wRet |= MK_LBUTTON; + if (IS_KEY_DOWN(gafAsyncKeyState, VK_RBUTTON)) wRet |= MK_RBUTTON; } - if (gafAsyncKeyState[VK_MBUTTON] & KS_DOWN_BIT) ret |= MK_MBUTTON; - if (gafAsyncKeyState[VK_SHIFT] & KS_DOWN_BIT) ret |= MK_SHIFT; - if (gafAsyncKeyState[VK_CONTROL] & KS_DOWN_BIT) ret |= MK_CONTROL; - if (gafAsyncKeyState[VK_XBUTTON1] & KS_DOWN_BIT) ret |= MK_XBUTTON1; - if (gafAsyncKeyState[VK_XBUTTON2] & KS_DOWN_BIT) ret |= MK_XBUTTON2; - return ret; + if (IS_KEY_DOWN(gafAsyncKeyState, VK_MBUTTON)) wRet |= MK_MBUTTON; + if (IS_KEY_DOWN(gafAsyncKeyState, VK_SHIFT)) wRet |= MK_SHIFT; + if (IS_KEY_DOWN(gafAsyncKeyState, VK_CONTROL)) wRet |= MK_CONTROL; + if (IS_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON1)) wRet |= MK_XBUTTON1; + if (IS_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON2)) wRet |= MK_XBUTTON2; + return wRet; } /* EOF */ diff --git a/reactos/subsystems/win32/win32k/ntuser/msgqueue.c b/reactos/subsystems/win32/win32k/ntuser/msgqueue.c index ead730cd4b4..7341827bd92 100644 --- a/reactos/subsystems/win32/win32k/ntuser/msgqueue.c +++ b/reactos/subsystems/win32/win32k/ntuser/msgqueue.c @@ -212,56 +212,57 @@ int UserShowCursor(BOOL bShow) return MessageQueue->ShowingCursor; } -DWORD FASTCALL UserGetKeyState(DWORD key) +DWORD FASTCALL +UserGetKeyState(DWORD dwKey) { - DWORD ret = 0; + DWORD dwRet = 0; PTHREADINFO pti; PUSER_MESSAGE_QUEUE MessageQueue; pti = PsGetCurrentThreadWin32Thread(); MessageQueue = pti->MessageQueue; - if (key < 0x100) + if (dwKey < 0x100) { - ret = (DWORD)MessageQueue->KeyState[key]; - if (MessageQueue->KeyState[key] & KS_DOWN_BIT) - ret |= 0xFF80; // If down, windows returns 0xFF80. - if (MessageQueue->KeyState[key] & KS_LOCK_BIT) - ret |= 0x1; + if (IS_KEY_DOWN(MessageQueue->afKeyState, dwKey)) + dwRet |= 0xFF80; // If down, windows returns 0xFF80. + if (IS_KEY_LOCKED(MessageQueue->afKeyState, dwKey)) + dwRet |= 0x1; } else { EngSetLastError(ERROR_INVALID_PARAMETER); } - return ret; + return dwRet; } /* change the input key state for a given key */ -static void set_input_key_state( PUSER_MESSAGE_QUEUE MessageQueue, UCHAR key, BOOL down ) +static VOID +UpdateKeyState(PUSER_MESSAGE_QUEUE MessageQueue, WORD wVk, BOOL bIsDown) { - TRACE("set_input_key_state key:%d, down:%d\n", key, down); + TRACE("UpdateKeyState wVk: %d, bIsDown: %d\n", wVk, bIsDown); - if (down) + if (bIsDown) { - if (!(MessageQueue->KeyState[key] & KS_DOWN_BIT)) - { - MessageQueue->KeyState[key] ^= KS_LOCK_BIT; - } - MessageQueue->KeyState[key] |= KS_DOWN_BIT; + /* If it's first key down event, xor lock bit */ + if (!IS_KEY_DOWN(MessageQueue->afKeyState, wVk)) + SET_KEY_LOCKED(MessageQueue->afKeyState, wVk, !IS_KEY_LOCKED(MessageQueue->afKeyState, wVk)); + + SET_KEY_DOWN(MessageQueue->afKeyState, wVk, TRUE); + MessageQueue->afKeyRecentDown[wVk / 8] |= (1 << (wVk % 8)); } else - { - MessageQueue->KeyState[key] &= ~KS_DOWN_BIT; - } + SET_KEY_DOWN(MessageQueue->afKeyState, wVk, FALSE); } /* update the input key state for a keyboard message */ -static void update_input_key_state( PUSER_MESSAGE_QUEUE MessageQueue, MSG* msg ) +static VOID +UpdateKeyStateFromMsg(PUSER_MESSAGE_QUEUE MessageQueue, MSG* msg) { UCHAR key; BOOL down = 0; - TRACE("update_input_key_state message:%d\n", msg->message); + TRACE("UpdateKeyStateFromMsg message:%d\n", msg->message); switch (msg->message) { @@ -269,28 +270,28 @@ static void update_input_key_state( PUSER_MESSAGE_QUEUE MessageQueue, MSG* msg ) down = 1; /* fall through */ case WM_LBUTTONUP: - set_input_key_state( MessageQueue, VK_LBUTTON, down ); + UpdateKeyState(MessageQueue, VK_LBUTTON, down); break; case WM_MBUTTONDOWN: down = 1; /* fall through */ case WM_MBUTTONUP: - set_input_key_state( MessageQueue, VK_MBUTTON, down ); + UpdateKeyState(MessageQueue, VK_MBUTTON, down); break; case WM_RBUTTONDOWN: down = 1; /* fall through */ case WM_RBUTTONUP: - set_input_key_state( MessageQueue, VK_RBUTTON, down ); + UpdateKeyState(MessageQueue, VK_RBUTTON, down); break; case WM_XBUTTONDOWN: down = 1; /* fall through */ case WM_XBUTTONUP: if (msg->wParam == XBUTTON1) - set_input_key_state( MessageQueue, VK_XBUTTON1, down ); + UpdateKeyState(MessageQueue, VK_XBUTTON1, down); else if (msg->wParam == XBUTTON2) - set_input_key_state( MessageQueue, VK_XBUTTON2, down ); + UpdateKeyState(MessageQueue, VK_XBUTTON2, down); break; case WM_KEYDOWN: case WM_SYSKEYDOWN: @@ -299,23 +300,23 @@ static void update_input_key_state( PUSER_MESSAGE_QUEUE MessageQueue, MSG* msg ) case WM_KEYUP: case WM_SYSKEYUP: key = (UCHAR)msg->wParam; - set_input_key_state( MessageQueue, key, down ); + UpdateKeyState(MessageQueue, key, down); switch(key) { case VK_LCONTROL: case VK_RCONTROL: - down = (MessageQueue->KeyState[VK_LCONTROL] | MessageQueue->KeyState[VK_RCONTROL]) & KS_DOWN_BIT; - set_input_key_state( MessageQueue, VK_CONTROL, down ); + down = IS_KEY_DOWN(MessageQueue->afKeyState, VK_LCONTROL) || IS_KEY_DOWN(MessageQueue->afKeyState, VK_RCONTROL); + UpdateKeyState(MessageQueue, VK_CONTROL, down); break; case VK_LMENU: case VK_RMENU: - down = (MessageQueue->KeyState[VK_LMENU] | MessageQueue->KeyState[VK_RMENU]) & KS_DOWN_BIT; - set_input_key_state( MessageQueue, VK_MENU, down ); + down = IS_KEY_DOWN(MessageQueue->afKeyState, VK_LMENU) || IS_KEY_DOWN(MessageQueue->afKeyState, VK_RMENU); + UpdateKeyState(MessageQueue, VK_MENU, down); break; case VK_LSHIFT: case VK_RSHIFT: - down = (MessageQueue->KeyState[VK_LSHIFT] | MessageQueue->KeyState[VK_RSHIFT]) & KS_DOWN_BIT; - set_input_key_state( MessageQueue, VK_SHIFT, down ); + down = IS_KEY_DOWN(MessageQueue->afKeyState, VK_LSHIFT) || IS_KEY_DOWN(MessageQueue->afKeyState, VK_RSHIFT); + UpdateKeyState(MessageQueue, VK_SHIFT, down); break; } break; @@ -627,84 +628,6 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook gcur_count = 0; // 0 - 63 is 64, FIFO forwards. } -// -// Note: Only called from input.c. -// -VOID FASTCALL -co_MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL bInjected) -{ - PUSER_MESSAGE_QUEUE FocusMessageQueue; - MSG Msg; - LARGE_INTEGER LargeTickCount; - KBDLLHOOKSTRUCT KbdHookData; - - TRACE("MsqPostKeyboardMessage(uMsg 0x%x, wParam 0x%x, lParam 0x%x)\n", - uMsg, wParam, lParam); - - // Condition may arise when calling MsqPostMessage and waiting for an event. - ASSERT(UserIsEntered()); - - FocusMessageQueue = IntGetFocusMessageQueue(); - - Msg.hwnd = 0; - - if (FocusMessageQueue && (FocusMessageQueue->FocusWindow != (HWND)0)) - Msg.hwnd = FocusMessageQueue->FocusWindow; - - Msg.message = uMsg; - Msg.wParam = wParam; - Msg.lParam = lParam; - - KeQueryTickCount(&LargeTickCount); - Msg.time = MsqCalculateMessageTime(&LargeTickCount); - - /* We can't get the Msg.pt point here since we don't know thread - (and thus the window station) the message will end up in yet. */ - - KbdHookData.vkCode = Msg.wParam; - KbdHookData.scanCode = (Msg.lParam >> 16) & 0xff; - KbdHookData.flags = 0; - if (Msg.lParam & 0x01000000) - KbdHookData.flags |= LLKHF_EXTENDED; - if (Msg.lParam & 0x20000000) - KbdHookData.flags |= LLKHF_ALTDOWN; - if (Msg.lParam & 0x80000000) - KbdHookData.flags |= LLKHF_UP; - if (bInjected) - KbdHookData.flags |= LLKHF_INJECTED; - KbdHookData.time = Msg.time; - KbdHookData.dwExtraInfo = 0; - if (co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, Msg.message, (LPARAM) &KbdHookData)) - { - ERR("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n", - Msg.message, Msg.wParam, Msg.lParam); - return; - } - - if (FocusMessageQueue == NULL) - { - TRACE("No focus message queue\n"); - return; - } - - if (FocusMessageQueue->FocusWindow != (HWND)0) - { - Msg.hwnd = FocusMessageQueue->FocusWindow; - TRACE("Msg.hwnd = %x\n", Msg.hwnd); - - FocusMessageQueue->Desktop->pDeskInfo->LastInputWasKbd = TRUE; - - Msg.pt = gpsi->ptCursor; - MsqPostMessage(FocusMessageQueue, &Msg, TRUE, QS_KEY); - } - else - { - TRACE("Invalid focus window handle\n"); - } - - return; -} - VOID FASTCALL MsqPostHotKeyMessage(PVOID Thread, HWND hWnd, WPARAM wParam, LPARAM lParam) { @@ -1293,7 +1216,7 @@ MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue, MSG* Msg, BOOLEAN HardwareMessa InsertTailList(&MessageQueue->HardwareMessagesListHead, &Message->ListEntry); - update_input_key_state( MessageQueue, Msg ); + UpdateKeyStateFromMsg( MessageQueue, Msg ); } Message->QS_Flags = MessageBits; @@ -1801,7 +1724,7 @@ co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue, if (Remove) { - update_input_key_state(MessageQueue, &msg); + UpdateKeyStateFromMsg(MessageQueue, &msg); RemoveEntryList(&CurrentMessage->ListEntry); ClearMsgBitsMask(MessageQueue, CurrentMessage->QS_Flags); MsqDestroyMessage(CurrentMessage); @@ -1930,7 +1853,7 @@ MsqInitializeMessageQueue(struct _ETHREAD *Thread, PUSER_MESSAGE_QUEUE MessageQu MessageQueue->NewMessagesHandle = NULL; MessageQueue->ShowingCursor = 0; MessageQueue->CursorObject = NULL; - RtlCopyMemory(MessageQueue->KeyState, gafAsyncKeyState, sizeof(gafAsyncKeyState)); + RtlCopyMemory(MessageQueue->afKeyState, gafAsyncKeyState, sizeof(gafAsyncKeyState)); Status = ZwCreateEvent(&MessageQueue->NewMessagesHandle, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); @@ -2281,7 +2204,7 @@ DWORD APIENTRY NtUserGetKeyboardState(LPBYTE lpKeyState) { - DWORD ret = TRUE; + DWORD i, ret = TRUE; PTHREADINFO pti; PUSER_MESSAGE_QUEUE MessageQueue; @@ -2292,8 +2215,16 @@ NtUserGetKeyboardState(LPBYTE lpKeyState) _SEH2_TRY { - ProbeForWrite(lpKeyState,sizeof(MessageQueue->KeyState) ,1); - RtlCopyMemory(lpKeyState,MessageQueue->KeyState,sizeof(MessageQueue->KeyState)); + /* Probe and copy key state to an array */ + ProbeForWrite(lpKeyState, 256 * sizeof(BYTE), 1); + for (i = 0; i < 256; ++i) + { + lpKeyState[i] = 0; + if (IS_KEY_DOWN(MessageQueue->afKeyState, i)) + lpKeyState[i] |= KS_DOWN_BIT; + if (IS_KEY_LOCKED(MessageQueue->afKeyState, i)) + lpKeyState[i] |= KS_LOCK_BIT; + } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { @@ -2309,9 +2240,10 @@ NtUserGetKeyboardState(LPBYTE lpKeyState) BOOL APIENTRY -NtUserSetKeyboardState(LPBYTE lpKeyState) +NtUserSetKeyboardState(LPBYTE pKeyState) { - DWORD ret = TRUE; + UINT i; + BOOL bRet = TRUE; PTHREADINFO pti; PUSER_MESSAGE_QUEUE MessageQueue; @@ -2322,19 +2254,23 @@ NtUserSetKeyboardState(LPBYTE lpKeyState) _SEH2_TRY { - ProbeForRead(lpKeyState,sizeof(MessageQueue->KeyState) ,1); - RtlCopyMemory(MessageQueue->KeyState,lpKeyState,sizeof(MessageQueue->KeyState)); + ProbeForRead(pKeyState, 256 * sizeof(BYTE), 1); + for (i = 0; i < 256; ++i) + { + SET_KEY_DOWN(MessageQueue->afKeyState, i, pKeyState[i] & KS_DOWN_BIT); + SET_KEY_LOCKED(MessageQueue->afKeyState, i, pKeyState[i] & KS_LOCK_BIT); + } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastNtError(_SEH2_GetExceptionCode()); - ret = FALSE; + bRet = FALSE; } _SEH2_END; UserLeave(); - return ret; + return bRet; } /* EOF */