https://git.reactos.org/?p=reactos.git;a=commitdiff;h=aa8fc872a098d261e13e48...
commit aa8fc872a098d261e13e48aeb32fb85808e36d1d Author: Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com AuthorDate: Sun Oct 17 19:32:48 2021 +0900 Commit: GitHub noreply@github.com CommitDate: Sun Oct 17 19:32:48 2021 +0900
[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 --- dll/win32/imm32/compstr.c | 372 ++++++++++++++++++++++++++++++- modules/rostests/winetests/imm32/imm32.c | 8 + sdk/include/psdk/imm.h | 8 +- 3 files changed, 372 insertions(+), 16 deletions(-)
diff --git a/dll/win32/imm32/compstr.c b/dll/win32/imm32/compstr.c index df0726c2fa2..7fa9a0e4111 100644 --- a/dll/win32/imm32/compstr.c +++ b/dll/win32/imm32/compstr.c @@ -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); diff --git a/modules/rostests/winetests/imm32/imm32.c b/modules/rostests/winetests/imm32/imm32.c index fef5b0dbb0d..407dfe1f6f7 100644 --- a/modules/rostests/winetests/imm32/imm32.c +++ b/modules/rostests/winetests/imm32/imm32.c @@ -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; diff --git a/sdk/include/psdk/imm.h b/sdk/include/psdk/imm.h index fb7032181a7..ebd3bb4cb47 100644 --- a/sdk/include/psdk/imm.h +++ b/sdk/include/psdk/imm.h @@ -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)