[PATCH] ucrtbase: Added __stdio_common_vsnwprintf_s()

Nikolay Sivov nsivov at codeweavers.com
Thu Jul 28 14:21:49 CDT 2016


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---

For https://bugs.winehq.org/show_bug.cgi?id=40757

 .../api-ms-win-crt-stdio-l1-1-0.spec               |  2 +-
 dlls/msvcrt/wcs.c                                  | 70 ++++++++++++++--------
 dlls/ucrtbase/tests/printf.c                       | 56 +++++++++++++++++
 dlls/ucrtbase/ucrtbase.spec                        |  2 +-
 4 files changed, 103 insertions(+), 27 deletions(-)

diff --git a/dlls/api-ms-win-crt-stdio-l1-1-0/api-ms-win-crt-stdio-l1-1-0.spec b/dlls/api-ms-win-crt-stdio-l1-1-0/api-ms-win-crt-stdio-l1-1-0.spec
index 29d2e1a..4dcc065 100644
--- a/dlls/api-ms-win-crt-stdio-l1-1-0/api-ms-win-crt-stdio-l1-1-0.spec
+++ b/dlls/api-ms-win-crt-stdio-l1-1-0/api-ms-win-crt-stdio-l1-1-0.spec
@@ -10,7 +10,7 @@
 @ stub __stdio_common_vfwprintf_s
 @ stub __stdio_common_vfwscanf
 @ cdecl __stdio_common_vsnprintf_s(int64 ptr long long ptr ptr ptr) ucrtbase.__stdio_common_vsnprintf_s
-@ stub __stdio_common_vsnwprintf_s
+@ cdecl __stdio_common_vsnwprintf_s(int64 ptr long long ptr ptr ptr) ucrtbase.__stdio_common_vsnwprintf_s
 @ cdecl __stdio_common_vsprintf(int64 ptr long ptr ptr ptr) ucrtbase.__stdio_common_vsprintf
 @ stub __stdio_common_vsprintf_p
 @ cdecl __stdio_common_vsprintf_s(int64 ptr long ptr ptr ptr) ucrtbase.__stdio_common_vsprintf_s
diff --git a/dlls/msvcrt/wcs.c b/dlls/msvcrt/wcs.c
index 4935e54..04a2f76 100644
--- a/dlls/msvcrt/wcs.c
+++ b/dlls/msvcrt/wcs.c
@@ -844,6 +844,37 @@ static int CDECL MSVCRT_vsnprintf_s_l_opt( char *str, MSVCRT_size_t sizeOfBuffer
     return ret;
 }
 
+static int MSVCRT_vsnwprintf_s_l_opt( MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer,
+        MSVCRT_size_t count, const MSVCRT_wchar_t *format, DWORD options,
+        MSVCRT__locale_t locale, __ms_va_list valist)
+{
+    static const MSVCRT_wchar_t nullbyte = '\0';
+    struct _str_ctx_w ctx;
+    int len, ret;
+
+    len = sizeOfBuffer;
+    if(count!=-1 && len>count+1)
+        len = count+1;
+
+    ctx.len = len;
+    ctx.buf = str;
+    ret = pf_printf_w(puts_clbk_str_w, &ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
+            arg_clbk_valist, NULL, &valist);
+    puts_clbk_str_w(&ctx, 1, &nullbyte);
+
+    if(ret<0 || ret==len) {
+        if(count!=MSVCRT__TRUNCATE && count>sizeOfBuffer) {
+            MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", MSVCRT_ERANGE);
+            memset(str, 0, sizeOfBuffer*sizeof(MSVCRT_wchar_t));
+        } else
+            str[len-1] = '\0';
+
+        return -1;
+    }
+
+    return ret;
+}
+
 /*********************************************************************
  *		_vsnprintf_s_l (MSVCRT.@)
  */
@@ -899,6 +930,18 @@ int CDECL MSVCRT__stdio_common_vsnprintf_s( unsigned __int64 options,
 }
 
 /*********************************************************************
+ *		__stdio_common_vsnwprintf_s (MSVCRT.@)
+ */
+int CDECL MSVCRT__stdio_common_vsnwprintf_s( unsigned __int64 options,
+        MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer, MSVCRT_size_t count,
+        const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list valist )
+{
+    if (options & ~UCRTBASE_PRINTF_MASK)
+        FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
+    return MSVCRT_vsnwprintf_s_l_opt(str, sizeOfBuffer, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
+}
+
+/*********************************************************************
  *		__stdio_common_vsprintf_s (MSVCRT.@)
  */
 int CDECL MSVCRT__stdio_common_vsprintf_s( unsigned __int64 options,
@@ -1098,6 +1141,7 @@ int CDECL MSVCRT__vswprintf_p(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
     return MSVCRT_vswprintf_p_l(buffer, length, format, NULL, args);
 }
 
+
 /*********************************************************************
  *              _vsnwprintf_s_l (MSVCRT.@)
  */
@@ -1105,31 +1149,7 @@ int CDECL MSVCRT_vsnwprintf_s_l( MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer
         MSVCRT_size_t count, const MSVCRT_wchar_t *format,
         MSVCRT__locale_t locale, __ms_va_list valist)
 {
-    static const MSVCRT_wchar_t nullbyte = '\0';
-    struct _str_ctx_w ctx;
-    int len, ret;
-
-    len = sizeOfBuffer;
-    if(count!=-1 && len>count+1)
-        len = count+1;
-
-    ctx.len = len;
-    ctx.buf = str;
-    ret = pf_printf_w(puts_clbk_str_w, &ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
-            arg_clbk_valist, NULL, &valist);
-    puts_clbk_str_w(&ctx, 1, &nullbyte);
-
-    if(ret<0 || ret==len) {
-        if(count!=MSVCRT__TRUNCATE && count>sizeOfBuffer) {
-            MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", MSVCRT_ERANGE);
-            memset(str, 0, sizeOfBuffer*sizeof(MSVCRT_wchar_t));
-        } else
-            str[len-1] = '\0';
-
-        return -1;
-    }
-
-    return ret;
+    return MSVCRT_vsnwprintf_s_l_opt(str, sizeOfBuffer, count, format, 0, locale, valist);
 }
 
 /*********************************************************************
diff --git a/dlls/ucrtbase/tests/printf.c b/dlls/ucrtbase/tests/printf.c
index 196b9cb..973217e 100644
--- a/dlls/ucrtbase/tests/printf.c
+++ b/dlls/ucrtbase/tests/printf.c
@@ -99,6 +99,8 @@ static int (__cdecl *p_vsprintf_s)(unsigned __int64 options, char *str, size_t c
                                     void *locale, __ms_va_list valist);
 static int (__cdecl *p_vswprintf)(unsigned __int64 options, wchar_t *str, size_t len, const wchar_t *format,
                                   void *locale, __ms_va_list valist);
+static int (__cdecl *p_vsnwprintf_s)(unsigned __int64 options, WCHAR *str, size_t sizeOfBuffer, size_t count, const WCHAR *format,
+                                    void *locale, __ms_va_list valist);
 
 static FILE *(__cdecl *p_fopen)(const char *name, const char *mode);
 static int (__cdecl *p_fclose)(FILE *file);
@@ -135,6 +137,7 @@ static BOOL init( void )
     p_vfwprintf = (void *)GetProcAddress(hmod, "__stdio_common_vfwprintf");
     p_vsprintf = (void *)GetProcAddress(hmod, "__stdio_common_vsprintf");
     p_vsnprintf_s = (void *)GetProcAddress(hmod, "__stdio_common_vsnprintf_s");
+    p_vsnwprintf_s = (void *)GetProcAddress(hmod, "__stdio_common_vsnwprintf_s");
     p_vsprintf_s = (void *)GetProcAddress(hmod, "__stdio_common_vsprintf_s");
     p_vswprintf = (void *)GetProcAddress(hmod, "__stdio_common_vswprintf");
 
@@ -516,6 +519,58 @@ static void test_vsnprintf_s(void)
     ok( !strcmp(out1, buffer), "buffer wrong, got=%s\n", buffer);
 }
 
+static int __cdecl _vsnwprintf_s_wrapper(WCHAR *str, size_t sizeOfBuffer,
+                                        size_t count, const WCHAR *format, ...)
+{
+    int ret;
+    __ms_va_list valist;
+    __ms_va_start(valist, format);
+    ret = p_vsnwprintf_s(0, str, sizeOfBuffer, count, format, NULL, valist);
+    __ms_va_end(valist);
+    return ret;
+}
+
+static void test_vsnwprintf_s(void)
+{
+    const WCHAR format[] = {'A','B','%','u','C',0};
+    const WCHAR out7[] = {'A','B','1','2','3','C',0};
+    const WCHAR out6[] = {'A','B','1','2','3',0};
+    const WCHAR out2[] = {'A',0};
+    const WCHAR out1[] = {0};
+    WCHAR buffer[14] = { 0 };
+    int exp, got;
+
+    /* Enough room. */
+    exp = lstrlenW(out7);
+
+    got = _vsnwprintf_s_wrapper(buffer, 14, _TRUNCATE, format, 123);
+    ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
+    ok( !lstrcmpW(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
+
+    got = _vsnwprintf_s_wrapper(buffer, 12, _TRUNCATE, format, 123);
+    ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
+    ok( !lstrcmpW(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
+
+    got = _vsnwprintf_s_wrapper(buffer, 7, _TRUNCATE, format, 123);
+    ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
+    ok( !lstrcmpW(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
+
+    /* Not enough room. */
+    exp = -1;
+
+    got = _vsnwprintf_s_wrapper(buffer, 6, _TRUNCATE, format, 123);
+    ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
+    ok( !lstrcmpW(out6, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
+
+    got = _vsnwprintf_s_wrapper(buffer, 2, _TRUNCATE, format, 123);
+    ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
+    ok( !lstrcmpW(out2, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
+
+    got = _vsnwprintf_s_wrapper(buffer, 1, _TRUNCATE, format, 123);
+    ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
+    ok( !lstrcmpW(out1, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
+}
+
 static void test_printf_legacy_wide(void)
 {
     const wchar_t wide[] = {'A','B','C','D',0};
@@ -614,6 +669,7 @@ START_TEST(printf)
     test_fprintf();
     test_fwprintf();
     test_vsnprintf_s();
+    test_vsnwprintf_s();
     test_printf_legacy_wide();
     test_printf_legacy_msvcrt();
     test_printf_legacy_three_digit_exp();
diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec
index 2a34404..24a7f1f 100644
--- a/dlls/ucrtbase/ucrtbase.spec
+++ b/dlls/ucrtbase/ucrtbase.spec
@@ -155,7 +155,7 @@
 @ stub __stdio_common_vfwprintf_s
 @ stub __stdio_common_vfwscanf
 @ cdecl __stdio_common_vsnprintf_s(int64 ptr long long ptr ptr ptr) MSVCRT__stdio_common_vsnprintf_s
-@ stub __stdio_common_vsnwprintf_s
+@ cdecl __stdio_common_vsnwprintf_s(int64 ptr long long ptr ptr ptr) MSVCRT__stdio_common_vsnwprintf_s
 @ cdecl __stdio_common_vsprintf(int64 ptr long ptr ptr ptr) MSVCRT__stdio_common_vsprintf
 @ stub __stdio_common_vsprintf_p
 @ cdecl __stdio_common_vsprintf_s(int64 ptr long ptr ptr ptr) MSVCRT__stdio_common_vsprintf_s
-- 
2.8.1




More information about the wine-patches mailing list