Module: wine Branch: master Commit: 08bf605acb4d319e016a7eafe0c675509445bd4a URL: https://source.winehq.org/git/wine.git/?a=commit;h=08bf605acb4d319e016a7eafe...
Author: Akihiro Sagawa sagawa.aki@gmail.com Date: Sun Feb 9 20:51:31 2020 +0900
user32: Fix wsprintfA %S conversion.
Signed-off-by: Akihiro Sagawa sagawa.aki@gmail.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/user32/tests/wsprintf.c | 16 ++++++---------- dlls/user32/wsprintf.c | 31 +++++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 16 deletions(-)
diff --git a/dlls/user32/tests/wsprintf.c b/dlls/user32/tests/wsprintf.c index ca0c4802f9..ab4f4dae04 100644 --- a/dlls/user32/tests/wsprintf.c +++ b/dlls/user32/tests/wsprintf.c @@ -61,16 +61,14 @@ static void wsprintfATest(void) const char *fmt; const char *str; int rc; - BOOL todo_rc; - BOOL todo_str; } testcase[] = { - { starW, "%.1S", partial, 1, TRUE, TRUE }, - { starW, "%.2S", star, 2, FALSE, TRUE }, - { starW, "%.3S", star, 2, FALSE, TRUE }, - { fffeW, "%.1S", "?", 1, FALSE, TRUE }, - { fffeW, "%.2S", "?", 1, FALSE, TRUE }, - { wineW, "%.2S", "??", 2, FALSE, TRUE }, + { starW, "%.1S", partial, 1 }, + { starW, "%.2S", star, 2 }, + { starW, "%.3S", star, 2 }, + { fffeW, "%.1S", "?", 1 }, + { fffeW, "%.2S", "?", 1 }, + { wineW, "%.2S", "??", 2 }, { star, "%.1s", partial, 1 }, }; CPINFO cpinfo; @@ -110,12 +108,10 @@ static void wsprintfATest(void) memset(buf, 0x11, sizeof(buf)); rc = wsprintfA(buf, testcase[i].fmt, testcase[i].input);
- todo_wine_if(testcase[i].todo_rc) ok(rc == testcase[i].rc, "%u: expected %d, got %d\n", i, testcase[i].rc, rc);
- todo_wine_if(testcase[i].todo_str) ok(!strcmp(buf, testcase[i].str), "%u: expected %s, got %s\n", i, wine_dbgstr_a(testcase[i].str), wine_dbgstr_an(buf, rc)); diff --git a/dlls/user32/wsprintf.c b/dlls/user32/wsprintf.c index 17d39a4d17..478583d926 100644 --- a/dlls/user32/wsprintf.c +++ b/dlls/user32/wsprintf.c @@ -30,6 +30,7 @@ #include "winbase.h" #include "wingdi.h" #include "winuser.h" +#include "winnls.h"
#include "wine/debug.h"
@@ -245,7 +246,7 @@ static INT WPRINTF_ParseFormatW( LPCWSTR format, WPRINTF_FORMAT *res ) * WPRINTF_GetLen */ static UINT WPRINTF_GetLen( WPRINTF_FORMAT *format, WPRINTF_DATA *arg, - LPSTR number, UINT maxlen ) + LPSTR number, UINT maxlen, BOOL dst_is_wide ) { UINT len;
@@ -264,8 +265,18 @@ static UINT WPRINTF_GetLen( WPRINTF_FORMAT *format, WPRINTF_DATA *arg, return (format->precision = len); case WPR_WSTRING: if (!arg->lpcwstr_view) arg->lpcwstr_view = null_stringW; - for (len = 0; !format->precision || (len < format->precision); len++) - if (!*(arg->lpcwstr_view + len)) break; + if (dst_is_wide) + { + for (len = 0; !format->precision || (len < format->precision); len++) + if (!*(arg->lpcwstr_view + len)) break; + } + else + { + LPCWSTR p = arg->lpcwstr_view; + for (len = 0; (!format->precision || len < format->precision) && *p; p++) + len += WideCharToMultiByte( CP_ACP, 0, p, 1, NULL, 0, NULL, NULL ); + if (format->precision && len > format->precision) len = format->precision; + } if (len > maxlen) len = maxlen; return (format->precision = len); case WPR_SIGNED: @@ -354,7 +365,7 @@ static INT wvsnprintfA( LPSTR buffer, UINT maxlen, LPCSTR spec, __ms_va_list arg break; }
- len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 ); + len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1, FALSE ); sign = 0; if (!(format.flags & WPRINTF_LEFTALIGN)) for (i = format.precision; i < format.width; i++, maxlen--) @@ -374,7 +385,15 @@ static INT wvsnprintfA( LPSTR buffer, UINT maxlen, LPCSTR spec, __ms_va_list arg case WPR_WSTRING: { LPCWSTR ptr = argData.lpcwstr_view; - for (i = 0; i < len; i++) *p++ = (CHAR)*ptr++; + for (i = 0; i < len; ptr++) + { + CHAR mb[5]; /* 5 is MB_LEN_MAX */ + int ret = WideCharToMultiByte( CP_ACP, 0, ptr, 1, mb, sizeof(mb), NULL, NULL ); + i += ret; + if (i > len) ret = len - (p - buffer); + memcpy( p, mb, ret ); + p += ret; + } } break; case WPR_HEXA: @@ -459,7 +478,7 @@ static INT wvsnprintfW( LPWSTR buffer, UINT maxlen, LPCWSTR spec, __ms_va_list a break; }
- len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 ); + len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1, TRUE ); sign = 0; if (!(format.flags & WPRINTF_LEFTALIGN)) for (i = format.precision; i < format.width; i++, maxlen--)