[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); 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 static inline LONG APIENTRY
Imm32CompStrAnsiToWide(LPCSTR psz, DWORD cb, LPWSTR lpBuf, DWORD dwBufLen, UINT uCodePage) Imm32CompStrAnsiToWide(LPCSTR psz, DWORD cb, LPWSTR lpBuf, DWORD dwBufLen, UINT uCodePage)
{ {
DWORD ret = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, psz, cb / sizeof(CHAR), DWORD ret = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, psz, cb / sizeof(CHAR),
lpBuf, dwBufLen / sizeof(WCHAR)); lpBuf, dwBufLen / sizeof(WCHAR));
if ((ret + 1) * sizeof(WCHAR) <= dwBufLen) if (lpBuf && (ret + 1) * sizeof(WCHAR) <= dwBufLen)
lpBuf[ret] = 0; lpBuf[ret] = 0;
return ret * sizeof(WCHAR); 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), DWORD ret = WideCharToMultiByte(uCodePage, 0, psz, cb / sizeof(WCHAR),
lpBuf, dwBufLen / sizeof(CHAR), NULL, NULL); lpBuf, dwBufLen / sizeof(CHAR), NULL, NULL);
if ((ret + 1) * sizeof(CHAR) <= dwBufLen) if (lpBuf && (ret + 1) * sizeof(CHAR) <= dwBufLen)
lpBuf[ret] = 0; lpBuf[ret] = 0;
return ret * sizeof(CHAR); return ret * sizeof(CHAR);
} }
@ -44,6 +69,7 @@ Imm32CompAttrWideToAnsi(const BYTE *src, INT src_len, LPCWSTR text,
if (!src_len) if (!src_len)
return 0; return 0;
str_len /= sizeof(WCHAR);
rc = WideCharToMultiByte(uCodePage, 0, text, str_len, NULL, 0, NULL, NULL); rc = WideCharToMultiByte(uCodePage, 0, text, str_len, NULL, 0, NULL, NULL);
if (dst_len) if (dst_len)
@ -66,7 +92,7 @@ end:
rc = j; rc = j;
} }
return rc; return rc * sizeof(BYTE);
} }
static INT APIENTRY static INT APIENTRY
@ -79,6 +105,7 @@ Imm32CompAttrAnsiToWide(const BYTE *src, INT src_len, LPCSTR text,
if (!src_len) if (!src_len)
return 0; return 0;
str_len /= sizeof(CHAR);
rc = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, text, str_len, NULL, 0); rc = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, text, str_len, NULL, 0);
if (dst_len) if (dst_len)
@ -100,7 +127,7 @@ Imm32CompAttrAnsiToWide(const BYTE *src, INT src_len, LPCSTR text,
rc = j; rc = j;
} }
return rc; return rc * sizeof(BYTE);
} }
static INT APIENTRY static INT APIENTRY
@ -487,11 +514,332 @@ Imm32GetCompStrW(HIMC hIMC, const COMPOSITIONSTRING *pCS, DWORD dwIndex,
} }
BOOL APIENTRY BOOL APIENTRY
Imm32SetCompositionStringAW(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen, Imm32SetCompositionStringAW(HIMC hIMC, DWORD dwIndex, LPVOID pComp, DWORD dwCompLen,
LPCVOID lpRead, DWORD dwReadLen, BOOL bAnsi) LPVOID pRead, DWORD dwReadLen, BOOL bAnsiAPI)
{ {
FIXME("TODO:\n"); BOOL ret = FALSE, bAnsiClient;
return FALSE; 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.@) * ImmSetCompositionStringA (IMM32.@)
*/ */
BOOL WINAPI BOOL WINAPI
ImmSetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen, ImmSetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPVOID lpComp, DWORD dwCompLen,
LPCVOID lpRead, DWORD dwReadLen) LPVOID lpRead, DWORD dwReadLen)
{ {
TRACE("(%p, %lu, %p, %lu, %p, %lu)\n", TRACE("(%p, %lu, %p, %lu, %p, %lu)\n",
hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
@ -595,8 +943,8 @@ ImmSetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompL
* ImmSetCompositionStringW (IMM32.@) * ImmSetCompositionStringW (IMM32.@)
*/ */
BOOL WINAPI BOOL WINAPI
ImmSetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen, ImmSetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID lpComp, DWORD dwCompLen,
LPCVOID lpRead, DWORD dwReadLen) LPVOID lpRead, DWORD dwReadLen)
{ {
TRACE("(%p, %lu, %p, %lu, %p, %lu)\n", TRACE("(%p, %lu, %p, %lu, %p, %lu)\n",
hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);

View file

@ -293,7 +293,11 @@ static void cleanup(void) {
} }
static void test_ImmNotifyIME(void) { static void test_ImmNotifyIME(void) {
#ifdef __REACTOS__
static char string[] = "wine";
#else
static const char string[] = "wine"; static const char string[] = "wine";
#endif
char resstr[16] = ""; char resstr[16] = "";
HIMC imc; HIMC imc;
BOOL ret; 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) static void test_ImmGetCompositionString(void)
{ {
HIMC imc; 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}; static const WCHAR string[] = {'w','i','n','e',0x65e5,0x672c,0x8a9e};
#endif
char cstring[20]; char cstring[20];
WCHAR wstring[20]; WCHAR wstring[20];
LONG len; LONG len;

View file

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