ReactOS 0.4.16-dev-1541-g7e1d9ef
install.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS IMM32
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Implementing IME installation
5 * COPYRIGHT: Copyright 2020-2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6 */
7
8#include "precomp.h"
9
11
12/* An IME layout entry in registry */
13typedef struct tagREG_IME_LAYOUT
14{
16 WCHAR szImeKey[20]; /* "E0XXYYYY": "E0XX" is the device handle. "YYYY" is a LANGID. */
17 WCHAR szFileName[80]; /* The IME module filename */
19
20/* For using version.dll */
24
28
29/* Used in Imm32CopyImeFile */
33
34/* Gets a version information entry by using version!VerQueryValueW */
35static LPWSTR
37 _In_reads_bytes_(cbVerInfo) LPCVOID pVerInfo,
38 _In_ DWORD cbVerInfo,
39 _Inout_ PWSTR pszKey,
40 _In_ DWORD cchKey,
41 _In_ PCWSTR pszName)
42{
43 size_t cchExtra;
44 LPWSTR pszValue;
45 UINT cbValue = 0;
46
47 StringCchLengthW(pszKey, cchKey, &cchExtra);
48
49 StringCchCatW(pszKey, cchKey, pszName);
50 s_fnVerQueryValueW(pVerInfo, pszKey, (LPVOID *)&pszValue, &cbValue);
51 pszKey[cchExtra] = UNICODE_NULL; /* Avoid buffer overrun */
52
53 ASSERT(cbValue <= cbVerInfo);
54
55 return (cbValue ? pszValue : NULL);
56}
57
58/* Gets the language and description of an IME */
59static BOOL
61 _Inout_ PIMEINFOEX pInfoEx,
62 _In_reads_bytes_(cbVerInfo) LPCVOID pVerInfo,
63 _In_ DWORD cbVerInfo)
64{
65 /* Getting the version info. See VerQueryValue */
66 LPWORD pw;
67 UINT cbData;
68 BOOL ret = s_fnVerQueryValueW(pVerInfo, L"\\VarFileInfo\\Translation", (LPVOID *)&pw, &cbData);
69 if (!ret || !cbData)
70 {
71 ERR("Translation not available\n");
72 return FALSE;
73 }
74
75 ASSERT(cbData <= cbVerInfo);
76
77 if (pInfoEx->hkl == NULL)
78 pInfoEx->hkl = UlongToHandle(*pw);
79
80 /* Try the current language and the Unicode codepage (0x04B0) */
82 WCHAR szKey[80];
83 StringCchPrintfW(szKey, _countof(szKey), L"\\StringFileInfo\\%04X04B0\\", LangID);
84 LPWSTR pszDesc = Imm32GetVerInfoValue(pVerInfo, cbVerInfo, szKey, _countof(szKey), L"FileDescription");
85 if (!pszDesc)
86 {
87 /* Retry the language and codepage of the IME module */
88 StringCchPrintfW(szKey, _countof(szKey), L"\\StringFileInfo\\%04X%04X\\", pw[0], pw[1]);
89 pszDesc = Imm32GetVerInfoValue(pVerInfo, cbVerInfo, szKey, _countof(szKey), L"FileDescription");
90 }
91
92 /* The description */
93 if (pszDesc)
94 StringCchCopyW(pInfoEx->wszImeDescription, _countof(pInfoEx->wszImeDescription), pszDesc);
95 else
96 pInfoEx->wszImeDescription[0] = UNICODE_NULL;
97
98 return TRUE;
99}
100
101/* Gets the fixed version info from IME */
102static BOOL
104 _Out_ PIMEINFOEX pInfoEx,
105 _In_reads_bytes_(cbVerInfo) LPCVOID pVerInfo,
106 _In_ DWORD cbVerInfo)
107{
108 UINT cbFixed = 0;
109 VS_FIXEDFILEINFO *pFixed;
110 if (!s_fnVerQueryValueW(pVerInfo, L"\\", (LPVOID *)&pFixed, &cbFixed) || !cbFixed)
111 {
112 ERR("Fixed version info not available\n");
113 return FALSE;
114 }
115
116 ASSERT(cbFixed <= cbVerInfo);
117
118 /* NOTE: The IME module must contain a version info of input method driver. */
119 if (pFixed->dwFileType != VFT_DRV || pFixed->dwFileSubtype != VFT2_DRV_INPUTMETHOD)
120 {
121 ERR("DLL '%s' is not an IME\n", debugstr_w(pInfoEx->wszImeFile));
122 return FALSE;
123 }
124
125 pInfoEx->dwProdVersion = pFixed->dwProductVersionMS;
126 pInfoEx->dwImeWinVersion = IMEVER_0400;
127 return TRUE;
128}
129
130/* Generates a new IMM IME HKL (0xE0XXYYYY) */
131static HKL
133 _In_ UINT cKLs,
134 _In_reads_(cKLs) const REG_IME_LAYOUT *pLayouts,
135 _In_ WORD wLangID)
136{
137#define MIN_SYSTEM_IMM_IME_ID 0xE000
138#define MAX_SYSTEM_IMM_IME_ID 0xE0FF
139#define MIN_USER_IMM_IME_ID 0xE020
140#define MAX_USER_IMM_IME_ID MAX_SYSTEM_IMM_IME_ID
141 UINT iKL, wLow = MAX_USER_IMM_IME_ID, wHigh = MIN_USER_IMM_IME_ID;
142
143 for (iKL = 0; iKL < cKLs; ++iKL)
144 {
145 wHigh = max(wHigh, HIWORD(pLayouts[iKL].hKL));
146 wLow = min(wLow, HIWORD(pLayouts[iKL].hKL));
147 }
148
149 UINT wNextImeId = 0;
150 if (wHigh < MAX_SYSTEM_IMM_IME_ID)
151 {
152 wNextImeId = wHigh + 1;
153 }
154 else if (wLow > MIN_SYSTEM_IMM_IME_ID)
155 {
156 wNextImeId = wLow - 1;
157 }
158 else
159 {
160 UINT wID;
161 for (wID = MIN_USER_IMM_IME_ID; wID <= MAX_USER_IMM_IME_ID; ++wID)
162 {
163 for (iKL = 0; iKL < cKLs; ++iKL)
164 {
165 if (LOWORD(pLayouts[iKL].hKL) == wLangID && HIWORD(pLayouts[iKL].hKL) == wID)
166 break;
167 }
168
169 if (iKL >= cKLs)
170 break;
171 }
172
173 if (wID <= MAX_SYSTEM_IMM_IME_ID)
174 wNextImeId = wID;
175 }
176
177 if (!wNextImeId)
178 {
179 ERR("No next IMM IME ID\n");
180 return NULL;
181 }
182
183 return UlongToHandle(MAKELONG(wLangID, wNextImeId));
184}
185
186static UINT
188 _Out_writes_opt_(cLayouts) PREG_IME_LAYOUT pLayouts,
189 _In_ UINT cLayouts)
190{
191 /* Open the registry keyboard layouts */
192 HKEY hkeyLayouts;
194 if (IS_ERROR_UNEXPECTEDLY(lError))
195 return 0;
196
197 UINT iKey, nCount;
198 WCHAR szImeFileName[80], szImeKey[20];
199 DWORD cbData, Value;
200 HKL hKL;
201 for (iKey = nCount = 0; ; ++iKey)
202 {
203 /* Get the key name */
204 lError = RegEnumKeyW(hkeyLayouts, iKey, szImeKey, _countof(szImeKey));
205 if (lError != ERROR_SUCCESS)
206 break;
207
208 if (szImeKey[0] != L'E' && szImeKey[0] != L'e')
209 continue; /* Not an IME layout */
210
211 if (pLayouts == NULL) /* for counting only */
212 {
213 ++nCount;
214 continue;
215 }
216
217 if (cLayouts <= nCount)
218 break;
219
220 HKEY hkeyIME;
221 lError = RegOpenKeyW(hkeyLayouts, szImeKey, &hkeyIME); /* Open the IME key */
222 if (IS_ERROR_UNEXPECTEDLY(lError))
223 continue;
224
225 /* Load the "Ime File" value */
226 szImeFileName[0] = UNICODE_NULL;
227 cbData = sizeof(szImeFileName);
228 RegQueryValueExW(hkeyIME, L"Ime File", NULL, NULL, (LPBYTE)szImeFileName, &cbData);
229 szImeFileName[_countof(szImeFileName) - 1] = UNICODE_NULL; /* Avoid buffer overrun */
230
231 RegCloseKey(hkeyIME);
232
233 /* We don't allow the invalid "IME File" values for security reason */
234 if (!szImeFileName[0] || wcscspn(szImeFileName, L":\\/") != wcslen(szImeFileName))
235 {
236 WARN("Invalid IME Filename (%s)\n", debugstr_w(szImeFileName));
237 continue;
238 }
239
240 Imm32StrToUInt(szImeKey, &Value, 16);
241 hKL = UlongToHandle(Value);
242 if (!IS_IME_HKL(hKL)) /* Not an IMM IME */
243 {
244 WARN("Not IMM IME HKL: %p\n", hKL);
245 continue;
246 }
247
248 /* Store the IME key and the IME filename */
249 pLayouts[nCount].hKL = hKL;
250 StringCchCopyW(pLayouts[nCount].szImeKey, _countof(pLayouts[nCount].szImeKey), szImeKey);
251 StringCchCopyW(pLayouts[nCount].szFileName, _countof(pLayouts[nCount].szFileName),
252 szImeFileName);
253 ++nCount;
254 }
255
256 RegCloseKey(hkeyLayouts);
257 return nCount;
258}
259
260/* Write an IME layout to registry */
261static BOOL
263 _In_ HKL hKL,
264 _In_ PCWSTR pchFileTitle,
265 _In_ PCWSTR pszLayoutText)
266{
267 UINT iPreload;
268 HKEY hkeyLayouts, hkeyIME, hkeyPreload;
269 WCHAR szImeKey[20], szPreloadNumber[20], szPreloadKey[20];
270 DWORD cbData;
272 LONG lError;
273 LPCWSTR pszLayoutFile;
274
275 /* Open the registry keyboard layouts */
277 if (IS_ERROR_UNEXPECTEDLY(lError))
278 return FALSE;
279
280 /* Get the IME key from hKL */
281 StringCchPrintfW(szImeKey, _countof(szImeKey), L"%08X", HandleToUlong(hKL));
282
283 /* Create a registry IME key */
284 lError = RegCreateKeyW(hkeyLayouts, szImeKey, &hkeyIME);
285 if (IS_ERROR_UNEXPECTEDLY(lError))
286 goto Failure;
287
288 /* Write "Ime File" */
289 cbData = (wcslen(pchFileTitle) + 1) * sizeof(WCHAR);
290 lError = RegSetValueExW(hkeyIME, L"Ime File", 0, REG_SZ, (LPBYTE)pchFileTitle, cbData);
291 if (IS_ERROR_UNEXPECTEDLY(lError))
292 goto Failure;
293
294 /* Write "Layout Text" */
295 cbData = (wcslen(pszLayoutText) + 1) * sizeof(WCHAR);
296 lError = RegSetValueExW(hkeyIME, L"Layout Text", 0, REG_SZ, (LPBYTE)pszLayoutText, cbData);
297 if (IS_ERROR_UNEXPECTEDLY(lError))
298 goto Failure;
299
300 /* Choose "Layout File" from hKL */
301 LangID = LOWORD(hKL);
302 switch (LOBYTE(LangID))
303 {
304 case LANG_JAPANESE: pszLayoutFile = L"kbdjpn.dll"; break;
305 case LANG_KOREAN: pszLayoutFile = L"kbdkor.dll"; break;
306 default: pszLayoutFile = L"kbdus.dll"; break;
307 }
308
309 /* Write "Layout File" */
310 cbData = (wcslen(pszLayoutFile) + 1) * sizeof(WCHAR);
311 lError = RegSetValueExW(hkeyIME, L"Layout File", 0, REG_SZ, (LPBYTE)pszLayoutFile, cbData);
312 if (IS_ERROR_UNEXPECTEDLY(lError))
313 goto Failure;
314
315 RegCloseKey(hkeyIME);
316 RegCloseKey(hkeyLayouts);
317
318 /* Create "Preload" key */
319 RegCreateKeyW(HKEY_CURRENT_USER, L"Keyboard Layout\\Preload", &hkeyPreload);
320
321#define MAX_PRELOAD 0x400
322 for (iPreload = 1; iPreload < MAX_PRELOAD; ++iPreload)
323 {
324 Imm32UIntToStr(iPreload, 10, szPreloadNumber, _countof(szPreloadNumber));
325
326 /* Load the key of the preload number */
327 cbData = sizeof(szPreloadKey);
328 lError = RegQueryValueExW(hkeyPreload, szPreloadNumber, NULL, NULL,
329 (LPBYTE)szPreloadKey, &cbData);
330 szPreloadKey[_countof(szPreloadKey) - 1] = UNICODE_NULL; /* Avoid buffer overrun */
331
332 if (lError != ERROR_SUCCESS || _wcsicmp(szImeKey, szPreloadKey) == 0)
333 break; /* Found an empty room or the same key */
334 }
335
336 if (iPreload >= MAX_PRELOAD) /* Not found */
337 {
338 ERR("iPreload: %u\n", iPreload);
339 RegCloseKey(hkeyPreload);
340 return FALSE;
341 }
342#undef MAX_PRELOAD
343
344 /* Write the IME key to the preload number */
345 cbData = (wcslen(szImeKey) + 1) * sizeof(WCHAR);
346 lError = RegSetValueExW(hkeyPreload, szPreloadNumber, 0, REG_SZ, (LPBYTE)szImeKey, cbData);
347 RegCloseKey(hkeyPreload);
348 return lError == ERROR_SUCCESS;
349
350Failure:
351 RegCloseKey(hkeyIME);
352 RegDeleteKeyW(hkeyLayouts, szImeKey);
353 RegCloseKey(hkeyLayouts);
354 return FALSE;
355}
356
357/* Copy an IME file with using LZ decompression */
358static BOOL
360 _In_ PCWSTR pszOldFile,
361 _In_ PCWSTR pszNewFile)
362{
363 BOOL ret = FALSE, bLoaded = FALSE;
364
365 /* Load LZ32.dll for copying/decompressing file */
366 WCHAR szLZ32Path[MAX_PATH];
367 Imm32GetSystemLibraryPath(szLZ32Path, _countof(szLZ32Path), L"LZ32");
368 HMODULE hinstLZ32 = GetModuleHandleW(szLZ32Path);
369 if (!hinstLZ32)
370 {
371 hinstLZ32 = LoadLibraryW(szLZ32Path);
372 if (IS_NULL_UNEXPECTEDLY(hinstLZ32))
373 return FALSE;
374 bLoaded = TRUE;
375 }
376
377 FN_LZOpenFileW fnLZOpenFileW;
378 FN_LZCopy fnLZCopy;
379 FN_LZClose fnLZClose;
380#define GET_FN(name) do { \
381 fn##name = (FN_##name)GetProcAddress(hinstLZ32, #name); \
382 if (!fn##name) goto Quit; \
383} while (0)
385 GET_FN(LZCopy);
387#undef GET_FN
388
389 CHAR szDestA[MAX_PATH];
390 HFILE hfDest, hfSrc;
391 OFSTRUCT OFStruct;
392
393 if (!WideCharToMultiByte(CP_ACP, 0, pszNewFile, -1, szDestA, _countof(szDestA), NULL, NULL))
394 goto Quit;
395 szDestA[_countof(szDestA) - 1] = ANSI_NULL; /* Avoid buffer overrun */
396
397 hfSrc = fnLZOpenFileW((PWSTR)pszOldFile, &OFStruct, OF_READ);
398 if (hfSrc < 0)
399 goto Quit;
400
401 hfDest = OpenFile(szDestA, &OFStruct, OF_CREATE);
402 if (hfDest != HFILE_ERROR)
403 {
404 ret = (fnLZCopy(hfSrc, hfDest) >= 0);
405 _lclose(hfDest);
406 }
407
408 fnLZClose(hfSrc);
409
410Quit:
411 if (bLoaded)
412 FreeLibrary(hinstLZ32);
413 return ret;
414}
415
416/* Loads version info of an IME by using version!{GetFileVersionInfo,VerQueryValue} etc. */
417BOOL
419{
420 HINSTANCE hinstVersion;
421 BOOL ret = FALSE, bLoaded = FALSE;
423 LPVOID pVerInfo;
424 DWORD cbVerInfo, dwHandle;
425
426 /* Load version.dll to use the version info API */
428 hinstVersion = GetModuleHandleW(szPath);
429 if (!hinstVersion)
430 {
431 hinstVersion = LoadLibraryW(szPath);
432 if (IS_NULL_UNEXPECTEDLY(hinstVersion))
433 return FALSE;
434
435 bLoaded = TRUE;
436 }
437
438#define GET_FN(name) do { \
439 s_fn##name = (FN_##name)GetProcAddress(hinstVersion, #name); \
440 if (!s_fn##name) goto Quit; \
441} while (0)
445#undef GET_FN
446
447 /* The path of the IME module */
448 Imm32GetSystemLibraryPath(szPath, _countof(szPath), pImeInfoEx->wszImeFile);
449
450 cbVerInfo = s_fnGetFileVersionInfoSizeW(szPath, &dwHandle);
451 if (IS_ZERO_UNEXPECTEDLY(cbVerInfo))
452 goto Quit;
453
454 pVerInfo = ImmLocalAlloc(0, cbVerInfo);
455 if (IS_NULL_UNEXPECTEDLY(pVerInfo))
456 goto Quit;
457
458 /* Load the version info of the IME module */
459 if (s_fnGetFileVersionInfoW(szPath, dwHandle, cbVerInfo, pVerInfo) &&
460 Imm32LoadImeFixedInfo(pImeInfoEx, pVerInfo, cbVerInfo))
461 {
462 ret = Imm32LoadImeLangAndDesc(pImeInfoEx, pVerInfo, cbVerInfo);
463 }
464
465 ImmLocalFree(pVerInfo);
466
467Quit:
468 if (bLoaded)
469 FreeLibrary(hinstVersion);
470 TRACE("ret: %d\n", ret);
471 return ret;
472}
473
474/***********************************************************************
475 * ImmInstallIMEA (IMM32.@)
476 */
479 _In_ LPCSTR lpszIMEFileName,
480 _In_ LPCSTR lpszLayoutText)
481{
482 HKL hKL = NULL;
483 LPWSTR pszFileNameW = NULL, pszLayoutTextW = NULL;
484
485 TRACE("(%s, %s)\n", debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText));
486
487 pszFileNameW = Imm32WideFromAnsi(CP_ACP, lpszIMEFileName);
488 if (IS_NULL_UNEXPECTEDLY(pszFileNameW))
489 goto Quit;
490
491 pszLayoutTextW = Imm32WideFromAnsi(CP_ACP, lpszLayoutText);
492 if (IS_NULL_UNEXPECTEDLY(pszLayoutTextW))
493 goto Quit;
494
495 hKL = ImmInstallIMEW(pszFileNameW, pszLayoutTextW);
496
497Quit:
498 ImmLocalFree(pszFileNameW);
499 ImmLocalFree(pszLayoutTextW);
500 return hKL;
501}
502
503/***********************************************************************
504 * ImmInstallIMEW (IMM32.@)
505 */
508 _In_ LPCWSTR lpszIMEFileName,
509 _In_ LPCWSTR lpszLayoutText)
510{
511 TRACE("(%s, %s)\n", debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText));
512
513 /* Get full pathname and file title */
514 WCHAR szImeFileName[MAX_PATH];
515 PWSTR pchFileTitle;
516 GetFullPathNameW(lpszIMEFileName, _countof(szImeFileName), szImeFileName, &pchFileTitle);
517 if (IS_NULL_UNEXPECTEDLY(pchFileTitle))
518 return NULL;
519
520 /* Load the IME version info */
521 IMEINFOEX InfoEx;
522 HKL hNewKL;
523 InfoEx.hkl = hNewKL = NULL;
524 StringCchCopyW(InfoEx.wszImeFile, _countof(InfoEx.wszImeFile), pchFileTitle);
525 if (!Imm32LoadImeVerInfo(&InfoEx) || !InfoEx.hkl)
526 {
527 ERR("Can't get version info (error: %lu)\n", GetLastError());
528 return NULL;
529 }
530 WORD wLangID = LOWORD(InfoEx.hkl);
531
532 /* Get the IME layouts from registry */
533 PREG_IME_LAYOUT pLayouts = NULL;
534 UINT iLayout, cLayouts = Imm32GetImeLayoutList(NULL, 0);
535 if (cLayouts)
536 {
537 pLayouts = ImmLocalAlloc(0, cLayouts * sizeof(REG_IME_LAYOUT));
538 if (IS_NULL_UNEXPECTEDLY(pLayouts))
539 return NULL;
540
541 if (!Imm32GetImeLayoutList(pLayouts, cLayouts))
542 {
543 ERR("Can't get IME layouts\n");
544 ImmLocalFree(pLayouts);
545 return NULL;
546 }
547
548 for (iLayout = 0; iLayout < cLayouts; ++iLayout)
549 {
550 if (_wcsicmp(pLayouts[iLayout].szFileName, pchFileTitle) == 0)
551 {
552 if (wLangID != LOWORD(pLayouts[iLayout].hKL))
553 {
554 ERR("The language is mismatched\n");
555 goto Quit;
556 }
557
558 hNewKL = pLayouts[iLayout].hKL; /* Found */
559 break;
560 }
561 }
562 }
563
564 /* If the IME for the specified filename is already loaded, then unload it now */
565 if (ImmGetImeInfoEx(&InfoEx, ImeInfoExImeFileName, pchFileTitle) &&
566 !UnloadKeyboardLayout(InfoEx.hkl))
567 {
568 ERR("Can't unload laybout\n");
569 hNewKL = NULL;
570 goto Quit;
571 }
572
573 WCHAR szImeDestPath[MAX_PATH], szImeKey[20];
574 Imm32GetSystemLibraryPath(szImeDestPath, _countof(szImeDestPath), pchFileTitle);
575
576 /* If the source and the destination pathnames were different, then copy the IME file */
577 if (_wcsicmp(szImeFileName, szImeDestPath) != 0 &&
578 !Imm32CopyImeFile(szImeFileName, szImeDestPath))
579 {
580 ERR("Can't copy file (%s -> %s)\n", debugstr_w(szImeFileName), debugstr_w(szImeDestPath));
581 hNewKL = NULL;
582 goto Quit;
583 }
584
585 if (hNewKL == NULL)
586 hNewKL = Imm32AssignNewLayout(cLayouts, pLayouts, wLangID);
587
588 if (hNewKL)
589 {
590 /* Write the IME layout to registry */
591 if (Imm32WriteImeLayout(hNewKL, pchFileTitle, lpszLayoutText))
592 {
593 /* Replace the current keyboard layout */
594 StringCchPrintfW(szImeKey, _countof(szImeKey), L"%08X", HandleToUlong(hNewKL));
595 hNewKL = LoadKeyboardLayoutW(szImeKey, KLF_REPLACELANG);
596 }
597 else
598 {
599 ERR("Can't write IME layout to registry\n");
600 hNewKL = NULL;
601 }
602 }
603
604Quit:
605 ImmLocalFree(pLayouts);
606 return hNewKL;
607}
#define VOID
Definition: acefi.h:82
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define UlongToHandle(ul)
Definition: basetsd.h:97
#define HandleToUlong(h)
Definition: basetsd.h:79
#define RegCloseKey(hKey)
Definition: registry.h:49
#define ERROR_SUCCESS
Definition: deptool.c:10
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
LONG WINAPI RegOpenKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3268
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4882
LONG WINAPI RegDeleteKeyW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey)
Definition: reg.c:1239
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
LONG WINAPI RegCreateKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1201
#define CP_ACP
Definition: compat.h:109
#define FreeLibrary(x)
Definition: compat.h:748
#define MAX_PATH
Definition: compat.h:34
#define WideCharToMultiByte
Definition: compat.h:111
#define LoadLibraryW(x)
Definition: compat.h:747
HFILE WINAPI OpenFile(LPCSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle)
Definition: create.c:368
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
LCID WINAPI GetThreadLocale(void)
Definition: locale.c:2803
BOOL WINAPI GetFileVersionInfoW(LPCWSTR filename, DWORD handle, DWORD datasize, LPVOID data)
Definition: version.c:967
BOOL WINAPI VerQueryValueW(LPCVOID pBlock, LPCWSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen)
Definition: version.c:1171
DWORD WINAPI GetFileVersionInfoSizeW(LPCWSTR filename, LPDWORD handle)
Definition: version.c:738
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
#define IS_IME_HKL(hKL)
Definition: imm32_undoc.h:21
BOOL WINAPI ImmGetImeInfoEx(_Out_ PIMEINFOEX pImeInfoEx, _In_ IMEINFOEXCLASS SearchType, _In_ PVOID pvSearchKey)
@ ImeInfoExImeFileName
Definition: imm32_undoc.h:82
#define IMEVER_0400
Definition: imm.h:243
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define LOBYTE(W)
Definition: jmemdos.c:487
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
#define REG_SZ
Definition: layer.c:22
int WINAPI _lclose(HFILE hFile)
Definition: lfile.c:138
USHORT LANGID
Definition: mui.h:9
HFILE WINAPI LZOpenFileW(LPWSTR fn, LPOFSTRUCT ofs, WORD mode)
Definition: lzexpand.c:580
LONG WINAPI LZCopy(HFILE src, HFILE dest)
Definition: lzexpand.c:467
void WINAPI LZClose(HFILE fd)
Definition: lzexpand.c:595
#define ASSERT(a)
Definition: mode.c:44
LPCWSTR szPath
Definition: env.c:37
static HANDLE LPVOID
Definition: install.c:28
static INT
Definition: install.c:29
#define min(a, b)
Definition: monoChain.cc:55
UINT_PTR HKL
Definition: msctf.idl:125
unsigned int * PUINT
Definition: ndis.h:50
unsigned int UINT
Definition: ndis.h:50
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
#define _In_reads_(s)
Definition: no_sal2.h:168
#define _Inout_
Definition: no_sal2.h:162
#define _Out_writes_opt_(s)
Definition: no_sal2.h:226
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define BOOL
Definition: nt_native.h:43
#define LPDWORD
Definition: nt_native.h:46
#define DWORD
Definition: nt_native.h:44
#define UNICODE_NULL
#define ANSI_NULL
#define LOWORD(l)
Definition: pedump.c:82
long LONG
Definition: pedump.c:60
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_Check_return_ _CRTIMP size_t __cdecl wcscspn(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_Control)
#define LANGIDFROMLCID(l)
Definition: nls.h:18
#define LANG_JAPANESE
Definition: nls.h:76
#define LANG_KOREAN
Definition: nls.h:84
#define _countof(array)
Definition: sndvol32.h:70
#define TRACE(s)
Definition: solgame.cpp:4
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
STRSAFEAPI StringCchCatW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:325
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
STRSAFEAPI StringCchLengthW(STRSAFE_LPCWSTR psz, size_t cchMax, size_t *pcchLength)
Definition: strsafe.h:842
WCHAR wszImeFile[80]
Definition: imm32_undoc.h:69
WCHAR szFileName[80]
Definition: install.c:17
WCHAR szImeKey[20]
Definition: install.c:16
DWORD dwProductVersionMS
Definition: compat.h:904
DWORD dwFileSubtype
Definition: compat.h:910
#define max(a, b)
Definition: svc.c:63
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
unsigned char * LPBYTE
Definition: typedefs.h:53
uint16_t * LPWORD
Definition: typedefs.h:56
#define MAKELONG(a, b)
Definition: typedefs.h:249
#define HIWORD(l)
Definition: typedefs.h:247
#define VFT_DRV
Definition: verrsrc.h:77
#define VFT2_DRV_INPUTMETHOD
Definition: verrsrc.h:95
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_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
static HKL Imm32AssignNewLayout(_In_ UINT cKLs, _In_reads_(cKLs) const REG_IME_LAYOUT *pLayouts, _In_ WORD wLangID)
Definition: install.c:132
static BOOL Imm32LoadImeLangAndDesc(_Inout_ PIMEINFOEX pInfoEx, _In_reads_bytes_(cbVerInfo) LPCVOID pVerInfo, _In_ DWORD cbVerInfo)
Definition: install.c:60
#define MAX_USER_IMM_IME_ID
INT(WINAPI * FN_LZOpenFileW)(LPWSTR, LPOFSTRUCT, WORD)
Definition: install.c:30
static FN_GetFileVersionInfoW s_fnGetFileVersionInfoW
Definition: install.c:25
#define MIN_SYSTEM_IMM_IME_ID
struct tagREG_IME_LAYOUT REG_IME_LAYOUT
#define MIN_USER_IMM_IME_ID
#define GET_FN(name)
static UINT Imm32GetImeLayoutList(_Out_writes_opt_(cLayouts) PREG_IME_LAYOUT pLayouts, _In_ UINT cLayouts)
Definition: install.c:187
BOOL(WINAPI * FN_VerQueryValueW)(LPCVOID, LPCWSTR, LPVOID *, PUINT)
Definition: install.c:23
LONG(WINAPI * FN_LZCopy)(INT, INT)
Definition: install.c:31
#define MAX_SYSTEM_IMM_IME_ID
BOOL Imm32LoadImeVerInfo(_Inout_ PIMEINFOEX pImeInfoEx)
Definition: install.c:418
static BOOL Imm32CopyImeFile(_In_ PCWSTR pszOldFile, _In_ PCWSTR pszNewFile)
Definition: install.c:359
DWORD(WINAPI * FN_GetFileVersionInfoSizeW)(LPCWSTR, LPDWORD)
Definition: install.c:22
static LPWSTR Imm32GetVerInfoValue(_In_reads_bytes_(cbVerInfo) LPCVOID pVerInfo, _In_ DWORD cbVerInfo, _Inout_ PWSTR pszKey, _In_ DWORD cchKey, _In_ PCWSTR pszName)
Definition: install.c:36
static BOOL Imm32LoadImeFixedInfo(_Out_ PIMEINFOEX pInfoEx, _In_reads_bytes_(cbVerInfo) LPCVOID pVerInfo, _In_ DWORD cbVerInfo)
Definition: install.c:103
static FN_GetFileVersionInfoSizeW s_fnGetFileVersionInfoSizeW
Definition: install.c:26
static BOOL Imm32WriteImeLayout(_In_ HKL hKL, _In_ PCWSTR pchFileTitle, _In_ PCWSTR pszLayoutText)
Definition: install.c:262
struct tagREG_IME_LAYOUT * PREG_IME_LAYOUT
BOOL(WINAPI * FN_GetFileVersionInfoW)(LPCWSTR, DWORD, DWORD, LPVOID)
Definition: install.c:21
HKL WINAPI ImmInstallIMEW(_In_ LPCWSTR lpszIMEFileName, _In_ LPCWSTR lpszLayoutText)
Definition: install.c:507
VOID(WINAPI * FN_LZClose)(INT)
Definition: install.c:32
static FN_VerQueryValueW s_fnVerQueryValueW
Definition: install.c:27
#define MAX_PRELOAD
HKL WINAPI ImmInstallIMEA(_In_ LPCSTR lpszIMEFileName, _In_ LPCSTR lpszLayoutText)
Definition: install.c:478
#define IS_ZERO_UNEXPECTEDLY(p)
Definition: precomp.h:67
#define ImmLocalFree(lpData)
Definition: precomp.h:105
LPWSTR Imm32WideFromAnsi(UINT uCodePage, LPCSTR pszA)
Definition: utils.c:96
#define REGKEY_KEYBOARD_LAYOUTS
Definition: precomp.h:85
#define IS_ERROR_UNEXPECTEDLY(x)
Definition: precomp.h:69
BOOL Imm32GetSystemLibraryPath(LPWSTR pszPath, DWORD cchPath, LPCWSTR pszFileName)
Definition: utils.c:152
HRESULT Imm32UIntToStr(_In_ DWORD dwValue, _In_ ULONG nBase, _Out_ PWSTR pszBuff, _In_ USHORT cchBuff)
Definition: utils.c:56
#define IS_NULL_UNEXPECTEDLY(p)
Definition: precomp.h:66
LPVOID ImmLocalAlloc(_In_ DWORD dwFlags, _In_ DWORD dwBytes)
Definition: utils.c:275
HRESULT Imm32StrToUInt(_In_ PCWSTR pszText, _Out_ PDWORD pdwValue, _In_ ULONG nBase)
Definition: utils.c:40
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
struct _OFSTRUCT * LPOFSTRUCT
#define HFILE_ERROR
Definition: winbase.h:119
#define OF_READ
Definition: winbase.h:124
#define OF_CREATE
Definition: winbase.h:133
int HFILE
Definition: windef.h:298
CONST void * LPCVOID
Definition: windef.h:191
#define WINAPI
Definition: msvc.h:6
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11
BOOL WINAPI UnloadKeyboardLayout(_In_ HKL)
#define KLF_REPLACELANG
Definition: winuser.h:115
HKL WINAPI LoadKeyboardLayoutW(_In_ LPCWSTR, _In_ UINT)
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
char CHAR
Definition: xmlstorage.h:175