ReactOS 0.4.15-dev-8021-g7ce96fd
KLID.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Test for Keyboard Layout ID (KLID), HKL, and registry
5 * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6 */
7
8#include "precomp.h"
9
10#include <stdlib.h>
11#include <imm32_undoc.h>
12#include <strsafe.h>
13
14typedef enum tagHKL_TYPE
15{
21
23{
24 /* 0xEXXXYYYY: An IME HKL. EXXX is an IME keyboard. YYYY is a language */
25 if (IS_IME_HKL(hKL))
26 return HKL_TYPE_IME;
27
28 /* 0xFXXXYYYY: A special HKL. XXX is a special ID. YYYY is a language */
29 if (IS_SPECIAL_HKL(hKL))
30 return HKL_TYPE_SPECIAL;
31
32 /* 0xXXXXXXXX: The keyboard layout and language is the same value */
33 if (LOWORD(hKL) == HIWORD(hKL))
34 return HKL_TYPE_PURE;
35
36 /* 0xXXXXYYYY: XXXX is a keyboard. YYYY is a language */
37 return HKL_TYPE_CHIMERA;
38}
39
41{
42 HKEY hKey = NULL;
44 L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts",
45 0, KEY_READ, &hKey);
46 return hKey;
47}
48
50{
51 WCHAR szName[16], szLayoutId[16];
52 HKEY hkeyLayouts, hkeyKLID;
54 DWORD dwSpecialId, dwLayoutId, cbValue, dwKLID = 0;
55
56 hkeyLayouts = OpenKeyboardLayouts();
57 ok(hkeyLayouts != NULL, "hkeyLayouts was NULL\n");
58
59 dwSpecialId = SPECIALIDFROMHKL(hKL);
60
61 /* Search from "Keyboard Layouts" registry key */
62 for (DWORD dwIndex = 0; dwIndex < 1000; ++dwIndex)
63 {
64 error = RegEnumKeyW(hkeyLayouts, dwIndex, szName, _countof(szName));
65 szName[_countof(szName) - 1] = UNICODE_NULL; /* Avoid buffer overrun */
66 if (error != ERROR_SUCCESS)
67 break;
68
69 error = RegOpenKeyExW(hkeyLayouts, szName, 0, KEY_READ, &hkeyKLID);
70 if (error != ERROR_SUCCESS)
71 break;
72
73 cbValue = sizeof(szLayoutId);
74 error = RegQueryValueExW(hkeyKLID, L"Layout Id", NULL, NULL, (LPBYTE)szLayoutId, &cbValue);
75 szLayoutId[_countof(szLayoutId) - 1] = UNICODE_NULL; /* Avoid buffer overrun */
76 if (error != ERROR_SUCCESS)
77 {
78 RegCloseKey(hkeyKLID);
79 continue;
80 }
81
82 dwLayoutId = wcstoul(szLayoutId, NULL, 16);
83 RegCloseKey(hkeyKLID);
84 if (dwLayoutId == dwSpecialId) /* Found */
85 {
86 dwKLID = wcstoul(szName, NULL, 16);
87 break;
88 }
89 }
90
91 RegCloseKey(hkeyLayouts);
92 return dwKLID;
93}
94
96{
98
99 trace("type: %d\n", type);
100 switch (type)
101 {
102 case HKL_TYPE_PURE:
103 case HKL_TYPE_CHIMERA:
104 return HIWORD(hKL);
105
106 case HKL_TYPE_SPECIAL:
107 return KLIDFromSpecialHKL(hKL);
108
109 case HKL_TYPE_IME:
110 return HandleToUlong(hKL);
111 }
112
113 return 0;
114}
115
116static void Test_KLID(DWORD dwKLID, HKL hKL)
117{
118 WCHAR szKLID[16], szValue[MAX_PATH];
120 DWORD dwValue, cbValue;
121 HKEY hkeyKLID, hkeyLayouts;
123
124 hkeyLayouts = OpenKeyboardLayouts();
125 ok(hkeyLayouts != NULL, "hkeyLayouts was NULL\n");
126
127 StringCchPrintfW(szKLID, _countof(szKLID), L"%08lX", dwKLID);
128 RegOpenKeyExW(hkeyLayouts, szKLID, 0, KEY_READ, &hkeyKLID);
129 ok(hkeyKLID != NULL, "hkeyKLID was NULL\n");
130
131 error = RegQueryValueExW(hkeyKLID, L"Layout File", NULL, NULL, NULL, NULL);
133
134 type = GetHKLType(hKL);
135
136 if (type == HKL_TYPE_IME)
137 {
138 ok_long(dwKLID, HandleToUlong(hKL));
139 error = RegQueryValueExW(hkeyKLID, L"IME File", NULL, NULL, NULL, NULL);
141 }
142
143 if (type == HKL_TYPE_SPECIAL)
144 {
145 cbValue = sizeof(szValue);
146 error = RegQueryValueExW(hkeyKLID, L"Layout Id", NULL, NULL, (LPBYTE)&szValue, &cbValue);
148
149 dwValue = wcstoul(szValue, NULL, 16);
150 ok_long(dwValue, SPECIALIDFROMHKL(hKL));
151 }
152
153 RegCloseKey(hkeyKLID);
154 RegCloseKey(hkeyLayouts);
155}
156
157static void Test_HKL(HKL hKL)
158{
159 DWORD dwKLID;
160
161 ok(hKL != NULL, "hKL was NULL\n");
162
163 dwKLID = KLIDFromHKL(hKL);
164 trace("dwKLID 0x%08lX, hKL %p\n", dwKLID, hKL);
165
166 Test_KLID(dwKLID, hKL);
167}
168
170{
171 HKL *phKLs;
172 INT iKL, cKLs;
173
174 cKLs = GetKeyboardLayoutList(0, NULL);
175 trace("cKLs: %d\n", cKLs);
176 if (!cKLs)
177 {
178 skip("cKLs was zero\n");
179 return;
180 }
181
182 phKLs = calloc(cKLs, sizeof(HKL));
183 if (!phKLs)
184 {
185 skip("!phKLs\n");
186 return;
187 }
188
189 ok_int(GetKeyboardLayoutList(cKLs, phKLs), cKLs);
190
191 for (iKL = 0; iKL < cKLs; ++iKL)
192 {
193 trace("---\n");
194 trace("phKLs[%d]: %p\n", iKL, phKLs[iKL]);
195 Test_HKL(phKLs[iKL]);
196 }
197
198 free(phKLs);
199}
static void Test_HKL(HKL hKL)
Definition: KLID.c:157
static void Test_KLID(DWORD dwKLID, HKL hKL)
Definition: KLID.c:116
tagHKL_TYPE
Definition: KLID.c:15
@ HKL_TYPE_PURE
Definition: KLID.c:16
@ HKL_TYPE_IME
Definition: KLID.c:18
@ HKL_TYPE_CHIMERA
Definition: KLID.c:19
@ HKL_TYPE_SPECIAL
Definition: KLID.c:17
static DWORD KLIDFromSpecialHKL(HKL hKL)
Definition: KLID.c:49
static DWORD KLIDFromHKL(HKL hKL)
Definition: KLID.c:95
enum tagHKL_TYPE HKL_TYPE
static HKEY OpenKeyboardLayouts(void)
Definition: KLID.c:40
static HKL_TYPE GetHKLType(HKL hKL)
Definition: KLID.c:22
#define ok_long(expression, result)
Definition: atltest.h:133
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define ok_int(expression, result)
Definition: atltest.h:134
#define HandleToUlong(h)
Definition: basetsd.h:79
#define RegCloseKey(hKey)
Definition: registry.h:49
#define free
Definition: debug_ros.c:5
#define ERROR_SUCCESS
Definition: deptool.c:10
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
#define NULL
Definition: types.h:112
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
LONG WINAPI RegEnumKeyW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, DWORD cbName)
Definition: reg.c:2393
#define MAX_PATH
Definition: compat.h:34
unsigned long DWORD
Definition: ntddk_ex.h:95
FxAutoRegKey hKey
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define SPECIALIDFROMHKL(hKL)
Definition: imm32_undoc.h:22
#define IS_SPECIAL_HKL(hKL)
Definition: imm32_undoc.h:21
#define IS_IME_HKL(hKL)
Definition: imm32_undoc.h:20
_Check_return_ unsigned long __cdecl wcstoul(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
ULONG KLID
Definition: mui.h:10
#define error(str)
Definition: mkdosfs.c:1605
UINT_PTR HKL
Definition: msctf.idl:143
#define KEY_READ
Definition: nt_native.h:1023
#define UNICODE_NULL
#define L(x)
Definition: ntvdm.h:50
#define LOWORD(l)
Definition: pedump.c:82
static const WCHAR szName[]
Definition: powrprof.c:45
#define calloc
Definition: rosglue.h:14
#define _countof(array)
Definition: sndvol32.h:68
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
unsigned char * LPBYTE
Definition: typedefs.h:53
int32_t INT
Definition: typedefs.h:58
#define HIWORD(l)
Definition: typedefs.h:247
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
UINT WINAPI GetKeyboardLayoutList(_In_ int nBuff, _Out_writes_to_opt_(nBuff, return) HKL FAR *lpList)
__wchar_t WCHAR
Definition: xmlstorage.h:180