Alexandre Julliard : kernelbase: Support UTF-8 as default Ansi codepage in WideCharToMultiByte().

Alexandre Julliard julliard at winehq.org
Mon Apr 11 15:54:59 CDT 2022


Module: wine
Branch: master
Commit: 1790546d03d8f61e0b01c17529e5ac88b31e1752
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=1790546d03d8f61e0b01c17529e5ac88b31e1752

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Apr 11 17:27:34 2022 +0200

kernelbase: Support UTF-8 as default Ansi codepage in WideCharToMultiByte().

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/tests/codepage.c | 16 ++++++-------
 dlls/kernelbase/locale.c       | 54 +++++++++++++++---------------------------
 2 files changed, 27 insertions(+), 43 deletions(-)

diff --git a/dlls/kernel32/tests/codepage.c b/dlls/kernel32/tests/codepage.c
index b0dbd812346..0a5185d1804 100644
--- a/dlls/kernel32/tests/codepage.c
+++ b/dlls/kernel32/tests/codepage.c
@@ -263,32 +263,32 @@ static void test_other_invalid_parameters(void)
     ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%lx\n", len, GetLastError());
 
 
-    /* CP_UTF7, CP_UTF8, or CP_SYMBOL and defchar not NULL => ERROR_INVALID_PARAMETER */
-    /* CP_SYMBOL's behavior here is undocumented */
+    /* CP_UTF7 or CP_SYMBOL and defchar not NULL => ERROR_INVALID_PARAMETER */
+    /* CP_UTF8 allows it since win10 1709 */
     SetLastError(0xdeadbeef);
     len = WideCharToMultiByte(CP_UTF7, 0, w_string, w_string_len, c_string, c_string_len, c_string, NULL);
     ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%lx\n", len, GetLastError());
 
     SetLastError(0xdeadbeef);
     len = WideCharToMultiByte(CP_UTF8, 0, w_string, w_string_len, c_string, c_string_len, c_string, NULL);
-    ok((len == 0 && GetLastError() == ERROR_INVALID_PARAMETER)
-            || broken(len == 12) /* Win10 1709+ */, "len=%d error=%lx\n", len, GetLastError());
+    ok(len == 12 || broken(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER),
+       "len=%d error=%lx\n", len, GetLastError());
 
     SetLastError(0xdeadbeef);
     len = WideCharToMultiByte(CP_SYMBOL, 0, w_string, w_string_len, c_string, c_string_len, c_string, NULL);
     ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%lx\n", len, GetLastError());
 
 
-    /* CP_UTF7, CP_UTF8, or CP_SYMBOL and used not NULL => ERROR_INVALID_PARAMETER */
-    /* CP_SYMBOL's behavior here is undocumented */
+    /* CP_UTF7 or CP_SYMBOL and used not NULL => ERROR_INVALID_PARAMETER */
+    /* CP_UTF8 allows it since win10 1709 */
     SetLastError(0xdeadbeef);
     len = WideCharToMultiByte(CP_UTF7, 0, w_string, w_string_len, c_string, c_string_len, NULL, &used);
     ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "len=%d error=%lx\n", len, GetLastError());
 
     SetLastError(0xdeadbeef);
     len = WideCharToMultiByte(CP_UTF8, 0, w_string, w_string_len, c_string, c_string_len, NULL, &used);
-    ok((len == 0 && GetLastError() == ERROR_INVALID_PARAMETER)
-            || broken(len == 12) /* Win10 1709+ */, "len=%d error=%lx\n", len, GetLastError());
+    ok(len == 12 || broken(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER),
+       "len=%d error=%lx\n", len, GetLastError());
 
     SetLastError(0xdeadbeef);
     len = WideCharToMultiByte(CP_SYMBOL, 0, w_string, w_string_len, c_string, c_string_len, NULL, &used);
diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c
index c807b1e0124..358aa8c123c 100644
--- a/dlls/kernelbase/locale.c
+++ b/dlls/kernelbase/locale.c
@@ -2687,17 +2687,7 @@ static int wcstombs_utf8( DWORD flags, const WCHAR *src, int srclen, char *dst,
     DWORD reslen;
     NTSTATUS status;
 
-    if (defchar || used)
-    {
-        SetLastError( ERROR_INVALID_PARAMETER );
-        return 0;
-    }
-    if (flags & ~(WC_DISCARDNS | WC_SEPCHARS | WC_DEFAULTCHAR | WC_ERR_INVALID_CHARS |
-                  WC_COMPOSITECHECK | WC_NO_BEST_FIT_CHARS))
-    {
-        SetLastError( ERROR_INVALID_FLAGS );
-        return 0;
-    }
+    if (used) *used = FALSE;
     if (!dstlen) dst = NULL;
     status = RtlUnicodeToUTF8N( dst, dstlen, &reslen, src, srclen * sizeof(WCHAR) );
     if (status == STATUS_SOME_NOT_MAPPED)
@@ -2707,6 +2697,7 @@ static int wcstombs_utf8( DWORD flags, const WCHAR *src, int srclen, char *dst,
             SetLastError( ERROR_NO_UNICODE_TRANSLATION );
             return 0;
         }
+        if (used) *used = TRUE;
     }
     else if (!set_ntstatus( status )) reslen = 0;
     return reslen;
@@ -3054,22 +3045,9 @@ static int wcstombs_dbcs_slow( const CPTABLEINFO *info, DWORD flags, const WCHAR
 }
 
 
-static int wcstombs_codepage( UINT codepage, DWORD flags, const WCHAR *src, int srclen,
+static int wcstombs_codepage( const CPTABLEINFO *info, DWORD flags, const WCHAR *src, int srclen,
                               char *dst, int dstlen, const char *defchar, BOOL *used )
 {
-    const CPTABLEINFO *info = get_codepage_table( codepage );
-
-    if (!info)
-    {
-        SetLastError( ERROR_INVALID_PARAMETER );
-        return 0;
-    }
-    if (flags & ~(WC_DISCARDNS | WC_SEPCHARS | WC_DEFAULTCHAR | WC_ERR_INVALID_CHARS |
-                  WC_COMPOSITECHECK | WC_NO_BEST_FIT_CHARS))
-    {
-        SetLastError( ERROR_INVALID_FLAGS );
-        return 0;
-    }
     if (flags || defchar || used)
     {
         if (!defchar) defchar = (const char *)&info->DefaultChar;
@@ -6468,6 +6446,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH VerLanguageNameW( DWORD lang, LPWSTR buffer, DWOR
 INT WINAPI DECLSPEC_HOTPATCH WideCharToMultiByte( UINT codepage, DWORD flags, LPCWSTR src, INT srclen,
                                                   LPSTR dst, INT dstlen, LPCSTR defchar, BOOL *used )
 {
+    const CPTABLEINFO *info;
     int ret;
 
     if (!src || !srclen || (!dst && dstlen) || dstlen < 0)
@@ -6486,20 +6465,25 @@ INT WINAPI DECLSPEC_HOTPATCH WideCharToMultiByte( UINT codepage, DWORD flags, LP
     case CP_UTF7:
         ret = wcstombs_utf7( flags, src, srclen, dst, dstlen, defchar, used );
         break;
-    case CP_UTF8:
-        ret = wcstombs_utf8( flags, src, srclen, dst, dstlen, defchar, used );
-        break;
     case CP_UNIXCP:
-        if (unix_cp == CP_UTF8)
-        {
-            if (used) *used = FALSE;
-            ret = wcstombs_utf8( flags, src, srclen, dst, dstlen, NULL, NULL );
-            break;
-        }
         codepage = unix_cp;
         /* fall through */
     default:
-        ret = wcstombs_codepage( codepage, flags, src, srclen, dst, dstlen, defchar, used );
+        if (!(info = get_codepage_table( codepage )))
+        {
+            SetLastError( ERROR_INVALID_PARAMETER );
+            return 0;
+        }
+        if (flags & ~(WC_DISCARDNS | WC_SEPCHARS | WC_DEFAULTCHAR | WC_ERR_INVALID_CHARS |
+                      WC_COMPOSITECHECK | WC_NO_BEST_FIT_CHARS))
+        {
+            SetLastError( ERROR_INVALID_FLAGS );
+            return 0;
+        }
+        if (info->CodePage == CP_UTF8)
+            ret = wcstombs_utf8( flags, src, srclen, dst, dstlen, defchar, used );
+        else
+            ret = wcstombs_codepage( info, flags, src, srclen, dst, dstlen, defchar, used );
         break;
     }
     TRACE( "cp %d %s -> %s, ret = %d\n", codepage, debugstr_wn(src, srclen), debugstr_an(dst, ret), ret );




More information about the wine-cvs mailing list