diff --git a/dlls/api-ms-win-crt-locale-l1-1-0/api-ms-win-crt-locale-l1-1-0.spec b/dlls/api-ms-win-crt-locale-l1-1-0/api-ms-win-crt-locale-l1-1-0.spec index c7e5aae86db..60c588b712d 100644 --- a/dlls/api-ms-win-crt-locale-l1-1-0/api-ms-win-crt-locale-l1-1-0.spec +++ b/dlls/api-ms-win-crt-locale-l1-1-0/api-ms-win-crt-locale-l1-1-0.spec @@ -14,7 +14,7 @@ @ cdecl _lock_locales() ucrtbase._lock_locales @ cdecl _setmbcp(long) ucrtbase._setmbcp @ cdecl _unlock_locales() ucrtbase._unlock_locales -@ stub _wcreate_locale +@ cdecl _wcreate_locale(long wstr) ucrtbase._wcreate_locale @ cdecl _wsetlocale(long wstr) ucrtbase._wsetlocale @ cdecl localeconv() ucrtbase.localeconv @ cdecl setlocale(long str) ucrtbase.setlocale diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec index 5f33acf6684..1890a13f7a1 100644 --- a/dlls/msvcr110/msvcr110.spec +++ b/dlls/msvcr110/msvcr110.spec @@ -1844,7 +1844,7 @@ @ cdecl _wchmod(wstr long) MSVCRT__wchmod @ extern _wcmdln MSVCRT__wcmdln @ cdecl _wcreat(wstr long) MSVCRT__wcreat -@ stub _wcreate_locale +@ cdecl _wcreate_locale(long wstr) MSVCRT__wcreate_locale @ cdecl _wcscoll_l(wstr wstr ptr) MSVCRT__wcscoll_l @ cdecl _wcsdup(wstr) MSVCRT__wcsdup @ cdecl _wcserror(long) MSVCRT__wcserror diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index 953cdba7642..66334d8df33 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -1862,7 +1862,7 @@ @ cdecl _wchmod(wstr long) MSVCRT__wchmod @ extern _wcmdln MSVCRT__wcmdln @ cdecl _wcreat(wstr long) MSVCRT__wcreat -@ stub _wcreate_locale +@ cdecl _wcreate_locale(long wstr) MSVCRT__wcreate_locale @ cdecl _wcscoll_l(wstr wstr ptr) MSVCRT__wcscoll_l @ cdecl _wcsdup(wstr) MSVCRT__wcsdup @ cdecl _wcserror(long) MSVCRT__wcserror diff --git a/dlls/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c index 25330f1c4d5..4ecea51d7b5 100644 --- a/dlls/msvcr120/tests/msvcr120.c +++ b/dlls/msvcr120/tests/msvcr120.c @@ -170,6 +170,8 @@ static double (CDECL *p_remainder)(double, double); static int* (CDECL *p_errno)(void); static int (CDECL *p_fegetenv)(fenv_t*); static int (CDECL *p__clearfp)(void); +static _locale_t (__cdecl *p_wcreate_locale)(int, const wchar_t *); +static void (__cdecl *p_free_locale)(_locale_t); /* make sure we use the correct errno */ #undef errno @@ -215,6 +217,8 @@ static BOOL init(void) p_wcstof = (void*)GetProcAddress(module, "wcstof"); p_remainder = (void*)GetProcAddress(module, "remainder"); p_errno = (void*)GetProcAddress(module, "_errno"); + p_wcreate_locale = (void*)GetProcAddress(module, "_wcreate_locale"); + p_free_locale = (void*)GetProcAddress(module, "_free_locale"); SET(p_fegetenv, "fegetenv"); SET(p__clearfp, "_clearfp"); if(sizeof(void*) == 8) { /* 64-bit initialization */ @@ -710,6 +714,50 @@ static void test_fegetenv(void) ok(!env.status, "env.status = %x\n", env.status); } +static void test__wcreate_locale(void) +{ + static const wchar_t c_locale[] = {'C',0}; + static const wchar_t bogus[] = {'b','o','g','u','s',0}; + static const wchar_t empty[] = {0}; + _locale_t lcl; + errno_t e; + + /* simple success */ + errno = -1; + lcl = p_wcreate_locale(LC_ALL, c_locale); + e = errno; + ok(!!lcl, "expected success, but got NULL\n"); + ok(errno == -1, "expected errno -1, but got %i\n", e); + p_free_locale(lcl); + + errno = -1; + lcl = p_wcreate_locale(LC_ALL, empty); + e = errno; + ok(!!lcl, "expected success, but got NULL\n"); + ok(errno == -1, "expected errno -1, but got %i\n", e); + p_free_locale(lcl); + + /* bogus category */ + errno = -1; + lcl = p_wcreate_locale(-1, c_locale); + e = errno; + ok(!lcl, "expected failure, but got %p\n", lcl); + ok(errno == -1, "expected errno -1, but got %i\n", e); + + /* bogus names */ + errno = -1; + lcl = p_wcreate_locale(LC_ALL, bogus); + e = errno; + ok(!lcl, "expected failure, but got %p\n", lcl); + ok(errno == -1, "expected errno -1, but got %i\n", e); + + errno = -1; + lcl = p_wcreate_locale(LC_ALL, NULL); + e = errno; + ok(!lcl, "expected failure, but got %p\n", lcl); + ok(errno == -1, "expected errno -1, but got %i\n", e); +} + START_TEST(msvcr120) { if (!init()) return; @@ -724,4 +772,5 @@ START_TEST(msvcr120) test_remainder(); test_critical_section(); test_fegetenv(); + test__wcreate_locale(); } diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec index c88cde02be2..6f0daca367e 100644 --- a/dlls/msvcr120_app/msvcr120_app.spec +++ b/dlls/msvcr120_app/msvcr120_app.spec @@ -1555,7 +1555,7 @@ @ cdecl _wchmod(wstr long) msvcr120._wchmod @ extern _wcmdln msvcr120._wcmdln @ cdecl _wcreat(wstr long) msvcr120._wcreat -@ stub _wcreate_locale +@ cdecl _wcreate_locale(long wstr) msvcr120._wcreate_locale @ cdecl _wcscoll_l(wstr wstr ptr) msvcr120._wcscoll_l @ cdecl _wcsdup(wstr) msvcr120._wcsdup @ cdecl _wcserror(long) msvcr120._wcserror diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index 024ec997274..c3e5630d9d5 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -1633,6 +1633,31 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale) return loc; } +/********************************************************************* + * _wcreate_locale (MSVCRT.@) + */ +MSVCRT__locale_t CDECL MSVCRT__wcreate_locale(int category, const MSVCRT_wchar_t *locale) +{ + MSVCRT__locale_t loc; + MSVCRT_size_t len; + char *str; + + if(categoryMSVCRT_LC_MAX || !locale) + return NULL; + + len = MSVCRT_wcstombs(NULL, locale, 0); + if(len == -1) + return NULL; + if(!(str = MSVCRT_malloc(++len))) + return NULL; + MSVCRT_wcstombs(str, locale, len); + + loc = MSVCRT__create_locale(category, str); + + MSVCRT_free(str); + return loc; +} + /********************************************************************* * setlocale (MSVCRT.@) */ diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index 1adc80af861..0e1faa11e53 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -2011,7 +2011,7 @@ @ cdecl _wchdir(wstr) MSVCRT__wchdir @ cdecl _wchmod(wstr long) MSVCRT__wchmod @ cdecl _wcreat(wstr long) MSVCRT__wcreat -@ stub _wcreate_locale +@ cdecl _wcreate_locale(long wstr) MSVCRT__wcreate_locale @ cdecl _wcscoll_l(wstr wstr ptr) MSVCRT__wcscoll_l @ cdecl _wcsdup(wstr) MSVCRT__wcsdup @ cdecl _wcserror(long) MSVCRT__wcserror