diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 94bc52cc146..299bface9a1 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1406,6 +1406,7 @@ @ cdecl _memccpy(ptr ptr long long) @ cdecl _memicmp(str str long) @ varargs _snprintf(ptr long str) NTDLL__snprintf +@ varargs _snprintf_s(ptr long long str) _snprintf_s @ varargs _snwprintf(ptr long wstr) NTDLL__snwprintf @ cdecl _splitpath(str ptr ptr ptr ptr) @ cdecl _strcmpi(str str) _stricmp @@ -1420,6 +1421,7 @@ @ cdecl _ultoa(long ptr long) @ cdecl _ultow(long ptr long) @ cdecl -norelay _vsnprintf(ptr long str ptr) NTDLL__vsnprintf +@ cdecl _vsnprintf_s(ptr long str ptr) _vsnprintf_s @ cdecl _vsnwprintf(ptr long wstr ptr) NTDLL__vsnwprintf @ cdecl _wcsicmp(wstr wstr) NTDLL__wcsicmp @ cdecl _wcslwr(wstr) NTDLL__wcslwr diff --git a/dlls/ntdll/printf.c b/dlls/ntdll/printf.c index 6b7293be0c9..018f774dc00 100644 --- a/dlls/ntdll/printf.c +++ b/dlls/ntdll/printf.c @@ -764,6 +764,51 @@ int WINAPIV NTDLL__snwprintf( WCHAR *str, SIZE_T len, const WCHAR *format, ... ) } +/********************************************************************* + * _vsnprintf_s (NTDLL.@) + */ +int CDECL _vsnprintf_s( char *str, SIZE_T size, SIZE_T len, const char *format, __ms_va_list args ) +{ + DWORD sz; + LPWSTR formatW = NULL; + pf_output out; + int r; + + out.unicode = FALSE; + out.buf.A = str; + out.used = 0; + out.len = min( size, len ); + + if (format) + { + RtlMultiByteToUnicodeSize( &sz, format, strlen(format) + 1 ); + if (!(formatW = RtlAllocateHeap( GetProcessHeap(), 0, sz ))) return -1; + RtlMultiByteToUnicodeN( formatW, sz, NULL, format, strlen(format) + 1 ); + } + r = pf_vsnprintf( &out, formatW, args ); + RtlFreeHeap( GetProcessHeap(), 0, formatW ); + if (out.used < size) str[out.used] = 0; + else str[0] = 0; + if (r == size) r = -1; + return r; +} + + +/********************************************************************* + * _snprintf_s (NTDLL.@) + */ +int WINAPIV _snprintf_s( char *str, SIZE_T size, SIZE_T len, const char *format, ... ) +{ + int ret; + __ms_va_list valist; + + __ms_va_start( valist, format ); + ret = _vsnprintf_s( str, size, len, format, valist ); + __ms_va_end( valist ); + return ret; +} + + /********************************************************************* * vsprintf (NTDLL.@) */ diff --git a/dlls/ntdll/tests/string.c b/dlls/ntdll/tests/string.c index 79545087e3e..5a2d8458c21 100644 --- a/dlls/ntdll/tests/string.c +++ b/dlls/ntdll/tests/string.c @@ -61,6 +61,7 @@ static LPWSTR (WINAPIV *p_wcsrchr)(LPCWSTR, WCHAR); static void (__cdecl *p_qsort)(void *,size_t,size_t, int(__cdecl *compar)(const void *, const void *) ); static void* (__cdecl *p_bsearch)(void *,void*,size_t,size_t, int(__cdecl *compar)(const void *, const void *) ); static int (WINAPIV *p__snprintf)(char *, size_t, const char *, ...); +static int (WINAPIV *p__snprintf_s)(char *, size_t, size_t, const char *, ...); static int (__cdecl *p_tolower)(int); static int (__cdecl *p_toupper)(int); @@ -103,6 +104,7 @@ static void InitFunctionPtrs(void) p_bsearch= (void *)GetProcAddress(hntdll, "bsearch"); p__snprintf = (void *)GetProcAddress(hntdll, "_snprintf"); + p__snprintf_s = (void *)GetProcAddress(hntdll, "_snprintf_s"); p_tolower = (void *)GetProcAddress(hntdll, "tolower"); p_toupper = (void *)GetProcAddress(hntdll, "toupper"); @@ -1333,6 +1335,53 @@ static void test__snprintf(void) res = p__snprintf(buffer, strlen(teststring) + 1, teststring); ok(res == lstrlenA(teststring), "_snprintf returned %d, expected %d.\n", res, lstrlenA(teststring)); ok(!strcmp(buffer, teststring), "_snprintf returned buffer '%s', expected '%s'.\n", buffer, teststring); + + memset(buffer, 0x7c, sizeof(buffer)); + res = p__snprintf(buffer, 4, "test"); + ok(res == 4, "res = %d\n", res); + ok(!memcmp(buffer, "test", 4), "buf = %s\n", buffer); + ok(buffer[4] == 0x7c, "buffer[4] = %x\n", buffer[4]); + + memset(buffer, 0x7c, sizeof(buffer)); + res = p__snprintf(buffer, 3, "test"); + ok(res == -1, "res = %d\n", res); + } + +static void test__snprintf_s(void) +{ + char buf[32]; + int res; + + memset(buf, 0xcc, sizeof(buf)); + res = p__snprintf_s(buf, sizeof(buf), sizeof(buf), "test"); + ok(res == 4, "res = %d\n", res); + ok(!strcmp(buf, "test"), "buf = %s\n", buf); + + memset(buf, 0xcc, sizeof(buf)); + res = p__snprintf_s(buf, 4, 4, "test"); + ok(res == -1, "res = %d\n", res); + ok(!buf[0], "buf = %s\n", buf); + + memset(buf, 0xcc, sizeof(buf)); + res = p__snprintf_s(buf, 5, 4, "test"); + ok(res == 4, "res = %d\n", res); + ok(!strcmp(buf, "test"), "buf = %s\n", buf); + + memset(buf, 0xcc, sizeof(buf)); + res = p__snprintf_s(buf, 5, 3, "test"); + ok(res == -1, "res = %d\n", res); + ok(!strcmp(buf, "tes"), "buf = %s\n", buf); + + memset(buf, 0xcc, sizeof(buf)); + res = p__snprintf_s(buf, 4, 10, "test"); + ok(res == -1, "res = %d\n", res); + ok(!buf[0], "buf = %s\n", buf); + + memset(buf, 0xcc, sizeof(buf)); + res = p__snprintf_s(buf, 6, 5, "test%c", 0); + ok(res == 5, "res = %d\n", res); + ok(!memcmp(buf, "test\0", 6), "buf = %s\n", buf); + } static void test_tolower(void) @@ -1442,6 +1491,10 @@ START_TEST(string) test_bsearch(); if (p__snprintf) test__snprintf(); + if (p__snprintf_s) + test__snprintf_s(); + else + win_skip("_snprintf_s not available\n"); test_tolower(); test_toupper(); test__strnicmp();