mirror of
https://github.com/reactos/reactos.git
synced 2025-05-28 05:28:14 +00:00
[IMM32_APITEST] Add KLID testcase (#6590)
Confirming keyboard layout implementation by checking HKL, KLID, and registry. JIRA issue: CORE-19268 - Add KLID testcase. - Check HKLs, KLIDs (Keyboard Layout IDs), and related registry, with using user32!GetKeyboardLayoutList function.
This commit is contained in:
parent
0c65ceca3c
commit
e6c0081c28
3 changed files with 203 additions and 1 deletions
|
@ -10,11 +10,12 @@ list(APPEND SOURCE
|
|||
ImmIsUIMessage.c
|
||||
JapanImeConvTestA.c
|
||||
JapanImeConvTestW.c
|
||||
KLID.c
|
||||
testlist.c
|
||||
resource.rc)
|
||||
|
||||
add_executable(imm32_apitest ${SOURCE})
|
||||
target_link_libraries(imm32_apitest wine ${PSEH_LIB})
|
||||
set_module_type(imm32_apitest win32cui)
|
||||
add_importlibs(imm32_apitest imm32 msvcrt user32 kernel32 ntdll)
|
||||
add_importlibs(imm32_apitest advapi32 imm32 msvcrt user32 kernel32 ntdll)
|
||||
add_rostests_file(TARGET imm32_apitest)
|
||||
|
|
199
modules/rostests/apitests/imm32/KLID.c
Normal file
199
modules/rostests/apitests/imm32/KLID.c
Normal file
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* PROJECT: ReactOS api tests
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Test for Keyboard Layout ID (KLID), HKL, and registry
|
||||
* COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <imm32_undoc.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
typedef enum tagHKL_TYPE
|
||||
{
|
||||
HKL_TYPE_PURE = 0,
|
||||
HKL_TYPE_SPECIAL = 1,
|
||||
HKL_TYPE_IME = 2,
|
||||
HKL_TYPE_CHIMERA = 3,
|
||||
} HKL_TYPE;
|
||||
|
||||
static HKL_TYPE GetHKLType(HKL hKL)
|
||||
{
|
||||
/* 0xEXXXYYYY: An IME HKL. EXXX is an IME keyboard. YYYY is a language */
|
||||
if (IS_IME_HKL(hKL))
|
||||
return HKL_TYPE_IME;
|
||||
|
||||
/* 0xFXXXYYYY: A special HKL. XXX is a special ID. YYYY is a language */
|
||||
if (IS_SPECIAL_HKL(hKL))
|
||||
return HKL_TYPE_SPECIAL;
|
||||
|
||||
/* 0xXXXXXXXX: The keyboard layout and language is the same value */
|
||||
if (LOWORD(hKL) == HIWORD(hKL))
|
||||
return HKL_TYPE_PURE;
|
||||
|
||||
/* 0xXXXXYYYY: XXXX is a keyboard. YYYY is a language */
|
||||
return HKL_TYPE_CHIMERA;
|
||||
}
|
||||
|
||||
static HKEY OpenKeyboardLayouts(void)
|
||||
{
|
||||
HKEY hKey = NULL;
|
||||
RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
||||
L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts",
|
||||
0, KEY_READ, &hKey);
|
||||
return hKey;
|
||||
}
|
||||
|
||||
static DWORD KLIDFromSpecialHKL(HKL hKL)
|
||||
{
|
||||
WCHAR szName[16], szLayoutId[16];
|
||||
HKEY hkeyLayouts, hkeyKLID;
|
||||
LSTATUS error;
|
||||
DWORD dwSpecialId, dwLayoutId, cbValue, dwKLID = 0;
|
||||
|
||||
hkeyLayouts = OpenKeyboardLayouts();
|
||||
ok(hkeyLayouts != NULL, "hkeyLayouts was NULL\n");
|
||||
|
||||
dwSpecialId = SPECIALIDFROMHKL(hKL);
|
||||
|
||||
/* Search from "Keyboard Layouts" registry key */
|
||||
for (DWORD dwIndex = 0; dwIndex < 1000; ++dwIndex)
|
||||
{
|
||||
error = RegEnumKeyW(hkeyLayouts, dwIndex, szName, _countof(szName));
|
||||
szName[_countof(szName) - 1] = UNICODE_NULL; /* Avoid buffer overrun */
|
||||
if (error != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
error = RegOpenKeyExW(hkeyLayouts, szName, 0, KEY_READ, &hkeyKLID);
|
||||
if (error != ERROR_SUCCESS)
|
||||
break;
|
||||
|
||||
cbValue = sizeof(szLayoutId);
|
||||
error = RegQueryValueExW(hkeyKLID, L"Layout Id", NULL, NULL, (LPBYTE)szLayoutId, &cbValue);
|
||||
szLayoutId[_countof(szLayoutId) - 1] = UNICODE_NULL; /* Avoid buffer overrun */
|
||||
if (error != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(hkeyKLID);
|
||||
continue;
|
||||
}
|
||||
|
||||
dwLayoutId = wcstoul(szLayoutId, NULL, 16);
|
||||
RegCloseKey(hkeyKLID);
|
||||
if (dwLayoutId == dwSpecialId) /* Found */
|
||||
{
|
||||
dwKLID = wcstoul(szName, NULL, 16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RegCloseKey(hkeyLayouts);
|
||||
return dwKLID;
|
||||
}
|
||||
|
||||
static DWORD KLIDFromHKL(HKL hKL)
|
||||
{
|
||||
HKL_TYPE type = GetHKLType(hKL);
|
||||
|
||||
trace("type: %d\n", type);
|
||||
switch (type)
|
||||
{
|
||||
case HKL_TYPE_PURE:
|
||||
case HKL_TYPE_CHIMERA:
|
||||
return HIWORD(hKL);
|
||||
|
||||
case HKL_TYPE_SPECIAL:
|
||||
return KLIDFromSpecialHKL(hKL);
|
||||
|
||||
case HKL_TYPE_IME:
|
||||
return HandleToUlong(hKL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void Test_KLID(DWORD dwKLID, HKL hKL)
|
||||
{
|
||||
WCHAR szKLID[16], szValue[MAX_PATH];
|
||||
LSTATUS error;
|
||||
DWORD dwValue, cbValue;
|
||||
HKEY hkeyKLID, hkeyLayouts;
|
||||
HKL_TYPE type;
|
||||
|
||||
hkeyLayouts = OpenKeyboardLayouts();
|
||||
ok(hkeyLayouts != NULL, "hkeyLayouts was NULL\n");
|
||||
|
||||
StringCchPrintfW(szKLID, _countof(szKLID), L"%08lX", dwKLID);
|
||||
RegOpenKeyExW(hkeyLayouts, szKLID, 0, KEY_READ, &hkeyKLID);
|
||||
ok(hkeyKLID != NULL, "hkeyKLID was NULL\n");
|
||||
|
||||
error = RegQueryValueExW(hkeyKLID, L"Layout File", NULL, NULL, NULL, NULL);
|
||||
ok_long(error, ERROR_SUCCESS);
|
||||
|
||||
type = GetHKLType(hKL);
|
||||
|
||||
if (type == HKL_TYPE_IME)
|
||||
{
|
||||
ok_long(dwKLID, HandleToUlong(hKL));
|
||||
error = RegQueryValueExW(hkeyKLID, L"IME File", NULL, NULL, NULL, NULL);
|
||||
ok_long(error, ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
if (type == HKL_TYPE_SPECIAL)
|
||||
{
|
||||
cbValue = sizeof(szValue);
|
||||
error = RegQueryValueExW(hkeyKLID, L"Layout Id", NULL, NULL, (LPBYTE)&szValue, &cbValue);
|
||||
ok_long(error, ERROR_SUCCESS);
|
||||
|
||||
dwValue = wcstoul(szValue, NULL, 16);
|
||||
ok_long(dwValue, SPECIALIDFROMHKL(hKL));
|
||||
}
|
||||
|
||||
RegCloseKey(hkeyKLID);
|
||||
RegCloseKey(hkeyLayouts);
|
||||
}
|
||||
|
||||
static void Test_HKL(HKL hKL)
|
||||
{
|
||||
DWORD dwKLID;
|
||||
|
||||
ok(hKL != NULL, "hKL was NULL\n");
|
||||
|
||||
dwKLID = KLIDFromHKL(hKL);
|
||||
trace("dwKLID 0x%08lX, hKL %p\n", dwKLID, hKL);
|
||||
|
||||
Test_KLID(dwKLID, hKL);
|
||||
}
|
||||
|
||||
START_TEST(KLID)
|
||||
{
|
||||
HKL *phKLs;
|
||||
INT iKL, cKLs;
|
||||
|
||||
cKLs = GetKeyboardLayoutList(0, NULL);
|
||||
trace("cKLs: %d\n", cKLs);
|
||||
if (!cKLs)
|
||||
{
|
||||
skip("cKLs was zero\n");
|
||||
return;
|
||||
}
|
||||
|
||||
phKLs = calloc(cKLs, sizeof(HKL));
|
||||
if (!phKLs)
|
||||
{
|
||||
skip("!phKLs\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ok_int(GetKeyboardLayoutList(cKLs, phKLs), cKLs);
|
||||
|
||||
for (iKL = 0; iKL < cKLs; ++iKL)
|
||||
{
|
||||
trace("---\n");
|
||||
trace("phKLs[%d]: %p\n", iKL, phKLs[iKL]);
|
||||
Test_HKL(phKLs[iKL]);
|
||||
}
|
||||
|
||||
free(phKLs);
|
||||
}
|
|
@ -8,6 +8,7 @@ extern void func_imcc(void);
|
|||
extern void func_ImmEnumInputContext(void);
|
||||
extern void func_ImmGetImeInfoEx(void);
|
||||
extern void func_ImmIsUIMessage(void);
|
||||
extern void func_KLID(void);
|
||||
extern void func_JapanImeConvTestA(void);
|
||||
extern void func_JapanImeConvTestW(void);
|
||||
|
||||
|
@ -19,6 +20,7 @@ const struct test winetest_testlist[] =
|
|||
{ "ImmEnumInputContext", func_ImmEnumInputContext },
|
||||
{ "ImmGetImeInfoEx", func_ImmGetImeInfoEx },
|
||||
{ "ImmIsUIMessage", func_ImmIsUIMessage },
|
||||
{ "KLID", func_KLID },
|
||||
{ "JapanImeConvTestA", func_JapanImeConvTestA },
|
||||
{ "JapanImeConvTestW", func_JapanImeConvTestW },
|
||||
{ 0, 0 }
|
||||
|
|
Loading…
Reference in a new issue