mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
[USER32] Implement UnloadKeyboardLayout (#4503)
- Add IntSetFeKeyboardFlags, CliImmSetHotKeyWorker, CliSetDefaultImeHotKeys, CliGetPreloadKeyboardLayouts, CliGetImeHotKeysFromRegistry, CliImmInitializeHotKeys, CliSetSingleHotKey, and CliReadRegistryValue helper functions. CORE-11700
This commit is contained in:
parent
fa52f2fae0
commit
7396ba84ce
2 changed files with 286 additions and 1 deletions
|
@ -703,7 +703,7 @@
|
|||
694 stdcall UnhookWindowsHook(long ptr)
|
||||
695 stdcall UnhookWindowsHookEx(long) NtUserUnhookWindowsHookEx
|
||||
696 stdcall UnionRect(ptr ptr ptr)
|
||||
697 stdcall UnloadKeyboardLayout(long) NtUserUnloadKeyboardLayout
|
||||
697 stdcall UnloadKeyboardLayout(ptr)
|
||||
698 stdcall UnlockWindowStation(long) NtUserUnlockWindowStation
|
||||
699 stdcall UnpackDDElParam(long long ptr ptr)
|
||||
700 stdcall UnregisterClassA(str long)
|
||||
|
|
|
@ -31,6 +31,279 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(user32);
|
||||
|
||||
typedef struct tagIMEHOTKEYENTRY
|
||||
{
|
||||
DWORD dwHotKeyId;
|
||||
UINT uVirtualKey;
|
||||
UINT uModifiers;
|
||||
HKL hKL;
|
||||
} IMEHOTKEYENTRY, *PIMEHOTKEYENTRY;
|
||||
|
||||
// Japanese
|
||||
IMEHOTKEYENTRY DefaultHotKeyTableJ[] =
|
||||
{
|
||||
{ IME_JHOTKEY_CLOSE_OPEN, VK_KANJI, MOD_IGNORE_ALL_MODIFIER, NULL },
|
||||
};
|
||||
|
||||
// Chinese Traditional
|
||||
IMEHOTKEYENTRY DefaultHotKeyTableT[] =
|
||||
{
|
||||
{ IME_THOTKEY_IME_NONIME_TOGGLE, VK_SPACE, MOD_LEFT | MOD_RIGHT | MOD_CONTROL, NULL },
|
||||
{ IME_THOTKEY_SHAPE_TOGGLE, VK_SPACE, MOD_LEFT | MOD_RIGHT | MOD_SHIFT, NULL },
|
||||
};
|
||||
|
||||
// Chinese Simplified
|
||||
IMEHOTKEYENTRY DefaultHotKeyTableC[] =
|
||||
{
|
||||
{ IME_CHOTKEY_IME_NONIME_TOGGLE, VK_SPACE, MOD_LEFT | MOD_RIGHT | MOD_CONTROL, NULL },
|
||||
{ IME_CHOTKEY_SHAPE_TOGGLE, VK_SPACE, MOD_LEFT | MOD_RIGHT | MOD_SHIFT, NULL },
|
||||
};
|
||||
|
||||
// The far-east flags
|
||||
#define FE_JAPANESE (1 << 0)
|
||||
#define FE_CHINESE_TRADITIONAL (1 << 1)
|
||||
#define FE_CHINESE_SIMPLIFIED (1 << 2)
|
||||
#define FE_KOREAN (1 << 3)
|
||||
|
||||
// Sets the far-east flags
|
||||
// Win: SetFeKeyboardFlags
|
||||
VOID FASTCALL IntSetFeKeyboardFlags(LANGID LangID, PBYTE pbFlags)
|
||||
{
|
||||
switch (LangID)
|
||||
{
|
||||
case MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT):
|
||||
*pbFlags |= FE_JAPANESE;
|
||||
break;
|
||||
|
||||
case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL):
|
||||
case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_HONGKONG):
|
||||
*pbFlags |= FE_CHINESE_TRADITIONAL;
|
||||
break;
|
||||
|
||||
case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED):
|
||||
case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SINGAPORE):
|
||||
*pbFlags |= FE_CHINESE_SIMPLIFIED;
|
||||
break;
|
||||
|
||||
case MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN):
|
||||
*pbFlags |= FE_KOREAN;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD FASTCALL CliReadRegistryValue(HANDLE hKey, LPCWSTR pszName)
|
||||
{
|
||||
DWORD dwValue, cbValue;
|
||||
LONG error;
|
||||
|
||||
cbValue = sizeof(dwValue);
|
||||
error = RegQueryValueExW(hKey, pszName, NULL, NULL, (LPBYTE)&dwValue, &cbValue);
|
||||
if (error != ERROR_SUCCESS || cbValue < sizeof(DWORD))
|
||||
return 0;
|
||||
|
||||
return dwValue;
|
||||
}
|
||||
|
||||
BOOL APIENTRY
|
||||
CliImmSetHotKeyWorker(DWORD dwHotKeyId, UINT uModifiers, UINT uVirtualKey, HKL hKL, DWORD dwAction)
|
||||
{
|
||||
if (dwAction == SETIMEHOTKEY_ADD)
|
||||
{
|
||||
if (IME_HOTKEY_DSWITCH_FIRST <= dwHotKeyId && dwHotKeyId <= IME_HOTKEY_DSWITCH_LAST)
|
||||
{
|
||||
if (!hKL)
|
||||
goto Failure;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hKL)
|
||||
goto Failure;
|
||||
|
||||
if (IME_KHOTKEY_SHAPE_TOGGLE <= dwHotKeyId &&
|
||||
dwHotKeyId < IME_THOTKEY_IME_NONIME_TOGGLE)
|
||||
{
|
||||
// The Korean cannot set the IME hotkeys
|
||||
goto Failure;
|
||||
}
|
||||
}
|
||||
|
||||
#define MOD_ALL_MODS (MOD_ALT | MOD_CONTROL | MOD_SHIFT | MOD_WIN)
|
||||
if ((uModifiers & MOD_ALL_MODS) && !(uModifiers & (MOD_LEFT | MOD_RIGHT)))
|
||||
goto Failure;
|
||||
#undef MOD_ALL_MODS
|
||||
}
|
||||
|
||||
return NtUserSetImeHotKey(dwHotKeyId, uModifiers, uVirtualKey, hKL, dwAction);
|
||||
|
||||
Failure:
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL FASTCALL CliSetSingleHotKey(LPCWSTR pszSubKey, HANDLE hKey)
|
||||
{
|
||||
LONG error;
|
||||
HKEY hSubKey;
|
||||
DWORD dwHotKeyId = 0;
|
||||
UINT uModifiers = 0, uVirtualKey = 0;
|
||||
HKL hKL = NULL;
|
||||
UNICODE_STRING ustrName;
|
||||
|
||||
error = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_READ, &hSubKey);
|
||||
if (error != ERROR_SUCCESS)
|
||||
return FALSE;
|
||||
|
||||
RtlInitUnicodeString(&ustrName, pszSubKey);
|
||||
RtlUnicodeStringToInteger(&ustrName, 16, &dwHotKeyId);
|
||||
|
||||
uModifiers = CliReadRegistryValue(hSubKey, L"Key Modifiers");
|
||||
hKL = (HKL)(ULONG_PTR)CliReadRegistryValue(hSubKey, L"Target IME");
|
||||
uVirtualKey = CliReadRegistryValue(hSubKey, L"Virtual Key");
|
||||
|
||||
RegCloseKey(hSubKey);
|
||||
|
||||
return CliImmSetHotKeyWorker(dwHotKeyId, uModifiers, uVirtualKey, hKL, SETIMEHOTKEY_ADD);
|
||||
}
|
||||
|
||||
BOOL FASTCALL CliGetImeHotKeysFromRegistry(VOID)
|
||||
{
|
||||
HKEY hKey;
|
||||
LONG error;
|
||||
BOOL ret = FALSE;
|
||||
DWORD dwIndex, cchKeyName;
|
||||
WCHAR szKeyName[16];
|
||||
|
||||
error = RegOpenKeyExW(HKEY_CURRENT_USER,
|
||||
L"Control Panel\\Input Method\\Hot Keys",
|
||||
0,
|
||||
KEY_ALL_ACCESS,
|
||||
&hKey);
|
||||
if (error != ERROR_SUCCESS)
|
||||
return ret;
|
||||
|
||||
for (dwIndex = 0; ; ++dwIndex)
|
||||
{
|
||||
cchKeyName = _countof(szKeyName);
|
||||
error = RegEnumKeyExW(hKey, dwIndex, szKeyName, &cchKeyName, NULL, NULL, NULL, NULL);
|
||||
if (error == ERROR_NO_MORE_ITEMS || error != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
szKeyName[_countof(szKeyName) - 1] = 0;
|
||||
|
||||
if (CliSetSingleHotKey(szKeyName, hKey))
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
return ret;
|
||||
}
|
||||
|
||||
VOID APIENTRY CliGetPreloadKeyboardLayouts(PBYTE pbFlags)
|
||||
{
|
||||
WCHAR szValueName[8], szValue[16];
|
||||
UNICODE_STRING ustrValue;
|
||||
DWORD dwKL, cbValue, dwType;
|
||||
UINT iNumber;
|
||||
HKEY hKey;
|
||||
LONG error;
|
||||
|
||||
error = RegOpenKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout\\Preload", 0, KEY_READ, &hKey);
|
||||
if (error != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
for (iNumber = 1; iNumber < 1000; ++iNumber)
|
||||
{
|
||||
StringCchPrintfW(szValueName, _countof(szValueName), L"%u", iNumber);
|
||||
|
||||
cbValue = sizeof(szValue);
|
||||
error = RegQueryValueExW(hKey, szValueName, NULL, &dwType, (LPBYTE)szValue, &cbValue);
|
||||
if (error != ERROR_SUCCESS || dwType != REG_SZ)
|
||||
break;
|
||||
|
||||
szValue[_countof(szValue) - 1] = 0;
|
||||
|
||||
RtlInitUnicodeString(&ustrValue, szValue);
|
||||
RtlUnicodeStringToInteger(&ustrValue, 16, &dwKL);
|
||||
|
||||
IntSetFeKeyboardFlags(LOWORD(dwKL), pbFlags);
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
VOID APIENTRY CliSetDefaultImeHotKeys(PIMEHOTKEYENTRY pEntries, UINT nCount, BOOL bCheck)
|
||||
{
|
||||
UINT uVirtualKey, uModifiers;
|
||||
HKL hKL;
|
||||
|
||||
while (nCount-- > 0)
|
||||
{
|
||||
if (!bCheck || !NtUserGetImeHotKey(pEntries->dwHotKeyId, &uModifiers, &uVirtualKey, &hKL))
|
||||
{
|
||||
CliImmSetHotKeyWorker(pEntries->dwHotKeyId,
|
||||
pEntries->uModifiers,
|
||||
pEntries->uVirtualKey,
|
||||
pEntries->hKL,
|
||||
SETIMEHOTKEY_ADD);
|
||||
}
|
||||
++pEntries;
|
||||
}
|
||||
}
|
||||
|
||||
VOID APIENTRY CliImmInitializeHotKeys(DWORD dwAction, HKL hKL)
|
||||
{
|
||||
UINT nCount;
|
||||
LPHKL pList;
|
||||
UINT iIndex;
|
||||
LANGID LangID;
|
||||
BYTE bFlags = 0;
|
||||
BOOL bCheck;
|
||||
|
||||
NtUserSetImeHotKey(0, 0, 0, NULL, SETIMEHOTKEY_DELETEALL);
|
||||
|
||||
bCheck = CliGetImeHotKeysFromRegistry();
|
||||
|
||||
if (dwAction == SETIMEHOTKEY_DELETEALL)
|
||||
{
|
||||
LangID = LANGIDFROMLCID(GetUserDefaultLCID());
|
||||
IntSetFeKeyboardFlags(LangID, &bFlags);
|
||||
|
||||
CliGetPreloadKeyboardLayouts(&bFlags);
|
||||
}
|
||||
else
|
||||
{
|
||||
nCount = NtUserGetKeyboardLayoutList(0, NULL);
|
||||
if (!nCount)
|
||||
return;
|
||||
|
||||
pList = RtlAllocateHeap(RtlGetProcessHeap(), 0, nCount * sizeof(HKL));
|
||||
if (!pList)
|
||||
return;
|
||||
|
||||
NtUserGetKeyboardLayoutList(nCount, pList);
|
||||
|
||||
for (iIndex = 0; iIndex < nCount; ++iIndex)
|
||||
{
|
||||
LangID = LOWORD(pList[iIndex]);
|
||||
IntSetFeKeyboardFlags(LangID, &bFlags);
|
||||
}
|
||||
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, pList);
|
||||
}
|
||||
|
||||
if (bFlags & FE_JAPANESE)
|
||||
CliSetDefaultImeHotKeys(DefaultHotKeyTableJ, _countof(DefaultHotKeyTableJ), bCheck);
|
||||
|
||||
if (bFlags & FE_CHINESE_TRADITIONAL)
|
||||
CliSetDefaultImeHotKeys(DefaultHotKeyTableT, _countof(DefaultHotKeyTableT), bCheck);
|
||||
|
||||
if (bFlags & FE_CHINESE_SIMPLIFIED)
|
||||
CliSetDefaultImeHotKeys(DefaultHotKeyTableC, _countof(DefaultHotKeyTableC), bCheck);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
@ -330,6 +603,18 @@ LoadKeyboardLayoutW(LPCWSTR pwszKLID,
|
|||
dwhkl, Flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOL WINAPI UnloadKeyboardLayout(HKL hKL)
|
||||
{
|
||||
if (!NtUserUnloadKeyboardLayout(hKL))
|
||||
return FALSE;
|
||||
|
||||
CliImmInitializeHotKeys(SETIMEHOTKEY_DELETE, hKL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue