mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 02:25:17 +00:00
[IMM32] Rewrite ImmInstallIMEW (#4044)
- Add Imm32StrToUInt and Imm32UIntToStr helper functions. - Add Imm32LoadImeVerInfo, Imm32GetRegImes, Imm32WriteRegIme, Imm32GetNextHKL, Imm32CopyFile helper functions. - Add REG_IME structure for registered IMEs. - Rewrite ImmInstallIMEW function. - Improve ImmLoadLayout and Imm32LoadImeInfo functions. CORE-11700
This commit is contained in:
parent
d26409cc34
commit
a37d9a4e14
5 changed files with 642 additions and 124 deletions
|
@ -152,6 +152,7 @@ BOOL APIENTRY Imm32LoadImeInfo(PIMEINFOEX pImeInfoEx, PIMEDPI pImeDpi)
|
||||||
WCHAR szPath[MAX_PATH];
|
WCHAR szPath[MAX_PATH];
|
||||||
HINSTANCE hIME;
|
HINSTANCE hIME;
|
||||||
FARPROC fn;
|
FARPROC fn;
|
||||||
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
if (!Imm32GetSystemLibraryPath(szPath, _countof(szPath), pImeInfoEx->wszImeFile))
|
if (!Imm32GetSystemLibraryPath(szPath, _countof(szPath), pImeInfoEx->wszImeFile))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -172,27 +173,46 @@ BOOL APIENTRY Imm32LoadImeInfo(PIMEINFOEX pImeInfoEx, PIMEDPI pImeDpi)
|
||||||
do { \
|
do { \
|
||||||
fn = GetProcAddress(hIME, #name); \
|
fn = GetProcAddress(hIME, #name); \
|
||||||
if (fn) pImeDpi->name = (FN_##name)fn; \
|
if (fn) pImeDpi->name = (FN_##name)fn; \
|
||||||
else if (!(optional)) goto Failed; \
|
else if (!(optional)) { \
|
||||||
|
ERR("'%s' not found in the IME module '%s'.\n", #name, debugstr_w(szPath)); \
|
||||||
|
goto Failed; \
|
||||||
|
} \
|
||||||
} while (0);
|
} while (0);
|
||||||
#include "imetable.h"
|
#include "imetable.h"
|
||||||
#undef DEFINE_IME_ENTRY
|
#undef DEFINE_IME_ENTRY
|
||||||
|
|
||||||
if (!Imm32InquireIme(pImeDpi))
|
if (Imm32InquireIme(pImeDpi))
|
||||||
{
|
{
|
||||||
ERR("Imm32LoadImeInfo: Imm32InquireIme failed\n");
|
ret = TRUE;
|
||||||
goto Failed;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (pImeInfoEx->fLoadFlag)
|
{
|
||||||
return TRUE;
|
ERR("Imm32InquireIme failed\n");
|
||||||
|
|
||||||
NtUserSetImeOwnerWindow(pImeInfoEx, TRUE);
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
Failed:
|
Failed:
|
||||||
|
ret = FALSE;
|
||||||
FreeLibrary(pImeDpi->hInst);
|
FreeLibrary(pImeDpi->hInst);
|
||||||
pImeDpi->hInst = NULL;
|
pImeDpi->hInst = NULL;
|
||||||
return FALSE;
|
}
|
||||||
|
|
||||||
|
if (pImeInfoEx->fLoadFlag == 0)
|
||||||
|
{
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
C_ASSERT(sizeof(pImeInfoEx->wszUIClass) == sizeof(pImeDpi->szUIClass));
|
||||||
|
pImeInfoEx->ImeInfo = pImeDpi->ImeInfo;
|
||||||
|
RtlCopyMemory(pImeInfoEx->wszUIClass, pImeDpi->szUIClass,
|
||||||
|
sizeof(pImeInfoEx->wszUIClass));
|
||||||
|
pImeInfoEx->fLoadFlag = 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pImeInfoEx->fLoadFlag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
NtUserSetImeInfoEx(pImeInfoEx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
PIMEDPI APIENTRY Ime32LoadImeDpi(HKL hKL, BOOL bLock)
|
PIMEDPI APIENTRY Ime32LoadImeDpi(HKL hKL, BOOL bLock)
|
||||||
|
@ -475,6 +495,127 @@ Quit:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* ImmInstallIMEA (IMM32.@)
|
||||||
|
*/
|
||||||
|
HKL WINAPI ImmInstallIMEA(LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
|
||||||
|
{
|
||||||
|
HKL hKL = NULL;
|
||||||
|
LPWSTR pszFileNameW = NULL, pszLayoutTextW = NULL;
|
||||||
|
|
||||||
|
TRACE("(%s, %s)\n", debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText));
|
||||||
|
|
||||||
|
pszFileNameW = Imm32WideFromAnsi(lpszIMEFileName);
|
||||||
|
if (!pszFileNameW)
|
||||||
|
goto Quit;
|
||||||
|
|
||||||
|
pszLayoutTextW = Imm32WideFromAnsi(lpszLayoutText);
|
||||||
|
if (!pszLayoutTextW)
|
||||||
|
goto Quit;
|
||||||
|
|
||||||
|
hKL = ImmInstallIMEW(pszFileNameW, pszLayoutTextW);
|
||||||
|
|
||||||
|
Quit:
|
||||||
|
Imm32HeapFree(pszFileNameW);
|
||||||
|
Imm32HeapFree(pszLayoutTextW);
|
||||||
|
return hKL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* ImmInstallIMEW (IMM32.@)
|
||||||
|
*/
|
||||||
|
HKL WINAPI ImmInstallIMEW(LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
|
||||||
|
{
|
||||||
|
WCHAR szImeFileName[MAX_PATH], szImeDestPath[MAX_PATH], szImeKey[20];
|
||||||
|
IMEINFOEX InfoEx;
|
||||||
|
LPWSTR pchFilePart;
|
||||||
|
UINT iLayout, cLayouts;
|
||||||
|
HKL hNewKL;
|
||||||
|
WORD wLangID;
|
||||||
|
PREG_IME pLayouts = NULL;
|
||||||
|
|
||||||
|
TRACE("(%s, %s)\n", debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText));
|
||||||
|
|
||||||
|
GetFullPathNameW(lpszIMEFileName, _countof(szImeFileName), szImeFileName, &pchFilePart);
|
||||||
|
CharUpperW(szImeFileName);
|
||||||
|
if (!pchFilePart)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Load the IME version info */
|
||||||
|
InfoEx.hkl = hNewKL = NULL;
|
||||||
|
StringCchCopyW(InfoEx.wszImeFile, _countof(InfoEx.wszImeFile), pchFilePart);
|
||||||
|
if (Imm32LoadImeVerInfo(&InfoEx) && InfoEx.hkl)
|
||||||
|
wLangID = LOWORD(InfoEx.hkl);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Get the IME layouts from registry */
|
||||||
|
cLayouts = Imm32GetRegImes(NULL, 0);
|
||||||
|
if (cLayouts)
|
||||||
|
{
|
||||||
|
pLayouts = Imm32HeapAlloc(0, cLayouts * sizeof(REG_IME));
|
||||||
|
if (!pLayouts || !Imm32GetRegImes(pLayouts, cLayouts))
|
||||||
|
{
|
||||||
|
Imm32HeapFree(pLayouts);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (iLayout = 0; iLayout < cLayouts; ++iLayout)
|
||||||
|
{
|
||||||
|
if (lstrcmpiW(pLayouts[iLayout].szFileName, pchFilePart) == 0)
|
||||||
|
{
|
||||||
|
if (wLangID != LOWORD(pLayouts[iLayout].hKL))
|
||||||
|
goto Quit; /* The language is different */
|
||||||
|
|
||||||
|
hNewKL = pLayouts[iLayout].hKL; /* Found */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the IME for the specified filename is valid, then unload it now */
|
||||||
|
/* FIXME: ImmGetImeInfoEx is broken */
|
||||||
|
if (ImmGetImeInfoEx(&InfoEx, 3, pchFilePart) &&
|
||||||
|
!UnloadKeyboardLayout(InfoEx.hkl))
|
||||||
|
{
|
||||||
|
hNewKL = NULL;
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Imm32GetSystemLibraryPath(szImeDestPath, _countof(szImeDestPath), pchFilePart);
|
||||||
|
CharUpperW(szImeDestPath);
|
||||||
|
|
||||||
|
/* If the source and the destination pathnames were different, then copy the IME file */
|
||||||
|
if (lstrcmpiW(szImeFileName, szImeDestPath) != 0 &&
|
||||||
|
!Imm32CopyFile(szImeFileName, szImeDestPath))
|
||||||
|
{
|
||||||
|
hNewKL = NULL;
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hNewKL == NULL)
|
||||||
|
hNewKL = Imm32GetNextHKL(cLayouts, pLayouts, wLangID);
|
||||||
|
|
||||||
|
if (hNewKL)
|
||||||
|
{
|
||||||
|
/* Write the IME layout to registry */
|
||||||
|
if (Imm32WriteRegIme(hNewKL, pchFilePart, lpszLayoutText))
|
||||||
|
{
|
||||||
|
/* Load the keyboard layout */
|
||||||
|
Imm32UIntToStr((DWORD)(DWORD_PTR)hNewKL, 16, szImeKey, _countof(szImeKey));
|
||||||
|
hNewKL = LoadKeyboardLayoutW(szImeKey, KLF_REPLACELANG);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hNewKL = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Quit:
|
||||||
|
Imm32HeapFree(pLayouts);
|
||||||
|
return hNewKL;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ImmIsIME (IMM32.@)
|
* ImmIsIME (IMM32.@)
|
||||||
*/
|
*/
|
||||||
|
@ -482,7 +623,8 @@ BOOL WINAPI ImmIsIME(HKL hKL)
|
||||||
{
|
{
|
||||||
IMEINFOEX info;
|
IMEINFOEX info;
|
||||||
TRACE("(%p)\n", hKL);
|
TRACE("(%p)\n", hKL);
|
||||||
return !!ImmGetImeInfoEx(&info, ImeInfoExImeWindow, &hKL);
|
/* FIXME: ImmGetImeInfoEx is broken */
|
||||||
|
return !!ImmGetImeInfoEx(&info, 1, &hKL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -542,6 +684,7 @@ ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx, IMEINFOEXCLASS SearchType, PVOID pvSearch
|
||||||
BOOL bDisabled = FALSE;
|
BOOL bDisabled = FALSE;
|
||||||
HKL hKL;
|
HKL hKL;
|
||||||
|
|
||||||
|
/* FIXME: broken */
|
||||||
switch (SearchType)
|
switch (SearchType)
|
||||||
{
|
{
|
||||||
case ImeInfoExKeyboardLayout:
|
case ImeInfoExKeyboardLayout:
|
||||||
|
|
|
@ -51,54 +51,64 @@ BOOL WINAPI ImmRegisterClient(PSHAREDINFO ptr, HINSTANCE hMod)
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ImmLoadLayout (IMM32.@)
|
* ImmLoadLayout (IMM32.@)
|
||||||
*/
|
*/
|
||||||
HKL WINAPI ImmLoadLayout(HKL hKL, PIMEINFOEX pImeInfoEx)
|
BOOL WINAPI ImmLoadLayout(HKL hKL, PIMEINFOEX pImeInfoEx)
|
||||||
{
|
{
|
||||||
DWORD cbData;
|
DWORD cbData;
|
||||||
UNICODE_STRING UnicodeString;
|
|
||||||
HKEY hLayoutKey = NULL, hLayoutsKey = NULL;
|
HKEY hLayoutKey = NULL, hLayoutsKey = NULL;
|
||||||
LONG error;
|
LONG error;
|
||||||
NTSTATUS Status;
|
|
||||||
WCHAR szLayout[MAX_PATH];
|
WCHAR szLayout[MAX_PATH];
|
||||||
|
|
||||||
TRACE("(%p, %p)\n", hKL, pImeInfoEx);
|
TRACE("(%p, %p)\n", hKL, pImeInfoEx);
|
||||||
|
|
||||||
if (IS_IME_HKL(hKL) || !Imm32IsCiceroMode() || Imm32Is16BitMode())
|
if (IS_IME_HKL(hKL) || !Imm32IsCiceroMode() || Imm32Is16BitMode())
|
||||||
{
|
{
|
||||||
UnicodeString.Buffer = szLayout;
|
Imm32UIntToStr((DWORD)(DWORD_PTR)hKL, 16, szLayout, _countof(szLayout));
|
||||||
UnicodeString.MaximumLength = sizeof(szLayout);
|
|
||||||
Status = RtlIntegerToUnicodeString((DWORD_PTR)hKL, 16, &UnicodeString);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
error = RegOpenKeyW(HKEY_LOCAL_MACHINE, REGKEY_KEYBOARD_LAYOUTS, &hLayoutsKey);
|
error = RegOpenKeyW(HKEY_LOCAL_MACHINE, REGKEY_KEYBOARD_LAYOUTS, &hLayoutsKey);
|
||||||
if (error)
|
if (error)
|
||||||
return NULL;
|
{
|
||||||
|
ERR("RegOpenKeyW: 0x%08lX\n", error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
error = RegOpenKeyW(hLayoutsKey, szLayout, &hLayoutKey);
|
error = RegOpenKeyW(hLayoutsKey, szLayout, &hLayoutKey);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
ERR("RegOpenKeyW: 0x%08lX\n", error);
|
||||||
|
RegCloseKey(hLayoutsKey);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error = RegOpenKeyW(HKEY_LOCAL_MACHINE, REGKEY_IMM, &hLayoutKey);
|
error = RegOpenKeyW(HKEY_LOCAL_MACHINE, REGKEY_IMM, &hLayoutKey);
|
||||||
}
|
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
ERR("RegOpenKeyW error: 0x%08lX\n", error);
|
ERR("RegOpenKeyW: 0x%08lX\n", error);
|
||||||
hKL = NULL;
|
return FALSE;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
cbData = sizeof(pImeInfoEx->wszImeFile);
|
cbData = sizeof(pImeInfoEx->wszImeFile);
|
||||||
error = RegQueryValueExW(hLayoutKey, L"Ime File", 0, 0,
|
error = RegQueryValueExW(hLayoutKey, L"Ime File", 0, 0,
|
||||||
(LPBYTE)pImeInfoEx->wszImeFile, &cbData);
|
(LPBYTE)pImeInfoEx->wszImeFile, &cbData);
|
||||||
if (error)
|
pImeInfoEx->wszImeFile[_countof(pImeInfoEx->wszImeFile) - 1] = 0;
|
||||||
hKL = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
RegCloseKey(hLayoutKey);
|
RegCloseKey(hLayoutKey);
|
||||||
if (hLayoutsKey)
|
if (hLayoutsKey)
|
||||||
RegCloseKey(hLayoutsKey);
|
RegCloseKey(hLayoutsKey);
|
||||||
return hKL;
|
|
||||||
|
pImeInfoEx->fLoadFlag = 0;
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
ERR("RegQueryValueExW: 0x%08lX\n", error);
|
||||||
|
pImeInfoEx->hkl = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pImeInfoEx->hkl = hKL;
|
||||||
|
return Imm32LoadImeVerInfo(pImeInfoEx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -476,10 +486,6 @@ BOOL WINAPI ImmActivateLayout(HKL hKL)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
|
|
||||||
static const WCHAR szLayoutTextW[] = {'L','a','y','o','u','t',' ','T','e','x','t',0};
|
|
||||||
static const WCHAR szImeRegFmt[] = {'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','s','\\','%','0','8','l','x',0};
|
|
||||||
|
|
||||||
static VOID APIENTRY Imm32CiceroSetActiveContext(HIMC hIMC, BOOL fActive, HWND hWnd, HKL hKL)
|
static VOID APIENTRY Imm32CiceroSetActiveContext(HIMC hIMC, BOOL fActive, HWND hWnd, HKL hKL)
|
||||||
{
|
{
|
||||||
FIXME("We have to do something\n");
|
FIXME("We have to do something\n");
|
||||||
|
@ -1015,89 +1021,6 @@ BOOL WINAPI CtfImmIsCiceroEnabled(VOID)
|
||||||
return Imm32IsCiceroMode();
|
return Imm32IsCiceroMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* ImmInstallIMEA (IMM32.@)
|
|
||||||
*/
|
|
||||||
HKL WINAPI ImmInstallIMEA(LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
|
|
||||||
{
|
|
||||||
HKL hKL = NULL;
|
|
||||||
LPWSTR pszFileNameW = NULL, pszLayoutTextW = NULL;
|
|
||||||
|
|
||||||
TRACE("(%s, %s)\n", debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText));
|
|
||||||
|
|
||||||
pszFileNameW = Imm32WideFromAnsi(lpszIMEFileName);
|
|
||||||
if (pszFileNameW == NULL)
|
|
||||||
goto Quit;
|
|
||||||
|
|
||||||
pszLayoutTextW = Imm32WideFromAnsi(lpszLayoutText);
|
|
||||||
if (pszLayoutTextW == NULL)
|
|
||||||
goto Quit;
|
|
||||||
|
|
||||||
hKL = ImmInstallIMEW(pszFileNameW, pszLayoutTextW);
|
|
||||||
|
|
||||||
Quit:
|
|
||||||
Imm32HeapFree(pszFileNameW);
|
|
||||||
Imm32HeapFree(pszLayoutTextW);
|
|
||||||
return hKL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* ImmInstallIMEW (IMM32.@)
|
|
||||||
*/
|
|
||||||
HKL WINAPI ImmInstallIMEW(LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
|
|
||||||
{
|
|
||||||
INT lcid = GetUserDefaultLCID();
|
|
||||||
INT count;
|
|
||||||
HKL hkl;
|
|
||||||
DWORD rc;
|
|
||||||
HKEY hkey;
|
|
||||||
WCHAR regKey[ARRAY_SIZE(szImeRegFmt)+8];
|
|
||||||
|
|
||||||
TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName),
|
|
||||||
debugstr_w(lpszLayoutText));
|
|
||||||
|
|
||||||
/* Start with 2. e001 will be blank and so default to the wine internal IME */
|
|
||||||
count = 2;
|
|
||||||
|
|
||||||
while (count < 0xfff)
|
|
||||||
{
|
|
||||||
DWORD disposition = 0;
|
|
||||||
|
|
||||||
hkl = (HKL)MAKELPARAM( lcid, 0xe000 | count );
|
|
||||||
wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hkl);
|
|
||||||
|
|
||||||
rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &disposition);
|
|
||||||
if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
|
|
||||||
break;
|
|
||||||
else if (rc == ERROR_SUCCESS)
|
|
||||||
RegCloseKey(hkey);
|
|
||||||
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 0xfff)
|
|
||||||
{
|
|
||||||
WARN("Unable to find slot to install IME\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc == ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (const BYTE*)lpszIMEFileName,
|
|
||||||
(lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR));
|
|
||||||
if (rc == ERROR_SUCCESS)
|
|
||||||
rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (const BYTE*)lpszLayoutText,
|
|
||||||
(lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR));
|
|
||||||
RegCloseKey(hkey);
|
|
||||||
return hkl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WARN("Unable to set IME registry values\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ImmLockIMC(IMM32.@)
|
* ImmLockIMC(IMM32.@)
|
||||||
*
|
*
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <winnls.h>
|
#include <winnls.h>
|
||||||
#include <winreg.h>
|
#include <winreg.h>
|
||||||
#include <winnls32.h>
|
#include <winnls32.h>
|
||||||
|
#include <winver.h>
|
||||||
|
|
||||||
#include <imm.h>
|
#include <imm.h>
|
||||||
#include <ddk/imm.h>
|
#include <ddk/imm.h>
|
||||||
|
@ -61,6 +62,13 @@
|
||||||
|
|
||||||
#define ROUNDUP4(n) (((n) + 3) & ~3) /* DWORD alignment */
|
#define ROUNDUP4(n) (((n) + 3) & ~3) /* DWORD alignment */
|
||||||
|
|
||||||
|
typedef struct REG_IME
|
||||||
|
{
|
||||||
|
HKL hKL;
|
||||||
|
WCHAR szImeKey[20]; /* "E0XXYYYY": "E0XX" is the device handle. "YYYY" is a LANGID. */
|
||||||
|
WCHAR szFileName[80]; /* The IME module filename */
|
||||||
|
} REG_IME, *PREG_IME;
|
||||||
|
|
||||||
extern HMODULE g_hImm32Inst;
|
extern HMODULE g_hImm32Inst;
|
||||||
extern RTL_CRITICAL_SECTION g_csImeDpi;
|
extern RTL_CRITICAL_SECTION g_csImeDpi;
|
||||||
extern PIMEDPI g_pImeDpiList;
|
extern PIMEDPI g_pImeDpiList;
|
||||||
|
@ -139,3 +147,11 @@ DWORD APIENTRY
|
||||||
Imm32ReconvertAnsiFromWide(LPRECONVERTSTRING pDest, const RECONVERTSTRING *pSrc, UINT uCodePage);
|
Imm32ReconvertAnsiFromWide(LPRECONVERTSTRING pDest, const RECONVERTSTRING *pSrc, UINT uCodePage);
|
||||||
DWORD APIENTRY
|
DWORD APIENTRY
|
||||||
Imm32ReconvertWideFromAnsi(LPRECONVERTSTRING pDest, const RECONVERTSTRING *pSrc, UINT uCodePage);
|
Imm32ReconvertWideFromAnsi(LPRECONVERTSTRING pDest, const RECONVERTSTRING *pSrc, UINT uCodePage);
|
||||||
|
|
||||||
|
HRESULT APIENTRY Imm32StrToUInt(LPCWSTR pszText, LPDWORD pdwValue, ULONG nBase);
|
||||||
|
HRESULT APIENTRY Imm32UIntToStr(DWORD dwValue, ULONG nBase, LPWSTR pszBuff, USHORT cchBuff);
|
||||||
|
BOOL APIENTRY Imm32LoadImeVerInfo(PIMEINFOEX pImeInfoEx);
|
||||||
|
UINT APIENTRY Imm32GetRegImes(PREG_IME pLayouts, UINT cLayouts);
|
||||||
|
BOOL APIENTRY Imm32WriteRegIme(HKL hKL, LPCWSTR pchFilePart, LPCWSTR pszLayout);
|
||||||
|
HKL APIENTRY Imm32GetNextHKL(UINT cKLs, const REG_IME *pLayouts, WORD wLangID);
|
||||||
|
BOOL APIENTRY Imm32CopyFile(LPWSTR pszOldFile, LPCWSTR pszNewFile);
|
||||||
|
|
|
@ -16,6 +16,48 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm);
|
||||||
|
|
||||||
HANDLE g_hImm32Heap = NULL;
|
HANDLE g_hImm32Heap = NULL;
|
||||||
|
|
||||||
|
HRESULT APIENTRY
|
||||||
|
Imm32StrToUInt(LPCWSTR pszText, LPDWORD pdwValue, ULONG nBase)
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
NTSTATUS Status;
|
||||||
|
UNICODE_STRING UnicodeString;
|
||||||
|
RtlInitUnicodeString(&UnicodeString, pszText);
|
||||||
|
Status = RtlUnicodeStringToInteger(&UnicodeString, nBase, pdwValue);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return E_FAIL;
|
||||||
|
return S_OK;
|
||||||
|
#else
|
||||||
|
LPWSTR endptr;
|
||||||
|
*pdwValue = wcstoul(pszText, &endptr, nBase);
|
||||||
|
return (*endptr ? E_FAIL : S_OK);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT APIENTRY
|
||||||
|
Imm32UIntToStr(DWORD dwValue, ULONG nBase, LPWSTR pszBuff, USHORT cchBuff)
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
NTSTATUS Status;
|
||||||
|
UNICODE_STRING UnicodeString;
|
||||||
|
UnicodeString.Buffer = pszBuff;
|
||||||
|
UnicodeString.MaximumLength = cchBuff * sizeof(WCHAR);
|
||||||
|
Status = RtlIntegerToUnicodeString(dwValue, nBase, &UnicodeString);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return E_FAIL;
|
||||||
|
return S_OK;
|
||||||
|
#else
|
||||||
|
LPCWSTR pszFormat;
|
||||||
|
if (nBase == 16)
|
||||||
|
pszFormat = L"%lX";
|
||||||
|
else if (nBase == 10)
|
||||||
|
pszFormat = L"%lu";
|
||||||
|
else
|
||||||
|
return E_INVALIDARG;
|
||||||
|
return StringCchPrintfW(pszBuff, cchBuff, pszFormat, dwValue);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
BOOL WINAPI Imm32IsImcAnsi(HIMC hIMC)
|
BOOL WINAPI Imm32IsImcAnsi(HIMC hIMC)
|
||||||
{
|
{
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
@ -484,6 +526,400 @@ Imm32ReconvertAnsiFromWide(LPRECONVERTSTRING pDest, const RECONVERTSTRING *pSrc,
|
||||||
return cbDest;
|
return cbDest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef BOOL (WINAPI *FN_GetFileVersionInfoW)(LPCWSTR, DWORD, DWORD, LPVOID);
|
||||||
|
typedef DWORD (WINAPI *FN_GetFileVersionInfoSizeW)(LPCWSTR, LPDWORD);
|
||||||
|
typedef BOOL (WINAPI *FN_VerQueryValueW)(LPCVOID, LPCWSTR, LPVOID*, PUINT);
|
||||||
|
|
||||||
|
static FN_GetFileVersionInfoW s_fnGetFileVersionInfoW = NULL;
|
||||||
|
static FN_GetFileVersionInfoSizeW s_fnGetFileVersionInfoSizeW = NULL;
|
||||||
|
static FN_VerQueryValueW s_fnVerQueryValueW = NULL;
|
||||||
|
|
||||||
|
static BOOL APIENTRY Imm32LoadImeFixedInfo(PIMEINFOEX pInfoEx, LPCVOID pVerInfo)
|
||||||
|
{
|
||||||
|
UINT cbFixed = 0;
|
||||||
|
VS_FIXEDFILEINFO *pFixed;
|
||||||
|
if (!s_fnVerQueryValueW(pVerInfo, L"\\", (LPVOID*)&pFixed, &cbFixed) || !cbFixed)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* NOTE: The IME module must contain a version info of input method driver. */
|
||||||
|
if (pFixed->dwFileType != VFT_DRV || pFixed->dwFileSubtype != VFT2_DRV_INPUTMETHOD)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
pInfoEx->dwProdVersion = pFixed->dwProductVersionMS;
|
||||||
|
pInfoEx->dwImeWinVersion = 0x40000;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LPWSTR APIENTRY
|
||||||
|
Imm32GetVerInfoValue(LPCVOID pVerInfo, LPWSTR pszKey, DWORD cchKey, LPCWSTR pszName)
|
||||||
|
{
|
||||||
|
size_t cchExtra;
|
||||||
|
LPWSTR pszValue;
|
||||||
|
UINT cbValue = 0;
|
||||||
|
|
||||||
|
StringCchLengthW(pszKey, cchKey, &cchExtra);
|
||||||
|
|
||||||
|
StringCchCatW(pszKey, cchKey, pszName);
|
||||||
|
s_fnVerQueryValueW(pVerInfo, pszKey, (LPVOID*)&pszValue, &cbValue);
|
||||||
|
pszKey[cchExtra] = 0;
|
||||||
|
|
||||||
|
return (cbValue ? pszValue : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL APIENTRY Imm32LoadImeLangAndDesc(PIMEINFOEX pInfoEx, LPCVOID pVerInfo)
|
||||||
|
{
|
||||||
|
BOOL ret;
|
||||||
|
WCHAR szKey[80];
|
||||||
|
LPWSTR pszDesc;
|
||||||
|
LPWORD pw;
|
||||||
|
UINT cbData;
|
||||||
|
LANGID LangID;
|
||||||
|
|
||||||
|
/* Getting the version info. See VerQueryValue */
|
||||||
|
ret = s_fnVerQueryValueW(pVerInfo, L"\\VarFileInfo\\Translation", (LPVOID*)&pw, &cbData);
|
||||||
|
if (!ret || !cbData)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (pInfoEx->hkl == NULL)
|
||||||
|
pInfoEx->hkl = (HKL)(DWORD_PTR)*pw; /* This is an invalid HKL */
|
||||||
|
|
||||||
|
/* Try the current language and the Unicode codepage (0x04B0) */
|
||||||
|
LangID = LANGIDFROMLCID(GetThreadLocale());
|
||||||
|
StringCchPrintfW(szKey, _countof(szKey), L"\\StringFileInfo\\%04X04B0\\", LangID);
|
||||||
|
pszDesc = Imm32GetVerInfoValue(pVerInfo, szKey, _countof(szKey), L"FileDescription");
|
||||||
|
if (!pszDesc)
|
||||||
|
{
|
||||||
|
/* Retry the language and codepage of the IME module */
|
||||||
|
StringCchPrintfW(szKey, _countof(szKey), L"\\StringFileInfo\\%04X%04X\\", pw[0], pw[1]);
|
||||||
|
pszDesc = Imm32GetVerInfoValue(pVerInfo, szKey, _countof(szKey), L"FileDescription");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The description */
|
||||||
|
if (pszDesc)
|
||||||
|
StringCchCopyW(pInfoEx->wszImeDescription, _countof(pInfoEx->wszImeDescription), pszDesc);
|
||||||
|
else
|
||||||
|
pInfoEx->wszImeDescription[0] = 0;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL APIENTRY Imm32LoadImeVerInfo(PIMEINFOEX pImeInfoEx)
|
||||||
|
{
|
||||||
|
HINSTANCE hinstVersion;
|
||||||
|
BOOL ret = FALSE, bLoaded = FALSE;
|
||||||
|
WCHAR szPath[MAX_PATH];
|
||||||
|
LPVOID pVerInfo;
|
||||||
|
DWORD cbVerInfo, dwHandle;
|
||||||
|
|
||||||
|
/* Load version.dll to use the version info API */
|
||||||
|
Imm32GetSystemLibraryPath(szPath, _countof(szPath), L"version.dll");
|
||||||
|
hinstVersion = GetModuleHandleW(szPath);
|
||||||
|
if (!hinstVersion)
|
||||||
|
{
|
||||||
|
hinstVersion = LoadLibraryW(szPath);
|
||||||
|
if (!hinstVersion)
|
||||||
|
return FALSE;
|
||||||
|
bLoaded = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GET_FN(name) do { \
|
||||||
|
s_fn##name = (FN_##name)GetProcAddress(hinstVersion, #name); \
|
||||||
|
if (!s_fn##name) goto Quit; \
|
||||||
|
} while (0)
|
||||||
|
GET_FN(GetFileVersionInfoW);
|
||||||
|
GET_FN(GetFileVersionInfoSizeW);
|
||||||
|
GET_FN(VerQueryValueW);
|
||||||
|
#undef GET_FN
|
||||||
|
|
||||||
|
/* The path of the IME module */
|
||||||
|
Imm32GetSystemLibraryPath(szPath, _countof(szPath), pImeInfoEx->wszImeFile);
|
||||||
|
|
||||||
|
cbVerInfo = s_fnGetFileVersionInfoSizeW(szPath, &dwHandle);
|
||||||
|
if (!cbVerInfo)
|
||||||
|
goto Quit;
|
||||||
|
|
||||||
|
pVerInfo = Imm32HeapAlloc(0, cbVerInfo);
|
||||||
|
if (!pVerInfo)
|
||||||
|
goto Quit;
|
||||||
|
|
||||||
|
/* Load the version info of the IME module */
|
||||||
|
if (s_fnGetFileVersionInfoW(szPath, dwHandle, cbVerInfo, pVerInfo) &&
|
||||||
|
Imm32LoadImeFixedInfo(pImeInfoEx, pVerInfo))
|
||||||
|
{
|
||||||
|
ret = Imm32LoadImeLangAndDesc(pImeInfoEx, pVerInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
Imm32HeapFree(pVerInfo);
|
||||||
|
|
||||||
|
Quit:
|
||||||
|
if (bLoaded)
|
||||||
|
FreeLibrary(hinstVersion);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
HKL APIENTRY Imm32GetNextHKL(UINT cKLs, const REG_IME *pLayouts, WORD wLangID)
|
||||||
|
{
|
||||||
|
UINT iKL, wID, wLow = 0xE0FF, wHigh = 0xE01F, wNextID = 0;
|
||||||
|
|
||||||
|
for (iKL = 0; iKL < cKLs; ++iKL)
|
||||||
|
{
|
||||||
|
wHigh = max(wHigh, HIWORD(pLayouts[iKL].hKL));
|
||||||
|
wLow = min(wLow, HIWORD(pLayouts[iKL].hKL));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wHigh < 0xE0FF)
|
||||||
|
{
|
||||||
|
wNextID = wHigh + 1;
|
||||||
|
}
|
||||||
|
else if (wLow > 0xE001)
|
||||||
|
{
|
||||||
|
wNextID = wLow - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (wID = 0xE020; wID <= 0xE0FF; ++wID)
|
||||||
|
{
|
||||||
|
for (iKL = 0; iKL < cKLs; ++iKL)
|
||||||
|
{
|
||||||
|
if (LOWORD(pLayouts[iKL].hKL) == wLangID &&
|
||||||
|
HIWORD(pLayouts[iKL].hKL) == wID)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iKL >= cKLs)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wID <= 0xE0FF)
|
||||||
|
wNextID = wID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wNextID)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return (HKL)(DWORD_PTR)MAKELONG(wLangID, wNextID);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT APIENTRY Imm32GetRegImes(PREG_IME pLayouts, UINT cLayouts)
|
||||||
|
{
|
||||||
|
HKEY hkeyLayouts, hkeyIME;
|
||||||
|
WCHAR szImeFileName[80], szImeKey[20];
|
||||||
|
UINT iKey, nCount;
|
||||||
|
DWORD cbData;
|
||||||
|
LONG lError;
|
||||||
|
ULONG Value;
|
||||||
|
HKL hKL;
|
||||||
|
|
||||||
|
/* Open the registry keyboard layouts */
|
||||||
|
lError = RegOpenKeyW(HKEY_LOCAL_MACHINE, REGKEY_KEYBOARD_LAYOUTS, &hkeyLayouts);
|
||||||
|
if (lError != ERROR_SUCCESS)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (iKey = nCount = 0; ; ++iKey)
|
||||||
|
{
|
||||||
|
/* Get the key name */
|
||||||
|
lError = RegEnumKeyW(hkeyLayouts, iKey, szImeKey, _countof(szImeKey));
|
||||||
|
if (lError != ERROR_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (szImeKey[0] != L'E' && szImeKey[0] != L'e')
|
||||||
|
continue; /* Not an IME layout */
|
||||||
|
|
||||||
|
if (pLayouts == NULL) /* for counting only */
|
||||||
|
{
|
||||||
|
++nCount;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cLayouts <= nCount)
|
||||||
|
break;
|
||||||
|
|
||||||
|
lError = RegOpenKeyW(hkeyLayouts, szImeKey, &hkeyIME); /* Open the IME key */
|
||||||
|
if (lError != ERROR_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Load the "Ime File" value */
|
||||||
|
szImeFileName[0] = 0;
|
||||||
|
cbData = sizeof(szImeFileName);
|
||||||
|
RegQueryValueExW(hkeyIME, L"Ime File", NULL, NULL, (LPBYTE)szImeFileName, &cbData);
|
||||||
|
szImeFileName[_countof(szImeFileName) - 1] = 0;
|
||||||
|
|
||||||
|
RegCloseKey(hkeyIME);
|
||||||
|
|
||||||
|
if (!szImeFileName[0])
|
||||||
|
break;
|
||||||
|
|
||||||
|
Imm32StrToUInt(szImeKey, &Value, 16);
|
||||||
|
hKL = (HKL)(DWORD_PTR)Value;
|
||||||
|
if (!IS_IME_HKL(hKL))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Store the IME key and the IME filename */
|
||||||
|
pLayouts[nCount].hKL = hKL;
|
||||||
|
StringCchCopyW(pLayouts[nCount].szImeKey, _countof(pLayouts[nCount].szImeKey), szImeKey);
|
||||||
|
CharUpperW(szImeFileName);
|
||||||
|
StringCchCopyW(pLayouts[nCount].szFileName, _countof(pLayouts[nCount].szFileName),
|
||||||
|
szImeFileName);
|
||||||
|
++nCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegCloseKey(hkeyLayouts);
|
||||||
|
return nCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL APIENTRY Imm32WriteRegIme(HKL hKL, LPCWSTR pchFilePart, LPCWSTR pszLayout)
|
||||||
|
{
|
||||||
|
UINT iPreload;
|
||||||
|
HKEY hkeyLayouts, hkeyIME, hkeyPreload;
|
||||||
|
WCHAR szImeKey[20], szPreloadNumber[20], szPreloadKey[20], szImeFileName[80];
|
||||||
|
DWORD cbData;
|
||||||
|
LANGID LangID;
|
||||||
|
LONG lError;
|
||||||
|
LPCWSTR pszLayoutFile;
|
||||||
|
|
||||||
|
/* Open the registry keyboard layouts */
|
||||||
|
lError = RegOpenKeyW(HKEY_LOCAL_MACHINE, REGKEY_KEYBOARD_LAYOUTS, &hkeyLayouts);
|
||||||
|
if (lError != ERROR_SUCCESS)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Get the IME key from hKL */
|
||||||
|
Imm32UIntToStr((DWORD)(DWORD_PTR)hKL, 16, szImeKey, _countof(szImeKey));
|
||||||
|
|
||||||
|
/* Create a registry IME key */
|
||||||
|
lError = RegCreateKeyW(hkeyLayouts, szImeKey, &hkeyIME);
|
||||||
|
if (lError != ERROR_SUCCESS)
|
||||||
|
goto Failure;
|
||||||
|
|
||||||
|
/* Write "Ime File" */
|
||||||
|
cbData = (wcslen(pchFilePart) + 1) * sizeof(WCHAR);
|
||||||
|
lError = RegSetValueExW(hkeyIME, L"Ime File", 0, REG_SZ, (LPBYTE)pchFilePart, cbData);
|
||||||
|
if (lError != ERROR_SUCCESS)
|
||||||
|
goto Failure;
|
||||||
|
|
||||||
|
/* Write "Layout Text" */
|
||||||
|
cbData = (wcslen(pszLayout) + 1) * sizeof(WCHAR);
|
||||||
|
lError = RegSetValueExW(hkeyIME, L"Layout Text", 0, REG_SZ, (LPBYTE)pszLayout, cbData);
|
||||||
|
if (lError != ERROR_SUCCESS)
|
||||||
|
goto Failure;
|
||||||
|
|
||||||
|
/* Choose "Layout File" from hKL */
|
||||||
|
LangID = LOWORD(hKL);
|
||||||
|
switch (LOBYTE(LangID))
|
||||||
|
{
|
||||||
|
case LANG_JAPANESE: pszLayoutFile = L"kbdjpn.dll"; break;
|
||||||
|
case LANG_KOREAN: pszLayoutFile = L"kbdkor.dll"; break;
|
||||||
|
default: pszLayoutFile = L"kbdus.dll"; break;
|
||||||
|
}
|
||||||
|
StringCchCopyW(szImeFileName, _countof(szImeFileName), pszLayoutFile);
|
||||||
|
|
||||||
|
/* Write "Layout File" */
|
||||||
|
cbData = (wcslen(szImeFileName) + 1) * sizeof(WCHAR);
|
||||||
|
lError = RegSetValueExW(hkeyIME, L"Layout File", 0, REG_SZ, (LPBYTE)szImeFileName, cbData);
|
||||||
|
if (lError != ERROR_SUCCESS)
|
||||||
|
goto Failure;
|
||||||
|
|
||||||
|
RegCloseKey(hkeyIME);
|
||||||
|
RegCloseKey(hkeyLayouts);
|
||||||
|
|
||||||
|
/* Create "Preload" key */
|
||||||
|
RegCreateKeyW(HKEY_CURRENT_USER, L"Keyboard Layout\\Preload", &hkeyPreload);
|
||||||
|
|
||||||
|
#define MAX_PRELOAD 0x400
|
||||||
|
for (iPreload = 1; iPreload < MAX_PRELOAD; ++iPreload)
|
||||||
|
{
|
||||||
|
Imm32UIntToStr(iPreload, 10, szPreloadNumber, _countof(szPreloadNumber));
|
||||||
|
|
||||||
|
/* Load the key of the preload number */
|
||||||
|
cbData = sizeof(szPreloadKey);
|
||||||
|
lError = RegQueryValueExW(hkeyPreload, szPreloadNumber, NULL, NULL,
|
||||||
|
(LPBYTE)szPreloadKey, &cbData);
|
||||||
|
szPreloadKey[_countof(szPreloadKey) - 1] = 0;
|
||||||
|
|
||||||
|
if (lError != ERROR_SUCCESS || lstrcmpiW(szImeKey, szPreloadKey) == 0)
|
||||||
|
break; /* Found an empty room or the same key */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iPreload >= MAX_PRELOAD) /* Not found */
|
||||||
|
{
|
||||||
|
RegCloseKey(hkeyPreload);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
#undef MAX_PRELOAD
|
||||||
|
|
||||||
|
/* Write the IME key to the preload number */
|
||||||
|
cbData = (wcslen(szImeKey) + 1) * sizeof(WCHAR);
|
||||||
|
lError = RegSetValueExW(hkeyPreload, szPreloadNumber, 0, REG_SZ, (LPBYTE)szImeKey, cbData);
|
||||||
|
RegCloseKey(hkeyPreload);
|
||||||
|
return lError == ERROR_SUCCESS;
|
||||||
|
|
||||||
|
Failure:
|
||||||
|
RegCloseKey(hkeyIME);
|
||||||
|
RegDeleteKeyW(hkeyLayouts, szImeKey);
|
||||||
|
RegCloseKey(hkeyLayouts);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef INT (WINAPI *FN_LZOpenFileW)(LPWSTR, LPOFSTRUCT, WORD);
|
||||||
|
typedef LONG (WINAPI *FN_LZCopy)(INT, INT);
|
||||||
|
typedef VOID (WINAPI *FN_LZClose)(INT);
|
||||||
|
|
||||||
|
BOOL APIENTRY Imm32CopyFile(LPWSTR pszOldFile, LPCWSTR pszNewFile)
|
||||||
|
{
|
||||||
|
BOOL ret = FALSE, bLoaded = FALSE;
|
||||||
|
HMODULE hinstLZ32;
|
||||||
|
WCHAR szLZ32Path[MAX_PATH];
|
||||||
|
CHAR szDestA[MAX_PATH];
|
||||||
|
OFSTRUCT OFStruct;
|
||||||
|
FN_LZOpenFileW fnLZOpenFileW;
|
||||||
|
FN_LZCopy fnLZCopy;
|
||||||
|
FN_LZClose fnLZClose;
|
||||||
|
HFILE hfDest, hfSrc;
|
||||||
|
|
||||||
|
/* Load LZ32.dll for copying/decompressing file */
|
||||||
|
Imm32GetSystemLibraryPath(szLZ32Path, _countof(szLZ32Path), L"LZ32");
|
||||||
|
hinstLZ32 = GetModuleHandleW(szLZ32Path);
|
||||||
|
if (!hinstLZ32)
|
||||||
|
{
|
||||||
|
hinstLZ32 = LoadLibraryW(szLZ32Path);
|
||||||
|
if (!hinstLZ32)
|
||||||
|
return FALSE;
|
||||||
|
bLoaded = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GET_FN(name) do { \
|
||||||
|
fn##name = (FN_##name)GetProcAddress(hinstLZ32, #name); \
|
||||||
|
if (!fn##name) goto Quit; \
|
||||||
|
} while (0)
|
||||||
|
GET_FN(LZOpenFileW);
|
||||||
|
GET_FN(LZCopy);
|
||||||
|
GET_FN(LZClose);
|
||||||
|
#undef GET_FN
|
||||||
|
|
||||||
|
if (!WideCharToMultiByte(CP_ACP, 0, pszNewFile, -1, szDestA, _countof(szDestA), NULL, NULL))
|
||||||
|
goto Quit;
|
||||||
|
szDestA[_countof(szDestA) - 1] = 0;
|
||||||
|
|
||||||
|
hfSrc = fnLZOpenFileW(pszOldFile, &OFStruct, OF_READ);
|
||||||
|
if (hfSrc < 0)
|
||||||
|
goto Quit;
|
||||||
|
|
||||||
|
hfDest = OpenFile(szDestA, &OFStruct, OF_CREATE);
|
||||||
|
if (hfDest != HFILE_ERROR)
|
||||||
|
{
|
||||||
|
ret = (fnLZCopy(hfSrc, hfDest) >= 0);
|
||||||
|
_lclose(hfDest);
|
||||||
|
}
|
||||||
|
|
||||||
|
fnLZClose(hfSrc);
|
||||||
|
|
||||||
|
Quit:
|
||||||
|
if (bLoaded)
|
||||||
|
FreeLibrary(hinstLZ32);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* CtfImmIsTextFrameServiceDisabled(IMM32.@)
|
* CtfImmIsTextFrameServiceDisabled(IMM32.@)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1183,7 +1183,7 @@ typedef struct tagIMEINFOEX
|
||||||
};
|
};
|
||||||
} IMEINFOEX, *PIMEINFOEX;
|
} IMEINFOEX, *PIMEINFOEX;
|
||||||
|
|
||||||
typedef enum IMEINFOEXCLASS
|
typedef enum IMEINFOEXCLASS /* unconfirmed: buggy */
|
||||||
{
|
{
|
||||||
ImeInfoExKeyboardLayout,
|
ImeInfoExKeyboardLayout,
|
||||||
ImeInfoExImeWindow,
|
ImeInfoExImeWindow,
|
||||||
|
|
Loading…
Reference in a new issue