Module: wine Branch: master Commit: fd7cda93a33c9f65a6c1d1d530738c9fe4b9edf4 URL: https://source.winehq.org/git/wine.git/?a=commit;h=fd7cda93a33c9f65a6c1d1d53...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Thu Mar 7 11:23:36 2019 +0300
imm32: Fix output buffer length handling for no-conversion case of GCS_COMPSTR.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com Signed-off-by: Aric Stewart aric@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/imm32/imm.c | 28 +++++++++++++++++----------- dlls/imm32/tests/imm32.c | 25 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 11 deletions(-)
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c index 96a11ab..a385d88 100644 --- a/dlls/imm32/imm.c +++ b/dlls/imm32/imm.c @@ -1206,23 +1206,29 @@ BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
/* Helpers for the GetCompositionString functions */
-static INT CopyCompStringIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE target, INT tlen, - BOOL unicode ) +/* Source encoding is defined by context, source length is always given in respective characters. Destination buffer + length is always in bytes. */ +static INT CopyCompStringIMEtoClient(const InputContextData *data, const void *src, INT src_len, void *dst, + INT dst_len, BOOL unicode) { - INT rc; + int char_size = unicode ? sizeof(WCHAR) : sizeof(char); + INT ret;
- if (is_himc_ime_unicode(data) && !unicode) - rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)source, slen, (LPSTR)target, tlen, NULL, NULL); - else if (!is_himc_ime_unicode(data) && unicode) - rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)source, slen, (LPWSTR)target, tlen) * sizeof(WCHAR); + if (is_himc_ime_unicode(data) ^ unicode) + { + if (unicode) + ret = MultiByteToWideChar(CP_ACP, 0, src, src_len, dst, dst_len); + else + ret = WideCharToMultiByte(CP_ACP, 0, src, src_len, dst, dst_len, NULL, NULL); + ret *= char_size; + } else { - int dlen = (unicode)?sizeof(WCHAR):sizeof(CHAR); - memcpy( target, source, min(slen,tlen)*dlen); - rc = slen*dlen; + ret = min(src_len * char_size, dst_len); + memcpy(dst, src, ret); }
- return rc; + return ret; }
static INT CopyCompAttrIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen, diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c index ee1aeb3..d15fa9c 100644 --- a/dlls/imm32/tests/imm32.c +++ b/dlls/imm32/tests/imm32.c @@ -448,6 +448,31 @@ static void test_ImmGetCompositionString(void) ok(len*sizeof(WCHAR)==wlen,"GCS_COMPATTR(W) not returning correct count\n"); len = ImmGetCompositionStringA(imc, GCS_COMPATTR, NULL, 0); ok(len==alen,"GCS_COMPATTR(A) not returning correct count\n"); + + /* Get strings with exactly matching buffer sizes. */ + memset(wstring, 0x1a, sizeof(wstring)); + memset(cstring, 0x1a, sizeof(cstring)); + + len = ImmGetCompositionStringA(imc, GCS_COMPSTR, cstring, alen); + ok(len == alen, "Unexpected length %d.\n", len); + ok(cstring[alen] == 0x1a, "Unexpected buffer contents.\n"); + + len = ImmGetCompositionStringW(imc, GCS_COMPSTR, wstring, wlen); + ok(len == wlen, "Unexpected length %d.\n", len); + ok(wstring[wlen/sizeof(WCHAR)] == 0x1a1a, "Unexpected buffer contents.\n"); + + /* Get strings with exactly smaller buffer sizes. */ + memset(wstring, 0x1a, sizeof(wstring)); + memset(cstring, 0x1a, sizeof(cstring)); + + /* Returns 0 but still fills buffer. */ + len = ImmGetCompositionStringA(imc, GCS_COMPSTR, cstring, alen - 1); + ok(!len, "Unexpected length %d.\n", len); + ok(cstring[0] == 'w', "Unexpected buffer contents %s.\n", cstring); + + len = ImmGetCompositionStringW(imc, GCS_COMPSTR, wstring, wlen - 1); + ok(len == wlen - 1, "Unexpected length %d.\n", len); + ok(!memcmp(wstring, string, wlen - 1), "Unexpected buffer contents.\n"); } else win_skip("Composition string isn't available\n");