- 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
This commit is contained in:
Rafal Harabien 2011-10-09 20:12:12 +00:00
parent 0386650c63
commit 2a799f8ad8
7 changed files with 373 additions and 410 deletions

View 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 */

View 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)))

View 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);

View 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 (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);

View 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);

View 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_);
@ -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 */

View 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 */