mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 13:43:36 +00:00
[NTUSER] Implement NtUserSetImeHotKey (#4350)
- Modify NtUserGetImeHotKey and NtUserSetImeHotKey prototypes. - Define enum SETIMEHOTKEY_ACTION in <undocuser.h>. - Define IMEHOTKEY structure in ime.c. - Add IntGetImeHotKeyLangId, IntAddImeHotKey, IntGetImeHotKeyById, IntGetImeHotKeyByKeyAndLang, IntDeleteImeHotKey, IntFreeImeHotKeys, and IntSetImeHotKey helper functions. - Implement NtUserGetImeHotKey and NtUserSetImeHotKey functions. - Cleanup the IME hotkeys at process exit. CORE-11700
This commit is contained in:
parent
e0fc48d6e2
commit
5d5cc57869
5 changed files with 280 additions and 36 deletions
|
@ -394,6 +394,14 @@ typedef enum _QUERY_INPUT_CONTEXT
|
||||||
QIC_DEFAULTIMC
|
QIC_DEFAULTIMC
|
||||||
} QUERY_INPUT_CONTEXT;
|
} QUERY_INPUT_CONTEXT;
|
||||||
|
|
||||||
|
/* NtUserSetImeHotKey actions */
|
||||||
|
typedef enum tagSETIMEHOTKEY_ACTION
|
||||||
|
{
|
||||||
|
SETIMEHOTKEY_DELETE = 1,
|
||||||
|
SETIMEHOTKEY_ADD,
|
||||||
|
SETIMEHOTKEY_DELETEALL
|
||||||
|
} SETIMEHOTKEY_ACTION;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif /* defined(__cplusplus) */
|
#endif /* defined(__cplusplus) */
|
||||||
|
|
|
@ -2388,11 +2388,12 @@ NtUserGetIconSize(
|
||||||
LONG *plcx,
|
LONG *plcx,
|
||||||
LONG *plcy);
|
LONG *plcy);
|
||||||
|
|
||||||
BOOL NTAPI
|
BOOL
|
||||||
NtUserGetImeHotKey(IN DWORD dwHotKey,
|
NTAPI
|
||||||
OUT LPUINT lpuModifiers,
|
NtUserGetImeHotKey(DWORD dwHotKeyId,
|
||||||
OUT LPUINT lpuVKey,
|
LPUINT lpuModifiers,
|
||||||
OUT LPHKL lphKL);
|
LPUINT lpuVirtualKey,
|
||||||
|
LPHKL lphKL);
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -3184,14 +3185,14 @@ NTAPI
|
||||||
NtUserSetFocus(
|
NtUserSetFocus(
|
||||||
HWND hWnd);
|
HWND hWnd);
|
||||||
|
|
||||||
DWORD
|
BOOL
|
||||||
NTAPI
|
NTAPI
|
||||||
NtUserSetImeHotKey(
|
NtUserSetImeHotKey(
|
||||||
DWORD Unknown0,
|
DWORD dwHotKeyId,
|
||||||
DWORD Unknown1,
|
UINT uModifiers,
|
||||||
DWORD Unknown2,
|
UINT uVirtualKey,
|
||||||
DWORD Unknown3,
|
HKL hKL,
|
||||||
DWORD Unknown4);
|
DWORD dwAction);
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
NTAPI
|
NTAPI
|
||||||
|
|
|
@ -11,6 +11,14 @@
|
||||||
DBG_DEFAULT_CHANNEL(UserMisc);
|
DBG_DEFAULT_CHANNEL(UserMisc);
|
||||||
|
|
||||||
#define INVALID_THREAD_ID ((ULONG)-1)
|
#define INVALID_THREAD_ID ((ULONG)-1)
|
||||||
|
#define MOD_KEYS (MOD_CONTROL | MOD_SHIFT | MOD_ALT | MOD_WIN)
|
||||||
|
#define MOD_LEFT_RIGHT (MOD_LEFT | MOD_RIGHT)
|
||||||
|
|
||||||
|
#define LANGID_CHINESE_SIMPLIFIED MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
|
||||||
|
#define LANGID_JAPANESE MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT)
|
||||||
|
#define LANGID_KOREAN MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN)
|
||||||
|
#define LANGID_CHINESE_TRADITIONAL MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
|
||||||
|
#define LANGID_NEUTRAL MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
|
||||||
|
|
||||||
#define IS_WND_IMELIKE(pwnd) \
|
#define IS_WND_IMELIKE(pwnd) \
|
||||||
(((pwnd)->pcls->style & CS_IME) || \
|
(((pwnd)->pcls->style & CS_IME) || \
|
||||||
|
@ -37,6 +45,255 @@ HIMC ghIMC = NULL;
|
||||||
BOOL gfImeOpen = (BOOL)-1;
|
BOOL gfImeOpen = (BOOL)-1;
|
||||||
DWORD gdwImeConversion = (DWORD)-1;
|
DWORD gdwImeConversion = (DWORD)-1;
|
||||||
|
|
||||||
|
typedef struct tagIMEHOTKEY
|
||||||
|
{
|
||||||
|
struct tagIMEHOTKEY *pNext;
|
||||||
|
DWORD dwHotKeyId;
|
||||||
|
UINT uVirtualKey;
|
||||||
|
UINT uModifiers;
|
||||||
|
HKL hKL;
|
||||||
|
} IMEHOTKEY, *PIMEHOTKEY;
|
||||||
|
|
||||||
|
PIMEHOTKEY gpImeHotKeyList = NULL;
|
||||||
|
|
||||||
|
static LANGID FASTCALL IntGetImeHotKeyLangId(DWORD dwHotKeyId)
|
||||||
|
{
|
||||||
|
#define IME_CHOTKEY 0x10
|
||||||
|
#define IME_JHOTKEY 0x30
|
||||||
|
#define IME_KHOTKEY 0x50
|
||||||
|
#define IME_THOTKEY 0x70
|
||||||
|
#define IME_XHOTKEY 0x90
|
||||||
|
static const LANGID s_array[] =
|
||||||
|
{
|
||||||
|
/* 0x00 */ (WORD)-1,
|
||||||
|
/* 0x10 */ LANGID_CHINESE_SIMPLIFIED,
|
||||||
|
/* 0x20 */ LANGID_CHINESE_SIMPLIFIED,
|
||||||
|
/* 0x30 */ LANGID_JAPANESE,
|
||||||
|
/* 0x40 */ LANGID_JAPANESE,
|
||||||
|
/* 0x50 */ LANGID_KOREAN,
|
||||||
|
/* 0x60 */ LANGID_KOREAN,
|
||||||
|
/* 0x70 */ LANGID_CHINESE_TRADITIONAL,
|
||||||
|
/* 0x80 */ LANGID_CHINESE_TRADITIONAL
|
||||||
|
};
|
||||||
|
|
||||||
|
if (IME_CHOTKEY <= dwHotKeyId && dwHotKeyId < IME_XHOTKEY)
|
||||||
|
return s_array[(dwHotKeyId & 0xF0) >> 4];
|
||||||
|
return LANGID_NEUTRAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FASTCALL IntAddImeHotKey(PIMEHOTKEY *ppList, PIMEHOTKEY pHotKey)
|
||||||
|
{
|
||||||
|
PIMEHOTKEY pNode;
|
||||||
|
|
||||||
|
if (!*ppList)
|
||||||
|
{
|
||||||
|
*ppList = pHotKey;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (pNode = *ppList; pNode; pNode = pNode->pNext)
|
||||||
|
{
|
||||||
|
if (!pNode->pNext)
|
||||||
|
{
|
||||||
|
pNode->pNext = pHotKey;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PIMEHOTKEY FASTCALL IntGetImeHotKeyById(PIMEHOTKEY pList, DWORD dwHotKeyId)
|
||||||
|
{
|
||||||
|
PIMEHOTKEY pNode;
|
||||||
|
for (pNode = pList; pNode; pNode = pNode->pNext)
|
||||||
|
{
|
||||||
|
if (pNode->dwHotKeyId == dwHotKeyId)
|
||||||
|
return pNode;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PIMEHOTKEY APIENTRY
|
||||||
|
IntGetImeHotKeyByKeyAndLang(PIMEHOTKEY pList, UINT uModKeys, UINT uLeftRight,
|
||||||
|
UINT uVirtualKey, LANGID TargetLangId)
|
||||||
|
{
|
||||||
|
PIMEHOTKEY pNode;
|
||||||
|
LANGID LangID;
|
||||||
|
UINT uModifiers;
|
||||||
|
|
||||||
|
for (pNode = pList; pNode; pNode = pNode->pNext)
|
||||||
|
{
|
||||||
|
if (pNode->uVirtualKey != uVirtualKey)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
LangID = IntGetImeHotKeyLangId(pNode->dwHotKeyId);
|
||||||
|
if (LangID != TargetLangId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uModifiers = pNode->uModifiers;
|
||||||
|
if (uModifiers & MOD_IGNORE_ALL_MODIFIER)
|
||||||
|
return pNode;
|
||||||
|
|
||||||
|
if ((uModifiers & MOD_KEYS) != uModKeys)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((uModifiers & uLeftRight) || (uModifiers & MOD_LEFT_RIGHT) == uLeftRight)
|
||||||
|
return pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FASTCALL IntDeleteImeHotKey(PIMEHOTKEY *ppList, PIMEHOTKEY pHotKey)
|
||||||
|
{
|
||||||
|
PIMEHOTKEY pNode;
|
||||||
|
|
||||||
|
if (*ppList == pHotKey)
|
||||||
|
{
|
||||||
|
*ppList = pHotKey->pNext;
|
||||||
|
ExFreePoolWithTag(pHotKey, USERTAG_IMEHOTKEY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (pNode = *ppList; pNode; pNode = pNode->pNext)
|
||||||
|
{
|
||||||
|
if (pNode->pNext == pHotKey)
|
||||||
|
{
|
||||||
|
pNode->pNext = pHotKey->pNext;
|
||||||
|
ExFreePoolWithTag(pHotKey, USERTAG_IMEHOTKEY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FASTCALL IntFreeImeHotKeys(VOID)
|
||||||
|
{
|
||||||
|
PIMEHOTKEY pNode, pNext;
|
||||||
|
for (pNode = gpImeHotKeyList; pNode; pNode = pNext)
|
||||||
|
{
|
||||||
|
pNext = pNode->pNext;
|
||||||
|
ExFreePoolWithTag(pNode, USERTAG_IMEHOTKEY);
|
||||||
|
}
|
||||||
|
gpImeHotKeyList = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL APIENTRY
|
||||||
|
IntSetImeHotKey(DWORD dwHotKeyId, UINT uModifiers, UINT uVirtualKey, HKL hKL, DWORD dwAction)
|
||||||
|
{
|
||||||
|
PIMEHOTKEY pNode;
|
||||||
|
LANGID LangId;
|
||||||
|
|
||||||
|
switch (dwAction)
|
||||||
|
{
|
||||||
|
case SETIMEHOTKEY_DELETE:
|
||||||
|
pNode = IntGetImeHotKeyById(gpImeHotKeyList, dwHotKeyId);
|
||||||
|
if (!pNode)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
IntDeleteImeHotKey(&gpImeHotKeyList, pNode);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case SETIMEHOTKEY_ADD:
|
||||||
|
if (uVirtualKey == VK_PACKET)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
LangId = IntGetImeHotKeyLangId(dwHotKeyId);
|
||||||
|
if (LangId == LANGID_KOREAN)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
pNode = IntGetImeHotKeyByKeyAndLang(gpImeHotKeyList,
|
||||||
|
(uModifiers & MOD_KEYS),
|
||||||
|
(uModifiers & MOD_LEFT_RIGHT),
|
||||||
|
uVirtualKey, LangId);
|
||||||
|
if (!pNode)
|
||||||
|
pNode = IntGetImeHotKeyById(gpImeHotKeyList, dwHotKeyId);
|
||||||
|
|
||||||
|
if (pNode)
|
||||||
|
{
|
||||||
|
pNode->uModifiers = uModifiers;
|
||||||
|
pNode->uVirtualKey = uVirtualKey;
|
||||||
|
pNode->hKL = hKL;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pNode = ExAllocatePoolWithTag(PagedPool, sizeof(IMEHOTKEY), USERTAG_IMEHOTKEY);
|
||||||
|
if (!pNode)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
pNode->pNext = NULL;
|
||||||
|
pNode->dwHotKeyId = dwHotKeyId;
|
||||||
|
pNode->uModifiers = uModifiers;
|
||||||
|
pNode->uVirtualKey = uVirtualKey;
|
||||||
|
pNode->hKL = hKL;
|
||||||
|
IntAddImeHotKey(&gpImeHotKeyList, pNode);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case SETIMEHOTKEY_DELETEALL:
|
||||||
|
IntFreeImeHotKeys();
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL NTAPI
|
||||||
|
NtUserGetImeHotKey(DWORD dwHotKeyId, LPUINT lpuModifiers, LPUINT lpuVirtualKey, LPHKL lphKL)
|
||||||
|
{
|
||||||
|
PIMEHOTKEY pNode = NULL;
|
||||||
|
|
||||||
|
UserEnterExclusive();
|
||||||
|
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
ProbeForWrite(lpuModifiers, sizeof(UINT), 1);
|
||||||
|
ProbeForWrite(lpuVirtualKey, sizeof(UINT), 1);
|
||||||
|
if (lphKL)
|
||||||
|
ProbeForWrite(lphKL, sizeof(HKL), 1);
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
|
||||||
|
pNode = IntGetImeHotKeyById(gpImeHotKeyList, dwHotKeyId);
|
||||||
|
if (!pNode)
|
||||||
|
goto Quit;
|
||||||
|
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
*lpuModifiers = pNode->uModifiers;
|
||||||
|
*lpuVirtualKey = pNode->uVirtualKey;
|
||||||
|
if (lphKL)
|
||||||
|
*lphKL = pNode->hKL;
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
pNode = NULL;
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
|
||||||
|
Quit:
|
||||||
|
UserLeave();
|
||||||
|
return !!pNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
NTAPI
|
||||||
|
NtUserSetImeHotKey(
|
||||||
|
DWORD dwHotKeyId,
|
||||||
|
UINT uModifiers,
|
||||||
|
UINT uVirtualKey,
|
||||||
|
HKL hKL,
|
||||||
|
DWORD dwAction)
|
||||||
|
{
|
||||||
|
BOOL ret;
|
||||||
|
UserEnterExclusive();
|
||||||
|
ret = IntSetImeHotKey(dwHotKeyId, uModifiers, uVirtualKey, hKL, dwAction);
|
||||||
|
UserLeave();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
PWND FASTCALL IntGetTopLevelWindow(PWND pwnd)
|
PWND FASTCALL IntGetTopLevelWindow(PWND pwnd)
|
||||||
{
|
{
|
||||||
if (!pwnd)
|
if (!pwnd)
|
||||||
|
@ -194,17 +451,6 @@ Quit:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI
|
|
||||||
NtUserGetImeHotKey(IN DWORD dwHotKey,
|
|
||||||
OUT LPUINT lpuModifiers,
|
|
||||||
OUT LPUINT lpuVKey,
|
|
||||||
OUT LPHKL lphKL)
|
|
||||||
{
|
|
||||||
STUB
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VOID FASTCALL UserSetImeConversionKeyState(PTHREADINFO pti, DWORD dwConversion)
|
static VOID FASTCALL UserSetImeConversionKeyState(PTHREADINFO pti, DWORD dwConversion)
|
||||||
{
|
{
|
||||||
HKL hKL;
|
HKL hKL;
|
||||||
|
@ -305,20 +551,6 @@ Quit:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD
|
|
||||||
APIENTRY
|
|
||||||
NtUserSetImeHotKey(
|
|
||||||
DWORD Unknown0,
|
|
||||||
DWORD Unknown1,
|
|
||||||
DWORD Unknown2,
|
|
||||||
DWORD Unknown3,
|
|
||||||
DWORD Unknown4)
|
|
||||||
{
|
|
||||||
STUB
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD
|
DWORD
|
||||||
APIENTRY
|
APIENTRY
|
||||||
NtUserCheckImeHotKey(
|
NtUserCheckImeHotKey(
|
||||||
|
|
|
@ -85,6 +85,7 @@ BOOL NTAPI UserSendMouseInput(MOUSEINPUT *pMouseInput, BOOL bInjected);
|
||||||
|
|
||||||
/* IMM */
|
/* IMM */
|
||||||
UINT FASTCALL IntImmProcessKey(PUSER_MESSAGE_QUEUE, PWND, UINT, WPARAM, LPARAM);
|
UINT FASTCALL IntImmProcessKey(PUSER_MESSAGE_QUEUE, PWND, UINT, WPARAM, LPARAM);
|
||||||
|
VOID FASTCALL IntFreeImeHotKeys(VOID);
|
||||||
|
|
||||||
extern DWORD gSystemFS;
|
extern DWORD gSystemFS;
|
||||||
extern UINT gSystemCPCharSet;
|
extern UINT gSystemCPCharSet;
|
||||||
|
|
|
@ -180,6 +180,8 @@ UserProcessDestroy(PEPROCESS Process)
|
||||||
if (ppiScrnSaver == ppiCurrent)
|
if (ppiScrnSaver == ppiCurrent)
|
||||||
ppiScrnSaver = NULL;
|
ppiScrnSaver = NULL;
|
||||||
|
|
||||||
|
IntFreeImeHotKeys();
|
||||||
|
|
||||||
if (gpwlCache)
|
if (gpwlCache)
|
||||||
{
|
{
|
||||||
ExFreePoolWithTag(gpwlCache, USERTAG_WINDOWLIST);
|
ExFreePoolWithTag(gpwlCache, USERTAG_WINDOWLIST);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue