ReactOS 0.4.16-dev-2300-g249be9e
keyboard.c File Reference
#include <win32k.h>
Include dependency graph for keyboard.c:

Go to the source code of this file.

Enumerations

enum  _ALTNUM_STATE { ALTNUM_INACTIVE , ALTNUM_OEM , ALTNUM_ACP }
 

Functions

 DBG_DEFAULT_CHANNEL (UserKbd)
 
NTSTATUS NTAPI InitKeyboardImpl (VOID)
 
NTSTATUS APIENTRY IntKeyboardGetIndicatorTrans (HANDLE hKeyboardDevice, PKEYBOARD_INDICATOR_TRANSLATION *ppIndicatorTrans)
 
static NTSTATUS APIENTRY IntKeyboardUpdateLeds (HANDLE hKeyboardDevice, WORD wVk, WORD wScanCode)
 
VOID NTAPI UserInitKeyboard (HANDLE hKeyboardDevice)
 
static WORD IntSimplifyVk (WORD wVk)
 
static WORD IntFixVk (WORD wVk, BOOL bExt)
 
static WORD IntTranslateNumpadKey (WORD wVk)
 
static DWORD IntGetModBits (PKBDTABLES pKbdTbl, PBYTE pKeyState)
 
static BOOL IntTranslateChar (WORD wVirtKey, PBYTE pKeyState, PBOOL pbDead, PBOOL pbLigature, PWCHAR pwcTranslatedChar, PKBDTABLES pKbdTbl)
 
static int APIENTRY IntToUnicodeEx (UINT wVirtKey, UINT wScanCode, PBYTE pKeyState, LPWSTR pwszBuff, int cchBuff, UINT wFlags, PKBDTABLES pKbdTbl)
 
static WORD FASTCALL IntVkToVsc (WORD wVk, PKBDTABLES pKbdTbl)
 
static WORD FASTCALL IntVscToVk (WORD wScanCode, PKBDTABLES pKbdTbl)
 
static WCHAR FASTCALL IntVkToChar (WORD wVk, PKBDTABLES pKbdTbl)
 
SHORT APIENTRY NtUserGetAsyncKeyState (INT Key)
 
static VOID NTAPI UpdateAsyncKeyState (WORD wVk, BOOL bIsDown)
 
static LRESULT co_CallLowLevelKeyboardHook (WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
 
static VOID SnapWindow (HWND hWnd)
 
static PKL FASTCALL IntGetNextKL (_In_ PKL pKL, _In_ BOOL bNext, _In_ BOOL bSameLang)
 
static VOID IntLanguageToggle (_In_ PUSER_MESSAGE_QUEUE pFocusQueue, _In_ BOOL bSameLang, _In_ INT nKeyState)
 
static BOOL IntCheckLanguageToggle (_In_ PUSER_MESSAGE_QUEUE pFocusQueue, _In_ BOOL bIsDown, _In_ WORD wVk, _Inout_ PINT pKeyState)
 
static BOOL IntHandleAltNumpad (_In_ WORD wVk, _In_ BOOL bIsDown, _In_ DWORD dwTime)
 Handles Alt+Numpad character composition.
 
BOOL NTAPI ProcessKeyEvent (WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
 
BOOL NTAPI UserSendKeyboardInput (KEYBDINPUT *pKbdInput, BOOL bInjected)
 
VOID NTAPI UserProcessKeyboardInput (PKEYBOARD_INPUT_DATA pKbdInputData)
 
BOOL FASTCALL IntTranslateKbdMessage (LPMSG lpMsg, UINT flags)
 
static UINT IntMapVirtualKeyEx (UINT uCode, UINT Type, PKBDTABLES pKbdTbl)
 
UINT APIENTRY NtUserMapVirtualKeyEx (UINT uCode, UINT uType, DWORD keyboardId, HKL dwhkl)
 
int APIENTRY NtUserToUnicodeEx (UINT wVirtKey, UINT wScanCode, PBYTE pKeyStateUnsafe, LPWSTR pwszBuffUnsafe, INT cchBuff, UINT wFlags, HKL dwhkl)
 
DWORD APIENTRY NtUserGetKeyNameText (LONG lParam, LPWSTR lpString, int cchSize)
 
DWORD FASTCALL UserGetKeyboardType (DWORD dwTypeFlag)
 
DWORD APIENTRY NtUserVkKeyScanEx (WCHAR wch, HKL dwhkl, BOOL bUsehKL)
 

Variables

BYTE gafAsyncKeyState [256 *2/8]
 
static BYTE gafAsyncKeyStateRecentDown [256/8]
 
static PKEYBOARD_INDICATOR_TRANSLATION gpKeyboardIndicatorTrans = NULL
 
static KEYBOARD_INDICATOR_PARAMETERS gIndicators = {0, 0}
 
KEYBOARD_ATTRIBUTES gKeyboardInfo
 
INT gLanguageToggleKeyState = 0
 
DWORD gdwLanguageToggleKey = 1
 
INT gLayoutToggleKeyState = 0
 
DWORD gdwLayoutToggleKey = 2
 
static enum _ALTNUM_STATE gAltNumPadState = ALTNUM_INACTIVE
 
static ULONG gAltNumPadValue = 0
 

Enumeration Type Documentation

◆ _ALTNUM_STATE

Enumerator
ALTNUM_INACTIVE 
ALTNUM_OEM 
ALTNUM_ACP 

Definition at line 24 of file keyboard.c.

25{
static enum _ALTNUM_STATE gAltNumPadState
@ ALTNUM_INACTIVE
Definition: keyboard.c:26
@ ALTNUM_OEM
Definition: keyboard.c:27
@ ALTNUM_ACP
Definition: keyboard.c:28

Function Documentation

◆ co_CallLowLevelKeyboardHook()

static LRESULT co_CallLowLevelKeyboardHook ( WORD  wVk,
WORD  wScanCode,
DWORD  dwFlags,
BOOL  bInjected,
DWORD  dwTime,
DWORD  dwExtraInfo 
)
static

Definition at line 699 of file keyboard.c.

700{
701 KBDLLHOOKSTRUCT KbdHookData;
702 UINT uMsg;
703
704 KbdHookData.vkCode = wVk;
705 KbdHookData.scanCode = wScanCode;
706 KbdHookData.flags = 0;
708 KbdHookData.flags |= LLKHF_EXTENDED;
710 KbdHookData.flags |= LLKHF_ALTDOWN;
712 KbdHookData.flags |= LLKHF_UP;
713 if (bInjected)
714 KbdHookData.flags |= LLKHF_INJECTED;
715 KbdHookData.time = dwTime;
716 KbdHookData.dwExtraInfo = dwExtraInfo;
717
718 /* Note: it doesnt support WM_SYSKEYUP */
720 uMsg = WM_KEYUP;
722 uMsg = WM_SYSKEYDOWN;
723 else
724 uMsg = WM_KEYDOWN;
725
726 return co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, uMsg, (LPARAM)&KbdHookData);
727}
LONG_PTR LPARAM
Definition: minwindef.h:175
unsigned int UINT
Definition: ndis.h:50
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
LRESULT APIENTRY co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
Definition: hook.c:1102
DWORD dwTime
Definition: solitaire.cpp:27
ULONG_PTR dwExtraInfo
Definition: winuser.h:3914
#define IS_KEY_DOWN(ks, vk)
Definition: input.h:103
BYTE gafAsyncKeyState[256 *2/8]
Definition: keyboard.c:13
#define WM_KEYUP
Definition: winuser.h:1744
#define LLKHF_EXTENDED
Definition: winuser.h:2687
#define VK_CONTROL
Definition: winuser.h:2239
#define HC_ACTION
Definition: winuser.h:48
#define LLKHF_ALTDOWN
Definition: winuser.h:2689
#define LLKHF_UP
Definition: winuser.h:2690
#define WH_KEYBOARD_LL
Definition: winuser.h:43
#define LLKHF_INJECTED
Definition: winuser.h:2688
#define KEYEVENTF_EXTENDEDKEY
Definition: winuser.h:1112
#define WM_KEYDOWN
Definition: winuser.h:1743
#define KEYEVENTF_KEYUP
Definition: winuser.h:1113
#define WM_SYSKEYDOWN
Definition: winuser.h:1747
#define VK_MENU
Definition: winuser.h:2240

Referenced by ProcessKeyEvent().

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( UserKbd  )

◆ InitKeyboardImpl()

NTSTATUS NTAPI InitKeyboardImpl ( VOID  )

Definition at line 43 of file keyboard.c.

44{
47 // Clear and set default information.
49 gKeyboardInfo.KeyboardIdentifier.Type = 4; /* AT-101 */
50 gKeyboardInfo.NumberOfFunctionKeys = 12; /* We're doing an 101 for now, so return 12 F-keys */
51 return STATUS_SUCCESS;
52}
#define STATUS_SUCCESS
Definition: shellext.h:65
KEYBOARD_ID KeyboardIdentifier
Definition: ntddkbd.h:124
USHORT NumberOfFunctionKeys
Definition: ntddkbd.h:126
UCHAR Type
Definition: ntddkbd.h:101
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
KEYBOARD_ATTRIBUTES gKeyboardInfo
Definition: keyboard.c:17
static BYTE gafAsyncKeyStateRecentDown[256/8]
Definition: keyboard.c:14

Referenced by DriverEntry().

◆ IntCheckLanguageToggle()

static BOOL IntCheckLanguageToggle ( _In_ PUSER_MESSAGE_QUEUE  pFocusQueue,
_In_ BOOL  bIsDown,
_In_ WORD  wVk,
_Inout_ PINT  pKeyState 
)
static

Definition at line 866 of file keyboard.c.

871{
872 if (bIsDown) /* Toggle key combination is pressed? */
873 {
874 if (wVk == VK_LSHIFT)
875 *pKeyState = INPUTLANGCHANGE_FORWARD;
876 else if (wVk == VK_RSHIFT)
877 *pKeyState = INPUTLANGCHANGE_BACKWARD;
878 else if (!wVk && IS_KEY_DOWN(gafAsyncKeyState, VK_LSHIFT))
879 *pKeyState = INPUTLANGCHANGE_FORWARD;
880 else if (!wVk && IS_KEY_DOWN(gafAsyncKeyState, VK_RSHIFT))
881 *pKeyState = INPUTLANGCHANGE_BACKWARD;
882 else
883 return FALSE;
884 }
885 else
886 {
887 if (*pKeyState == 0)
888 return FALSE;
889
890 IntLanguageToggle(pFocusQueue, (pKeyState == &gLayoutToggleKeyState), *pKeyState);
891 *pKeyState = 0;
892 }
893 return TRUE;
894}
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
INT gLayoutToggleKeyState
Definition: keyboard.c:20
static VOID IntLanguageToggle(_In_ PUSER_MESSAGE_QUEUE pFocusQueue, _In_ BOOL bSameLang, _In_ INT nKeyState)
Definition: keyboard.c:829
#define VK_RSHIFT
Definition: winuser.h:2319
#define VK_LSHIFT
Definition: winuser.h:2318

Referenced by ProcessKeyEvent().

◆ IntFixVk()

static WORD IntFixVk ( WORD  wVk,
BOOL  bExt 
)
static

Definition at line 259 of file keyboard.c.

260{
261 switch (wVk)
262 {
263 case VK_SHIFT:
264 return bExt ? VK_RSHIFT : VK_LSHIFT;
265
266 case VK_CONTROL:
267 return bExt ? VK_RCONTROL : VK_LCONTROL;
268
269 case VK_MENU:
270 return bExt ? VK_RMENU : VK_LMENU;
271
272 default:
273 return wVk;
274 }
275}
#define VK_LCONTROL
Definition: winuser.h:2320
#define VK_RCONTROL
Definition: winuser.h:2321
#define VK_RMENU
Definition: winuser.h:2323
#define VK_SHIFT
Definition: winuser.h:2238
#define VK_LMENU
Definition: winuser.h:2322

Referenced by IntMapVirtualKeyEx(), and ProcessKeyEvent().

◆ IntGetModBits()

static DWORD IntGetModBits ( PKBDTABLES  pKbdTbl,
PBYTE  pKeyState 
)
static

Definition at line 310 of file keyboard.c.

311{
312 DWORD i, dwModBits = 0;
313
314 /* DumpKeyState( KeyState ); */
315
316 for (i = 0; pKbdTbl->pCharModifiers->pVkToBit[i].Vk; i++)
317 if (IS_KEY_DOWN(pKeyState, pKbdTbl->pCharModifiers->pVkToBit[i].Vk))
318 dwModBits |= pKbdTbl->pCharModifiers->pVkToBit[i].ModBits;
319
320 TRACE("Current Mod Bits: %lx\n", dwModBits);
321
322 return dwModBits;
323}
unsigned long DWORD
Definition: ntddk_ex.h:95
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define TRACE(s)
Definition: solgame.cpp:4
PMODIFIERS pCharModifiers
Definition: kbd.h:96
PVK_TO_BIT pVkToBit
Definition: kbd.h:27
BYTE ModBits
Definition: kbd.h:23
BYTE Vk
Definition: kbd.h:22

Referenced by IntTranslateChar().

◆ IntGetNextKL()

static PKL FASTCALL IntGetNextKL ( _In_ PKL  pKL,
_In_ BOOL  bNext,
_In_ BOOL  bSameLang 
)
static

Definition at line 808 of file keyboard.c.

812{
813 PKL pFirstKL = pKL;
814 LANGID LangID = LOWORD(pKL->hkl);
815
816 do
817 {
818 pKL = (bNext ? pKL->pklNext : pKL->pklPrev);
819
820 if (!(pKL->dwKL_Flags & KL_UNLOAD) && bSameLang == (LangID == LOWORD(pKL->hkl)))
821 return pKL;
822 } while (pKL != pFirstKL);
823
824 return pFirstKL;
825}
USHORT LANGID
Definition: mui.h:9
#define LOWORD(l)
Definition: pedump.c:82
Definition: input.h:27
#define KL_UNLOAD
Definition: undocuser.h:183
_Must_inspect_result_ _In_ WDFUSBDEVICE _In_opt_ WDFREQUEST _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_writes_opt_ NumCharacters PUSHORT _Inout_ PUSHORT _In_ UCHAR _In_opt_ USHORT LangID
Definition: wdfusb.h:1083

Referenced by IntLanguageToggle().

◆ IntHandleAltNumpad()

static BOOL IntHandleAltNumpad ( _In_ WORD  wVk,
_In_ BOOL  bIsDown,
_In_ DWORD  dwTime 
)
static

Handles Alt+Numpad character composition.

Parameters
[in]wVkThe virtual key code of the key being input, in its "simplified" shift-less version, as given by IntSimplifyVk().
[in]bIsDownTRUE if the current key is being pressed; FALSE if it is released.
Returns
TRUE if no further key processing needs to be done; FALSE if regular key processing has to be done by the caller.

Definition at line 911 of file keyboard.c.

916{
917 // TODO: Handle Unicode characters.
918 if (bIsDown &&
921 {
922 TRACE("VK_MENU && !VK_CONTROL - wVk: 0x%04x\n", wVk);
923
924 /* Check if the incoming key is a numpad digit */
925 if (wVk >= VK_NUMPAD0 && wVk <= VK_NUMPAD9)
926 {
927 UINT uDigit = wVk - VK_NUMPAD0;
928
929 /* Initialize the Alt+Numpad state if necessary */
931 gAltNumPadState = (uDigit == 0) ? ALTNUM_ACP : ALTNUM_OEM;
932
933 /* Build the decimal value; the value can overflow
934 * and be truncated (same behaviour as on Windows) */
935 gAltNumPadValue = (gAltNumPadValue * 10) + uDigit;
936
937 return TRUE; /* No key processing needs to be done */
938 }
939 /* Check if the incoming key is not the menu key itself/alone */
940 else if (wVk != VK_MENU)
941 {
942 /* Reset the Alt+Numpad state */
944 gAltNumPadValue = 0;
945 }
946 }
947 TRACE("gAltNumPadState: %lu, gAltNumPadValue: %lu\n",
949
950 /* Check for the end of an Alt+Numpad sequence, triggered by the release of the ALT key */
951 if ((gAltNumPadState != ALTNUM_INACTIVE) && !bIsDown && (wVk == VK_MENU))
952 {
954
955 TRACE("End of Alt+Numpad\n");
956 if (gAltNumPadValue != 0 && pFocusQueue && pFocusQueue->ptiKeyboard)
957 {
959 WCHAR wchUnicodeChar;
960 /*
961 * NOTE: the input value is considered modulo 256, because it
962 * is stored to a 1-byte CHAR. Other applications that hook and
963 * reimplement the Alt+Numpad system (e.g. WordPad, ...) store
964 * the value instead in a 2-byte WORD, hence they consider the
965 * value modulo 65536.
966 * See: https://devblogs.microsoft.com/oldnewthing/20240702-00/?p=109951
967 */
968 CHAR cAnsiChar = (CHAR)(gAltNumPadValue & 0xFF);
969
970 /* Convert the input character value to Unicode */
972 {
973 /* Use the OEM->Unicode function */
974 Status = RtlOemToUnicodeN(&wchUnicodeChar,
975 sizeof(wchUnicodeChar),
976 NULL,
977 &cAnsiChar,
978 sizeof(cAnsiChar));
979 }
980 else if (gAltNumPadState == ALTNUM_ACP)
981 {
982 /* The sequence started with '0', use the ANSI codepage
983 * (ACP)-aware MultiByte->Unicode function */
984 Status = RtlMultiByteToUnicodeN(&wchUnicodeChar,
985 sizeof(wchUnicodeChar),
986 NULL,
987 &cAnsiChar,
988 sizeof(cAnsiChar));
989 }
990
991 /* Post the Unicode character to the focused message queue if conversion succeeded */
992 if (NT_SUCCESS(Status))
993 {
994 MSG msgChar;
995 msgChar.hwnd = pFocusQueue->spwndFocus ? UserHMGetHandle(pFocusQueue->spwndFocus) : NULL;
996 msgChar.message = WM_CHAR;
997 msgChar.wParam = wchUnicodeChar;
998 msgChar.lParam = 1;
999 msgChar.time = dwTime;
1000 msgChar.pt = gpsi->ptCursor;
1001
1002 MsqPostMessage(pFocusQueue->ptiKeyboard, &msgChar, FALSE, QS_KEY, 0, 0);
1003 }
1004 }
1005
1006 /* Reset the Alt+Numpad state */
1008 gAltNumPadValue = 0;
1009 }
1010
1011 return FALSE; /* More key processing has to be done */
1012}
LONG NTSTATUS
Definition: precomp.h:26
#define CHAR(Char)
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
Status
Definition: gdiplustypes.h:25
PSERVERINFO gpsi
Definition: imm.c:18
#define UserHMGetHandle(obj)
Definition: ntuser.h:230
VOID FASTCALL MsqPostMessage(PTHREADINFO pti, MSG *Msg, BOOLEAN HardwareMessage, DWORD MessageBits, DWORD dwQEvent, LONG_PTR ExtraInfo)
Definition: msgqueue.c:1337
_Use_decl_annotations_ NTSTATUS NTAPI RtlMultiByteToUnicodeN(_Out_ PWCH UnicodeString, _In_ ULONG UnicodeSize, _Out_opt_ PULONG ResultSize, _In_ PCCH MbString, _In_ ULONG MbSize)
Definition: nlsboot.c:62
_Use_decl_annotations_ NTSTATUS NTAPI RtlOemToUnicodeN(_Out_ PWCHAR UnicodeString, _In_ ULONG UnicodeSize, _Out_opt_ PULONG ResultSize, _In_ PCCH OemString, _In_ ULONG OemSize)
Definition: nlsboot.c:282
PTHREADINFO ptiKeyboard
Definition: msgqueue.h:56
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
PUSER_MESSAGE_QUEUE FASTCALL IntGetFocusMessageQueue(VOID)
Definition: desktop.c:1324
static ULONG gAltNumPadValue
Definition: keyboard.c:31
#define QS_KEY
Definition: winuser.h:885
#define VK_NUMPAD0
Definition: winuser.h:2275
#define VK_NUMPAD9
Definition: winuser.h:2284
#define WM_CHAR
Definition: winuser.h:1745
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175

Referenced by ProcessKeyEvent().

◆ IntKeyboardGetIndicatorTrans()

NTSTATUS APIENTRY IntKeyboardGetIndicatorTrans ( HANDLE  hKeyboardDevice,
PKEYBOARD_INDICATOR_TRANSLATION ppIndicatorTrans 
)

Definition at line 62 of file keyboard.c.

64{
66 DWORD dwSize = 0;
67 IO_STATUS_BLOCK Block;
69
71
73 dwSize,
75
76 while (pRet)
77 {
78 Status = ZwDeviceIoControlFile(hKeyboardDevice,
79 NULL,
80 NULL,
81 NULL,
82 &Block,
84 NULL, 0,
85 pRet, dwSize);
86
88 break;
89
91
93
95 dwSize,
97 }
98
99 if (!pRet)
101
102 if (!NT_SUCCESS(Status))
103 {
105 return Status;
106 }
107
108 *ppIndicatorTrans = pRet;
109 return Status;
110}
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
struct _KEYBOARD_INDICATOR_TRANSLATION KEYBOARD_INDICATOR_TRANSLATION
#define IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION
Definition: ntddkbd.h:38
NTSYSAPI NTSTATUS NTAPI ZwDeviceIoControlFile(IN HANDLE DeviceHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, IN PVOID UserApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG IoControlCode, IN PVOID InputBuffer, IN ULONG InputBufferSize, OUT PVOID OutputBuffer, IN ULONG OutputBufferSize)
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define USERTAG_KBDTABLE
Definition: tags.h:247

Referenced by UserInitKeyboard().

◆ IntKeyboardUpdateLeds()

static NTSTATUS APIENTRY IntKeyboardUpdateLeds ( HANDLE  hKeyboardDevice,
WORD  wVk,
WORD  wScanCode 
)
static

Definition at line 119 of file keyboard.c.

122{
124 UINT i;
125 USHORT LedFlag = 0;
126 IO_STATUS_BLOCK Block;
127
130
131 switch (wVk)
132 {
133 case VK_CAPITAL: LedFlag = KEYBOARD_CAPS_LOCK_ON; break;
134 case VK_NUMLOCK: LedFlag = KEYBOARD_NUM_LOCK_ON; break;
135 case VK_SCROLL: LedFlag = KEYBOARD_SCROLL_LOCK_ON; break;
136 default:
138 {
140 {
142 break;
143 }
144 }
145 }
146
147 if (LedFlag)
148 {
149 gIndicators.LedFlags ^= LedFlag;
150
151 /* Update the lights on the hardware */
152 Status = ZwDeviceIoControlFile(hKeyboardDevice,
153 NULL,
154 NULL,
155 NULL,
156 &Block,
158 &gIndicators, sizeof(gIndicators),
159 NULL, 0);
160
161 return Status;
162 }
163
164 return STATUS_SUCCESS;
165}
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define KEYBOARD_CAPS_LOCK_ON
Definition: ntddkbd.h:81
#define IOCTL_KEYBOARD_SET_INDICATORS
Definition: ntddkbd.h:47
#define KEYBOARD_SCROLL_LOCK_ON
Definition: ntddkbd.h:83
#define KEYBOARD_NUM_LOCK_ON
Definition: ntddkbd.h:82
unsigned short USHORT
Definition: pedump.c:61
USHORT IndicatorFlags
Definition: ntddkbd.h:115
USHORT MakeCode
Definition: ntddkbd.h:114
INDICATOR_LIST IndicatorList[1]
Definition: ntddkbd.h:120
static KEYBOARD_INDICATOR_PARAMETERS gIndicators
Definition: keyboard.c:16
static PKEYBOARD_INDICATOR_TRANSLATION gpKeyboardIndicatorTrans
Definition: keyboard.c:15
#define VK_CAPITAL
Definition: winuser.h:2242
#define VK_SCROLL
Definition: winuser.h:2316
#define VK_NUMLOCK
Definition: winuser.h:2315

Referenced by ProcessKeyEvent().

◆ IntLanguageToggle()

static VOID IntLanguageToggle ( _In_ PUSER_MESSAGE_QUEUE  pFocusQueue,
_In_ BOOL  bSameLang,
_In_ INT  nKeyState 
)
static

Definition at line 829 of file keyboard.c.

833{
834 PWND pWnd;
835 PTHREADINFO pti;
836 PKL pkl;
837 WPARAM wParam = 0;
838
839 if (!pFocusQueue)
840 {
841 ERR("IntLanguageToggle(): NULL pFocusQueue\n");
842 return;
843 }
844 pWnd = pFocusQueue->spwndFocus;
845 if (!pWnd)
846 pWnd = pFocusQueue->spwndActive;
847 if (!pWnd)
848 return;
849
850 pti = pWnd->head.pti;
851 pkl = pti->KeyboardLayout;
852
853 if (nKeyState == INPUTLANGCHANGE_FORWARD)
854 pkl = IntGetNextKL(pkl, TRUE, bSameLang);
855 else if (nKeyState == INPUTLANGCHANGE_BACKWARD)
856 pkl = IntGetNextKL(pkl, FALSE, bSameLang);
857
858 if (gSystemFS & pkl->dwFontSigs)
859 wParam |= INPUTLANGCHANGE_SYSCHARSET;
860
861 UserPostMessage(UserHMGetHandle(pWnd), WM_INPUTLANGCHANGEREQUEST, wParam, (LPARAM)pkl->hkl);
862}
#define ERR(fmt,...)
Definition: precomp.h:57
WPARAM wParam
Definition: combotst.c:138
UINT_PTR WPARAM
Definition: minwindef.h:174
struct tagKL * KeyboardLayout
Definition: win32.h:90
Definition: ntuser.h:694
THRDESKHEAD head
Definition: ntuser.h:695
DWORD dwFontSigs
Definition: input.h:34
HKL hkl
Definition: input.h:32
DWORD gSystemFS
Definition: kbdlayout.c:24
static PKL FASTCALL IntGetNextKL(_In_ PKL pKL, _In_ BOOL bNext, _In_ BOOL bSameLang)
Definition: keyboard.c:808
BOOL FASTCALL UserPostMessage(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1395

Referenced by IntCheckLanguageToggle().

◆ IntMapVirtualKeyEx()

static UINT IntMapVirtualKeyEx ( UINT  uCode,
UINT  Type,
PKBDTABLES  pKbdTbl 
)
static

Definition at line 1529 of file keyboard.c.

1530{
1531 UINT uRet = 0;
1532
1533 switch (Type)
1534 {
1535 case MAPVK_VK_TO_VSC:
1536 uCode = IntFixVk(uCode, FALSE);
1537 uRet = IntVkToVsc(uCode, pKbdTbl);
1538 if (uRet > 0xFF) // Fail for scancodes with prefix (e0, e1)
1539 uRet = 0;
1540 break;
1541
1542 case MAPVK_VSC_TO_VK:
1543 uRet = IntVscToVk(uCode, pKbdTbl) & 0xFF;
1544 uRet = IntSimplifyVk(uRet);
1545 break;
1546
1547 case MAPVK_VK_TO_CHAR:
1548 uRet = (UINT)IntVkToChar(uCode, pKbdTbl);
1549 break;
1550
1551 case MAPVK_VSC_TO_VK_EX:
1552 uRet = IntVscToVk(uCode, pKbdTbl) & 0xFF;
1553 break;
1554
1555 case MAPVK_VK_TO_VSC_EX:
1556 uRet = IntVkToVsc(uCode, pKbdTbl);
1557 break;
1558
1559 default:
1561 ERR("Wrong type value: %u\n", Type);
1562 }
1563
1564 return uRet;
1565}
Type
Definition: Type.h:7
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
static WORD IntFixVk(WORD wVk, BOOL bExt)
Definition: keyboard.c:259
static WCHAR FASTCALL IntVkToChar(WORD wVk, PKBDTABLES pKbdTbl)
Definition: keyboard.c:617
static WORD FASTCALL IntVkToVsc(WORD wVk, PKBDTABLES pKbdTbl)
Definition: keyboard.c:537
static WORD FASTCALL IntVscToVk(WORD wScanCode, PKBDTABLES pKbdTbl)
Definition: keyboard.c:574
static WORD IntSimplifyVk(WORD wVk)
Definition: keyboard.c:231
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:22
#define MAPVK_VSC_TO_VK_EX
Definition: winuser.h:2394
#define MAPVK_VSC_TO_VK
Definition: winuser.h:2392
#define MAPVK_VK_TO_CHAR
Definition: winuser.h:2393
#define MAPVK_VK_TO_VSC
Definition: winuser.h:2391
#define MAPVK_VK_TO_VSC_EX
Definition: winuser.h:2395

Referenced by NtUserMapVirtualKeyEx().

◆ IntSimplifyVk()

static WORD IntSimplifyVk ( WORD  wVk)
static

Definition at line 231 of file keyboard.c.

232{
233 switch (wVk)
234 {
235 case VK_LSHIFT:
236 case VK_RSHIFT:
237 return VK_SHIFT;
238
239 case VK_LCONTROL:
240 case VK_RCONTROL:
241 return VK_CONTROL;
242
243 case VK_LMENU:
244 case VK_RMENU:
245 return VK_MENU;
246
247 default:
248 return wVk;
249 }
250}

Referenced by IntMapVirtualKeyEx(), and ProcessKeyEvent().

◆ IntToUnicodeEx()

static int APIENTRY IntToUnicodeEx ( UINT  wVirtKey,
UINT  wScanCode,
PBYTE  pKeyState,
LPWSTR  pwszBuff,
int  cchBuff,
UINT  wFlags,
PKBDTABLES  pKbdTbl 
)
static

Definition at line 444 of file keyboard.c.

451{
452 WCHAR wchTranslatedChar;
453 BOOL bDead, bLigature;
454 static WCHAR wchDead = 0;
455 int iRet = 0;
456
457 ASSERT(pKbdTbl);
458
459 if (!IntTranslateChar(wVirtKey,
460 pKeyState,
461 &bDead,
462 &bLigature,
463 &wchTranslatedChar,
464 pKbdTbl))
465 {
466 return 0;
467 }
468
469 if (bLigature)
470 {
471 WARN("Not handling ligature (yet)\n" );
472 return 0;
473 }
474
475 /* If we got dead char in previous call check dead keys in keyboard layout */
476 if (wchDead)
477 {
478 UINT i;
479 WCHAR wchFirst, wchSecond;
480 TRACE("Previous dead char: %lc (%x)\n", wchDead, wchDead);
481
482 if (pKbdTbl->pDeadKey)
483 {
484 for (i = 0; pKbdTbl->pDeadKey[i].dwBoth; i++)
485 {
486 wchFirst = pKbdTbl->pDeadKey[i].dwBoth >> 16;
487 wchSecond = pKbdTbl->pDeadKey[i].dwBoth & 0xFFFF;
488 if (wchFirst == wchDead && wchSecond == wchTranslatedChar)
489 {
490 wchTranslatedChar = pKbdTbl->pDeadKey[i].wchComposed;
491 wchDead = 0;
492 bDead = FALSE;
493 break;
494 }
495 }
496 }
497 else
498 {
499#if defined(__GNUC__)
500 if (wchDead == 0x8000)
501 {
502 ERR("GCC is inventing bits, ignoring fake dead key\n");
503 wchDead = 0;
504 }
505#endif
506 }
507
508 TRACE("Final char: %lc (%x)\n", wchTranslatedChar, wchTranslatedChar);
509 }
510
511 /* Dead char has not been not found */
512 if (wchDead)
513 {
514 /* Treat both characters normally */
515 if (cchBuff > iRet)
516 pwszBuff[iRet++] = wchDead;
517 bDead = FALSE;
518 }
519
520 /* Add character to the buffer */
521 if (cchBuff > iRet)
522 pwszBuff[iRet++] = wchTranslatedChar;
523
524 /* Save dead character */
525 wchDead = bDead ? wchTranslatedChar : 0;
526
527 return bDead ? -iRet : iRet;
528}
#define WARN(fmt,...)
Definition: precomp.h:61
unsigned int BOOL
Definition: ntddk_ex.h:94
#define ASSERT(a)
Definition: mode.c:44
WCHAR wchComposed
Definition: kbd.h:58
DWORD dwBoth
Definition: kbd.h:57
PDEADKEY pDeadKey
Definition: kbd.h:98
static BOOL IntTranslateChar(WORD wVirtKey, PBYTE pKeyState, PBOOL pbDead, PBOOL pbLigature, PWCHAR pwcTranslatedChar, PKBDTABLES pKbdTbl)
Definition: keyboard.c:332

Referenced by IntTranslateKbdMessage(), and NtUserToUnicodeEx().

◆ IntTranslateChar()

static BOOL IntTranslateChar ( WORD  wVirtKey,
PBYTE  pKeyState,
PBOOL  pbDead,
PBOOL  pbLigature,
PWCHAR  pwcTranslatedChar,
PKBDTABLES  pKbdTbl 
)
static

Definition at line 332 of file keyboard.c.

338{
339 PVK_TO_WCHAR_TABLE pVkToVchTbl;
340 PVK_TO_WCHARS10 pVkToVch;
341 DWORD i, dwModBits, dwVkModBits, dwModNumber = 0;
342 WCHAR wch;
343 BOOL bAltGr;
344 WORD wCaplokAttr;
345
346 dwModBits = pKeyState ? IntGetModBits(pKbdTbl, pKeyState) : 0;
347 bAltGr = pKeyState && (pKbdTbl->fLocaleFlags & KLLF_ALTGR) && IS_KEY_DOWN(pKeyState, VK_RMENU);
348 wCaplokAttr = bAltGr ? CAPLOKALTGR : CAPLOK;
349
350 TRACE("TryToTranslate: %04x %x\n", wVirtKey, dwModBits);
351
352 /* If ALT without CTRL has ben used, remove ALT flag */
353 if ((dwModBits & (KBDALT|KBDCTRL)) == KBDALT)
354 dwModBits &= ~KBDALT;
355
356 if (dwModBits > pKbdTbl->pCharModifiers->wMaxModBits)
357 {
358 TRACE("dwModBits %x > wMaxModBits %x\n", dwModBits, pKbdTbl->pCharModifiers->wMaxModBits);
359 return FALSE;
360 }
361
362 for (i = 0; pKbdTbl->pVkToWcharTable[i].pVkToWchars; i++)
363 {
364 pVkToVchTbl = &pKbdTbl->pVkToWcharTable[i];
365 pVkToVch = (PVK_TO_WCHARS10)(pVkToVchTbl->pVkToWchars);
366 while (pVkToVch->VirtualKey)
367 {
368 if (wVirtKey == (pVkToVch->VirtualKey & 0xFF))
369 {
370 dwVkModBits = dwModBits;
371
372 /* If CapsLock is enabled for this key and locked, add SHIFT bit */
373 if ((pVkToVch->Attributes & wCaplokAttr) &&
374 pKeyState &&
375 IS_KEY_LOCKED(pKeyState, VK_CAPITAL))
376 {
377 /* Note: we use special value here instead of getting VK_SHIFT mod bit - it's verified */
378 dwVkModBits ^= KBDSHIFT;
379 }
380
381 if (dwVkModBits > pKbdTbl->pCharModifiers->wMaxModBits)
382 break;
383
384 /* Get modification number */
385 dwModNumber = pKbdTbl->pCharModifiers->ModNumber[dwVkModBits];
386 if (dwModNumber >= pVkToVchTbl->nModifications)
387 {
388 TRACE("dwModNumber %u >= nModifications %u\n", dwModNumber, pVkToVchTbl->nModifications);
389 break;
390 }
391
392 /* Read character */
393 wch = pVkToVch->wch[dwModNumber];
394 if (wch == WCH_NONE)
395 break;
396
397 *pbDead = (wch == WCH_DEAD);
398 *pbLigature = (wch == WCH_LGTR);
399 *pwcTranslatedChar = wch;
400
401 TRACE("%lu %04x: dwModNumber %08x Char %04x\n",
402 i, wVirtKey, dwModNumber, wch);
403
404 if (*pbDead)
405 {
406 /* After WCH_DEAD, real character is located */
407 pVkToVch = (PVK_TO_WCHARS10)(((BYTE *)pVkToVch) + pVkToVchTbl->cbSize);
408 if (pVkToVch->VirtualKey != 0xFF)
409 {
410 WARN("Found dead key with no trailer in the table.\n");
411 WARN("VK: %04x, ADDR: %p\n", wVirtKey, pVkToVch);
412 break;
413 }
414 *pwcTranslatedChar = pVkToVch->wch[dwModNumber];
415 }
416 return TRUE;
417 }
418 pVkToVch = (PVK_TO_WCHARS10)(((BYTE *)pVkToVch) + pVkToVchTbl->cbSize);
419 }
420 }
421
422 /* If nothing has been found in layout, check if this is ASCII control character.
423 Note: we could add it to layout table, but windows does not have it there */
424 if (wVirtKey >= 'A' && wVirtKey <= 'Z' &&
425 pKeyState && IS_KEY_DOWN(pKeyState, VK_CONTROL) &&
426 !IS_KEY_DOWN(pKeyState, VK_MENU))
427 {
428 *pwcTranslatedChar = (wVirtKey - 'A') + 1; /* ASCII control character */
429 *pbDead = FALSE;
430 *pbLigature = FALSE;
431 return TRUE;
432 }
433
434 return FALSE;
435}
unsigned short WORD
Definition: ntddk_ex.h:93
#define WCH_DEAD
Definition: kbd.h:114
#define CAPLOK
Definition: kbd.h:118
#define WCH_LGTR
Definition: kbd.h:115
#define KBDALT
Definition: kbd.h:16
#define WCH_NONE
Definition: kbd.h:113
#define CAPLOKALTGR
Definition: kbd.h:120
#define KBDCTRL
Definition: kbd.h:15
#define KLLF_ALTGR
Definition: kbd.h:91
#define KBDSHIFT
Definition: kbd.h:14
PVK_TO_WCHAR_TABLE pVkToWcharTable
Definition: kbd.h:97
DWORD fLocaleFlags
Definition: kbd.h:106
WORD wMaxModBits
Definition: kbd.h:28
BYTE ModNumber[]
Definition: kbd.h:29
BYTE cbSize
Definition: kbd.h:53
PVK_TO_WCHARS1 pVkToWchars
Definition: kbd.h:51
BYTE nModifications
Definition: kbd.h:52
#define IS_KEY_LOCKED(ks, vk)
Definition: input.h:104
static DWORD IntGetModBits(PKBDTABLES pKbdTbl, PBYTE pKeyState)
Definition: keyboard.c:310
unsigned char BYTE
Definition: xxhash.c:193

Referenced by IntToUnicodeEx(), and IntVkToChar().

◆ IntTranslateKbdMessage()

BOOL FASTCALL IntTranslateKbdMessage ( LPMSG  lpMsg,
UINT  flags 
)

Definition at line 1412 of file keyboard.c.

1414{
1415 PTHREADINFO pti;
1416 INT cch = 0, i;
1417 WCHAR wch[3] = { 0 };
1418 MSG NewMsg = { 0 };
1419 PKBDTABLES pKbdTbl;
1420 BOOL bResult = FALSE;
1421
1422 switch(lpMsg->message)
1423 {
1424 case WM_KEYDOWN:
1425 case WM_KEYUP:
1426 case WM_SYSKEYDOWN:
1427 case WM_SYSKEYUP:
1428 break;
1429 default:
1430 return FALSE;
1431 }
1432
1434
1435 if (!pti->KeyboardLayout)
1436 {
1437 PKL pDefKL = W32kGetDefaultKeyLayout();
1438 UserAssignmentLock((PVOID*)&(pti->KeyboardLayout), pDefKL);
1439 if (pDefKL)
1440 {
1441 pti->pClientInfo->hKL = pDefKL->hkl;
1442 pKbdTbl = pDefKL->spkf->pKbdTbl;
1443 }
1444 else
1445 {
1446 pti->pClientInfo->hKL = NULL;
1447 pKbdTbl = NULL;
1448 }
1449 }
1450 else
1451 pKbdTbl = pti->KeyboardLayout->spkf->pKbdTbl;
1452 if (!pKbdTbl)
1453 return FALSE;
1454
1455 if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN)
1456 return FALSE;
1457
1458 /* Init pt, hwnd and time msg fields */
1459 NewMsg.pt = gpsi->ptCursor;
1460 NewMsg.hwnd = lpMsg->hwnd;
1461 NewMsg.time = EngGetTickCount32();
1462
1463 TRACE("Enter IntTranslateKbdMessage msg %s, vk %x\n",
1464 lpMsg->message == WM_SYSKEYDOWN ? "WM_SYSKEYDOWN" : "WM_KEYDOWN", lpMsg->wParam);
1465
1466 if (lpMsg->wParam == VK_PACKET)
1467 {
1468 NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
1469 NewMsg.wParam = HIWORD(lpMsg->lParam);
1470 NewMsg.lParam = LOWORD(lpMsg->lParam);
1471 MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0, 0);
1472 return TRUE;
1473 }
1474
1475 cch = IntToUnicodeEx(lpMsg->wParam,
1476 HIWORD(lpMsg->lParam) & 0xFF,
1477 pti->MessageQueue->afKeyState,
1478 wch,
1479 sizeof(wch) / sizeof(wch[0]),
1480 0,
1481 pKbdTbl);
1482
1483 if (cch)
1484 {
1485 if (cch > 0) /* Normal characters */
1486 NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
1487 else /* Dead character */
1488 {
1489 cch = -cch;
1490 NewMsg.message =
1492 }
1493 NewMsg.lParam = lpMsg->lParam;
1494
1495 /* Send all characters */
1496 for (i = 0; i < cch; ++i)
1497 {
1498 TRACE("Msg: %x '%lc' (%04x) %08x\n", NewMsg.message, wch[i], wch[i], NewMsg.lParam);
1499 NewMsg.wParam = wch[i];
1500 MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0, 0);
1501 }
1502 bResult = TRUE;
1503 }
1504
1505 TRACE("Leave IntTranslateKbdMessage ret %d, cch %d, msg %x, wch %x\n",
1506 bResult, cch, NewMsg.message, NewMsg.wParam);
1507 return bResult;
1508}
#define EngGetTickCount32()
Definition: eng.h:43
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
_In_ UINT _In_ UINT cch
Definition: shellapi.h:432
Definition: kbd.h:95
struct _CLIENTINFO * pClientInfo
Definition: win32.h:94
struct _USER_MESSAGE_QUEUE * MessageQueue
Definition: win32.h:89
struct _KBDTABLES * pKbdTbl
Definition: input.h:21
PKBDFILE spkf
Definition: input.h:33
UINT message
Definition: winuser.h:3217
HWND hwnd
Definition: winuser.h:3216
WPARAM wParam
Definition: winuser.h:3218
LPARAM lParam
Definition: winuser.h:3219
int32_t INT
Definition: typedefs.h:58
#define HIWORD(l)
Definition: typedefs.h:247
PKL W32kGetDefaultKeyLayout(VOID)
Definition: kbdlayout.c:512
static int APIENTRY IntToUnicodeEx(UINT wVirtKey, UINT wScanCode, PBYTE pKeyState, LPWSTR pwszBuff, int cchBuff, UINT wFlags, PKBDTABLES pKbdTbl)
Definition: keyboard.c:444
PVOID FASTCALL UserAssignmentLock(PVOID *ppvObj, PVOID pvNew)
Definition: object.c:839
#define WM_SYSCHAR
Definition: winuser.h:1749
#define WM_SYSDEADCHAR
Definition: winuser.h:1750
#define WM_SYSKEYUP
Definition: winuser.h:1748
#define WM_DEADCHAR
Definition: winuser.h:1746

Referenced by DefWndDoSizeMove(), DefWndStartSizeMove(), MENU_TrackMenu(), and NtUserTranslateMessage().

◆ IntTranslateNumpadKey()

static WORD IntTranslateNumpadKey ( WORD  wVk)
static

Definition at line 284 of file keyboard.c.

285{
286 switch (wVk)
287 {
288 case VK_INSERT: return VK_NUMPAD0;
289 case VK_END: return VK_NUMPAD1;
290 case VK_DOWN: return VK_NUMPAD2;
291 case VK_NEXT: return VK_NUMPAD3;
292 case VK_LEFT: return VK_NUMPAD4;
293 case VK_CLEAR: return VK_NUMPAD5;
294 case VK_RIGHT: return VK_NUMPAD6;
295 case VK_HOME: return VK_NUMPAD7;
296 case VK_UP: return VK_NUMPAD8;
297 case VK_PRIOR: return VK_NUMPAD9;
298 case VK_DELETE: return VK_DECIMAL;
299 default: return wVk;
300 }
301}
#define VK_CLEAR
Definition: winuser.h:2236
#define VK_NUMPAD3
Definition: winuser.h:2278
#define VK_NUMPAD1
Definition: winuser.h:2276
#define VK_NUMPAD2
Definition: winuser.h:2277
#define VK_NUMPAD4
Definition: winuser.h:2279
#define VK_UP
Definition: winuser.h:2261
#define VK_NUMPAD6
Definition: winuser.h:2281
#define VK_NEXT
Definition: winuser.h:2257
#define VK_END
Definition: winuser.h:2258
#define VK_HOME
Definition: winuser.h:2259
#define VK_NUMPAD5
Definition: winuser.h:2280
#define VK_LEFT
Definition: winuser.h:2260
#define VK_NUMPAD7
Definition: winuser.h:2282
#define VK_RIGHT
Definition: winuser.h:2262
#define VK_DOWN
Definition: winuser.h:2263
#define VK_PRIOR
Definition: winuser.h:2256
#define VK_DELETE
Definition: winuser.h:2269
#define VK_NUMPAD8
Definition: winuser.h:2283
#define VK_DECIMAL
Definition: winuser.h:2289
#define VK_INSERT
Definition: winuser.h:2268

Referenced by UserProcessKeyboardInput().

◆ IntVkToChar()

static WCHAR FASTCALL IntVkToChar ( WORD  wVk,
PKBDTABLES  pKbdTbl 
)
static

Definition at line 617 of file keyboard.c.

618{
619 WCHAR wch;
620 BOOL bDead, bLigature;
621
622 ASSERT(pKbdTbl);
623
624 if (IntTranslateChar(wVk,
625 NULL,
626 &bDead,
627 &bLigature,
628 &wch,
629 pKbdTbl))
630 {
631 return wch;
632 }
633
634 return 0;
635}

Referenced by IntMapVirtualKeyEx(), and NtUserGetKeyNameText().

◆ IntVkToVsc()

static WORD FASTCALL IntVkToVsc ( WORD  wVk,
PKBDTABLES  pKbdTbl 
)
static

Definition at line 537 of file keyboard.c.

538{
539 unsigned i;
540
541 ASSERT(pKbdTbl);
542
543 /* Check standard keys first */
544 for (i = 0; i < pKbdTbl->bMaxVSCtoVK; i++)
545 {
546 if ((pKbdTbl->pusVSCtoVK[i] & 0xFF) == wVk)
547 return i;
548 }
549
550 /* Check extended keys now */
551 for (i = 0; pKbdTbl->pVSCtoVK_E0[i].Vsc; i++)
552 {
553 if ((pKbdTbl->pVSCtoVK_E0[i].Vk & 0xFF) == wVk)
554 return 0xE000 | pKbdTbl->pVSCtoVK_E0[i].Vsc;
555 }
556
557 for (i = 0; pKbdTbl->pVSCtoVK_E1[i].Vsc; i++)
558 {
559 if ((pKbdTbl->pVSCtoVK_E1[i].Vk & 0xFF) == wVk)
560 return 0xE100 | pKbdTbl->pVSCtoVK_E1[i].Vsc;
561 }
562
563 /* Virtual key has not been found */
564 return 0;
565}
BYTE bMaxVSCtoVK
Definition: kbd.h:103
USHORT * pusVSCtoVK
Definition: kbd.h:102
PVSC_VK pVSCtoVK_E0
Definition: kbd.h:104
PVSC_VK pVSCtoVK_E1
Definition: kbd.h:105
USHORT Vk
Definition: kbd.h:73
BYTE Vsc
Definition: kbd.h:72

Referenced by IntMapVirtualKeyEx().

◆ IntVscToVk()

static WORD FASTCALL IntVscToVk ( WORD  wScanCode,
PKBDTABLES  pKbdTbl 
)
static

Definition at line 574 of file keyboard.c.

575{
576 unsigned i;
577 WORD wVk = 0;
578
579 ASSERT(pKbdTbl);
580
581 if ((wScanCode & 0xFF00) == 0xE000)
582 {
583 for (i = 0; pKbdTbl->pVSCtoVK_E0[i].Vsc; i++)
584 {
585 if (pKbdTbl->pVSCtoVK_E0[i].Vsc == (wScanCode & 0xFF))
586 {
587 wVk = pKbdTbl->pVSCtoVK_E0[i].Vk;
588 }
589 }
590 }
591 else if ((wScanCode & 0xFF00) == 0xE100)
592 {
593 for (i = 0; pKbdTbl->pVSCtoVK_E1[i].Vsc; i++)
594 {
595 if (pKbdTbl->pVSCtoVK_E1[i].Vsc == (wScanCode & 0xFF))
596 {
597 wVk = pKbdTbl->pVSCtoVK_E1[i].Vk;
598 }
599 }
600 }
601 else if (wScanCode < pKbdTbl->bMaxVSCtoVK)
602 {
603 wVk = pKbdTbl->pusVSCtoVK[wScanCode];
604 }
605
606 /* 0xFF nad 0x00 are invalid VKs */
607 return wVk != 0xFF ? wVk : 0;
608}

Referenced by IntMapVirtualKeyEx(), NtUserGetKeyNameText(), UserProcessKeyboardInput(), and UserSendKeyboardInput().

◆ NtUserGetAsyncKeyState()

SHORT APIENTRY NtUserGetAsyncKeyState ( INT  Key)

Definition at line 644 of file keyboard.c.

645{
646 WORD wRet = 0;
647
648 TRACE("Enter NtUserGetAsyncKeyState\n");
649
650 if (Key >= 0x100 || Key < 0)
651 {
653 ERR("Invalid parameter Key\n");
654 return 0;
655 }
656
658
660 wRet |= 0x8000; // If down, windows returns 0x8000.
661 if (gafAsyncKeyStateRecentDown[Key / 8] & (1 << (Key % 8)))
662 wRet |= 0x1;
663 gafAsyncKeyStateRecentDown[Key / 8] &= ~(1 << (Key % 8));
664
665 UserLeave();
666
667 TRACE("Leave NtUserGetAsyncKeyState, ret=%u\n", wRet);
668 return wRet;
669}
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:258
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:249

Referenced by GetAsyncKeyState(), and START_TEST().

◆ NtUserGetKeyNameText()

DWORD APIENTRY NtUserGetKeyNameText ( LONG  lParam,
LPWSTR  lpString,
int  cchSize 
)

Definition at line 1720 of file keyboard.c.

1721{
1722 PTHREADINFO pti;
1723 DWORD i, dwRet = 0;
1724 SIZE_T cchKeyName;
1725 WORD wScanCode = (lParam >> 16) & 0xFF;
1726 BOOL bExtKey = (HIWORD(lParam) & KF_EXTENDED) ? TRUE : FALSE;
1727 PKBDTABLES pKbdTbl;
1728 VSC_LPWSTR *pKeyNames = NULL;
1729 CONST WCHAR *pKeyName = NULL;
1730 WCHAR KeyNameBuf[2];
1731
1732 TRACE("Enter NtUserGetKeyNameText\n");
1733
1735
1736 /* Get current keyboard layout */
1738 pKbdTbl = pti ? pti->KeyboardLayout->spkf->pKbdTbl : NULL;
1739
1740 if (!pKbdTbl || cchSize < 1)
1741 {
1742 ERR("Invalid parameter\n");
1743 goto cleanup;
1744 }
1745
1746 /* "Do not care" flag */
1748 {
1749 /* Note: We could do vsc -> vk -> vsc conversion, instead of using
1750 hardcoded scan codes, but it's not what Windows does */
1751 if (wScanCode == SCANCODE_RSHIFT && !bExtKey)
1752 wScanCode = SCANCODE_LSHIFT;
1753 else if (wScanCode == SCANCODE_CTRL || wScanCode == SCANCODE_ALT)
1754 bExtKey = FALSE;
1755 }
1756
1757 if (bExtKey)
1758 pKeyNames = pKbdTbl->pKeyNamesExt;
1759 else
1760 pKeyNames = pKbdTbl->pKeyNames;
1761
1762 for (i = 0; pKeyNames[i].pwsz; i++)
1763 {
1764 if (pKeyNames[i].vsc == wScanCode)
1765 {
1766 pKeyName = pKeyNames[i].pwsz;
1767 break;
1768 }
1769 }
1770
1771 if (!pKeyName)
1772 {
1773 WORD wVk = IntVscToVk(wScanCode, pKbdTbl);
1774
1775 if (wVk)
1776 {
1777 KeyNameBuf[0] = IntVkToChar(wVk, pKbdTbl);
1778 KeyNameBuf[1] = 0;
1779 if (KeyNameBuf[0])
1780 pKeyName = KeyNameBuf;
1781 }
1782 }
1783
1784 if (pKeyName)
1785 {
1786 cchKeyName = wcslen(pKeyName);
1787 if (cchKeyName > (cchSize - 1UL))
1788 cchKeyName = cchSize - 1UL; // Don't count '\0'
1789
1790 _SEH2_TRY
1791 {
1792 ProbeForWrite(lpString, (cchKeyName + 1) * sizeof(WCHAR), 1);
1793 RtlCopyMemory(lpString, pKeyName, cchKeyName * sizeof(WCHAR));
1794 lpString[cchKeyName] = UNICODE_NULL;
1795 dwRet = cchKeyName;
1796 }
1798 {
1800 }
1801 _SEH2_END;
1802 }
1803 else
1804 {
1806 }
1807
1808cleanup:
1809 UserLeave();
1810 TRACE("Leave NtUserGetKeyNameText, ret=%lu\n", dwRet);
1811 return dwRet;
1812}
LPARAM lParam
Definition: combotst.c:139
static void cleanup(void)
Definition: main.c:1335
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2983
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define SCANCODE_LSHIFT
Definition: kbd.h:128
#define SCANCODE_ALT
Definition: kbd.h:131
#define SCANCODE_RSHIFT
Definition: kbd.h:129
#define SCANCODE_CTRL
Definition: kbd.h:130
#define UNICODE_NULL
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:242
#define CONST
Definition: pedump.c:81
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:181
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:82
#define _SEH2_END
Definition: pseh2_64.h:171
#define _SEH2_TRY
Definition: pseh2_64.h:71
VSC_LPWSTR * pKeyNamesExt
Definition: kbd.h:100
VSC_LPWSTR * pKeyNames
Definition: kbd.h:99
LPWSTR pwsz
Definition: kbd.h:68
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
VOID FASTCALL SetLastNtError(_In_ NTSTATUS Status)
Definition: error.c:31
#define LP_DO_NOT_CARE_BIT
Definition: input.h:56
#define KF_EXTENDED
Definition: winuser.h:2482

Referenced by GetKeyNameTextA(), and GetKeyNameTextW().

◆ NtUserMapVirtualKeyEx()

UINT APIENTRY NtUserMapVirtualKeyEx ( UINT  uCode,
UINT  uType,
DWORD  keyboardId,
HKL  dwhkl 
)

Definition at line 1575 of file keyboard.c.

1576{
1577 PKBDTABLES pKbdTbl = NULL;
1578 UINT ret = 0;
1579
1580 TRACE("Enter NtUserMapVirtualKeyEx\n");
1582
1583 if (!dwhkl)
1584 {
1585 PTHREADINFO pti;
1586
1588 if (pti && pti->KeyboardLayout)
1589 pKbdTbl = pti->KeyboardLayout->spkf->pKbdTbl;
1590 }
1591 else
1592 {
1593 PKL pKl;
1594
1595 pKl = UserHklToKbl(dwhkl);
1596 if (pKl)
1597 pKbdTbl = pKl->spkf->pKbdTbl;
1598 }
1599
1600 if (pKbdTbl)
1601 ret = IntMapVirtualKeyEx(uCode, uType, pKbdTbl);
1602
1603 UserLeave();
1604 TRACE("Leave NtUserMapVirtualKeyEx, ret=%u\n", ret);
1605 return ret;
1606}
return ret
Definition: mutex.c:146
PKL NTAPI UserHklToKbl(HKL hKl)
Definition: kbdlayout.c:539
static UINT IntMapVirtualKeyEx(UINT uCode, UINT Type, PKBDTABLES pKbdTbl)
Definition: keyboard.c:1529

Referenced by MapVirtualKeyExA(), MapVirtualKeyExW(), and MapVirtualKeyW().

◆ NtUserToUnicodeEx()

int APIENTRY NtUserToUnicodeEx ( UINT  wVirtKey,
UINT  wScanCode,
PBYTE  pKeyStateUnsafe,
LPWSTR  pwszBuffUnsafe,
INT  cchBuff,
UINT  wFlags,
HKL  dwhkl 
)

Definition at line 1615 of file keyboard.c.

1623{
1624 PTHREADINFO pti;
1625 BYTE afKeyState[256 * 2 / 8] = {0};
1626 PWCHAR pwszBuff = NULL;
1627 INT i, iRet = 0;
1628 PKL pKl = NULL;
1630
1631 TRACE("Enter NtUserSetKeyboardState\n");
1632
1633 /* Return 0 if SC_KEY_UP bit is set */
1634 if (wScanCode & SC_KEY_UP || wVirtKey >= 0x100)
1635 {
1636 ERR("Invalid parameter\n");
1637 return 0;
1638 }
1639
1640 _SEH2_TRY
1641 {
1642 /* Probe and copy key state to smaller bitmap */
1643 ProbeForRead(pKeyStateUnsafe, 256 * sizeof(BYTE), 1);
1644 for (i = 0; i < 256; ++i)
1645 {
1646 if (pKeyStateUnsafe[i] & KS_DOWN_BIT)
1647 SET_KEY_DOWN(afKeyState, i, TRUE);
1648 if (pKeyStateUnsafe[i] & KS_LOCK_BIT)
1649 SET_KEY_LOCKED(afKeyState, i, TRUE);
1650 }
1651 }
1653 {
1654 ERR("Cannot copy key state\n");
1656 _SEH2_YIELD(return 0);
1657 }
1658 _SEH2_END;
1659
1660 pwszBuff = ExAllocatePoolWithTag(NonPagedPool, sizeof(WCHAR) * cchBuff, TAG_STRING);
1661 if (!pwszBuff)
1662 {
1663 ERR("ExAllocatePoolWithTag(%u) failed\n", sizeof(WCHAR) * cchBuff);
1664 return 0;
1665 }
1666 RtlZeroMemory(pwszBuff, sizeof(WCHAR) * cchBuff);
1667
1668 UserEnterExclusive(); // Note: We modify wchDead static variable
1669
1670 if (dwhkl)
1671 pKl = UserHklToKbl(dwhkl);
1672
1673 if (!pKl)
1674 {
1676 pKl = pti->KeyboardLayout;
1677 }
1678
1679 if (pKl)
1680 {
1681 iRet = IntToUnicodeEx(wVirtKey,
1682 wScanCode,
1683 afKeyState,
1684 pwszBuff,
1685 cchBuff,
1686 wFlags,
1687 pKl->spkf->pKbdTbl);
1688
1689 if (iRet)
1690 {
1691 Status = MmCopyToCaller(pwszBuffUnsafe, pwszBuff, cchBuff * sizeof(WCHAR));
1692 }
1693 }
1694 else
1695 {
1696 ERR("No keyboard layout ?!\n");
1698 }
1699
1700 ExFreePoolWithTag(pwszBuff, TAG_STRING);
1701
1702 if (!NT_SUCCESS(Status))
1703 {
1704 iRet = 0;
1706 }
1707
1708 UserLeave();
1709 TRACE("Leave NtUserSetKeyboardState, ret=%i\n", iRet);
1710 return iRet;
1711}
#define STATUS_INVALID_HANDLE
Definition: d3dkmdt.h:40
#define NonPagedPool
Definition: env_spec_w32.h:307
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#define MmCopyToCaller(x, y, z)
Definition: mmcopy.h:19
#define TAG_STRING
Definition: oslist.h:22
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:184
uint16_t * PWCHAR
Definition: typedefs.h:56
#define SET_KEY_DOWN(ks, vk, down)
Definition: input.h:105
#define KS_DOWN_BIT
Definition: input.h:51
#define SC_KEY_UP
Definition: input.h:54
#define KS_LOCK_BIT
Definition: input.h:52
#define SET_KEY_LOCKED(ks, vk, down)
Definition: input.h:108
WINBASEAPI _In_ DWORD _Out_ _In_ WORD wFlags
Definition: wincon_undoc.h:337

◆ NtUserVkKeyScanEx()

DWORD APIENTRY NtUserVkKeyScanEx ( WCHAR  wch,
HKL  dwhkl,
BOOL  bUsehKL 
)

Definition at line 1845 of file keyboard.c.

1849{
1850 PKBDTABLES pKbdTbl;
1851 PVK_TO_WCHAR_TABLE pVkToWchTbl;
1852 PVK_TO_WCHARS10 pVkToWch;
1853 PKL pKl = NULL;
1854 DWORD i, dwModBits = 0, dwModNumber = 0, Ret = (DWORD)-1;
1855
1856 TRACE("NtUserVkKeyScanEx() wch %u, KbdLayout 0x%p\n", wch, dwhkl);
1858
1859 if (bUsehKL)
1860 {
1861 // Use given keyboard layout
1862 if (dwhkl)
1863 pKl = UserHklToKbl(dwhkl);
1864 }
1865 else
1866 {
1867 // Use thread keyboard layout
1868 pKl = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->KeyboardLayout;
1869 }
1870
1871 if (!pKl)
1872 goto Exit;
1873
1874 pKbdTbl = pKl->spkf->pKbdTbl;
1875
1876 // Interate through all VkToWchar tables while pVkToWchars is not NULL
1877 for (i = 0; pKbdTbl->pVkToWcharTable[i].pVkToWchars; i++)
1878 {
1879 pVkToWchTbl = &pKbdTbl->pVkToWcharTable[i];
1880 pVkToWch = (PVK_TO_WCHARS10)(pVkToWchTbl->pVkToWchars);
1881
1882 // Interate through all virtual keys
1883 while (pVkToWch->VirtualKey)
1884 {
1885 for (dwModNumber = 0; dwModNumber < pVkToWchTbl->nModifications; dwModNumber++)
1886 {
1887 if (pVkToWch->wch[dwModNumber] == wch)
1888 {
1889 dwModBits = pKbdTbl->pCharModifiers->ModNumber[dwModNumber];
1890 TRACE("i %lu wC %04x: dwModBits %08x dwModNumber %08x MaxModBits %08x\n",
1891 i, wch, dwModBits, dwModNumber, pKbdTbl->pCharModifiers->wMaxModBits);
1892 Ret = (dwModBits << 8) | (pVkToWch->VirtualKey & 0xFF);
1893 goto Exit;
1894 }
1895 }
1896 pVkToWch = (PVK_TO_WCHARS10)(((BYTE *)pVkToWch) + pVkToWchTbl->cbSize);
1897 }
1898 }
1899Exit:
1900 UserLeave();
1901 return Ret;
1902}
#define DWORD
Definition: nt_native.h:44
struct _THREADINFO * PTHREADINFO
Definition: ntwin32.h:6
static void Exit(void)
Definition: sock.c:1330

Referenced by VkKeyScanExA(), VkKeyScanExW(), and VkKeyScanW().

◆ ProcessKeyEvent()

BOOL NTAPI ProcessKeyEvent ( WORD  wVk,
WORD  wScanCode,
DWORD  dwFlags,
BOOL  bInjected,
DWORD  dwTime,
DWORD  dwExtraInfo 
)

Definition at line 1020 of file keyboard.c.

1021{
1022 WORD wSimpleVk, wFixedVk, wVk2;
1023 PUSER_MESSAGE_QUEUE pFocusQueue;
1024 PTHREADINFO pti;
1026 BOOL bIsDown = (dwFlags & KEYEVENTF_KEYUP) ? FALSE : TRUE;
1027 BOOL bPacket = (dwFlags & KEYEVENTF_UNICODE) ? TRUE : FALSE;
1028 BOOL bWasSimpleDown = FALSE, bPostMsg = TRUE, bIsSimpleDown;
1029 MSG Msg;
1030 static BOOL bMenuDownRecently = FALSE;
1031 BOOL bLangToggled = FALSE;
1032
1033 /* Get virtual key without shifts (VK_(L|R)* -> VK_*) */
1034 wSimpleVk = IntSimplifyVk(wVk);
1035
1037 {
1038 /* Japanese special! */
1040 {
1041 if (wSimpleVk == VK_OEM_ATTN)
1042 wSimpleVk = VK_CAPITAL;
1043 else if (wSimpleVk == VK_OEM_COPY)
1044 wSimpleVk = VK_OEM_FINISH;
1045 }
1046 }
1047
1048 /* Handle Alt+Numpad character composition */
1049 if (IntHandleAltNumpad(wSimpleVk, bIsDown, dwTime))
1050 return TRUE;
1051
1052 bWasSimpleDown = IS_KEY_DOWN(gafAsyncKeyState, wSimpleVk);
1053
1054 /* Update key without shifts */
1055 wVk2 = IntFixVk(wSimpleVk, !bExt);
1056 bIsSimpleDown = bIsDown || IS_KEY_DOWN(gafAsyncKeyState, wVk2);
1057 UpdateAsyncKeyState(wSimpleVk, bIsSimpleDown);
1058
1059 if (bIsDown)
1060 {
1061 /* Update keyboard LEDs */
1063 wSimpleVk,
1064 wScanCode);
1065 }
1066
1067 /* Call WH_KEYBOARD_LL hook */
1068 if (co_CallLowLevelKeyboardHook(wVk, wScanCode, dwFlags, bInjected, dwTime, dwExtraInfo))
1069 {
1070 ERR("Kbd msg dropped by WH_KEYBOARD_LL hook\n");
1071 bPostMsg = FALSE;
1072 }
1073
1074 /* Check if this is a hotkey */
1075 if (co_UserProcessHotKeys(wSimpleVk, bIsDown))
1076 {
1077 TRACE("HotKey Processed\n");
1078 bPostMsg = FALSE;
1079 }
1080
1081 wFixedVk = IntFixVk(wSimpleVk, bExt); /* LSHIFT + EXT = RSHIFT */
1082 if (wSimpleVk == VK_SHIFT) /* shift can't be extended */
1083 bExt = FALSE;
1084
1085 /* If we have a focus queue, post a keyboard message */
1086 pFocusQueue = IntGetFocusMessageQueue();
1087 TRACE("ProcessKeyEvent Q 0x%p Active pWnd 0x%p Focus pWnd 0x%p\n",
1088 pFocusQueue,
1089 (pFocusQueue ? pFocusQueue->spwndActive : NULL),
1090 (pFocusQueue ? pFocusQueue->spwndFocus : NULL));
1091
1092 /* If it is F10 or ALT is down and CTRL is up, it's a system key */
1093 if ( wVk == VK_F10 ||
1094 (wSimpleVk == VK_MENU && bMenuDownRecently) ||
1097 // See MSDN WM_SYSKEYDOWN/UP fixes last wine Win test_keyboard_input.
1098 (pFocusQueue && !pFocusQueue->spwndFocus) )
1099 {
1100 bMenuDownRecently = FALSE; // reset
1101 if (bIsDown)
1102 {
1103 Msg.message = WM_SYSKEYDOWN;
1104 if (wSimpleVk == VK_MENU)
1105 {
1106 // Note: If only LALT is pressed WM_SYSKEYUP is generated instead of WM_KEYUP
1107 bMenuDownRecently = TRUE;
1108 }
1109 }
1110 else
1111 Msg.message = WM_SYSKEYUP;
1112 }
1113 else
1114 {
1115 if (bIsDown)
1116 Msg.message = WM_KEYDOWN;
1117 else
1118 Msg.message = WM_KEYUP;
1119 }
1120
1121 /* Update async state of not simplified vk here.
1122 See user32_apitest:GetKeyState */
1123 UpdateAsyncKeyState(wFixedVk, bIsDown);
1124
1125 /* Alt-Tab/Esc Check. Use FocusQueue or RIT Queue */
1126 if (bIsSimpleDown && !bWasSimpleDown &&
1129 (wVk == VK_ESCAPE || wVk == VK_TAB))
1130 {
1131 TRACE("Alt-Tab/Esc Pressed wParam %x\n",wVk);
1132 }
1133
1134 /*
1135 * Check Language/Layout Toggle by [Left Alt]+Shift or Ctrl+Shift.
1136 * @see https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc976564%28v=technet.10%29
1137 */
1139 {
1140 if (wSimpleVk == VK_SHIFT) /* Shift key is pressed or released */
1141 {
1142 UINT targetKey = ((gdwLanguageToggleKey == 1) ? VK_LMENU : VK_CONTROL);
1143 if (IS_KEY_DOWN(gafAsyncKeyState, targetKey))
1144 bLangToggled = IntCheckLanguageToggle(pFocusQueue, bIsDown, wVk, &gLanguageToggleKeyState);
1145 }
1146 else if ((wSimpleVk == VK_MENU && gdwLanguageToggleKey == 1) ||
1147 (wSimpleVk == VK_CONTROL && gdwLanguageToggleKey == 2))
1148 {
1150 bLangToggled = IntCheckLanguageToggle(pFocusQueue, bIsDown, 0, &gLanguageToggleKeyState);
1151 }
1152 }
1153 if (!bLangToggled && (gdwLayoutToggleKey == 1 || gdwLayoutToggleKey == 2))
1154 {
1155 if (wSimpleVk == VK_SHIFT) /* Shift key is pressed or released */
1156 {
1157 UINT targetKey = ((gdwLayoutToggleKey == 1) ? VK_LMENU : VK_CONTROL);
1158 if (IS_KEY_DOWN(gafAsyncKeyState, targetKey))
1159 IntCheckLanguageToggle(pFocusQueue, bIsDown, wVk, &gLayoutToggleKeyState);
1160 }
1161 else if ((wSimpleVk == VK_MENU && gdwLayoutToggleKey == 1) ||
1162 (wSimpleVk == VK_CONTROL && gdwLayoutToggleKey == 2))
1163 {
1165 IntCheckLanguageToggle(pFocusQueue, bIsDown, 0, &gLayoutToggleKeyState);
1166 }
1167 }
1168
1169 if (bIsDown && wVk == VK_SNAPSHOT)
1170 {
1171 if (pFocusQueue &&
1174 {
1175 // Snap from Active Window, Focus can be null.
1176 SnapWindow(pFocusQueue->spwndActive ? UserHMGetHandle(pFocusQueue->spwndActive) : NULL);
1177 }
1178 else
1179 SnapWindow(NULL); // Snap Desktop.
1180 }
1181 else if (pFocusQueue && bPostMsg)
1182 {
1183 PWND Wnd = pFocusQueue->spwndFocus; // SysInit.....
1184
1185 pti = pFocusQueue->ptiKeyboard;
1186
1187 if (!Wnd && pFocusQueue->spwndActive) // SysInit.....
1188 {
1189 // Going with Active. WM_SYSKEYXXX last wine Win test_keyboard_input.
1190 Wnd = pFocusQueue->spwndActive;
1191 }
1192 if (Wnd) pti = Wnd->head.pti;
1193
1194 /* Init message */
1195 Msg.hwnd = Wnd ? UserHMGetHandle(Wnd) : NULL;
1196 Msg.wParam = wFixedVk & 0xFF; /* Note: It's simplified by msg queue */
1197 Msg.lParam = MAKELPARAM(1, wScanCode);
1198 Msg.time = dwTime;
1199 Msg.pt = gpsi->ptCursor;
1200
1201 if ( Msg.message == WM_KEYDOWN || Msg.message == WM_SYSKEYDOWN )
1202 {
1203 if ( (Msg.wParam == VK_SHIFT ||
1204 Msg.wParam == VK_CONTROL ||
1205 Msg.wParam == VK_MENU ) &&
1207 {
1208 ERR("Set last input\n");
1209 //ptiLastInput = pti;
1210 }
1211 }
1212
1213 /* If it is VK_PACKET, high word of wParam is used for wchar */
1214 if (!bPacket)
1215 {
1216 if (bExt)
1217 Msg.lParam |= KF_EXTENDED << 16;
1219 Msg.lParam |= KF_ALTDOWN << 16;
1220 if (bWasSimpleDown)
1221 Msg.lParam |= KF_REPEAT << 16;
1222 if (!bIsDown)
1223 Msg.lParam |= KF_UP << 16;
1224 /* FIXME: Set KF_DLGMODE and KF_MENUMODE when needed */
1225 if (pFocusQueue->QF_flags & QF_DIALOGACTIVE)
1226 Msg.lParam |= KF_DLGMODE << 16;
1227 if (pFocusQueue->MenuOwner) // pti->pMenuState->fMenuStarted
1228 Msg.lParam |= KF_MENUMODE << 16;
1229 }
1230
1231 // Post mouse move before posting key buttons, to keep it syned.
1232 if (pFocusQueue->QF_flags & QF_MOUSEMOVED)
1233 {
1235 }
1236
1237 /* Post a keyboard message */
1238 TRACE("Posting keyboard msg %u wParam 0x%x lParam 0x%x\n", Msg.message, Msg.wParam, Msg.lParam);
1239 if (!Wnd) {ERR("Window is NULL\n");}
1240 MsqPostMessage(pti, &Msg, TRUE, QS_KEY, 0, dwExtraInfo);
1241 }
1242 return TRUE;
1243}
struct @1740 Msg[]
VOID FASTCALL IntCoalesceMouseMove(PTHREADINFO pti)
Definition: msgqueue.c:551
#define QF_DIALOGACTIVE
Definition: msgqueue.h:106
#define QF_MOUSEMOVED
Definition: msgqueue.h:99
#define LANG_JAPANESE
Definition: nls.h:76
#define PRIMARYLANGID(l)
Definition: nls.h:16
USHORT gusLanguageID
Definition: init.c:12
BOOL NTAPI co_UserProcessHotKeys(WORD wVk, BOOL bIsDown)
Definition: hotkey.c:191
HANDLE ghKeyboardDevice
Definition: input.c:19
static NTSTATUS APIENTRY IntKeyboardUpdateLeds(HANDLE hKeyboardDevice, WORD wVk, WORD wScanCode)
Definition: keyboard.c:119
static VOID SnapWindow(HWND hWnd)
Definition: keyboard.c:735
DWORD gdwLanguageToggleKey
Definition: keyboard.c:19
DWORD gdwLayoutToggleKey
Definition: keyboard.c:21
static BOOL IntCheckLanguageToggle(_In_ PUSER_MESSAGE_QUEUE pFocusQueue, _In_ BOOL bIsDown, _In_ WORD wVk, _Inout_ PINT pKeyState)
Definition: keyboard.c:866
static LRESULT co_CallLowLevelKeyboardHook(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
Definition: keyboard.c:699
static BOOL IntHandleAltNumpad(_In_ WORD wVk, _In_ BOOL bIsDown, _In_ DWORD dwTime)
Handles Alt+Numpad character composition.
Definition: keyboard.c:911
static VOID NTAPI UpdateAsyncKeyState(WORD wVk, BOOL bIsDown)
Definition: keyboard.c:678
INT gLanguageToggleKeyState
Definition: keyboard.c:18
#define VK_SNAPSHOT
Definition: winuser.h:2267
#define VK_TAB
Definition: winuser.h:2235
#define MAKELPARAM(l, h)
Definition: winuser.h:4110
#define VK_F10
Definition: winuser.h:2300
#define KF_ALTDOWN
Definition: winuser.h:2485
#define VK_OEM_FINISH
Definition: winuser.h:2375
#define KF_UP
Definition: winuser.h:2487
#define KF_MENUMODE
Definition: winuser.h:2484
#define VK_OEM_ATTN
Definition: winuser.h:2374
#define VK_OEM_COPY
Definition: winuser.h:2376
#define KF_REPEAT
Definition: winuser.h:2486
#define VK_ESCAPE
Definition: winuser.h:2250
#define KF_DLGMODE
Definition: winuser.h:2483

Referenced by UserSendKeyboardInput().

◆ SnapWindow()

static VOID SnapWindow ( HWND  hWnd)
static

Definition at line 735 of file keyboard.c.

736{
737 HBITMAP hbm = NULL, hbmOld;
738 HDC hdc = NULL, hdcMem;
739 SETCLIPBDATA scd;
740 INT cx, cy;
741 PWND pWnd = NULL;
742
743 TRACE("SnapWindow(%p)\n", hWnd);
744
745 /* If no windows is given, make snapshot of desktop window */
746 if (!hWnd)
748
750 if (!pWnd)
751 {
752 ERR("Invalid window\n");
753 goto cleanup;
754 }
755
757 if (!hdc)
758 {
759 ERR("UserGetDCEx failed!\n");
760 goto cleanup;
761 }
762
763 cx = pWnd->rcWindow.right - pWnd->rcWindow.left;
764 cy = pWnd->rcWindow.bottom - pWnd->rcWindow.top;
765
767 if (!hbm)
768 {
769 ERR("NtGdiCreateCompatibleBitmap failed!\n");
770 goto cleanup;
771 }
772
774 if (!hdcMem)
775 {
776 ERR("NtGdiCreateCompatibleDC failed!\n");
777 goto cleanup;
778 }
779
780 hbmOld = NtGdiSelectBitmap(hdcMem, hbm);
781 NtGdiBitBlt(hdcMem, 0, 0, cx, cy, hdc, 0, 0, SRCCOPY, CLR_INVALID, 0);
782 NtGdiSelectBitmap(hdcMem, hbmOld);
784
785 /* Save snapshot in clipboard */
787 {
790 scd.fGlobalHandle = FALSE;
792 {
793 /* Bitmap is managed by system now */
794 hbm = NULL;
795 }
797 }
798
799cleanup:
800 if (hbm)
802 if (hdc)
803 UserReleaseDC(pWnd, hdc, FALSE);
804}
#define DCX_USESTYLE
Definition: GetDCEx.c:10
HWND hWnd
Definition: settings.c:17
#define CF_BITMAP
Definition: constants.h:397
BOOL FASTCALL IntGdiDeleteDC(HDC, BOOL)
Definition: dclife.c:892
HDC hdc
Definition: main.c:9
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:88
_In_ HBITMAP hbm
Definition: ntgdi.h:2776
__kernel_entry W32KAPI HBITMAP APIENTRY NtGdiCreateCompatibleBitmap(_In_ HDC hdc, _In_ INT cx, _In_ INT cy)
__kernel_entry W32KAPI HDC APIENTRY NtGdiCreateCompatibleDC(_In_opt_ HDC hdc)
__kernel_entry W32KAPI BOOL APIENTRY NtGdiBitBlt(_In_ HDC hdcDst, _In_ INT x, _In_ INT y, _In_ INT cx, _In_ INT cy, _In_opt_ HDC hdcSrc, _In_ INT xSrc, _In_ INT ySrc, _In_ DWORD rop4, _In_ DWORD crBackColor, _In_ FLONG fl)
__kernel_entry W32KAPI HBITMAP APIENTRY NtGdiSelectBitmap(_In_ HDC hdc, _In_ HBITMAP hbm)
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:586
_Out_opt_ int * cx
Definition: commctrl.h:585
RECT rcWindow
Definition: ntuser.h:716
LONG right
Definition: windef.h:108
LONG bottom
Definition: windef.h:109
LONG top
Definition: windef.h:107
LONG left
Definition: windef.h:106
BOOL fIncSerialNumber
Definition: ntuser.h:1169
BOOL fGlobalHandle
Definition: ntuser.h:1168
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:124
INT FASTCALL UserReleaseDC(PWND Window, HDC hDc, BOOL EndPaint)
Definition: windc.c:918
HDC FASTCALL UserGetDCEx(PWND Window OPTIONAL, HANDLE ClipRegion, ULONG Flags)
HDC hdcMem
Definition: welcome.c:104
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1165
BOOL NTAPI UserEmptyClipboard(VOID)
Definition: clipboard.c:680
BOOL NTAPI UserCloseClipboard(VOID)
Definition: clipboard.c:545
BOOL NTAPI UserOpenClipboard(HWND hWnd)
Definition: clipboard.c:488
HANDLE NTAPI UserSetClipboardData(UINT fmt, HANDLE hData, PSETCLIPBDATA scd)
Definition: clipboard.c:1023
HWND FASTCALL IntGetDesktopWindow(VOID)
Definition: desktop.c:1391
#define CLR_INVALID
Definition: wingdi.h:883
#define SRCCOPY
Definition: wingdi.h:333
#define DCX_WINDOW
Definition: winuser.h:2149

Referenced by ProcessKeyEvent().

◆ UpdateAsyncKeyState()

static VOID NTAPI UpdateAsyncKeyState ( WORD  wVk,
BOOL  bIsDown 
)
static

Definition at line 678 of file keyboard.c.

679{
680 if (bIsDown)
681 {
682 /* If it's first key down event, xor lock bit */
683 if (!IS_KEY_DOWN(gafAsyncKeyState, wVk))
685
687 gafAsyncKeyStateRecentDown[wVk / 8] |= (1 << (wVk % 8));
688 }
689 else
691}

Referenced by ProcessKeyEvent().

◆ UserGetKeyboardType()

DWORD FASTCALL UserGetKeyboardType ( DWORD  dwTypeFlag)

Definition at line 1820 of file keyboard.c.

1822{
1823 switch (dwTypeFlag)
1824 {
1825 case 0: /* Keyboard type */
1827 case 1: /* Keyboard Subtype */
1829 case 2: /* Number of F-keys */
1831 default:
1832 ERR("Unknown type!\n");
1833 return 0; /* Note: we don't have to set last error here */
1834 }
1835}
UCHAR Subtype
Definition: ntddkbd.h:102

Referenced by NtUserCallOneParam().

◆ UserInitKeyboard()

VOID NTAPI UserInitKeyboard ( HANDLE  hKeyboardDevice)

Definition at line 173 of file keyboard.c.

174{
176 IO_STATUS_BLOCK Block;
177
179
180 Status = ZwDeviceIoControlFile(hKeyboardDevice,
181 NULL,
182 NULL,
183 NULL,
184 &Block,
186 NULL, 0,
188 sizeof(gIndicators));
189
190 if (!NT_SUCCESS(Status))
191 {
192 WARN("NtDeviceIoControlFile() failed, ignored\n");
195 }
196
203
204 // FIXME: Need device driver to work! HID support more than one!!!!
205 Status = ZwDeviceIoControlFile(hKeyboardDevice,
206 NULL,
207 NULL,
208 NULL,
209 &Block,
211 NULL, 0,
212 &gKeyboardInfo, sizeof(gKeyboardInfo));
213
214 if (!NT_SUCCESS(Status))
215 {
216 ERR("NtDeviceIoControlFile() failed, ignored\n");
217 }
218 TRACE("Keyboard type %u, subtype %u and number of func keys %u\n",
222}
#define IOCTL_KEYBOARD_QUERY_INDICATORS
Definition: ntddkbd.h:35
#define IOCTL_KEYBOARD_QUERY_ATTRIBUTES
Definition: ntddkbd.h:32
NTSTATUS APIENTRY IntKeyboardGetIndicatorTrans(HANDLE hKeyboardDevice, PKEYBOARD_INDICATOR_TRANSLATION *ppIndicatorTrans)
Definition: keyboard.c:62

Referenced by RawInputThreadMain().

◆ UserProcessKeyboardInput()

VOID NTAPI UserProcessKeyboardInput ( PKEYBOARD_INPUT_DATA  pKbdInputData)

Definition at line 1327 of file keyboard.c.

1329{
1330 WORD wScanCode, wVk;
1331 PKL pKl = NULL;
1332 PKBDTABLES pKbdTbl;
1333 PUSER_MESSAGE_QUEUE pFocusQueue;
1334
1335 /* Calculate scan code with prefix */
1336 wScanCode = pKbdInputData->MakeCode & 0x7F;
1337 if (pKbdInputData->Flags & KEY_E0)
1338 wScanCode |= 0xE000;
1339 if (pKbdInputData->Flags & KEY_E1)
1340 wScanCode |= 0xE100;
1341
1342 /* Find the target thread whose locale is in effect */
1343 pFocusQueue = IntGetFocusMessageQueue();
1344
1345 if (pFocusQueue && pFocusQueue->ptiKeyboard)
1346 {
1347 pKl = pFocusQueue->ptiKeyboard->KeyboardLayout;
1348 }
1349
1350 if (!pKl)
1352 if (!pKl)
1353 return;
1354
1355 pKbdTbl = pKl->spkf->pKbdTbl;
1356
1357 /* Convert scan code to virtual key.
1358 Note: We could call UserSendKeyboardInput using scan code,
1359 but it wouldn't interpret E1 key(s) properly */
1360 wVk = IntVscToVk(wScanCode, pKbdTbl);
1361 TRACE("UserProcessKeyboardInput: %x (break: %u) -> %x\n",
1362 wScanCode, (pKbdInputData->Flags & KEY_BREAK) ? 1u : 0, wVk);
1363
1364 if (wVk)
1365 {
1366 KEYBDINPUT KbdInput;
1367
1368 /* Support numlock */
1370 {
1371 wVk = IntTranslateNumpadKey(wVk & 0xFF);
1372 }
1373
1374 /* Send keyboard input */
1375 KbdInput.wVk = wVk & 0xFF;
1376 KbdInput.wScan = wScanCode & 0x7F;
1377 KbdInput.dwFlags = 0;
1378 if (pKbdInputData->Flags & KEY_BREAK)
1379 KbdInput.dwFlags |= KEYEVENTF_KEYUP;
1380
1381 if (wVk & KBDEXT)
1382 KbdInput.dwFlags |= KEYEVENTF_EXTENDEDKEY;
1383 //
1384 // Based on wine input:test_Input_blackbox this is okay. It seems the
1385 // bit did not get set and more research is needed. Now the right
1386 // shift works.
1387 //
1388 if (wVk == VK_RSHIFT)
1389 KbdInput.dwFlags |= KEYEVENTF_EXTENDEDKEY;
1390
1391 KbdInput.time = 0;
1392 KbdInput.dwExtraInfo = pKbdInputData->ExtraInformation;
1393 UserSendKeyboardInput(&KbdInput, FALSE);
1394
1395 /* E1 keys don't have break code */
1396 if (pKbdInputData->Flags & KEY_E1)
1397 {
1398 /* Send key up event */
1399 KbdInput.dwFlags |= KEYEVENTF_KEYUP;
1400 UserSendKeyboardInput(&KbdInput, FALSE);
1401 }
1402 }
1403}
#define KBDNUMPAD
Definition: kbd.h:11
#define KBDEXT
Definition: kbd.h:8
#define KEY_BREAK
Definition: ntddkbd.h:71
#define KEY_E1
Definition: ntddkbd.h:73
#define KEY_E0
Definition: ntddkbd.h:72
ULONG ExtraInformation
Definition: ntddkbd.h:90
DWORD dwFlags
Definition: winable.h:49
WORD wVk
Definition: winable.h:47
WORD wScan
Definition: winable.h:48
ULONG_PTR dwExtraInfo
Definition: winable.h:51
DWORD time
Definition: winable.h:50
BOOL NTAPI UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected)
Definition: keyboard.c:1246
static WORD IntTranslateNumpadKey(WORD wVk)
Definition: keyboard.c:284

Referenced by RawInputThreadMain().

◆ UserSendKeyboardInput()

BOOL NTAPI UserSendKeyboardInput ( KEYBDINPUT pKbdInput,
BOOL  bInjected 
)

Definition at line 1246 of file keyboard.c.

1247{
1248 WORD wScanCode, wVk;
1249 PKL pKl = NULL;
1250 PKBDTABLES pKbdTbl;
1251 PUSER_MESSAGE_QUEUE pFocusQueue;
1252 DWORD dwTime;
1253 BOOL bExt = (pKbdInput->dwFlags & KEYEVENTF_EXTENDEDKEY) ? TRUE : FALSE;
1254
1256
1257 /* Find the target thread whose locale is in effect */
1258 pFocusQueue = IntGetFocusMessageQueue();
1259
1260 if (pFocusQueue && pFocusQueue->ptiKeyboard)
1261 {
1262 pKl = pFocusQueue->ptiKeyboard->KeyboardLayout;
1263 }
1264
1265 if (!pKl)
1267 if (!pKl)
1268 {
1269 ERR("No keyboard layout!\n");
1270 return FALSE;
1271 }
1272
1273 pKbdTbl = pKl->spkf->pKbdTbl;
1274
1275 /* Note: wScan field is always used */
1276 wScanCode = pKbdInput->wScan;
1277
1278 if (pKbdInput->dwFlags & KEYEVENTF_UNICODE)
1279 {
1280 /* Generate WM_KEYDOWN msg with wParam == VK_PACKET and
1281 high order word of lParam == pKbdInput->wScan */
1282 wVk = VK_PACKET;
1283 }
1284 else
1285 {
1286 wScanCode &= 0x7F;
1287 if (pKbdInput->dwFlags & KEYEVENTF_SCANCODE)
1288 {
1289 /* Don't ignore invalid scan codes */
1290 wVk = IntVscToVk(wScanCode | (bExt ? 0xE000 : 0), pKbdTbl);
1291 if (!wVk) /* use 0xFF if vsc is invalid */
1292 wVk = 0xFF;
1293 }
1294 else
1295 {
1296 wVk = pKbdInput->wVk;
1297 }
1298
1299 /* Remove all virtual key flags (KBDEXT, KBDMULTIVK, KBDSPECIAL, KBDNUMPAD) */
1300 wVk &= 0xFF;
1301 }
1302
1303 /* If time is given, use it */
1304 if (pKbdInput->time)
1305 dwTime = pKbdInput->time;
1306 else
1307 {
1309 }
1310
1311 if (wVk == VK_RMENU && (pKbdTbl->fLocaleFlags & KLLF_ALTGR))
1312 {
1313 /* For AltGr keyboards RALT generates CTRL events */
1314 ProcessKeyEvent(VK_LCONTROL, 0, pKbdInput->dwFlags & KEYEVENTF_KEYUP, bInjected, dwTime, 0);
1315 }
1316
1317 /* Finally process this key */
1318 return ProcessKeyEvent(wVk, wScanCode, pKbdInput->dwFlags, bInjected, dwTime, pKbdInput->dwExtraInfo);
1319}
PPROCESSINFO gppiInputProvider
Definition: ntuser.c:16
BOOL NTAPI ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
Definition: keyboard.c:1020

Referenced by NtUserSendInput(), and UserProcessKeyboardInput().

Variable Documentation

◆ gafAsyncKeyState

◆ gafAsyncKeyStateRecentDown

BYTE gafAsyncKeyStateRecentDown[256/8]
static

Definition at line 14 of file keyboard.c.

Referenced by InitKeyboardImpl(), NtUserGetAsyncKeyState(), and UpdateAsyncKeyState().

◆ gAltNumPadState

enum _ALTNUM_STATE gAltNumPadState = ALTNUM_INACTIVE
static

Referenced by IntHandleAltNumpad().

◆ gAltNumPadValue

ULONG gAltNumPadValue = 0
static

Definition at line 31 of file keyboard.c.

Referenced by IntHandleAltNumpad().

◆ gdwLanguageToggleKey

DWORD gdwLanguageToggleKey = 1

Definition at line 19 of file keyboard.c.

Referenced by ProcessKeyEvent(), SpiGetSet(), and SpiUpdatePerUserSystemParameters().

◆ gdwLayoutToggleKey

DWORD gdwLayoutToggleKey = 2

Definition at line 21 of file keyboard.c.

Referenced by ProcessKeyEvent(), SpiGetSet(), and SpiUpdatePerUserSystemParameters().

◆ gIndicators

KEYBOARD_INDICATOR_PARAMETERS gIndicators = {0, 0}
static

Definition at line 16 of file keyboard.c.

Referenced by IntKeyboardUpdateLeds(), and UserInitKeyboard().

◆ gKeyboardInfo

KEYBOARD_ATTRIBUTES gKeyboardInfo

◆ gLanguageToggleKeyState

INT gLanguageToggleKeyState = 0

Definition at line 18 of file keyboard.c.

Referenced by ProcessKeyEvent().

◆ gLayoutToggleKeyState

INT gLayoutToggleKeyState = 0

Definition at line 20 of file keyboard.c.

Referenced by IntCheckLanguageToggle(), and ProcessKeyEvent().

◆ gpKeyboardIndicatorTrans

PKEYBOARD_INDICATOR_TRANSLATION gpKeyboardIndicatorTrans = NULL
static

Definition at line 15 of file keyboard.c.

Referenced by IntKeyboardUpdateLeds(), and UserInitKeyboard().