[WIN32K]
authorRafal Harabien <rafalh@reactos.org>
Sun, 9 Oct 2011 20:12:12 +0000 (20:12 +0000)
committerRafal Harabien <rafalh@reactos.org>
Sun, 9 Oct 2011 20:12:12 +0000 (20:12 +0000)
- Use 64 byte bitmap for keystate instead of 256 elements array (like Windows)
- Fix GetAsyncKeyState lowest bit meaning. See MSDN
- Call low level keyboard hook before setting async key state for keys which distinguish between left and right hand. Fixes user32:GetKeyState apitest failure
- Improve IsHotKey and delete GetHotKey function to avoid code duplication
- Support WIN key in hotkeys code instead of keyboard.c

svn path=/trunk/; revision=54063

reactos/subsystems/win32/win32k/include/hotkey.h
reactos/subsystems/win32/win32k/include/input.h
reactos/subsystems/win32/win32k/include/msgqueue.h
reactos/subsystems/win32/win32k/ntuser/hotkey.c
reactos/subsystems/win32/win32k/ntuser/input.c
reactos/subsystems/win32/win32k/ntuser/keyboard.c
reactos/subsystems/win32/win32k/ntuser/msgqueue.c

index c5e514b..a1dbd5c 100644 (file)
@@ -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 */
index 9eac220..fb9c04d 100644 (file)
@@ -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)))
+
index fac3131..073e402 100644 (file)
@@ -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);
index 120aa78..8c17fdc 100644 (file)
@@ -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 (hWnd != NULL)
-            *hWnd = HotKeyItem->hWnd;
+    if (IS_KEY_DOWN(pKeyState, VK_CONTROL))
+        fModifiers |= MOD_CONTROL;
 
-         if (id != NULL)
-            *id = HotKeyItem->id;
+    if (IS_KEY_DOWN(pKeyState, VK_MENU))
+        fModifiers |= MOD_ALT;
 
-         return TRUE;
-      }
-   }
+    if (IS_KEY_DOWN(pKeyState, VK_LWIN) || IS_KEY_DOWN(pKeyState, VK_RWIN))
+        fModifiers |= MOD_WIN;
 
-   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);
index 1f57219..3edba68 100644 (file)
@@ -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);
index e02bccd..206c27d 100644 (file)
@@ -10,7 +10,8 @@
 #include <win32k.h>
 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_);
@@ -666,43 +618,61 @@ CLEANUP:
 }
 
 /*
- * IntKeyboardSendWinKeyMsg
+ * co_IntKeyboardSendAltKeyMsg
  *
- * Sends syscommand to shell, when WIN key is pressed
+ * Sends syscommand enabling window menu
  */
 static
 VOID NTAPI
-IntKeyboardSendWinKeyMsg()
+co_IntKeyboardSendAltKeyMsg()
 {
-    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);
+    FIXME("co_IntKeyboardSendAltKeyMsg\n");
+    //co_MsqPostKeyboardMessage(WM_SYSCOMMAND,SC_KEYMENU,0); // This sends everything into a msg loop!
 }
 
+
 /*
- * co_IntKeyboardSendAltKeyMsg
+ * UpdateAsyncKeyState
  *
- * Sends syscommand enabling window menu
+ * Updates gafAsyncKeyState array
  */
 static
 VOID NTAPI
-co_IntKeyboardSendAltKeyMsg()
+UpdateAsyncKeyState(WORD wVk, BOOL bIsDown)
 {
-    FIXME("co_IntKeyboardSendAltKeyMsg\n");
-    //co_MsqPostKeyboardMessage(WM_SYSCOMMAND,SC_KEYMENU,0); // This sends everything into a msg loop!
+    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);
 }
 
 /*
@@ -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);
         }
-    }
 
-    if (!(pKbdInput->dwFlags & KEYEVENTF_UNICODE))
-    {
         /* Get virtual key without shifts (VK_(L|R)* -> VK_*) */
         wSimpleVk = IntSimplifyVk(wVk);
         wVkOtherSide = IntGetVkOtherSide(wVk);
-        PrevKeyState = gafAsyncKeyState[wSimpleVk];
+        bWasDown = IS_KEY_DOWN(gafAsyncKeyState, wSimpleVk);
+
+        if (xxxDoHotKeyStuff(wSimpleVk, bIsDown))
+            bPostMsg = FALSE;
 
-        /* Update global keyboard state. Begin from lock bit */
-        if (!bKeyUp && !(PrevKeyState & KS_DOWN_BIT))
-            gafAsyncKeyState[wVk] ^= KS_LOCK_BIT;
+        /* Update key without shifts */
+        UpdateAsyncKeyState(wSimpleVk, bIsDown || IS_KEY_DOWN(gafAsyncKeyState, wVkOtherSide));
+    }
 
-        /* Update down bit */
-        if (bKeyUp)
-            gafAsyncKeyState[wVk] &= ~KS_DOWN_BIT;
+    /* 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
-            gafAsyncKeyState[wVk] |= KS_DOWN_BIT;
+            Msg.message = WM_KEYUP;
+    }
 
-        /* Update key without shifts */
-        gafAsyncKeyState[wSimpleVk] = gafAsyncKeyState[wVk] | gafAsyncKeyState[wVkOtherSide];
+    /* Init hwnd and lParam */
+    Msg.hwnd = pFocusQueue->FocusWindow;
+    Msg.lParam = MAKELPARAM(1, wScanCode);
 
-        if (!bKeyUp)
+    /* 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))
+    {
+        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
+    {
+        /* 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("Couldn't copy key state from caller.\n");
+        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 */
index ead730c..7341827 100644 (file)
@@ -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 */