Akihiro Sagawa : user32: Fix wsprintfA %S conversion.

Alexandre Julliard julliard at winehq.org
Mon Feb 10 16:32:45 CST 2020


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

Author: Akihiro Sagawa <sagawa.aki at gmail.com>
Date:   Sun Feb  9 20:51:31 2020 +0900

user32: Fix wsprintfA %S conversion.

Signed-off-by: Akihiro Sagawa <sagawa.aki at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at 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--)




More information about the wine-cvs mailing list