Module: wine Branch: stable Commit: 598977af0ef15fc55a495a3dcef5413d29459dfc URL: http://source.winehq.org/git/wine.git/?a=commit;h=598977af0ef15fc55a495a3dce...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Thu Jul 28 22:21:49 2016 +0300
ucrtbase: Added __stdio_common_vsnwprintf_s().
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com Signed-off-by: Piotr Caban piotr@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org (cherry picked from commit 24291f2b6a96b0cffb738b5304e60fe9cf5efdd5) Signed-off-by: Michael Stefaniuc mstefani@winehq.org
---
.../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 223aa7c..11d3f1d 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 56625e9..f8b5205 100644 --- a/dlls/msvcrt/wcs.c +++ b/dlls/msvcrt/wcs.c @@ -810,6 +810,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.@) */ @@ -865,6 +896,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, @@ -1064,6 +1107,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.@) */ @@ -1071,31 +1115,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 d3ed0a2..b3084ae 100644 --- a/dlls/ucrtbase/tests/printf.c +++ b/dlls/ucrtbase/tests/printf.c @@ -67,6 +67,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); @@ -86,6 +88,7 @@ static BOOL init( void ) p_vfprintf = (void *)GetProcAddress(hmod, "__stdio_common_vfprintf"); 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");
@@ -360,6 +363,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}; @@ -457,6 +512,7 @@ START_TEST(printf) test_swprintf(); test_fprintf(); 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 f60aa29..24eba52 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