[IMM32][IMM32_WINETEST] Re-implement ImmSetCompositionStringA/W (#4040)

- Modify ImmSetCompositionStringA and ImmSetCompositionStringW prototypes (removing const of two arguments).
- Add Imm32OpenICAndCS helper function.
- Implement Imm32SetCompositionStringAW function.
- Modify imm32_winetest (due to removal of const).
CORE-11700
This commit is contained in:
Katayama Hirofumi MZ 2021-10-17 19:32:48 +09:00 committed by GitHub
parent e98684ed8b
commit aa8fc872a0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 372 additions and 16 deletions

View file

@ -14,12 +14,37 @@
WINE_DEFAULT_DEBUG_CHANNEL(imm);
BOOL APIENTRY
Imm32OpenICAndCS(HIMC hIMC, LPINPUTCONTEXT *ppIC, LPCOMPOSITIONSTRING *ppCS)
{
LPINPUTCONTEXT pIC;
LPCOMPOSITIONSTRING pCS;
*ppIC = NULL;
*ppCS = NULL;
pIC = ImmLockIMC(hIMC);
if (!pIC)
return FALSE;
pCS = ImmLockIMCC(pIC->hCompStr);
if (!pCS)
{
ImmUnlockIMC(hIMC);
return FALSE;
}
*ppIC = pIC;
*ppCS = pCS;
return TRUE;
}
static inline LONG APIENTRY
Imm32CompStrAnsiToWide(LPCSTR psz, DWORD cb, LPWSTR lpBuf, DWORD dwBufLen, UINT uCodePage)
{
DWORD ret = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, psz, cb / sizeof(CHAR),
lpBuf, dwBufLen / sizeof(WCHAR));
if ((ret + 1) * sizeof(WCHAR) <= dwBufLen)
if (lpBuf && (ret + 1) * sizeof(WCHAR) <= dwBufLen)
lpBuf[ret] = 0;
return ret * sizeof(WCHAR);
}
@ -29,7 +54,7 @@ Imm32CompStrWideToAnsi(LPCWSTR psz, DWORD cb, LPSTR lpBuf, DWORD dwBufLen, UINT
{
DWORD ret = WideCharToMultiByte(uCodePage, 0, psz, cb / sizeof(WCHAR),
lpBuf, dwBufLen / sizeof(CHAR), NULL, NULL);
if ((ret + 1) * sizeof(CHAR) <= dwBufLen)
if (lpBuf && (ret + 1) * sizeof(CHAR) <= dwBufLen)
lpBuf[ret] = 0;
return ret * sizeof(CHAR);
}
@ -44,6 +69,7 @@ Imm32CompAttrWideToAnsi(const BYTE *src, INT src_len, LPCWSTR text,
if (!src_len)
return 0;
str_len /= sizeof(WCHAR);
rc = WideCharToMultiByte(uCodePage, 0, text, str_len, NULL, 0, NULL, NULL);
if (dst_len)
@ -66,7 +92,7 @@ end:
rc = j;
}
return rc;
return rc * sizeof(BYTE);
}
static INT APIENTRY
@ -79,6 +105,7 @@ Imm32CompAttrAnsiToWide(const BYTE *src, INT src_len, LPCSTR text,
if (!src_len)
return 0;
str_len /= sizeof(CHAR);
rc = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, text, str_len, NULL, 0);
if (dst_len)
@ -100,7 +127,7 @@ Imm32CompAttrAnsiToWide(const BYTE *src, INT src_len, LPCSTR text,
rc = j;
}
return rc;
return rc * sizeof(BYTE);
}
static INT APIENTRY
@ -487,11 +514,332 @@ Imm32GetCompStrW(HIMC hIMC, const COMPOSITIONSTRING *pCS, DWORD dwIndex,
}
BOOL APIENTRY
Imm32SetCompositionStringAW(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen,
LPCVOID lpRead, DWORD dwReadLen, BOOL bAnsi)
Imm32SetCompositionStringAW(HIMC hIMC, DWORD dwIndex, LPVOID pComp, DWORD dwCompLen,
LPVOID pRead, DWORD dwReadLen, BOOL bAnsiAPI)
{
FIXME("TODO:\n");
return FALSE;
BOOL ret = FALSE, bAnsiClient;
LPVOID pCompNew = NULL, pReadNew = NULL;
DWORD dwThreadId, cbCompNew = 0, cbReadNew = 0;
LPINPUTCONTEXT pIC;
LPCOMPOSITIONSTRING pCS;
HKL hKL;
PIMEDPI pImeDpi;
UINT uCodePage;
LPRECONVERTSTRING pRS;
dwThreadId = NtUserQueryInputContext(hIMC, 1);
if (dwThreadId != GetCurrentThreadId())
return FALSE;
hKL = GetKeyboardLayout(dwThreadId);
pImeDpi = ImmLockImeDpi(hKL);
if (!pImeDpi)
return FALSE;
uCodePage = pImeDpi->uCodePage;
bAnsiClient = !ImeDpi_IsUnicode(pImeDpi);
switch (dwIndex)
{
case SCS_SETSTR: case SCS_CHANGEATTR: case SCS_CHANGECLAUSE:
break;
case SCS_SETRECONVERTSTRING: case SCS_QUERYRECONVERTSTRING:
if (pImeDpi->ImeInfo.fdwSCSCaps & SCS_CAP_SETRECONVERTSTRING)
break;
/* FALL THROUGH */
default:
ImmUnlockImeDpi(pImeDpi);
return FALSE;
}
if (bAnsiAPI == bAnsiClient || (!pComp && !pRead))
{
ret = pImeDpi->ImeSetCompositionString(hIMC, dwIndex, pComp, dwCompLen,
pRead, dwReadLen);
ImmUnlockImeDpi(pImeDpi);
return ret;
}
if (!Imm32OpenICAndCS(hIMC, &pIC, &pCS))
{
ImmUnlockImeDpi(pImeDpi);
return FALSE;
}
/*
* This code is really too complicated. But I cannot simplify.
* It converts like (pComp, dwCompLen) --> (pCompNew, cbCompNew) and
* (pRead, dwReadLen) --> (pReadNew, cbReadNew).
* (1) Check bAnsiClient, (2) Get the size, (3) Allocate a buffer for conversion,
* (4) Store converted data into the buffer.
*/
switch (dwIndex)
{
case SCS_SETSTR:
if (pComp)
{
if (bAnsiClient)
{
cbCompNew = Imm32CompStrWideToAnsi(pComp, dwCompLen, NULL, 0, uCodePage);
pCompNew = Imm32HeapAlloc(0, cbCompNew);
if (!pCompNew)
goto Quit;
Imm32CompStrWideToAnsi(pComp, dwCompLen, pCompNew, cbCompNew, uCodePage);
}
else
{
cbCompNew = Imm32CompStrAnsiToWide(pComp, dwCompLen, NULL, 0, uCodePage);
pCompNew = Imm32HeapAlloc(0, cbCompNew);
if (!pCompNew)
goto Quit;
Imm32CompStrAnsiToWide(pComp, dwCompLen, pCompNew, cbCompNew, uCodePage);
}
}
if (pRead)
{
if (bAnsiClient)
{
cbReadNew = Imm32CompStrWideToAnsi(pRead, dwReadLen, NULL, 0, uCodePage);
pReadNew = Imm32HeapAlloc(0, cbReadNew);
if (!pReadNew)
goto Quit;
Imm32CompStrWideToAnsi(pRead, dwReadLen, pReadNew, cbReadNew, uCodePage);
}
else
{
cbReadNew = Imm32CompStrAnsiToWide(pRead, dwReadLen, NULL, 0, uCodePage);
pReadNew = Imm32HeapAlloc(0, cbReadNew);
if (!pReadNew)
goto Quit;
Imm32CompStrAnsiToWide(pRead, dwReadLen, pReadNew, cbReadNew, uCodePage);
}
}
break;
case SCS_CHANGEATTR:
if (pComp)
{
if (bAnsiClient)
{
cbCompNew = Imm32CompAttrWideToAnsi(pComp, dwCompLen,
CS_StrW(pCS, CompStr),
CS_SizeW(pCS, CompStr),
NULL, 0, uCodePage);
pCompNew = Imm32HeapAlloc(0, cbCompNew);
if (!pCompNew)
goto Quit;
Imm32CompAttrWideToAnsi(pComp, dwCompLen,
CS_StrW(pCS, CompStr), CS_SizeW(pCS, CompStr),
pCompNew, cbCompNew, uCodePage);
}
else
{
cbCompNew = Imm32CompAttrAnsiToWide(pComp, dwCompLen,
CS_StrA(pCS, CompStr),
CS_SizeA(pCS, CompStr),
NULL, 0, uCodePage);
pCompNew = Imm32HeapAlloc(0, cbCompNew);
if (!pCompNew)
goto Quit;
Imm32CompAttrAnsiToWide(pComp, dwCompLen,
CS_StrA(pCS, CompStr), CS_SizeA(pCS, CompStr),
pCompNew, cbCompNew, uCodePage);
}
}
if (pRead)
{
if (bAnsiClient)
{
cbReadNew = Imm32CompAttrWideToAnsi(pRead, dwReadLen,
CS_StrW(pCS, CompReadStr),
CS_SizeW(pCS, CompReadStr),
NULL, 0, uCodePage);
pReadNew = Imm32HeapAlloc(0, cbReadNew);
if (!pReadNew)
goto Quit;
Imm32CompAttrWideToAnsi(pRead, dwReadLen,
CS_StrW(pCS, CompReadStr), CS_SizeW(pCS, CompReadStr),
pReadNew, cbReadNew, uCodePage);
}
else
{
cbReadNew = Imm32CompAttrAnsiToWide(pRead, dwReadLen,
CS_StrA(pCS, CompReadStr),
CS_SizeA(pCS, CompReadStr),
NULL, 0, uCodePage);
pReadNew = Imm32HeapAlloc(0, cbReadNew);
if (!pReadNew)
goto Quit;
Imm32CompAttrAnsiToWide(pRead, dwReadLen,
CS_StrA(pCS, CompReadStr), CS_SizeA(pCS, CompReadStr),
pReadNew, cbReadNew, uCodePage);
}
}
break;
case SCS_CHANGECLAUSE:
if (pComp)
{
if (bAnsiClient)
{
cbCompNew = Imm32CompClauseWideToAnsi(pComp, dwCompLen, CS_StrW(pCS, CompStr),
NULL, 0, uCodePage);
pCompNew = Imm32HeapAlloc(0, cbCompNew);
if (!pCompNew)
goto Quit;
Imm32CompClauseWideToAnsi(pComp, dwCompLen, CS_StrW(pCS, CompStr),
pCompNew, cbCompNew, uCodePage);
}
else
{
cbCompNew = Imm32CompClauseAnsiToWide(pComp, dwCompLen, CS_StrA(pCS, CompStr),
NULL, 0, uCodePage);
pCompNew = Imm32HeapAlloc(0, cbCompNew);
if (!pCompNew)
goto Quit;
Imm32CompClauseAnsiToWide(pComp, dwCompLen, CS_StrA(pCS, CompStr),
pCompNew, cbCompNew, uCodePage);
}
}
if (pRead)
{
if (bAnsiClient)
{
cbReadNew = Imm32CompClauseWideToAnsi(pRead, dwReadLen, CS_StrW(pCS, CompReadStr),
NULL, 0, uCodePage);
pReadNew = Imm32HeapAlloc(0, cbReadNew);
if (!pReadNew)
goto Quit;
Imm32CompClauseWideToAnsi(pRead, dwReadLen,
CS_StrW(pCS, CompReadStr),
pReadNew, cbReadNew, uCodePage);
}
else
{
cbReadNew = Imm32CompClauseAnsiToWide(pRead, dwReadLen, CS_StrA(pCS, CompReadStr),
NULL, 0, uCodePage);
pReadNew = Imm32HeapAlloc(0, cbReadNew);
if (!pReadNew)
goto Quit;
Imm32CompClauseAnsiToWide(pRead, dwReadLen, CS_StrA(pCS, CompReadStr),
pReadNew, cbReadNew, uCodePage);
}
}
break;
case SCS_SETRECONVERTSTRING: case SCS_QUERYRECONVERTSTRING:
{
if (pComp)
{
if (bAnsiClient)
{
cbCompNew = Imm32ReconvertAnsiFromWide(NULL, pComp, uCodePage);
pCompNew = Imm32HeapAlloc(0, cbCompNew);
if (!pCompNew)
goto Quit;
pRS = pCompNew;
pRS->dwSize = cbCompNew;
pRS->dwVersion = 0;
Imm32ReconvertAnsiFromWide(pRS, pComp, uCodePage);
}
else
{
cbCompNew = Imm32ReconvertWideFromAnsi(NULL, pComp, uCodePage);
pCompNew = Imm32HeapAlloc(0, cbCompNew);
if (!pCompNew)
goto Quit;
pRS = pCompNew;
pRS->dwSize = cbCompNew;
pRS->dwVersion = 0;
Imm32ReconvertWideFromAnsi(pRS, pComp, uCodePage);
}
}
if (pRead)
{
if (bAnsiClient)
{
cbReadNew = Imm32ReconvertAnsiFromWide(NULL, pRead, uCodePage);
pReadNew = Imm32HeapAlloc(0, cbReadNew);
if (!pReadNew)
goto Quit;
pRS = pReadNew;
pRS->dwSize = cbReadNew;
pRS->dwVersion = 0;
Imm32ReconvertAnsiFromWide(pRS, pRead, uCodePage);
}
else
{
cbReadNew = Imm32ReconvertWideFromAnsi(NULL, pRead, uCodePage);
pReadNew = Imm32HeapAlloc(0, cbReadNew);
if (!pReadNew)
goto Quit;
pRS = pReadNew;
pRS->dwSize = cbReadNew;
pRS->dwVersion = 0;
Imm32ReconvertWideFromAnsi(pRS, pRead, uCodePage);
}
}
break;
}
}
ImmUnlockIMCC(pIC->hCompStr);
pCS = NULL;
ImmUnlockIMC(hIMC);
pIC = NULL;
ret = pImeDpi->ImeSetCompositionString(hIMC, dwIndex, pCompNew, cbCompNew,
pReadNew, cbReadNew);
if (dwIndex == SCS_QUERYRECONVERTSTRING)
{
if (pComp)
{
if (bAnsiClient)
ret = Imm32ReconvertWideFromAnsi(pComp, pCompNew, uCodePage);
else
ret = Imm32ReconvertAnsiFromWide(pComp, pCompNew, uCodePage);
}
if (pRead)
{
if (bAnsiClient)
ret = Imm32ReconvertWideFromAnsi(pRead, pReadNew, uCodePage);
else
ret = Imm32ReconvertAnsiFromWide(pRead, pReadNew, uCodePage);
}
}
Quit:
if (pCS)
ImmUnlockIMCC(pIC->hCompStr);
if (pIC)
ImmUnlockIMC(hIMC);
Imm32HeapFree(pCompNew);
Imm32HeapFree(pReadNew);
ImmUnlockImeDpi(pImeDpi);
return ret;
}
/***********************************************************************
@ -582,8 +930,8 @@ LONG WINAPI ImmGetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWO
* ImmSetCompositionStringA (IMM32.@)
*/
BOOL WINAPI
ImmSetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen,
LPCVOID lpRead, DWORD dwReadLen)
ImmSetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPVOID lpComp, DWORD dwCompLen,
LPVOID lpRead, DWORD dwReadLen)
{
TRACE("(%p, %lu, %p, %lu, %p, %lu)\n",
hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
@ -595,8 +943,8 @@ ImmSetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompL
* ImmSetCompositionStringW (IMM32.@)
*/
BOOL WINAPI
ImmSetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen,
LPCVOID lpRead, DWORD dwReadLen)
ImmSetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID lpComp, DWORD dwCompLen,
LPVOID lpRead, DWORD dwReadLen)
{
TRACE("(%p, %lu, %p, %lu, %p, %lu)\n",
hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);

View file

@ -293,7 +293,11 @@ static void cleanup(void) {
}
static void test_ImmNotifyIME(void) {
#ifdef __REACTOS__
static char string[] = "wine";
#else
static const char string[] = "wine";
#endif
char resstr[16] = "";
HIMC imc;
BOOL ret;
@ -422,7 +426,11 @@ static LRESULT WINAPI test_ime_wnd_proc(HWND hWnd, UINT msg, WPARAM wParam, LPAR
static void test_ImmGetCompositionString(void)
{
HIMC imc;
#ifdef __REACTOS__
static WCHAR string[] = {'w','i','n','e',0x65e5,0x672c,0x8a9e};
#else
static const WCHAR string[] = {'w','i','n','e',0x65e5,0x672c,0x8a9e};
#endif
char cstring[20];
WCHAR wstring[20];
LONG len;

View file

@ -891,9 +891,9 @@ WINAPI
ImmSetCompositionStringA(
_In_ HIMC,
_In_ DWORD dwIndex,
_In_reads_bytes_opt_(dwCompLen) LPCVOID lpComp,
_Inout_updates_bytes_opt_(dwCompLen) LPVOID lpComp,
_In_ DWORD dwCompLen,
_In_reads_bytes_opt_(dwReadLen) LPCVOID lpRead,
_Inout_updates_bytes_opt_(dwReadLen) LPVOID lpRead,
_In_ DWORD dwReadLen);
BOOL
@ -901,9 +901,9 @@ WINAPI
ImmSetCompositionStringW(
_In_ HIMC,
_In_ DWORD dwIndex,
_In_reads_bytes_opt_(dwCompLen) LPCVOID lpComp,
_Inout_updates_bytes_opt_(dwCompLen) LPVOID lpComp,
_In_ DWORD dwCompLen,
_In_reads_bytes_opt_(dwReadLen) LPCVOID lpRead,
_Inout_updates_bytes_opt_(dwReadLen) LPVOID lpRead,
_In_ DWORD dwReadLen);
#define ImmSetCompositionString WINELIB_NAME_AW(ImmSetCompositionString)