ReactOS 0.4.16-dev-2359-g4b75ec5
keyboard.c File Reference
#include <win32k.h>
#include <cjkcode.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 , ALTNUM_HEX_ACP ,
  ALTNUM_HEX_UTF
}
 

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
 
static INT gLanguageToggleKeyState = 0
 
DWORD gdwLanguageToggleKey = 1
 
static INT gLayoutToggleKeyState = 0
 
DWORD gdwLayoutToggleKey = 2
 
static enum _ALTNUM_STATE gAltNumPadState = ALTNUM_INACTIVE
 
static ULONG gAltNumPadValue = 0
 
BOOL gbEnableHexNumpad = FALSE
 

Enumeration Type Documentation

◆ _ALTNUM_STATE

Enumerator
ALTNUM_INACTIVE 
ALTNUM_OEM 
ALTNUM_ACP 
ALTNUM_HEX_ACP 
ALTNUM_HEX_UTF 

Definition at line 26 of file keyboard.c.

27{
29 ALTNUM_OEM, // Alt xxx
30 ALTNUM_ACP, // Alt 0xxx
31 ALTNUM_HEX_ACP, // Alt .xxx
32 ALTNUM_HEX_UTF // Alt +xxx
static enum _ALTNUM_STATE gAltNumPadState
@ ALTNUM_INACTIVE
Definition: keyboard.c:28
@ ALTNUM_HEX_UTF
Definition: keyboard.c:32
@ ALTNUM_OEM
Definition: keyboard.c:29
@ ALTNUM_HEX_ACP
Definition: keyboard.c:31
@ ALTNUM_ACP
Definition: keyboard.c:30

Function Documentation

◆ co_CallLowLevelKeyboardHook()

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

Definition at line 704 of file keyboard.c.

705{
706 KBDLLHOOKSTRUCT KbdHookData;
707 UINT uMsg;
708
709 KbdHookData.vkCode = wVk;
710 KbdHookData.scanCode = wScanCode;
711 KbdHookData.flags = 0;
713 KbdHookData.flags |= LLKHF_EXTENDED;
715 KbdHookData.flags |= LLKHF_ALTDOWN;
717 KbdHookData.flags |= LLKHF_UP;
718 if (bInjected)
719 KbdHookData.flags |= LLKHF_INJECTED;
720 KbdHookData.time = dwTime;
721 KbdHookData.dwExtraInfo = dwExtraInfo;
722
723 /* Note: it doesnt support WM_SYSKEYUP */
725 uMsg = WM_KEYUP;
727 uMsg = WM_SYSKEYDOWN;
728 else
729 uMsg = WM_KEYDOWN;
730
731 return co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, uMsg, (LPARAM)&KbdHookData);
732}
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:102
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 48 of file keyboard.c.

49{
52 // Clear and set default information.
54 gKeyboardInfo.KeyboardIdentifier.Type = 4; /* AT-101 */
55 gKeyboardInfo.NumberOfFunctionKeys = 12; /* We're doing an 101 for now, so return 12 F-keys */
56 return STATUS_SUCCESS;
57}
#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 871 of file keyboard.c.

876{
877 if (bIsDown) /* Toggle key combination is pressed? */
878 {
879 if (wVk == VK_LSHIFT)
880 *pKeyState = INPUTLANGCHANGE_FORWARD;
881 else if (wVk == VK_RSHIFT)
882 *pKeyState = INPUTLANGCHANGE_BACKWARD;
883 else if (!wVk && IS_KEY_DOWN(gafAsyncKeyState, VK_LSHIFT))
884 *pKeyState = INPUTLANGCHANGE_FORWARD;
885 else if (!wVk && IS_KEY_DOWN(gafAsyncKeyState, VK_RSHIFT))
886 *pKeyState = INPUTLANGCHANGE_BACKWARD;
887 else
888 return FALSE;
889 }
890 else
891 {
892 if (*pKeyState == 0)
893 return FALSE;
894
895 IntLanguageToggle(pFocusQueue, (pKeyState == &gLayoutToggleKeyState), *pKeyState);
896 *pKeyState = 0;
897 }
898 return TRUE;
899}
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static INT gLayoutToggleKeyState
Definition: keyboard.c:20
static VOID IntLanguageToggle(_In_ PUSER_MESSAGE_QUEUE pFocusQueue, _In_ BOOL bSameLang, _In_ INT nKeyState)
Definition: keyboard.c:834
#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 264 of file keyboard.c.

265{
266 switch (wVk)
267 {
268 case VK_SHIFT:
269 return bExt ? VK_RSHIFT : VK_LSHIFT;
270
271 case VK_CONTROL:
272 return bExt ? VK_RCONTROL : VK_LCONTROL;
273
274 case VK_MENU:
275 return bExt ? VK_RMENU : VK_LMENU;
276
277 default:
278 return wVk;
279 }
280}
#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 315 of file keyboard.c.

316{
317 DWORD i, dwModBits = 0;
318
319 /* DumpKeyState( KeyState ); */
320
321 for (i = 0; pKbdTbl->pCharModifiers->pVkToBit[i].Vk; i++)
322 if (IS_KEY_DOWN(pKeyState, pKbdTbl->pCharModifiers->pVkToBit[i].Vk))
323 dwModBits |= pKbdTbl->pCharModifiers->pVkToBit[i].ModBits;
324
325 TRACE("Current Mod Bits: %lx\n", dwModBits);
326
327 return dwModBits;
328}
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 813 of file keyboard.c.

817{
818 PKL pFirstKL = pKL;
819 LANGID LangID = LOWORD(pKL->hkl);
820
821 do
822 {
823 pKL = (bNext ? pKL->pklNext : pKL->pklPrev);
824
825 if (!(pKL->dwKL_Flags & KL_UNLOAD) && bSameLang == (LangID == LOWORD(pKL->hkl)))
826 return pKL;
827 } while (pKL != pFirstKL);
828
829 return pFirstKL;
830}
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 916 of file keyboard.c.

921{
922 if (bIsDown &&
925 {
926 TRACE("VK_MENU && !VK_CONTROL - wVk: 0x%04x\n", wVk);
927
928 /* Initialize the Alt+Numpad state if necessary */
930 {
931 if (gbEnableHexNumpad && (wVk == VK_DECIMAL)) // || (wVk == VK_OEM_PERIOD)
932 gAltNumPadState = ALTNUM_HEX_ACP, wVk = VK_NUMPAD0; // Replace '.' by '0'
933 else if (gbEnableHexNumpad && (wVk == VK_ADD)) // || (wVk == VK_OEM_PLUS)
934 gAltNumPadState = ALTNUM_HEX_UTF, wVk = VK_NUMPAD0; // Replace '+' by '0'
935 else if (wVk >= VK_NUMPAD0 && wVk <= VK_NUMPAD9) // || (wVk >= '0' && wVk <= '9')
937 else
938 return FALSE; /* Unhandled, do regular key processing */
939 }
940
941 /* Check the incoming key */
942 switch (gAltNumPadState)
943 {
944 case ALTNUM_OEM: case ALTNUM_ACP:
945 {
946 UINT uDigit;
947
948 /* Check if it is a numpad digit */
949 if (wVk >= VK_NUMPAD0 && wVk <= VK_NUMPAD9)
950 uDigit = wVk - VK_NUMPAD0;
951 // else if (wVk >= '0' && wVk <= '9')
952 // uDigit = wVk - '0';
953 else
954 break;
955
956 /* Build the decimal value; the value can overflow
957 * and be truncated (same behaviour as on Windows) */
958 gAltNumPadValue = (gAltNumPadValue * 10) + uDigit;
959 return TRUE; /* No key processing needs to be done */
960 }
962 {
963 UINT uDigit;
964
965 /* Check if it represents a valid hexadecimal digit */
966 if (wVk >= VK_NUMPAD0 && wVk <= VK_NUMPAD9)
967 uDigit = wVk - VK_NUMPAD0;
968 else if (wVk >= '0' && wVk <= '9')
969 uDigit = wVk - '0';
970 else if (wVk >= 'A' && wVk <= 'F')
971 uDigit = wVk - 'A' + 10;
972 else
973 break;
974
975 /* Build the hexadecimal value; the value can overflow
976 * and be truncated (same behaviour as on Windows) */
977 gAltNumPadValue = (gAltNumPadValue * 16) + uDigit;
978 return TRUE; /* No key processing needs to be done */
979 }
981 }
982
983 /* If the incoming key is not the ALT key, reset the Alt+Numpad state */
984 if (wVk != VK_MENU)
985 {
987 gAltNumPadValue = 0;
988 }
989 }
990 TRACE("gAltNumPadState: %lu, gAltNumPadValue: %lu\n",
992
993 /* Check for the end of an Alt+Numpad sequence, triggered by the ALT key release */
994 if ((gAltNumPadState != ALTNUM_INACTIVE) && !bIsDown && (wVk == VK_MENU))
995 {
997
998 TRACE("End of Alt+Numpad\n");
999 if (gAltNumPadValue != 0 && pFocusQueue && pFocusQueue->ptiKeyboard)
1000 {
1002 WCHAR wchUnicodeChar;
1003
1004 /* Convert the input codepoint value to UTF-16 */
1006 {
1007 /* Convert the Unicode codepoint to UTF-16 */
1008 // FIXME: We currently support only the Basic Multilingual Plane
1009 // (equivalent to UCS-2) and don't exclude the surrogate range
1010 // (U+D800 to U+DFFF). In the future, we should handle all the
1011 // valid values, generating two UTF-16 code units if necessary
1012 // so as to support the other Unicode planes.
1013 // See https://en.wikipedia.org/wiki/UTF-16#Description
1014 wchUnicodeChar = (WCHAR)(gAltNumPadValue & 0xFFFF);
1016 }
1017 else
1018 {
1019 NTSTATUS (NTAPI* pRtlCPToUnicodeN)(
1023 _In_reads_bytes_(BytesInString) PCCH String,
1024 _In_ ULONG BytesInString);
1025
1026 USHORT AnsiCP, OemCP, wCodePage, mbChar;
1027
1028 /* Check the current codepage and select a conversion function.
1029 * NOTE: Windows WIN32K invokes the ClientCharToWchar
1030 * USER32 callback to perform the conversion. */
1031 RtlGetDefaultCodePage(&AnsiCP, &OemCP);
1033 {
1034 // TODO: Handle console where we do not know its active
1035 // OEM codepage. In this case we need to directly send
1036 // the raw OEM numpad value, OR'ed with ALTNUMPAD_BIT.
1037 // For more details, see:
1038 // https://github.com/microsoft/terminal/blob/e20e1f7bf92b61580baea69483a74a7f4578a586/src/host/stream.cpp#L170
1039
1040 /* Use the current OEM codepage -> Unicode function */
1041 wCodePage = OemCP;
1042 pRtlCPToUnicodeN = RtlOemToUnicodeN;
1043 }
1044 else // if ((gAltNumPadState == ALTNUM_ACP) ||
1045 // (gAltNumPadState == ALTNUM_HEX_ACP))
1046 {
1047 /* Use the current ANSI codepage (ACP) MultiByte -> Unicode function */
1048 wCodePage = AnsiCP;
1049 pRtlCPToUnicodeN = RtlMultiByteToUnicodeN;
1050 }
1051
1052 /* For CJK codepages, keep the input value on 2 bytes,
1053 * otherwise truncate it to 1 byte for legacy behaviour. */
1054 if (IsCJKCodePage(wCodePage))
1055 {
1056 mbChar = (USHORT)(gAltNumPadValue & 0xFFFF);
1057 }
1058 else
1059 {
1060 /*
1061 * NOTE: the input value is considered modulo 256 as it is
1062 * stored in a 1-byte CHAR. Other input systems that hook and
1063 * re-implement the Alt+Numpad system (e.g. RichEdit, ...)
1064 * store instead the value in a 2-byte WORD, i.e. consider
1065 * the value modulo 65536.
1066 * See: https://devblogs.microsoft.com/oldnewthing/20240702-00/?p=109951
1067 */
1068 mbChar = (USHORT)(gAltNumPadValue & 0xFF);
1069 }
1070
1071 Status = pRtlCPToUnicodeN(&wchUnicodeChar,
1072 sizeof(wchUnicodeChar),
1073 NULL,
1074 (PCCH)&mbChar,
1075 sizeof(mbChar));
1076 }
1077
1078 /* Post the Unicode character to the focused message queue if conversion succeeded */
1079 if (NT_SUCCESS(Status))
1080 {
1081 MSG msgChar;
1082 msgChar.hwnd = pFocusQueue->spwndFocus ? UserHMGetHandle(pFocusQueue->spwndFocus) : NULL;
1083 msgChar.message = WM_CHAR;
1084 msgChar.wParam = wchUnicodeChar;
1085 msgChar.lParam = 1;
1086 msgChar.time = dwTime;
1087 msgChar.pt = gpsi->ptCursor;
1088
1089 MsqPostMessage(pFocusQueue->ptiKeyboard, &msgChar, FALSE, QS_KEY, 0, 0);
1090 }
1091 }
1092
1093 /* Reset the Alt+Numpad state */
1095 gAltNumPadValue = 0;
1096 }
1097
1098 return FALSE; /* More key processing has to be done */
1099}
LONG NTSTATUS
Definition: precomp.h:26
#define IsCJKCodePage(CodePage)
Definition: cjkcode.h:27
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define NTSTATUS
Definition: precomp.h:19
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
*BytesInUnicodeString PWCH _In_ ULONG _Out_opt_ PULONG BytesInUnicodeString
Definition: rtlfuncs.h:2082
NTSYSAPI VOID NTAPI RtlGetDefaultCodePage(_Out_ PUSHORT AnsiCodePage, _Out_ PUSHORT OemCodePage)
*BytesInUnicodeString PWCH _In_ ULONG MaxBytesInUnicodeString
Definition: rtlfuncs.h:2081
_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
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
#define _Out_opt_
Definition: no_sal2.h:214
#define _Out_writes_bytes_to_(s, c)
Definition: no_sal2.h:190
#define _In_
Definition: no_sal2.h:158
WCHAR * PWCH
Definition: ntbasedef.h:422
#define DEFAULT_UNREACHABLE
CONST CHAR * PCCH
Definition: ntbasedef.h:404
unsigned short USHORT
Definition: pedump.c:61
PTHREADINFO ptiKeyboard
Definition: msgqueue.h:56
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2439
PUSER_MESSAGE_QUEUE FASTCALL IntGetFocusMessageQueue(VOID)
Definition: desktop.c:1324
static ULONG gAltNumPadValue
Definition: keyboard.c:35
BOOL gbEnableHexNumpad
Definition: keyboard.c:36
#define QS_KEY
Definition: winuser.h:885
#define VK_NUMPAD0
Definition: winuser.h:2275
#define VK_NUMPAD9
Definition: winuser.h:2284
#define VK_ADD
Definition: winuser.h:2286
#define WM_CHAR
Definition: winuser.h:1745
#define VK_DECIMAL
Definition: winuser.h:2289
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by ProcessKeyEvent().

◆ IntKeyboardGetIndicatorTrans()

NTSTATUS APIENTRY IntKeyboardGetIndicatorTrans ( HANDLE  hKeyboardDevice,
PKEYBOARD_INDICATOR_TRANSLATION ppIndicatorTrans 
)

Definition at line 67 of file keyboard.c.

69{
71 DWORD dwSize = 0;
72 IO_STATUS_BLOCK Block;
74
76
78 dwSize,
80
81 while (pRet)
82 {
83 Status = ZwDeviceIoControlFile(hKeyboardDevice,
84 NULL,
85 NULL,
86 NULL,
87 &Block,
89 NULL, 0,
90 pRet, dwSize);
91
93 break;
94
96
98
100 dwSize,
102 }
103
104 if (!pRet)
106
107 if (!NT_SUCCESS(Status))
108 {
110 return Status;
111 }
112
113 *ppIndicatorTrans = pRet;
114 return Status;
115}
#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 124 of file keyboard.c.

127{
129 UINT i;
130 USHORT LedFlag = 0;
131 IO_STATUS_BLOCK Block;
132
135
136 switch (wVk)
137 {
138 case VK_CAPITAL: LedFlag = KEYBOARD_CAPS_LOCK_ON; break;
139 case VK_NUMLOCK: LedFlag = KEYBOARD_NUM_LOCK_ON; break;
140 case VK_SCROLL: LedFlag = KEYBOARD_SCROLL_LOCK_ON; break;
141 default:
143 {
145 {
147 break;
148 }
149 }
150 }
151
152 if (LedFlag)
153 {
154 gIndicators.LedFlags ^= LedFlag;
155
156 /* Update the lights on the hardware */
157 Status = ZwDeviceIoControlFile(hKeyboardDevice,
158 NULL,
159 NULL,
160 NULL,
161 &Block,
163 &gIndicators, sizeof(gIndicators),
164 NULL, 0);
165
166 return Status;
167 }
168
169 return STATUS_SUCCESS;
170}
#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
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 834 of file keyboard.c.

838{
839 PWND pWnd;
840 PTHREADINFO pti;
841 PKL pkl;
842 WPARAM wParam = 0;
843
844 if (!pFocusQueue)
845 {
846 ERR("IntLanguageToggle(): NULL pFocusQueue\n");
847 return;
848 }
849 pWnd = pFocusQueue->spwndFocus;
850 if (!pWnd)
851 pWnd = pFocusQueue->spwndActive;
852 if (!pWnd)
853 return;
854
855 pti = pWnd->head.pti;
856 pkl = pti->KeyboardLayout;
857
858 if (nKeyState == INPUTLANGCHANGE_FORWARD)
859 pkl = IntGetNextKL(pkl, TRUE, bSameLang);
860 else if (nKeyState == INPUTLANGCHANGE_BACKWARD)
861 pkl = IntGetNextKL(pkl, FALSE, bSameLang);
862
863 if (gSystemFS & pkl->dwFontSigs)
864 wParam |= INPUTLANGCHANGE_SYSCHARSET;
865
866 UserPostMessage(UserHMGetHandle(pWnd), WM_INPUTLANGCHANGEREQUEST, wParam, (LPARAM)pkl->hkl);
867}
#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:813
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 1616 of file keyboard.c.

1617{
1618 UINT uRet = 0;
1619
1620 switch (Type)
1621 {
1622 case MAPVK_VK_TO_VSC:
1623 uCode = IntFixVk(uCode, FALSE);
1624 uRet = IntVkToVsc(uCode, pKbdTbl);
1625 if (uRet > 0xFF) // Fail for scancodes with prefix (e0, e1)
1626 uRet = 0;
1627 break;
1628
1629 case MAPVK_VSC_TO_VK:
1630 uRet = IntVscToVk(uCode, pKbdTbl) & 0xFF;
1631 uRet = IntSimplifyVk(uRet);
1632 break;
1633
1634 case MAPVK_VK_TO_CHAR:
1635 uRet = (UINT)IntVkToChar(uCode, pKbdTbl);
1636 break;
1637
1638 case MAPVK_VSC_TO_VK_EX:
1639 uRet = IntVscToVk(uCode, pKbdTbl) & 0xFF;
1640 break;
1641
1642 case MAPVK_VK_TO_VSC_EX:
1643 uRet = IntVkToVsc(uCode, pKbdTbl);
1644 break;
1645
1646 default:
1648 ERR("Wrong type value: %u\n", Type);
1649 }
1650
1651 return uRet;
1652}
Type
Definition: Type.h:7
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
static WORD IntFixVk(WORD wVk, BOOL bExt)
Definition: keyboard.c:264
static WCHAR FASTCALL IntVkToChar(WORD wVk, PKBDTABLES pKbdTbl)
Definition: keyboard.c:622
static WORD FASTCALL IntVkToVsc(WORD wVk, PKBDTABLES pKbdTbl)
Definition: keyboard.c:542
static WORD FASTCALL IntVscToVk(WORD wScanCode, PKBDTABLES pKbdTbl)
Definition: keyboard.c:579
static WORD IntSimplifyVk(WORD wVk)
Definition: keyboard.c:236
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 236 of file keyboard.c.

237{
238 switch (wVk)
239 {
240 case VK_LSHIFT:
241 case VK_RSHIFT:
242 return VK_SHIFT;
243
244 case VK_LCONTROL:
245 case VK_RCONTROL:
246 return VK_CONTROL;
247
248 case VK_LMENU:
249 case VK_RMENU:
250 return VK_MENU;
251
252 default:
253 return wVk;
254 }
255}

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 449 of file keyboard.c.

456{
457 WCHAR wchTranslatedChar;
458 BOOL bDead, bLigature;
459 static WCHAR wchDead = 0;
460 int iRet = 0;
461
462 ASSERT(pKbdTbl);
463
464 if (!IntTranslateChar(wVirtKey,
465 pKeyState,
466 &bDead,
467 &bLigature,
468 &wchTranslatedChar,
469 pKbdTbl))
470 {
471 return 0;
472 }
473
474 if (bLigature)
475 {
476 WARN("Not handling ligature (yet)\n" );
477 return 0;
478 }
479
480 /* If we got dead char in previous call check dead keys in keyboard layout */
481 if (wchDead)
482 {
483 UINT i;
484 WCHAR wchFirst, wchSecond;
485 TRACE("Previous dead char: %lc (%x)\n", wchDead, wchDead);
486
487 if (pKbdTbl->pDeadKey)
488 {
489 for (i = 0; pKbdTbl->pDeadKey[i].dwBoth; i++)
490 {
491 wchFirst = pKbdTbl->pDeadKey[i].dwBoth >> 16;
492 wchSecond = pKbdTbl->pDeadKey[i].dwBoth & 0xFFFF;
493 if (wchFirst == wchDead && wchSecond == wchTranslatedChar)
494 {
495 wchTranslatedChar = pKbdTbl->pDeadKey[i].wchComposed;
496 wchDead = 0;
497 bDead = FALSE;
498 break;
499 }
500 }
501 }
502 else
503 {
504#if defined(__GNUC__)
505 if (wchDead == 0x8000)
506 {
507 ERR("GCC is inventing bits, ignoring fake dead key\n");
508 wchDead = 0;
509 }
510#endif
511 }
512
513 TRACE("Final char: %lc (%x)\n", wchTranslatedChar, wchTranslatedChar);
514 }
515
516 /* Dead char has not been not found */
517 if (wchDead)
518 {
519 /* Treat both characters normally */
520 if (cchBuff > iRet)
521 pwszBuff[iRet++] = wchDead;
522 bDead = FALSE;
523 }
524
525 /* Add character to the buffer */
526 if (cchBuff > iRet)
527 pwszBuff[iRet++] = wchTranslatedChar;
528
529 /* Save dead character */
530 wchDead = bDead ? wchTranslatedChar : 0;
531
532 return bDead ? -iRet : iRet;
533}
#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:337

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 337 of file keyboard.c.

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

Referenced by IntToUnicodeEx(), and IntVkToChar().

◆ IntTranslateKbdMessage()

BOOL FASTCALL IntTranslateKbdMessage ( LPMSG  lpMsg,
UINT  flags 
)

Definition at line 1499 of file keyboard.c.

1501{
1502 PTHREADINFO pti;
1503 INT cch = 0, i;
1504 WCHAR wch[3] = { 0 };
1505 MSG NewMsg = { 0 };
1506 PKBDTABLES pKbdTbl;
1507 BOOL bResult = FALSE;
1508
1509 switch(lpMsg->message)
1510 {
1511 case WM_KEYDOWN:
1512 case WM_KEYUP:
1513 case WM_SYSKEYDOWN:
1514 case WM_SYSKEYUP:
1515 break;
1516 default:
1517 return FALSE;
1518 }
1519
1521
1522 if (!pti->KeyboardLayout)
1523 {
1524 PKL pDefKL = W32kGetDefaultKeyLayout();
1525 UserAssignmentLock((PVOID*)&(pti->KeyboardLayout), pDefKL);
1526 if (pDefKL)
1527 {
1528 pti->pClientInfo->hKL = pDefKL->hkl;
1529 pKbdTbl = pDefKL->spkf->pKbdTbl;
1530 }
1531 else
1532 {
1533 pti->pClientInfo->hKL = NULL;
1534 pKbdTbl = NULL;
1535 }
1536 }
1537 else
1538 pKbdTbl = pti->KeyboardLayout->spkf->pKbdTbl;
1539 if (!pKbdTbl)
1540 return FALSE;
1541
1542 if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN)
1543 return FALSE;
1544
1545 /* Init pt, hwnd and time msg fields */
1546 NewMsg.pt = gpsi->ptCursor;
1547 NewMsg.hwnd = lpMsg->hwnd;
1548 NewMsg.time = EngGetTickCount32();
1549
1550 TRACE("Enter IntTranslateKbdMessage msg %s, vk %x\n",
1551 lpMsg->message == WM_SYSKEYDOWN ? "WM_SYSKEYDOWN" : "WM_KEYDOWN", lpMsg->wParam);
1552
1553 if (lpMsg->wParam == VK_PACKET)
1554 {
1555 NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
1556 NewMsg.wParam = HIWORD(lpMsg->lParam);
1557 NewMsg.lParam = LOWORD(lpMsg->lParam);
1558 MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0, 0);
1559 return TRUE;
1560 }
1561
1562 cch = IntToUnicodeEx(lpMsg->wParam,
1563 HIWORD(lpMsg->lParam) & 0xFF,
1564 pti->MessageQueue->afKeyState,
1565 wch,
1566 sizeof(wch) / sizeof(wch[0]),
1567 0,
1568 pKbdTbl);
1569
1570 if (cch)
1571 {
1572 if (cch > 0) /* Normal characters */
1573 NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
1574 else /* Dead character */
1575 {
1576 cch = -cch;
1577 NewMsg.message =
1579 }
1580 NewMsg.lParam = lpMsg->lParam;
1581
1582 /* Send all characters */
1583 for (i = 0; i < cch; ++i)
1584 {
1585 TRACE("Msg: %x '%lc' (%04x) %08x\n", NewMsg.message, wch[i], wch[i], NewMsg.lParam);
1586 NewMsg.wParam = wch[i];
1587 MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0, 0);
1588 }
1589 bResult = TRUE;
1590 }
1591
1592 TRACE("Leave IntTranslateKbdMessage ret %d, cch %d, msg %x, wch %x\n",
1593 bResult, cch, NewMsg.message, NewMsg.wParam);
1594 return bResult;
1595}
#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:449
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 289 of file keyboard.c.

290{
291 switch (wVk)
292 {
293 case VK_INSERT: return VK_NUMPAD0;
294 case VK_END: return VK_NUMPAD1;
295 case VK_DOWN: return VK_NUMPAD2;
296 case VK_NEXT: return VK_NUMPAD3;
297 case VK_LEFT: return VK_NUMPAD4;
298 case VK_CLEAR: return VK_NUMPAD5;
299 case VK_RIGHT: return VK_NUMPAD6;
300 case VK_HOME: return VK_NUMPAD7;
301 case VK_UP: return VK_NUMPAD8;
302 case VK_PRIOR: return VK_NUMPAD9;
303 case VK_DELETE: return VK_DECIMAL;
304 default: return wVk;
305 }
306}
#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_INSERT
Definition: winuser.h:2268

Referenced by UserProcessKeyboardInput().

◆ IntVkToChar()

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

Definition at line 622 of file keyboard.c.

623{
624 WCHAR wch;
625 BOOL bDead, bLigature;
626
627 ASSERT(pKbdTbl);
628
629 if (IntTranslateChar(wVk,
630 NULL,
631 &bDead,
632 &bLigature,
633 &wch,
634 pKbdTbl))
635 {
636 return wch;
637 }
638
639 return 0;
640}

Referenced by IntMapVirtualKeyEx(), and NtUserGetKeyNameText().

◆ IntVkToVsc()

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

Definition at line 542 of file keyboard.c.

543{
544 unsigned i;
545
546 ASSERT(pKbdTbl);
547
548 /* Check standard keys first */
549 for (i = 0; i < pKbdTbl->bMaxVSCtoVK; i++)
550 {
551 if ((pKbdTbl->pusVSCtoVK[i] & 0xFF) == wVk)
552 return i;
553 }
554
555 /* Check extended keys now */
556 for (i = 0; pKbdTbl->pVSCtoVK_E0[i].Vsc; i++)
557 {
558 if ((pKbdTbl->pVSCtoVK_E0[i].Vk & 0xFF) == wVk)
559 return 0xE000 | pKbdTbl->pVSCtoVK_E0[i].Vsc;
560 }
561
562 for (i = 0; pKbdTbl->pVSCtoVK_E1[i].Vsc; i++)
563 {
564 if ((pKbdTbl->pVSCtoVK_E1[i].Vk & 0xFF) == wVk)
565 return 0xE100 | pKbdTbl->pVSCtoVK_E1[i].Vsc;
566 }
567
568 /* Virtual key has not been found */
569 return 0;
570}
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 579 of file keyboard.c.

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

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

◆ NtUserGetAsyncKeyState()

SHORT APIENTRY NtUserGetAsyncKeyState ( INT  Key)

Definition at line 649 of file keyboard.c.

650{
651 WORD wRet = 0;
652
653 TRACE("Enter NtUserGetAsyncKeyState\n");
654
655 if (Key >= 0x100 || Key < 0)
656 {
658 ERR("Invalid parameter Key\n");
659 return 0;
660 }
661
663
665 wRet |= 0x8000; // If down, windows returns 0x8000.
666 if (gafAsyncKeyStateRecentDown[Key / 8] & (1 << (Key % 8)))
667 wRet |= 0x1;
668 gafAsyncKeyStateRecentDown[Key / 8] &= ~(1 << (Key % 8));
669
670 UserLeave();
671
672 TRACE("Leave NtUserGetAsyncKeyState, ret=%u\n", wRet);
673 return wRet;
674}
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 1807 of file keyboard.c.

1808{
1809 PTHREADINFO pti;
1810 DWORD i, dwRet = 0;
1811 SIZE_T cchKeyName;
1812 WORD wScanCode = (lParam >> 16) & 0xFF;
1813 BOOL bExtKey = (HIWORD(lParam) & KF_EXTENDED) ? TRUE : FALSE;
1814 PKBDTABLES pKbdTbl;
1815 VSC_LPWSTR *pKeyNames = NULL;
1816 CONST WCHAR *pKeyName = NULL;
1817 WCHAR KeyNameBuf[2];
1818
1819 TRACE("Enter NtUserGetKeyNameText\n");
1820
1822
1823 /* Get current keyboard layout */
1825 pKbdTbl = pti ? pti->KeyboardLayout->spkf->pKbdTbl : NULL;
1826
1827 if (!pKbdTbl || cchSize < 1)
1828 {
1829 ERR("Invalid parameter\n");
1830 goto cleanup;
1831 }
1832
1833 /* "Do not care" flag */
1835 {
1836 /* Note: We could do vsc -> vk -> vsc conversion, instead of using
1837 hardcoded scan codes, but it's not what Windows does */
1838 if (wScanCode == SCANCODE_RSHIFT && !bExtKey)
1839 wScanCode = SCANCODE_LSHIFT;
1840 else if (wScanCode == SCANCODE_CTRL || wScanCode == SCANCODE_ALT)
1841 bExtKey = FALSE;
1842 }
1843
1844 if (bExtKey)
1845 pKeyNames = pKbdTbl->pKeyNamesExt;
1846 else
1847 pKeyNames = pKbdTbl->pKeyNames;
1848
1849 for (i = 0; pKeyNames[i].pwsz; i++)
1850 {
1851 if (pKeyNames[i].vsc == wScanCode)
1852 {
1853 pKeyName = pKeyNames[i].pwsz;
1854 break;
1855 }
1856 }
1857
1858 if (!pKeyName)
1859 {
1860 WORD wVk = IntVscToVk(wScanCode, pKbdTbl);
1861
1862 if (wVk)
1863 {
1864 KeyNameBuf[0] = IntVkToChar(wVk, pKbdTbl);
1865 KeyNameBuf[1] = 0;
1866 if (KeyNameBuf[0])
1867 pKeyName = KeyNameBuf;
1868 }
1869 }
1870
1871 if (pKeyName)
1872 {
1873 cchKeyName = wcslen(pKeyName);
1874 if (cchKeyName > (cchSize - 1UL))
1875 cchKeyName = cchSize - 1UL; // Don't count '\0'
1876
1877 _SEH2_TRY
1878 {
1879 ProbeForWrite(lpString, (cchKeyName + 1) * sizeof(WCHAR), 1);
1880 RtlCopyMemory(lpString, pKeyName, cchKeyName * sizeof(WCHAR));
1881 lpString[cchKeyName] = UNICODE_NULL;
1882 dwRet = cchKeyName;
1883 }
1885 {
1887 }
1888 _SEH2_END;
1889 }
1890 else
1891 {
1893 }
1894
1895cleanup:
1896 UserLeave();
1897 TRACE("Leave NtUserGetKeyNameText, ret=%lu\n", dwRet);
1898 return dwRet;
1899}
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 1662 of file keyboard.c.

1663{
1664 PKBDTABLES pKbdTbl = NULL;
1665 UINT ret = 0;
1666
1667 TRACE("Enter NtUserMapVirtualKeyEx\n");
1669
1670 if (!dwhkl)
1671 {
1672 PTHREADINFO pti;
1673
1675 if (pti && pti->KeyboardLayout)
1676 pKbdTbl = pti->KeyboardLayout->spkf->pKbdTbl;
1677 }
1678 else
1679 {
1680 PKL pKl;
1681
1682 pKl = UserHklToKbl(dwhkl);
1683 if (pKl)
1684 pKbdTbl = pKl->spkf->pKbdTbl;
1685 }
1686
1687 if (pKbdTbl)
1688 ret = IntMapVirtualKeyEx(uCode, uType, pKbdTbl);
1689
1690 UserLeave();
1691 TRACE("Leave NtUserMapVirtualKeyEx, ret=%u\n", ret);
1692 return ret;
1693}
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:1616

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 1702 of file keyboard.c.

1710{
1711 PTHREADINFO pti;
1712 BYTE afKeyState[256 * 2 / 8] = {0};
1713 PWCHAR pwszBuff = NULL;
1714 INT i, iRet = 0;
1715 PKL pKl = NULL;
1717
1718 TRACE("Enter NtUserSetKeyboardState\n");
1719
1720 /* Return 0 if SC_KEY_UP bit is set */
1721 if (wScanCode & SC_KEY_UP || wVirtKey >= 0x100)
1722 {
1723 ERR("Invalid parameter\n");
1724 return 0;
1725 }
1726
1727 _SEH2_TRY
1728 {
1729 /* Probe and copy key state to smaller bitmap */
1730 ProbeForRead(pKeyStateUnsafe, 256 * sizeof(BYTE), 1);
1731 for (i = 0; i < 256; ++i)
1732 {
1733 if (pKeyStateUnsafe[i] & KS_DOWN_BIT)
1734 SET_KEY_DOWN(afKeyState, i, TRUE);
1735 if (pKeyStateUnsafe[i] & KS_LOCK_BIT)
1736 SET_KEY_LOCKED(afKeyState, i, TRUE);
1737 }
1738 }
1740 {
1741 ERR("Cannot copy key state\n");
1743 _SEH2_YIELD(return 0);
1744 }
1745 _SEH2_END;
1746
1747 pwszBuff = ExAllocatePoolWithTag(NonPagedPool, sizeof(WCHAR) * cchBuff, TAG_STRING);
1748 if (!pwszBuff)
1749 {
1750 ERR("ExAllocatePoolWithTag(%u) failed\n", sizeof(WCHAR) * cchBuff);
1751 return 0;
1752 }
1753 RtlZeroMemory(pwszBuff, sizeof(WCHAR) * cchBuff);
1754
1755 UserEnterExclusive(); // Note: We modify wchDead static variable
1756
1757 if (dwhkl)
1758 pKl = UserHklToKbl(dwhkl);
1759
1760 if (!pKl)
1761 {
1763 pKl = pti->KeyboardLayout;
1764 }
1765
1766 if (pKl)
1767 {
1768 iRet = IntToUnicodeEx(wVirtKey,
1769 wScanCode,
1770 afKeyState,
1771 pwszBuff,
1772 cchBuff,
1773 wFlags,
1774 pKl->spkf->pKbdTbl);
1775
1776 if (iRet)
1777 {
1778 Status = MmCopyToCaller(pwszBuffUnsafe, pwszBuff, cchBuff * sizeof(WCHAR));
1779 }
1780 }
1781 else
1782 {
1783 ERR("No keyboard layout ?!\n");
1785 }
1786
1787 ExFreePoolWithTag(pwszBuff, TAG_STRING);
1788
1789 if (!NT_SUCCESS(Status))
1790 {
1791 iRet = 0;
1793 }
1794
1795 UserLeave();
1796 TRACE("Leave NtUserSetKeyboardState, ret=%i\n", iRet);
1797 return iRet;
1798}
#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:104
#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:107
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 1932 of file keyboard.c.

1936{
1937 PKBDTABLES pKbdTbl;
1938 PVK_TO_WCHAR_TABLE pVkToWchTbl;
1939 PVK_TO_WCHARS10 pVkToWch;
1940 PKL pKl = NULL;
1941 DWORD i, dwModBits = 0, dwModNumber = 0, Ret = (DWORD)-1;
1942
1943 TRACE("NtUserVkKeyScanEx() wch %u, KbdLayout 0x%p\n", wch, dwhkl);
1945
1946 if (bUsehKL)
1947 {
1948 // Use given keyboard layout
1949 if (dwhkl)
1950 pKl = UserHklToKbl(dwhkl);
1951 }
1952 else
1953 {
1954 // Use thread keyboard layout
1955 pKl = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->KeyboardLayout;
1956 }
1957
1958 if (!pKl)
1959 goto Exit;
1960
1961 pKbdTbl = pKl->spkf->pKbdTbl;
1962
1963 // Interate through all VkToWchar tables while pVkToWchars is not NULL
1964 for (i = 0; pKbdTbl->pVkToWcharTable[i].pVkToWchars; i++)
1965 {
1966 pVkToWchTbl = &pKbdTbl->pVkToWcharTable[i];
1967 pVkToWch = (PVK_TO_WCHARS10)(pVkToWchTbl->pVkToWchars);
1968
1969 // Interate through all virtual keys
1970 while (pVkToWch->VirtualKey)
1971 {
1972 for (dwModNumber = 0; dwModNumber < pVkToWchTbl->nModifications; dwModNumber++)
1973 {
1974 if (pVkToWch->wch[dwModNumber] == wch)
1975 {
1976 dwModBits = pKbdTbl->pCharModifiers->ModNumber[dwModNumber];
1977 TRACE("i %lu wC %04x: dwModBits %08x dwModNumber %08x MaxModBits %08x\n",
1978 i, wch, dwModBits, dwModNumber, pKbdTbl->pCharModifiers->wMaxModBits);
1979 Ret = (dwModBits << 8) | (pVkToWch->VirtualKey & 0xFF);
1980 goto Exit;
1981 }
1982 }
1983 pVkToWch = (PVK_TO_WCHARS10)(((BYTE *)pVkToWch) + pVkToWchTbl->cbSize);
1984 }
1985 }
1986Exit:
1987 UserLeave();
1988 return Ret;
1989}
#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 1107 of file keyboard.c.

1108{
1109 WORD wSimpleVk, wFixedVk, wVk2;
1110 PUSER_MESSAGE_QUEUE pFocusQueue;
1111 PTHREADINFO pti;
1113 BOOL bIsDown = (dwFlags & KEYEVENTF_KEYUP) ? FALSE : TRUE;
1114 BOOL bPacket = (dwFlags & KEYEVENTF_UNICODE) ? TRUE : FALSE;
1115 BOOL bWasSimpleDown = FALSE, bPostMsg = TRUE, bIsSimpleDown;
1116 MSG Msg;
1117 static BOOL bMenuDownRecently = FALSE;
1118 BOOL bLangToggled = FALSE;
1119
1120 /* Get virtual key without shifts (VK_(L|R)* -> VK_*) */
1121 wSimpleVk = IntSimplifyVk(wVk);
1122
1124 {
1125 /* Japanese special! */
1127 {
1128 if (wSimpleVk == VK_OEM_ATTN)
1129 wSimpleVk = VK_CAPITAL;
1130 else if (wSimpleVk == VK_OEM_COPY)
1131 wSimpleVk = VK_OEM_FINISH;
1132 }
1133 }
1134
1135 /* Handle Alt+Numpad character composition */
1136 if (IntHandleAltNumpad(wSimpleVk, bIsDown, dwTime))
1137 return TRUE;
1138
1139 bWasSimpleDown = IS_KEY_DOWN(gafAsyncKeyState, wSimpleVk);
1140
1141 /* Update key without shifts */
1142 wVk2 = IntFixVk(wSimpleVk, !bExt);
1143 bIsSimpleDown = bIsDown || IS_KEY_DOWN(gafAsyncKeyState, wVk2);
1144 UpdateAsyncKeyState(wSimpleVk, bIsSimpleDown);
1145
1146 if (bIsDown)
1147 {
1148 /* Update keyboard LEDs */
1150 wSimpleVk,
1151 wScanCode);
1152 }
1153
1154 /* Call WH_KEYBOARD_LL hook */
1155 if (co_CallLowLevelKeyboardHook(wVk, wScanCode, dwFlags, bInjected, dwTime, dwExtraInfo))
1156 {
1157 ERR("Kbd msg dropped by WH_KEYBOARD_LL hook\n");
1158 bPostMsg = FALSE;
1159 }
1160
1161 /* Check if this is a hotkey */
1162 if (co_UserProcessHotKeys(wSimpleVk, bIsDown))
1163 {
1164 TRACE("HotKey Processed\n");
1165 bPostMsg = FALSE;
1166 }
1167
1168 wFixedVk = IntFixVk(wSimpleVk, bExt); /* LSHIFT + EXT = RSHIFT */
1169 if (wSimpleVk == VK_SHIFT) /* shift can't be extended */
1170 bExt = FALSE;
1171
1172 /* If we have a focus queue, post a keyboard message */
1173 pFocusQueue = IntGetFocusMessageQueue();
1174 TRACE("ProcessKeyEvent Q 0x%p Active pWnd 0x%p Focus pWnd 0x%p\n",
1175 pFocusQueue,
1176 (pFocusQueue ? pFocusQueue->spwndActive : NULL),
1177 (pFocusQueue ? pFocusQueue->spwndFocus : NULL));
1178
1179 /* If it is F10 or ALT is down and CTRL is up, it's a system key */
1180 if ( wVk == VK_F10 ||
1181 (wSimpleVk == VK_MENU && bMenuDownRecently) ||
1184 // See MSDN WM_SYSKEYDOWN/UP fixes last wine Win test_keyboard_input.
1185 (pFocusQueue && !pFocusQueue->spwndFocus) )
1186 {
1187 bMenuDownRecently = FALSE; // reset
1188 if (bIsDown)
1189 {
1190 Msg.message = WM_SYSKEYDOWN;
1191 if (wSimpleVk == VK_MENU)
1192 {
1193 // Note: If only LALT is pressed WM_SYSKEYUP is generated instead of WM_KEYUP
1194 bMenuDownRecently = TRUE;
1195 }
1196 }
1197 else
1198 Msg.message = WM_SYSKEYUP;
1199 }
1200 else
1201 {
1202 if (bIsDown)
1203 Msg.message = WM_KEYDOWN;
1204 else
1205 Msg.message = WM_KEYUP;
1206 }
1207
1208 /* Update async state of not simplified vk here.
1209 See user32_apitest:GetKeyState */
1210 UpdateAsyncKeyState(wFixedVk, bIsDown);
1211
1212 /* Alt-Tab/Esc Check. Use FocusQueue or RIT Queue */
1213 if (bIsSimpleDown && !bWasSimpleDown &&
1216 (wVk == VK_ESCAPE || wVk == VK_TAB))
1217 {
1218 TRACE("Alt-Tab/Esc Pressed wParam %x\n",wVk);
1219 }
1220
1221 /*
1222 * Check Language/Layout Toggle by [Left Alt]+Shift or Ctrl+Shift.
1223 * @see https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc976564%28v=technet.10%29
1224 */
1226 {
1227 if (wSimpleVk == VK_SHIFT) /* Shift key is pressed or released */
1228 {
1229 UINT targetKey = ((gdwLanguageToggleKey == 1) ? VK_LMENU : VK_CONTROL);
1230 if (IS_KEY_DOWN(gafAsyncKeyState, targetKey))
1231 bLangToggled = IntCheckLanguageToggle(pFocusQueue, bIsDown, wVk, &gLanguageToggleKeyState);
1232 }
1233 else if ((wSimpleVk == VK_MENU && gdwLanguageToggleKey == 1) ||
1234 (wSimpleVk == VK_CONTROL && gdwLanguageToggleKey == 2))
1235 {
1237 bLangToggled = IntCheckLanguageToggle(pFocusQueue, bIsDown, 0, &gLanguageToggleKeyState);
1238 }
1239 }
1240 if (!bLangToggled && (gdwLayoutToggleKey == 1 || gdwLayoutToggleKey == 2))
1241 {
1242 if (wSimpleVk == VK_SHIFT) /* Shift key is pressed or released */
1243 {
1244 UINT targetKey = ((gdwLayoutToggleKey == 1) ? VK_LMENU : VK_CONTROL);
1245 if (IS_KEY_DOWN(gafAsyncKeyState, targetKey))
1246 IntCheckLanguageToggle(pFocusQueue, bIsDown, wVk, &gLayoutToggleKeyState);
1247 }
1248 else if ((wSimpleVk == VK_MENU && gdwLayoutToggleKey == 1) ||
1249 (wSimpleVk == VK_CONTROL && gdwLayoutToggleKey == 2))
1250 {
1252 IntCheckLanguageToggle(pFocusQueue, bIsDown, 0, &gLayoutToggleKeyState);
1253 }
1254 }
1255
1256 if (bIsDown && wVk == VK_SNAPSHOT)
1257 {
1258 if (pFocusQueue &&
1261 {
1262 // Snap from Active Window, Focus can be null.
1263 SnapWindow(pFocusQueue->spwndActive ? UserHMGetHandle(pFocusQueue->spwndActive) : NULL);
1264 }
1265 else
1266 SnapWindow(NULL); // Snap Desktop.
1267 }
1268 else if (pFocusQueue && bPostMsg)
1269 {
1270 PWND Wnd = pFocusQueue->spwndFocus; // SysInit.....
1271
1272 pti = pFocusQueue->ptiKeyboard;
1273
1274 if (!Wnd && pFocusQueue->spwndActive) // SysInit.....
1275 {
1276 // Going with Active. WM_SYSKEYXXX last wine Win test_keyboard_input.
1277 Wnd = pFocusQueue->spwndActive;
1278 }
1279 if (Wnd) pti = Wnd->head.pti;
1280
1281 /* Init message */
1282 Msg.hwnd = Wnd ? UserHMGetHandle(Wnd) : NULL;
1283 Msg.wParam = wFixedVk & 0xFF; /* Note: It's simplified by msg queue */
1284 Msg.lParam = MAKELPARAM(1, wScanCode);
1285 Msg.time = dwTime;
1286 Msg.pt = gpsi->ptCursor;
1287
1288 if ( Msg.message == WM_KEYDOWN || Msg.message == WM_SYSKEYDOWN )
1289 {
1290 if ( (Msg.wParam == VK_SHIFT ||
1291 Msg.wParam == VK_CONTROL ||
1292 Msg.wParam == VK_MENU ) &&
1294 {
1295 ERR("Set last input\n");
1296 //ptiLastInput = pti;
1297 }
1298 }
1299
1300 /* If it is VK_PACKET, high word of wParam is used for wchar */
1301 if (!bPacket)
1302 {
1303 if (bExt)
1304 Msg.lParam |= KF_EXTENDED << 16;
1306 Msg.lParam |= KF_ALTDOWN << 16;
1307 if (bWasSimpleDown)
1308 Msg.lParam |= KF_REPEAT << 16;
1309 if (!bIsDown)
1310 Msg.lParam |= KF_UP << 16;
1311 /* FIXME: Set KF_DLGMODE and KF_MENUMODE when needed */
1312 if (pFocusQueue->QF_flags & QF_DIALOGACTIVE)
1313 Msg.lParam |= KF_DLGMODE << 16;
1314 if (pFocusQueue->MenuOwner) // pti->pMenuState->fMenuStarted
1315 Msg.lParam |= KF_MENUMODE << 16;
1316 }
1317
1318 // Post mouse move before posting key buttons, to keep it syned.
1319 if (pFocusQueue->QF_flags & QF_MOUSEMOVED)
1320 {
1322 }
1323
1324 /* Post a keyboard message */
1325 TRACE("Posting keyboard msg %u wParam 0x%x lParam 0x%x\n", Msg.message, Msg.wParam, Msg.lParam);
1326 if (!Wnd) {ERR("Window is NULL\n");}
1327 MsqPostMessage(pti, &Msg, TRUE, QS_KEY, 0, dwExtraInfo);
1328 }
1329 return TRUE;
1330}
struct @1743 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:26
static NTSTATUS APIENTRY IntKeyboardUpdateLeds(HANDLE hKeyboardDevice, WORD wVk, WORD wScanCode)
Definition: keyboard.c:124
static VOID SnapWindow(HWND hWnd)
Definition: keyboard.c:740
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:871
static LRESULT co_CallLowLevelKeyboardHook(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
Definition: keyboard.c:704
static BOOL IntHandleAltNumpad(_In_ WORD wVk, _In_ BOOL bIsDown, _In_ DWORD dwTime)
Handles Alt+Numpad character composition.
Definition: keyboard.c:916
static VOID NTAPI UpdateAsyncKeyState(WORD wVk, BOOL bIsDown)
Definition: keyboard.c:683
static 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 740 of file keyboard.c.

741{
742 HBITMAP hbm = NULL, hbmOld;
743 HDC hdc = NULL, hdcMem;
744 SETCLIPBDATA scd;
745 INT cx, cy;
746 PWND pWnd = NULL;
747
748 TRACE("SnapWindow(%p)\n", hWnd);
749
750 /* If no windows is given, make snapshot of desktop window */
751 if (!hWnd)
753
755 if (!pWnd)
756 {
757 ERR("Invalid window\n");
758 goto cleanup;
759 }
760
762 if (!hdc)
763 {
764 ERR("UserGetDCEx failed!\n");
765 goto cleanup;
766 }
767
768 cx = pWnd->rcWindow.right - pWnd->rcWindow.left;
769 cy = pWnd->rcWindow.bottom - pWnd->rcWindow.top;
770
772 if (!hbm)
773 {
774 ERR("NtGdiCreateCompatibleBitmap failed!\n");
775 goto cleanup;
776 }
777
779 if (!hdcMem)
780 {
781 ERR("NtGdiCreateCompatibleDC failed!\n");
782 goto cleanup;
783 }
784
785 hbmOld = NtGdiSelectBitmap(hdcMem, hbm);
786 NtGdiBitBlt(hdcMem, 0, 0, cx, cy, hdc, 0, 0, SRCCOPY, CLR_INVALID, 0);
787 NtGdiSelectBitmap(hdcMem, hbmOld);
789
790 /* Save snapshot in clipboard */
792 {
795 scd.fGlobalHandle = FALSE;
797 {
798 /* Bitmap is managed by system now */
799 hbm = NULL;
800 }
802 }
803
804cleanup:
805 if (hbm)
807 if (hdc)
808 UserReleaseDC(pWnd, hdc, FALSE);
809}
#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 683 of file keyboard.c.

684{
685 if (bIsDown)
686 {
687 /* If it's first key down event, xor lock bit */
688 if (!IS_KEY_DOWN(gafAsyncKeyState, wVk))
690
692 gafAsyncKeyStateRecentDown[wVk / 8] |= (1 << (wVk % 8));
693 }
694 else
696}

Referenced by ProcessKeyEvent().

◆ UserGetKeyboardType()

DWORD FASTCALL UserGetKeyboardType ( DWORD  dwTypeFlag)

Definition at line 1907 of file keyboard.c.

1909{
1910 switch (dwTypeFlag)
1911 {
1912 case 0: /* Keyboard type */
1914 case 1: /* Keyboard Subtype */
1916 case 2: /* Number of F-keys */
1918 default:
1919 ERR("Unknown type!\n");
1920 return 0; /* Note: we don't have to set last error here */
1921 }
1922}
UCHAR Subtype
Definition: ntddkbd.h:102

Referenced by NtUserCallOneParam().

◆ UserInitKeyboard()

VOID NTAPI UserInitKeyboard ( HANDLE  hKeyboardDevice)

Definition at line 178 of file keyboard.c.

179{
181 IO_STATUS_BLOCK Block;
182
184
185 Status = ZwDeviceIoControlFile(hKeyboardDevice,
186 NULL,
187 NULL,
188 NULL,
189 &Block,
191 NULL, 0,
193 sizeof(gIndicators));
194
195 if (!NT_SUCCESS(Status))
196 {
197 WARN("NtDeviceIoControlFile() failed, ignored\n");
200 }
201
208
209 // FIXME: Need device driver to work! HID support more than one!!!!
210 Status = ZwDeviceIoControlFile(hKeyboardDevice,
211 NULL,
212 NULL,
213 NULL,
214 &Block,
216 NULL, 0,
217 &gKeyboardInfo, sizeof(gKeyboardInfo));
218
219 if (!NT_SUCCESS(Status))
220 {
221 ERR("NtDeviceIoControlFile() failed, ignored\n");
222 }
223 TRACE("Keyboard type %u, subtype %u and number of func keys %u\n",
227}
#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:67

Referenced by RawInputThreadMain().

◆ UserProcessKeyboardInput()

VOID NTAPI UserProcessKeyboardInput ( PKEYBOARD_INPUT_DATA  pKbdInputData)

Definition at line 1414 of file keyboard.c.

1416{
1417 WORD wScanCode, wVk;
1418 PKL pKl = NULL;
1419 PKBDTABLES pKbdTbl;
1420 PUSER_MESSAGE_QUEUE pFocusQueue;
1421
1422 /* Calculate scan code with prefix */
1423 wScanCode = pKbdInputData->MakeCode & 0x7F;
1424 if (pKbdInputData->Flags & KEY_E0)
1425 wScanCode |= 0xE000;
1426 if (pKbdInputData->Flags & KEY_E1)
1427 wScanCode |= 0xE100;
1428
1429 /* Find the target thread whose locale is in effect */
1430 pFocusQueue = IntGetFocusMessageQueue();
1431
1432 if (pFocusQueue && pFocusQueue->ptiKeyboard)
1433 {
1434 pKl = pFocusQueue->ptiKeyboard->KeyboardLayout;
1435 }
1436
1437 if (!pKl)
1439 if (!pKl)
1440 return;
1441
1442 pKbdTbl = pKl->spkf->pKbdTbl;
1443
1444 /* Convert scan code to virtual key.
1445 Note: We could call UserSendKeyboardInput using scan code,
1446 but it wouldn't interpret E1 key(s) properly */
1447 wVk = IntVscToVk(wScanCode, pKbdTbl);
1448 TRACE("UserProcessKeyboardInput: %x (break: %u) -> %x\n",
1449 wScanCode, (pKbdInputData->Flags & KEY_BREAK) ? 1u : 0, wVk);
1450
1451 if (wVk)
1452 {
1453 KEYBDINPUT KbdInput;
1454
1455 /* Support numlock */
1457 {
1458 wVk = IntTranslateNumpadKey(wVk & 0xFF);
1459 }
1460
1461 /* Send keyboard input */
1462 KbdInput.wVk = wVk & 0xFF;
1463 KbdInput.wScan = wScanCode & 0x7F;
1464 KbdInput.dwFlags = 0;
1465 if (pKbdInputData->Flags & KEY_BREAK)
1466 KbdInput.dwFlags |= KEYEVENTF_KEYUP;
1467
1468 if (wVk & KBDEXT)
1469 KbdInput.dwFlags |= KEYEVENTF_EXTENDEDKEY;
1470 //
1471 // Based on wine input:test_Input_blackbox this is okay. It seems the
1472 // bit did not get set and more research is needed. Now the right
1473 // shift works.
1474 //
1475 if (wVk == VK_RSHIFT)
1476 KbdInput.dwFlags |= KEYEVENTF_EXTENDEDKEY;
1477
1478 KbdInput.time = 0;
1479 KbdInput.dwExtraInfo = pKbdInputData->ExtraInformation;
1480 UserSendKeyboardInput(&KbdInput, FALSE);
1481
1482 /* E1 keys don't have break code */
1483 if (pKbdInputData->Flags & KEY_E1)
1484 {
1485 /* Send key up event */
1486 KbdInput.dwFlags |= KEYEVENTF_KEYUP;
1487 UserSendKeyboardInput(&KbdInput, FALSE);
1488 }
1489 }
1490}
#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:1333
static WORD IntTranslateNumpadKey(WORD wVk)
Definition: keyboard.c:289

Referenced by RawInputThreadMain().

◆ UserSendKeyboardInput()

BOOL NTAPI UserSendKeyboardInput ( KEYBDINPUT pKbdInput,
BOOL  bInjected 
)

Definition at line 1333 of file keyboard.c.

1334{
1335 WORD wScanCode, wVk;
1336 PKL pKl = NULL;
1337 PKBDTABLES pKbdTbl;
1338 PUSER_MESSAGE_QUEUE pFocusQueue;
1339 DWORD dwTime;
1340 BOOL bExt = (pKbdInput->dwFlags & KEYEVENTF_EXTENDEDKEY) ? TRUE : FALSE;
1341
1343
1344 /* Find the target thread whose locale is in effect */
1345 pFocusQueue = IntGetFocusMessageQueue();
1346
1347 if (pFocusQueue && pFocusQueue->ptiKeyboard)
1348 {
1349 pKl = pFocusQueue->ptiKeyboard->KeyboardLayout;
1350 }
1351
1352 if (!pKl)
1354 if (!pKl)
1355 {
1356 ERR("No keyboard layout!\n");
1357 return FALSE;
1358 }
1359
1360 pKbdTbl = pKl->spkf->pKbdTbl;
1361
1362 /* Note: wScan field is always used */
1363 wScanCode = pKbdInput->wScan;
1364
1365 if (pKbdInput->dwFlags & KEYEVENTF_UNICODE)
1366 {
1367 /* Generate WM_KEYDOWN msg with wParam == VK_PACKET and
1368 high order word of lParam == pKbdInput->wScan */
1369 wVk = VK_PACKET;
1370 }
1371 else
1372 {
1373 wScanCode &= 0x7F;
1374 if (pKbdInput->dwFlags & KEYEVENTF_SCANCODE)
1375 {
1376 /* Don't ignore invalid scan codes */
1377 wVk = IntVscToVk(wScanCode | (bExt ? 0xE000 : 0), pKbdTbl);
1378 if (!wVk) /* use 0xFF if vsc is invalid */
1379 wVk = 0xFF;
1380 }
1381 else
1382 {
1383 wVk = pKbdInput->wVk;
1384 }
1385
1386 /* Remove all virtual key flags (KBDEXT, KBDMULTIVK, KBDSPECIAL, KBDNUMPAD) */
1387 wVk &= 0xFF;
1388 }
1389
1390 /* If time is given, use it */
1391 if (pKbdInput->time)
1392 dwTime = pKbdInput->time;
1393 else
1394 {
1396 }
1397
1398 if (wVk == VK_RMENU && (pKbdTbl->fLocaleFlags & KLLF_ALTGR))
1399 {
1400 /* For AltGr keyboards RALT generates CTRL events */
1401 ProcessKeyEvent(VK_LCONTROL, 0, pKbdInput->dwFlags & KEYEVENTF_KEYUP, bInjected, dwTime, 0);
1402 }
1403
1404 /* Finally process this key */
1405 return ProcessKeyEvent(wVk, wScanCode, pKbdInput->dwFlags, bInjected, dwTime, pKbdInput->dwExtraInfo);
1406}
PPROCESSINFO gppiInputProvider
Definition: ntuser.c:16
BOOL NTAPI ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
Definition: keyboard.c:1107

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 35 of file keyboard.c.

Referenced by IntHandleAltNumpad().

◆ gbEnableHexNumpad

BOOL gbEnableHexNumpad = FALSE

Definition at line 36 of file keyboard.c.

Referenced by IntHandleAltNumpad(), and SpiUpdatePerUserSystemParameters().

◆ 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
static

Definition at line 18 of file keyboard.c.

Referenced by ProcessKeyEvent().

◆ gLayoutToggleKeyState

INT gLayoutToggleKeyState = 0
static

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().