[IMM32] Rewrite ImmGetImeMenuItemsA/W (#3983)

- Rewrite ImmGetImeMenuItemsA and ImmGetImeMenuItemsW functions.
- Add Imm32GetImeMenuItemsAW, Imm32IsImcAnsi, Imm32ImeMenuAnsiToWide and Imm32ImeMenuWideToAnsi helper functions.
- Make IME module's ImeGetImeMenuItems function optional.
CORE-11700
This commit is contained in:
Katayama Hirofumi MZ 2021-10-01 03:04:00 +09:00 committed by GitHub
parent 9adc538c9c
commit 33affbfecb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 246 additions and 146 deletions

View file

@ -168,11 +168,11 @@ BOOL APIENTRY Imm32LoadImeInfo(PIMEINFOEX pImeInfoEx, PIMEDPI pImeDpi)
}
pImeDpi->hInst = hIME;
#define DEFINE_IME_ENTRY(type, name, params, extended) \
#define DEFINE_IME_ENTRY(type, name, params, optional) \
do { \
fn = GetProcAddress(hIME, #name); \
if (fn) pImeDpi->name = (FN_##name)fn; \
else if (!(extended)) goto Failed; \
else if (!(optional)) goto Failed; \
} while (0);
#include "imetable.h"
#undef DEFINE_IME_ENTRY
@ -330,6 +330,151 @@ Quit:
return ret;
}
DWORD APIENTRY
Imm32GetImeMenuItemWCrossProcess(HIMC hIMC, DWORD dwFlags, DWORD dwType, LPVOID lpImeParentMenu,
LPVOID lpImeMenu, DWORD dwSize)
{
FIXME("We have to do something\n");
return 0;
}
DWORD APIENTRY
Imm32GetImeMenuItemsAW(HIMC hIMC, DWORD dwFlags, DWORD dwType, LPVOID lpImeParentMenu,
LPVOID lpImeMenu, DWORD dwSize, BOOL bTargetIsAnsi)
{
DWORD ret = 0, cbTotal, dwProcessId, dwThreadId, iItem;
LPINPUTCONTEXT pIC;
PIMEDPI pImeDpi = NULL;
IMEMENUITEMINFOA ParentA;
IMEMENUITEMINFOW ParentW;
LPIMEMENUITEMINFOA pItemA;
LPIMEMENUITEMINFOW pItemW;
LPVOID pNewItems = NULL, pNewParent = NULL;
BOOL bImcIsAnsi;
HKL hKL;
if (!hIMC)
return 0;
dwProcessId = NtUserQueryInputContext(hIMC, 0);
if (dwProcessId == 0)
return 0;
if (dwProcessId != GetCurrentProcessId())
{
if (bTargetIsAnsi)
return 0;
return Imm32GetImeMenuItemWCrossProcess(hIMC, dwFlags, dwType, lpImeParentMenu,
lpImeMenu, dwSize);
}
pIC = ImmLockIMC(hIMC);
if (pIC == NULL)
return 0;
dwThreadId = NtUserQueryInputContext(hIMC, 1);
if (dwThreadId == 0)
{
ImmUnlockIMC(hIMC);
return 0;
}
hKL = GetKeyboardLayout(dwThreadId);
pImeDpi = ImmLockImeDpi(hKL);
if (!pImeDpi)
{
ImmUnlockIMC(hIMC);
return 0;
}
if (pImeDpi->ImeGetImeMenuItems == NULL)
goto Quit;
bImcIsAnsi = Imm32IsImcAnsi(hIMC);
if (bImcIsAnsi != bTargetIsAnsi)
{
if (bTargetIsAnsi)
{
if (lpImeParentMenu)
pNewParent = &ParentW;
if (lpImeMenu)
{
cbTotal = ((dwSize / sizeof(IMEMENUITEMINFOA)) * sizeof(IMEMENUITEMINFOW));
pNewItems = Imm32HeapAlloc(0, cbTotal);
if (!pNewItems)
goto Quit;
}
}
else
{
if (lpImeParentMenu)
pNewParent = &ParentA;
if (lpImeMenu)
{
cbTotal = ((dwSize / sizeof(IMEMENUITEMINFOW)) * sizeof(IMEMENUITEMINFOA));
pNewItems = Imm32HeapAlloc(0, cbTotal);
if (!pNewItems)
goto Quit;
}
}
}
else
{
pNewItems = lpImeMenu;
pNewParent = lpImeParentMenu;
}
ret = pImeDpi->ImeGetImeMenuItems(hIMC, dwFlags, dwType, pNewParent, pNewItems, dwSize);
if (!ret || !lpImeMenu)
goto Quit;
if (bImcIsAnsi != bTargetIsAnsi)
{
if (bTargetIsAnsi)
{
if (pNewParent)
Imm32ImeMenuWideToAnsi(pNewParent, lpImeParentMenu, CP_ACP);
pItemW = pNewItems;
pItemA = lpImeMenu;
for (iItem = 0; iItem < ret; ++iItem, ++pItemW, ++pItemA)
{
if (!Imm32ImeMenuWideToAnsi(pItemW, pItemA, CP_ACP))
{
ret = 0;
break;
}
}
}
else
{
if (pNewParent)
Imm32ImeMenuAnsiToWide(pNewParent, lpImeParentMenu, pImeDpi->uCodePage, TRUE);
pItemA = pNewItems;
pItemW = lpImeMenu;
for (iItem = 0; iItem < dwSize; ++iItem, ++pItemA, ++pItemW)
{
if (!Imm32ImeMenuAnsiToWide(pItemA, pItemW, pImeDpi->uCodePage, TRUE))
{
ret = 0;
break;
}
}
}
}
Quit:
if (pNewItems != lpImeMenu)
Imm32HeapFree(pNewItems);
ImmUnlockImeDpi(pImeDpi);
ImmUnlockIMC(hIMC);
return ret;
}
/***********************************************************************
* ImmIsIME (IMM32.@)
*/
@ -1505,6 +1650,34 @@ Quit:
return ret;
}
/***********************************************************************
* ImmGetImeMenuItemsA (IMM32.@)
*/
DWORD WINAPI
ImmGetImeMenuItemsA(HIMC hIMC, DWORD dwFlags, DWORD dwType,
LPIMEMENUITEMINFOA lpImeParentMenu,
LPIMEMENUITEMINFOA lpImeMenu, DWORD dwSize)
{
TRACE("(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n",
hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize);
return Imm32GetImeMenuItemsAW(hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu,
dwSize, TRUE);
}
/***********************************************************************
* ImmGetImeMenuItemsW (IMM32.@)
*/
DWORD WINAPI
ImmGetImeMenuItemsW(HIMC hIMC, DWORD dwFlags, DWORD dwType,
LPIMEMENUITEMINFOW lpImeParentMenu,
LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize)
{
TRACE("(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n",
hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize);
return Imm32GetImeMenuItemsAW(hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu,
dwSize, FALSE);
}
/***********************************************************************
* ImmFreeLayout (IMM32.@)
*/

View file

@ -1425,148 +1425,6 @@ BOOL WINAPI ImmSetActiveContextConsoleIME(HWND hwnd, BOOL fFlag)
return FALSE;
}
/***********************************************************************
* ImmGetImeMenuItemsA (IMM32.@)
*/
DWORD WINAPI
ImmGetImeMenuItemsA(HIMC hIMC, DWORD dwFlags, DWORD dwType,
LPIMEMENUITEMINFOA lpImeParentMenu,
LPIMEMENUITEMINFOA lpImeMenu, DWORD dwSize)
{
InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
lpImeParentMenu, lpImeMenu, dwSize);
if (!data)
{
SetLastError(ERROR_INVALID_HANDLE);
return 0;
}
if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
{
if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
(IMEMENUITEMINFOW*)lpImeParentMenu,
(IMEMENUITEMINFOW*)lpImeMenu, dwSize);
else
{
IMEMENUITEMINFOW lpImeParentMenuW;
IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL;
DWORD rc;
if (lpImeParentMenu)
parent = &lpImeParentMenuW;
if (lpImeMenu)
{
int count = dwSize / sizeof(LPIMEMENUITEMINFOA);
dwSize = count * sizeof(IMEMENUITEMINFOW);
lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize);
}
else
lpImeMenuW = NULL;
rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
parent, lpImeMenuW, dwSize);
if (lpImeParentMenu)
{
memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA));
lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem;
WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString,
-1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE,
NULL, NULL);
}
if (lpImeMenu && rc)
{
unsigned int i;
for (i = 0; i < rc; i++)
{
memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA));
lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem;
WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString,
-1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE,
NULL, NULL);
}
}
HeapFree(GetProcessHeap(),0,lpImeMenuW);
return rc;
}
}
else
return 0;
}
/***********************************************************************
* ImmGetImeMenuItemsW (IMM32.@)
*/
DWORD WINAPI
ImmGetImeMenuItemsW(HIMC hIMC, DWORD dwFlags, DWORD dwType,
LPIMEMENUITEMINFOW lpImeParentMenu,
LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize)
{
InputContextData *data = get_imc_data(hIMC);
TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
lpImeParentMenu, lpImeMenu, dwSize);
if (!data)
{
SetLastError(ERROR_INVALID_HANDLE);
return 0;
}
if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
{
if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
lpImeParentMenu, lpImeMenu, dwSize);
else
{
IMEMENUITEMINFOA lpImeParentMenuA;
IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL;
DWORD rc;
if (lpImeParentMenu)
parent = &lpImeParentMenuA;
if (lpImeMenu)
{
int count = dwSize / sizeof(LPIMEMENUITEMINFOW);
dwSize = count * sizeof(IMEMENUITEMINFOA);
lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize);
}
else
lpImeMenuA = NULL;
rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
(IMEMENUITEMINFOW*)parent,
(IMEMENUITEMINFOW*)lpImeMenuA, dwSize);
if (lpImeParentMenu)
{
memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA));
lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem;
MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString,
-1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE);
}
if (lpImeMenu && rc)
{
unsigned int i;
for (i = 0; i < rc; i++)
{
memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA));
lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem;
MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString,
-1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE);
}
}
HeapFree(GetProcessHeap(),0,lpImeMenuA);
return rc;
}
}
else
return 0;
}
BOOL WINAPI User32InitializeImmEntryTable(DWORD);
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)

View file

@ -95,6 +95,8 @@ static inline BOOL Imm32IsCrossProcessAccess(HWND hWnd)
(DWORD_PTR)NtCurrentTeb()->ClientId.UniqueProcess);
}
BOOL WINAPI Imm32IsImcAnsi(HIMC hIMC);
#define ImeDpi_IsUnicode(pImeDpi) ((pImeDpi)->ImeInfo.fdwProperty & IME_PROP_UNICODE)
#define Imm32IsImmMode() (g_psi && (g_psi->dwSRVIFlags & SRVINFO_IMM32))
#define Imm32IsCiceroMode() (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
@ -112,3 +114,10 @@ Imm32NotifyAction(HIMC hIMC, HWND hwnd, DWORD dwAction, DWORD_PTR dwIndex, DWORD
DWORD_PTR dwCommand, DWORD_PTR dwData);
DWORD APIENTRY Imm32AllocAndBuildHimcList(DWORD dwThreadId, HIMC **pphList);
INT APIENTRY
Imm32ImeMenuAnsiToWide(const IMEMENUITEMINFOA *pItemA, LPIMEMENUITEMINFOW pItemW,
UINT uCodePage, BOOL bBitmap);
INT APIENTRY
Imm32ImeMenuWideToAnsi(const IMEMENUITEMINFOW *pItemW, LPIMEMENUITEMINFOA pItemA,
UINT uCodePage);

View file

@ -16,6 +16,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm);
HANDLE g_hImm32Heap = NULL;
BOOL WINAPI Imm32IsImcAnsi(HIMC hIMC)
{
BOOL ret;
PCLIENTIMC pClientImc = ImmLockClientImc(hIMC);
if (!pClientImc)
return -1;
ret = !(pClientImc->dwFlags & CLIENTIMC_WIDE);
ImmUnlockClientImc(pClientImc);
return ret;
}
LPWSTR APIENTRY Imm32WideFromAnsi(LPCSTR pszA)
{
INT cch = lstrlenA(pszA);
@ -202,6 +213,55 @@ DWORD APIENTRY Imm32AllocAndBuildHimcList(DWORD dwThreadId, HIMC **pphList)
#undef MAX_RETRY
}
INT APIENTRY
Imm32ImeMenuAnsiToWide(const IMEMENUITEMINFOA *pItemA, LPIMEMENUITEMINFOW pItemW,
UINT uCodePage, BOOL bBitmap)
{
INT ret;
pItemW->cbSize = pItemA->cbSize;
pItemW->fType = pItemA->fType;
pItemW->fState = pItemA->fState;
pItemW->wID = pItemA->wID;
if (bBitmap)
{
pItemW->hbmpChecked = pItemA->hbmpChecked;
pItemW->hbmpUnchecked = pItemA->hbmpUnchecked;
pItemW->hbmpItem = pItemA->hbmpItem;
}
pItemW->dwItemData = pItemA->dwItemData;
ret = MultiByteToWideChar(uCodePage, 0, pItemA->szString, -1,
pItemW->szString, _countof(pItemW->szString));
if (ret >= _countof(pItemW->szString))
{
ret = 0;
pItemW->szString[0] = 0;
}
return ret;
}
INT APIENTRY
Imm32ImeMenuWideToAnsi(const IMEMENUITEMINFOW *pItemW, LPIMEMENUITEMINFOA pItemA,
UINT uCodePage)
{
INT ret;
pItemA->cbSize = pItemW->cbSize;
pItemA->fType = pItemW->fType;
pItemA->fState = pItemW->fState;
pItemA->wID = pItemW->wID;
pItemA->hbmpChecked = pItemW->hbmpChecked;
pItemA->hbmpUnchecked = pItemW->hbmpUnchecked;
pItemA->dwItemData = pItemW->dwItemData;
pItemA->hbmpItem = pItemW->hbmpItem;
ret = WideCharToMultiByte(uCodePage, 0, pItemW->szString, -1,
pItemA->szString, _countof(pItemA->szString), NULL, NULL);
if (ret >= _countof(pItemA->szString))
{
ret = 0;
pItemA->szString[0] = 0;
}
return ret;
}
/***********************************************************************
* ImmCreateIMCC(IMM32.@)
*/

View file

@ -1,4 +1,4 @@
/* DEFINE_IME_ENTRY(type, name, params, extended) */
/* DEFINE_IME_ENTRY(type, name, params, optional) */
DEFINE_IME_ENTRY(BOOL, ImeInquire, (LPIMEINFO lpIMEInfo, LPVOID lpszWndClass, DWORD dwSystemInfoFlags), FALSE)
DEFINE_IME_ENTRY(DWORD, ImeConversionList, (HIMC hIMC, LPCVOID lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen, UINT uFlag), FALSE)
DEFINE_IME_ENTRY(BOOL, ImeRegisterWord, (LPCVOID lpszReading, DWORD dwStyle, LPCVOID lpszString), FALSE)
@ -14,7 +14,7 @@ DEFINE_IME_ENTRY(BOOL, ImeSetActiveContext, (HIMC hIMC, BOOL fFlag), FALSE)
DEFINE_IME_ENTRY(UINT, ImeToAsciiEx, (UINT uVirKey, UINT uScanCode, CONST LPBYTE lpbKeyState, LPTRANSMSGLIST lpTransMsgList, UINT fuState, HIMC hIMC), FALSE)
DEFINE_IME_ENTRY(BOOL, NotifyIME, (HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue), FALSE)
DEFINE_IME_ENTRY(BOOL, ImeSetCompositionString, (HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen, LPCVOID lpRead, DWORD dwReadLen), FALSE)
DEFINE_IME_ENTRY(DWORD, ImeGetImeMenuItems, (HIMC hIMC, DWORD dwFlags, DWORD dwType, LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize), FALSE)
DEFINE_IME_ENTRY(DWORD, ImeGetImeMenuItems, (HIMC hIMC, DWORD dwFlags, DWORD dwType, LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize), TRUE)
DEFINE_IME_ENTRY(BOOL, CtfImeInquireExW, (LPIMEINFO lpIMEInfo, LPVOID lpszWndClass, DWORD dwSystemInfoFlags, HKL hKL), TRUE)
DEFINE_IME_ENTRY(BOOL, CtfImeSelectEx, (HIMC hIMC, BOOL fSelect, HKL hKL), TRUE)
DEFINE_IME_ENTRY(LRESULT, CtfImeEscapeEx, (HIMC hIMC, UINT uSubFunc, LPVOID lpData, HKL hKL), TRUE)