[PATCH 2/3] imm32: Fix output buffer length handling for no-conversion case of GCS_COMPSTR.

Nikolay Sivov nsivov at codeweavers.com
Thu Mar 7 02:23:36 CST 2019


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 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 96a11abba5..a385d884cb 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 ee1aeb3965..d15fa9c9ff 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");
-- 
2.20.1




More information about the wine-devel mailing list