diff --git a/dlls/api-ms-win-crt-string-l1-1-0/api-ms-win-crt-string-l1-1-0.spec b/dlls/api-ms-win-crt-string-l1-1-0/api-ms-win-crt-string-l1-1-0.spec index d045996756f..bbc247c79cc 100644 --- a/dlls/api-ms-win-crt-string-l1-1-0/api-ms-win-crt-string-l1-1-0.spec +++ b/dlls/api-ms-win-crt-string-l1-1-0/api-ms-win-crt-string-l1-1-0.spec @@ -3,7 +3,7 @@ @ cdecl __iscsymf(long) ucrtbase.__iscsymf @ stub __iswcsym @ stub __iswcsymf -@ stub __strncnt +@ cdecl __strncnt(str long) ucrtbase.__strncnt @ stub __wcsncnt @ cdecl _isalnum_l(long ptr) ucrtbase._isalnum_l @ cdecl _isalpha_l(long ptr) ucrtbase._isalpha_l diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec index 1579415edc1..482dcbbf032 100644 --- a/dlls/msvcr100/msvcr100.spec +++ b/dlls/msvcr100/msvcr100.spec @@ -656,7 +656,7 @@ @ stub __set_flsgetvalue @ extern __setlc_active MSVCRT___setlc_active @ cdecl __setusermatherr(ptr) MSVCRT___setusermatherr -@ stub __strncnt +@ cdecl __strncnt(str long) MSVCRT___strncnt @ varargs __swprintf_l(ptr wstr ptr) MSVCRT___swprintf_l @ cdecl __sys_errlist() @ cdecl __sys_nerr() diff --git a/dlls/msvcr100/tests/msvcr100.c b/dlls/msvcr100/tests/msvcr100.c index 594ac28072c..8ac8f4ea3b8 100644 --- a/dlls/msvcr100/tests/msvcr100.c +++ b/dlls/msvcr100/tests/msvcr100.c @@ -235,6 +235,7 @@ static int (__cdecl *p__memicmp)(const char*, const char*, size_t); static int (__cdecl *p__memicmp_l)(const char*, const char*, size_t,_locale_t); static char* (__cdecl *p_setlocale)(int, const char*); +static size_t (__cdecl *p___strncnt)(const char*, size_t); /* make sure we use the correct errno */ #undef errno @@ -270,6 +271,7 @@ static BOOL init(void) SET(p__memicmp, "_memicmp"); SET(p__memicmp_l, "_memicmp_l"); SET(p_setlocale, "setlocale"); + SET(p___strncnt, "__strncnt"); SET(p_Context_Id, "?Id@Context@Concurrency@@SAIXZ"); SET(p_CurrentScheduler_Detach, "?Detach@CurrentScheduler@Concurrency@@SAXXZ"); @@ -1075,6 +1077,35 @@ static void test_setlocale(void) ok(!ret, "got %p\n", ret); } +static void test___strncnt(void) +{ + static const struct + { + const char *str; + size_t size; + size_t ret; + } + strncnt_tests[] = + { + { NULL, 0, 0 }, + { "a", 0, 0 }, + { "a", 1, 1 }, + { "a", 10, 1 }, + { "abc", 1, 1 }, + }; + unsigned int i; + size_t ret; + + if (0) /* crashes */ + ret = p___strncnt(NULL, 1); + + for (i = 0; i < ARRAY_SIZE(strncnt_tests); ++i) + { + ret = p___strncnt(strncnt_tests[i].str, strncnt_tests[i].size); + ok(ret == strncnt_tests[i].ret, "%u: unexpected return value %u.\n", i, (int)ret); + } +} + START_TEST(msvcr100) { if (!init()) @@ -1094,4 +1125,5 @@ START_TEST(msvcr100) test__memicmp(); test__memicmp_l(); test_setlocale(); + test___strncnt(); } diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec index 029620f72e6..4ad61d40227 100644 --- a/dlls/msvcr110/msvcr110.spec +++ b/dlls/msvcr110/msvcr110.spec @@ -1004,7 +1004,7 @@ @ cdecl __set_app_type(long) MSVCRT___set_app_type @ extern __setlc_active MSVCRT___setlc_active @ cdecl __setusermatherr(ptr) MSVCRT___setusermatherr -@ stub __strncnt +@ cdecl __strncnt(str long) MSVCRT___strncnt @ varargs __swprintf_l(ptr wstr ptr) MSVCRT___swprintf_l @ cdecl __sys_errlist() @ cdecl __sys_nerr() diff --git a/dlls/msvcr110/tests/msvcr110.c b/dlls/msvcr110/tests/msvcr110.c index dcee5c1eccc..09876131f07 100644 --- a/dlls/msvcr110/tests/msvcr110.c +++ b/dlls/msvcr110/tests/msvcr110.c @@ -32,6 +32,7 @@ #include static char* (CDECL *p_setlocale)(int category, const char* locale); +static size_t (CDECL *p___strncnt)(const char *str, size_t count); static unsigned int (CDECL *p_CurrentScheduler_GetNumberOfVirtualProcessors)(void); static unsigned int (CDECL *p__CurrentScheduler__GetNumberOfVirtualProcessors)(void); @@ -50,6 +51,7 @@ static BOOL init(void) } p_setlocale = (void*)GetProcAddress(module, "setlocale"); + p___strncnt = (void*)GetProcAddress(module, "__strncnt"); p_CurrentScheduler_GetNumberOfVirtualProcessors = (void*)GetProcAddress(module, "?GetNumberOfVirtualProcessors@CurrentScheduler@Concurrency@@SAIXZ"); p__CurrentScheduler__GetNumberOfVirtualProcessors = (void*)GetProcAddress(module, "?_GetNumberOfVirtualProcessors@_CurrentScheduler@details@Concurrency@@SAIXZ"); p_CurrentScheduler_Id = (void*)GetProcAddress(module, "?Id@CurrentScheduler@Concurrency@@SAIXZ"); @@ -112,9 +114,39 @@ static void test_setlocale(void) p_setlocale(LC_ALL, "C"); } +static void test___strncnt(void) +{ + static const struct + { + const char *str; + size_t size; + size_t ret; + } + strncnt_tests[] = + { + { NULL, 0, 0 }, + { "a", 0, 0 }, + { "a", 1, 1 }, + { "a", 10, 1 }, + { "abc", 1, 1 }, + }; + unsigned int i; + size_t ret; + + if (0) /* crashes */ + ret = p___strncnt(NULL, 1); + + for (i = 0; i < ARRAY_SIZE(strncnt_tests); ++i) + { + ret = p___strncnt(strncnt_tests[i].str, strncnt_tests[i].size); + ok(ret == strncnt_tests[i].ret, "%u: unexpected return value %u.\n", i, (int)ret); + } +} + START_TEST(msvcr110) { if (!init()) return; test_CurrentScheduler(); /* MUST be first (at least among Concurrency tests) */ test_setlocale(); + test___strncnt(); } diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index 89002ed15b0..47834e5d62a 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -994,7 +994,7 @@ @ cdecl __set_app_type(long) MSVCRT___set_app_type @ extern __setlc_active MSVCRT___setlc_active @ cdecl __setusermatherr(ptr) MSVCRT___setusermatherr -@ stub __strncnt +@ cdecl __strncnt(str long) MSVCRT___strncnt @ varargs __swprintf_l(ptr wstr ptr) MSVCRT___swprintf_l @ cdecl __sys_errlist() @ cdecl __sys_nerr() diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec index e926bbbf487..e5b26a4746f 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -965,7 +965,7 @@ @ stub __report_gsfailure @ extern __setlc_active msvcr120.__setlc_active @ cdecl __setusermatherr(ptr) msvcr120.__setusermatherr -@ stub __strncnt +@ cdecl __strncnt(str long) msvcr120.__strncnt @ varargs __swprintf_l(ptr wstr ptr) msvcr120.__swprintf_l @ cdecl __sys_errlist() msvcr120.__sys_errlist @ cdecl __sys_nerr() msvcr120.__sys_nerr diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec index 7aebe34f23b..69355cc1f78 100644 --- a/dlls/msvcr80/msvcr80.spec +++ b/dlls/msvcr80/msvcr80.spec @@ -305,7 +305,7 @@ @ stub __set_flsgetvalue @ extern __setlc_active MSVCRT___setlc_active @ cdecl __setusermatherr(ptr) MSVCRT___setusermatherr -@ stub __strncnt +@ cdecl __strncnt(str long) MSVCRT___strncnt @ varargs __swprintf_l(ptr wstr ptr) MSVCRT___swprintf_l @ cdecl __sys_errlist() @ cdecl __sys_nerr() diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec index eb70ff91538..33ec4b2df75 100644 --- a/dlls/msvcr90/msvcr90.spec +++ b/dlls/msvcr90/msvcr90.spec @@ -289,7 +289,7 @@ @ stub __set_flsgetvalue @ extern __setlc_active MSVCRT___setlc_active @ cdecl __setusermatherr(ptr) MSVCRT___setusermatherr -@ stub __strncnt +@ cdecl __strncnt(str long) MSVCRT___strncnt @ varargs __swprintf_l(ptr wstr ptr) MSVCRT___swprintf_l @ cdecl __sys_errlist() @ cdecl __sys_nerr() diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c index 777d4fee976..0ba1f1a7b18 100644 --- a/dlls/msvcr90/tests/msvcr90.c +++ b/dlls/msvcr90/tests/msvcr90.c @@ -134,6 +134,7 @@ static int (__cdecl *p__fpieee_flt)(ULONG, EXCEPTION_POINTERS*, int (__cdecl *ha static int (__cdecl *p__memicmp)(const char*, const char*, size_t); static int (__cdecl *p__memicmp_l)(const char*, const char*, size_t, _locale_t); static int (__cdecl *p__vsnwprintf)(wchar_t *buffer,size_t count, const wchar_t *format, __ms_va_list valist); +static size_t (__cdecl *p___strncnt)(const char *str, size_t count); /* make sure we use the correct errno */ #undef errno @@ -403,6 +404,7 @@ static BOOL init(void) SET(p__memicmp, "_memicmp"); SET(p__memicmp_l, "_memicmp_l"); SET(p__vsnwprintf, "_vsnwprintf"); + SET(p___strncnt, "__strncnt"); if (sizeof(void *) == 8) { @@ -1894,6 +1896,35 @@ static void test__vsnwprintf(void) ok(p_set_invalid_parameter_handler(old_handler) == test_invalid_parameter_handler, "Cannot reset invalid parameter handler\n"); } +static void test___strncnt(void) +{ + static const struct + { + const char *str; + size_t size; + size_t ret; + } + strncnt_tests[] = + { + { NULL, 0, 0 }, + { "a", 0, 0 }, + { "a", 1, 1 }, + { "a", 10, 1 }, + { "abc", 1, 1 }, + }; + unsigned int i; + size_t ret; + + if (0) + ret = p___strncnt(NULL, 1); + + for (i = 0; i < ARRAY_SIZE(strncnt_tests); ++i) + { + ret = p___strncnt(strncnt_tests[i].str, strncnt_tests[i].size); + ok(ret == strncnt_tests[i].ret, "%u: unexpected return value %u.\n", i, (int)ret); + } +} + START_TEST(msvcr90) { if(!init()) @@ -1931,4 +1962,5 @@ START_TEST(msvcr90) #ifdef __i386__ test__fpieee_flt(); #endif + test___strncnt(); } diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec index d963f7cbd98..7faecb261e9 100644 --- a/dlls/msvcrt/msvcrt.spec +++ b/dlls/msvcrt/msvcrt.spec @@ -281,7 +281,7 @@ @ cdecl __set_app_type(long) MSVCRT___set_app_type @ extern __setlc_active MSVCRT___setlc_active @ cdecl __setusermatherr(ptr) MSVCRT___setusermatherr -# stub __strncnt(str long) +@ cdecl __strncnt(str long) MSVCRT___strncnt @ cdecl __threadhandle() kernel32.GetCurrentThread @ cdecl __threadid() kernel32.GetCurrentThreadId @ cdecl __toascii(long) MSVCRT___toascii diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c index cbbb65b2496..fc827d80936 100644 --- a/dlls/msvcrt/string.c +++ b/dlls/msvcrt/string.c @@ -2060,3 +2060,22 @@ char* __cdecl MSVCRT_strpbrk(const char *str, const char *accept) { return strpbrk(str, accept); } + +/********************************************************************* + * __strncnt (MSVCRT.@) + */ +MSVCRT_size_t __cdecl MSVCRT___strncnt(const char *str, MSVCRT_size_t size) +{ + MSVCRT_size_t ret = 0; + +#if _MSVCR_VER >= 140 + while (*str++ && size--) +#else + while (size-- && *str++) +#endif + { + ret++; + } + + return ret; +} diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c index 670c7cf91f7..d0988bf86c3 100644 --- a/dlls/msvcrt/tests/string.c +++ b/dlls/msvcrt/tests/string.c @@ -100,6 +100,7 @@ static size_t (__cdecl *p__mbsnlen)(const unsigned char*, size_t); static int (__cdecl *p__mbccpy_s)(unsigned char*, size_t, int*, const unsigned char*); static int (__cdecl *p__memicmp)(const char*, const char*, size_t); static int (__cdecl *p__memicmp_l)(const char*, const char*, size_t, _locale_t); +static size_t (__cdecl *p___strncnt)(const char*, size_t); #define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y) #define SET(x,y) SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y) @@ -3568,6 +3569,41 @@ static void test__tcsnicoll(void) } } +static void test___strncnt(void) +{ + static const struct + { + const char *str; + size_t size; + size_t ret; + } + strncnt_tests[] = + { + { NULL, 0, 0 }, + { "a", 0, 0 }, + { "a", 1, 1 }, + { "a", 10, 1 }, + { "abc", 1, 1 }, + }; + unsigned int i; + size_t ret; + + if (!p___strncnt) + { + win_skip("__strncnt() is not available.\n"); + return; + } + + if (0) /* crashes */ + ret = p___strncnt(NULL, 1); + + for (i = 0; i < ARRAY_SIZE(strncnt_tests); ++i) + { + ret = p___strncnt(strncnt_tests[i].str, strncnt_tests[i].size); + ok(ret == strncnt_tests[i].ret, "%u: unexpected return value %u.\n", i, (int)ret); + } +} + START_TEST(string) { char mem[100]; @@ -3626,6 +3662,7 @@ START_TEST(string) p__mbccpy_s = (void*)GetProcAddress(hMsvcrt, "_mbccpy_s"); p__memicmp = (void*)GetProcAddress(hMsvcrt, "_memicmp"); p__memicmp_l = (void*)GetProcAddress(hMsvcrt, "_memicmp_l"); + p___strncnt = (void*)GetProcAddress(hMsvcrt, "__strncnt"); /* MSVCRT memcpy behaves like memmove for overlapping moves, MFC42 CString::Insert seems to rely on that behaviour */ @@ -3693,4 +3730,5 @@ START_TEST(string) test__strupr(); test__tcsncoll(); test__tcsnicoll(); + test___strncnt(); } diff --git a/dlls/ucrtbase/tests/string.c b/dlls/ucrtbase/tests/string.c index ab86f468104..34f5a78b073 100644 --- a/dlls/ucrtbase/tests/string.c +++ b/dlls/ucrtbase/tests/string.c @@ -89,6 +89,7 @@ static void __cdecl test_invalid_parameter_handler(const wchar_t *expression, static double (__cdecl *p_strtod)(const char*, char** end); static int (__cdecl *p__memicmp)(const char*, const char*, size_t); static int (__cdecl *p__memicmp_l)(const char*, const char*, size_t,_locale_t); +static size_t (__cdecl *p___strncnt)(const char*, size_t); static BOOL init(void) { @@ -105,6 +106,7 @@ static BOOL init(void) p_strtod = (void*)GetProcAddress(module, "strtod"); p__memicmp = (void*)GetProcAddress(module, "_memicmp"); p__memicmp_l = (void*)GetProcAddress(module, "_memicmp_l"); + p___strncnt = (void*)GetProcAddress(module, "__strncnt"); return TRUE; } @@ -244,10 +246,50 @@ static void test__memicmp_l(void) ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler, "Cannot reset invalid parameter handler\n"); } + + +static void test___strncnt(void) +{ + static const struct + { + const char *str; + size_t size; + size_t ret; + } + strncnt_tests[] = + { + { "a", 0, 0 }, + { "a", 1, 1 }, + { "a", 10, 1 }, + { "abc", 1, 1 }, + }; + unsigned int i; + size_t ret; + + for (i = 0; i < ARRAY_SIZE(strncnt_tests); ++i) + { + ret = p___strncnt(strncnt_tests[i].str, strncnt_tests[i].size); + ok(ret == strncnt_tests[i].ret, "%u: unexpected return value %u.\n", i, (int)ret); + } + + ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL, + "Invalid parameter handler was already set\n"); + + if (0) /* crashes */ + { + ret = p___strncnt(NULL, 0); + ret = p___strncnt(NULL, 1); + } + + ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler, + "Cannot reset invalid parameter handler\n"); +} + START_TEST(string) { if (!init()) return; test_strtod(); test__memicmp(); test__memicmp_l(); + test___strncnt(); } diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index 404da75f9a6..142ac869130 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -164,7 +164,7 @@ @ cdecl __stdio_common_vswprintf_p(int64 ptr long wstr ptr ptr) MSVCRT__stdio_common_vswprintf_p @ cdecl __stdio_common_vswprintf_s(int64 ptr long wstr ptr ptr) MSVCRT__stdio_common_vswprintf_s @ cdecl __stdio_common_vswscanf(int64 ptr long wstr ptr ptr) MSVCRT__stdio_common_vswscanf -@ stub __strncnt +@ cdecl __strncnt(str long) MSVCRT___strncnt @ cdecl __sys_errlist() @ cdecl __sys_nerr() @ cdecl __threadhandle() kernel32.GetCurrentThread