From: Victor Chiletto vchiletto@codeweavers.com
--- dlls/msvcr110/tests/msvcr110.c | 8 +- dlls/msvcr120/tests/msvcr120.c | 11 +- dlls/msvcrt/locale.c | 413 +++++++++++++++------------------ dlls/msvcrt/tests/locale.c | 8 +- include/msvcrt/corecrt.h | 2 - 5 files changed, 194 insertions(+), 248 deletions(-)
diff --git a/dlls/msvcr110/tests/msvcr110.c b/dlls/msvcr110/tests/msvcr110.c index e87b2508943..2afdc419641 100644 --- a/dlls/msvcr110/tests/msvcr110.c +++ b/dlls/msvcr110/tests/msvcr110.c @@ -166,25 +166,25 @@ static void test_setlocale(void) ret = p_setlocale(LC_ALL, "chinese"); ok(ret != NULL, "expected success, but got NULL\n"); if (ret) - todo_wine ok(!strcmp(ret, "Chinese_China.936"), "setlocale chinese failed, got %s\n", ret); + ok(!strcmp(ret, "Chinese_China.936"), "setlocale chinese failed, got %s\n", ret);
/* used to return Chinese (Simplified)_China.936 */ ret = p_setlocale(LC_ALL, "Chinese_China.936"); ok(ret != NULL, "expected success, but got NULL\n"); if (ret) - todo_wine ok(!strcmp(ret, "Chinese_China.936"), "setlocale Chinese_China.936 failed, got %s\n", ret); + ok(!strcmp(ret, "Chinese_China.936"), "setlocale Chinese_China.936 failed, got %s\n", ret);
/* used to return Chinese (Simplified)_China.936 */ ret = p_setlocale(LC_ALL, "chinese-simplified"); ok(ret != NULL, "expected success, but got NULL\n"); if (ret) - todo_wine ok(!strcmp(ret, "Chinese_China.936"), "setlocale chinese-simplified failed, got %s\n", ret); + ok(!strcmp(ret, "Chinese_China.936"), "setlocale chinese-simplified failed, got %s\n", ret);
/* used to return Chinese (Simplified)_China.936 */ ret = p_setlocale(LC_ALL, "chs"); ok(ret != NULL, "expected success, but got NULL\n"); if (ret) - todo_wine ok(!strcmp(ret, "Chinese_China.936"), "setlocale chs failed, got %s\n", ret); + ok(!strcmp(ret, "Chinese_China.936"), "setlocale chs failed, got %s\n", ret);
/* used to return Chinese (Traditional)_Taiwan.950 */ ret = p_setlocale(LC_ALL, "cht"); diff --git a/dlls/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c index 1508994ca79..838338c83f8 100644 --- a/dlls/msvcr120/tests/msvcr120.c +++ b/dlls/msvcr120/tests/msvcr120.c @@ -567,6 +567,7 @@ static void test____lc_locale_name_func(void) const WCHAR broken_name[10]; } tests[] = { { "American", {'e','n',0}, {'e','n','-','U','S',0} }, + { "Belgian", {'n','l','-','B','E',0} }, { "Chinese", {'z','h',0}, {'z','h','-','C','N',0} }, { "Dutch", {'n','l',0}, {'n','l','-','N','L',0} }, { "English", {'e','n',0}, {'e','n','-','U','S',0} }, @@ -586,7 +587,7 @@ static void test____lc_locale_name_func(void)
lc_names = p____lc_locale_name_func(); ok(lc_names[0] == NULL, "%d - lc_names[0] = %s\n", i, wine_dbgstr_w(lc_names[0])); - todo_wine ok(!lstrcmpW(lc_names[1], tests[i].name) || broken(!lstrcmpW(lc_names[1], tests[i].broken_name)), + ok(!lstrcmpW(lc_names[1], tests[i].name) || broken(!lstrcmpW(lc_names[1], tests[i].broken_name)), "%d - lc_names[1] = %s\n", i, wine_dbgstr_w(lc_names[1]));
for(j=LC_MIN+2; j<=LC_MAX; j++) { @@ -595,17 +596,13 @@ static void test____lc_locale_name_func(void) } }
- p_setlocale(LC_ALL, "Belgian"); - lc_names = p____lc_locale_name_func(); - ok(!lstrcmpW(lc_names[1], L"nl-BE"), "lc_names[1] expected nl-BE got %s\n", wine_dbgstr_w(lc_names[1])); - p_setlocale(LC_ALL, "zh-Hans"); lc_names = p____lc_locale_name_func(); - todo_wine ok(!lstrcmpW(lc_names[1], L"zh-Hans"), "lc_names[1] expected zh-Hans got %s\n", wine_dbgstr_w(lc_names[1])); + ok(!lstrcmpW(lc_names[1], L"zh-Hans"), "lc_names[1] expected zh-Hans got %s\n", wine_dbgstr_w(lc_names[1]));
p_setlocale(LC_ALL, "zh-Hant"); lc_names = p____lc_locale_name_func(); - todo_wine ok(!lstrcmpW(lc_names[1], L"zh-Hant"), "lc_names[1] expected zh-Hant got %s\n", wine_dbgstr_w(lc_names[1])); + ok(!lstrcmpW(lc_names[1], L"zh-Hant"), "lc_names[1] expected zh-Hant got %s\n", wine_dbgstr_w(lc_names[1]));
p_setlocale(LC_ALL, "C"); lc_names = p____lc_locale_name_func(); diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index 8a617d0212d..6527e06eacd 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -24,8 +24,10 @@ #include <stdio.h> #include <stdlib.h> #include <mbctype.h> +#include <wchar.h> #include <wctype.h>
+#include "string.h" #include "windef.h" #include "winbase.h" #include "winuser.h" @@ -426,12 +428,11 @@ static void copy_threadlocinfo_category(pthreadlocinfo locinfo, locinfo->lc_category[category].refcount = old_locinfo->lc_category[category].refcount; InterlockedIncrement((LONG *)locinfo->lc_category[category].refcount); } -#if _MSVCR_VER >= 110 + locinfo->lc_name[category] = old_locinfo->lc_name[category]; locinfo->lc_category[category].wrefcount = old_locinfo->lc_category[category].wrefcount; if(locinfo->lc_category[category].wrefcount) InterlockedIncrement((LONG *)locinfo->lc_category[category].wrefcount); -#endif }
static BOOL init_category_name(const char *name, int len, @@ -454,46 +455,30 @@ static BOOL init_category_name(const char *name, int len, return TRUE; }
-#if _MSVCR_VER >= 110 -static inline BOOL set_lc_locale_name(pthreadlocinfo locinfo, int cat) +static inline BOOL set_lc_locale_name(pthreadlocinfo locinfo, int cat, WCHAR *sname) { - LCID lcid = locinfo->lc_handle[cat]; - WCHAR buf[100]; - int len; + int len = wcslen(sname);
locinfo->lc_category[cat].wrefcount = malloc(sizeof(int)); if(!locinfo->lc_category[cat].wrefcount) return FALSE; *locinfo->lc_category[cat].wrefcount = 1;
- len = GetLocaleInfoW(lcid, LOCALE_SISO639LANGNAME - |LOCALE_NOUSEROVERRIDE, buf, 100); - if(!len) return FALSE; - - if(LocaleNameToLCID(buf, 0) != lcid) - len = LCIDToLocaleName(lcid, buf, 100, 0); - if(!len || !(locinfo->lc_name[cat] = malloc(len*sizeof(wchar_t)))) return FALSE;
- memcpy(locinfo->lc_name[cat], buf, len*sizeof(wchar_t)); - return TRUE; -} -#else -static inline BOOL set_lc_locale_name(pthreadlocinfo locinfo, int cat) -{ + wcscpy(locinfo->lc_name[cat], sname); return TRUE; } -#endif
/* INTERNAL: Set lc_handle, lc_id and lc_category in threadlocinfo struct */ -static BOOL update_threadlocinfo_category(LCID lcid, unsigned short cp, +static BOOL update_threadlocinfo_category(WCHAR *sname, unsigned short cp, pthreadlocinfo locinfo, int category) { - char buf[256], *p; + WCHAR wbuf[256], *p;
- if(GetLocaleInfoA(lcid, LOCALE_ILANGUAGE|LOCALE_NOUSEROVERRIDE, buf, 256)) { - p = buf; + if(GetLocaleInfoEx(sname, LOCALE_ILANGUAGE|LOCALE_NOUSEROVERRIDE, wbuf, 256)) { + p = wbuf;
locinfo->lc_id[category].wLanguage = 0; while(*p) { @@ -513,28 +498,29 @@ static BOOL update_threadlocinfo_category(LCID lcid, unsigned short cp,
locinfo->lc_id[category].wCodePage = cp;
- locinfo->lc_handle[category] = lcid; + locinfo->lc_handle[category] = LocaleNameToLCID(sname, LOCALE_ALLOW_NEUTRAL_NAMES);
- set_lc_locale_name(locinfo, category); + set_lc_locale_name(locinfo, category, sname);
if(!locinfo->lc_category[category].locale) { - /* new norwegian nynorsk LCID */ - static const LCID norwegian_nynorsk_lcid = 0x7814; + char buf[256]; int len = 0;
- if (lcid == norwegian_nynorsk_lcid) + if (!wcscmp(sname, L"nn")) { /* locale.nls contains "Norwegian Nynorsk" instead for LOCALE_SENGLANGUAGE */ - strcpy( buf, "Norwegian-Nynorsk" ); - len = strlen( buf ) + 1; + wcscpy( wbuf, L"Norwegian-Nynorsk" ); + len = wcslen( wbuf ) + 1; } - else len += GetLocaleInfoA(lcid, LOCALE_SENGLANGUAGE|LOCALE_NOUSEROVERRIDE, buf, 256); - buf[len-1] = '_'; - len += GetLocaleInfoA(lcid, LOCALE_SENGCOUNTRY - |LOCALE_NOUSEROVERRIDE, &buf[len], 256-len); - buf[len-1] = '.'; - sprintf(buf+len, "%d", cp); - len += strlen(buf+len); + else len += GetLocaleInfoEx(sname, LOCALE_SENGLANGUAGE|LOCALE_NOUSEROVERRIDE, wbuf, 256); + wbuf[len-1] = '_'; + len += GetLocaleInfoEx(sname, LOCALE_SENGCOUNTRY + |LOCALE_NOUSEROVERRIDE, &wbuf[len], 256-len); + wbuf[len-1] = '.'; + swprintf(wbuf+len, 256 - len,L"%d", cp); + len += wcslen(wbuf+len); + + WideCharToMultiByte(CP_ACP, 0, wbuf, -1, buf, 256, NULL, NULL);
return init_category_name(buf, len, locinfo, category); } @@ -1164,13 +1150,14 @@ void CDECL _free_locale(_locale_t locale) }
static inline BOOL category_needs_update(int cat, - const threadlocinfo *locinfo, LCID lcid, unsigned short cp) + const threadlocinfo *locinfo, WCHAR *sname, unsigned short cp) { if(!locinfo) return TRUE; - return lcid!=locinfo->lc_handle[cat] || cp!=locinfo->lc_id[cat].wCodePage; + if(!locinfo->lc_name[cat] || !sname) return TRUE; + return wcscmp(sname, locinfo->lc_name[cat]) != 0 || cp!=locinfo->lc_id[cat].wCodePage; }
-static __lc_time_data* create_time_data(LCID lcid) +static __lc_time_data* create_time_data(WCHAR *sname) { static const DWORD time_data[] = { LOCALE_SABBREVDAYNAME7, LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2, @@ -1192,6 +1179,7 @@ static __lc_time_data* create_time_data(LCID lcid)
__lc_time_data *cur; int i, ret, size; + LCID lcid = LocaleNameToLCID(sname, LOCALE_ALLOW_NEUTRAL_NAMES);
size = sizeof(__lc_time_data); for(i=0; i<ARRAY_SIZE(time_data); i++) { @@ -1201,14 +1189,14 @@ static __lc_time_data* create_time_data(LCID lcid) size += ret;
#if _MSVCR_VER == 0 || _MSVCR_VER >= 100 - ret = GetLocaleInfoW(lcid, time_data[i], NULL, 0); + ret = GetLocaleInfoEx(sname, time_data[i], NULL, 0); if(!ret) return NULL; size += ret*sizeof(wchar_t); #endif } #if _MSVCR_VER >= 110 - size += LCIDToLocaleName(lcid, NULL, 0, 0)*sizeof(wchar_t); + size += wcslen(sname)*sizeof(wchar_t); #endif
cur = malloc(size); @@ -1223,13 +1211,13 @@ static __lc_time_data* create_time_data(LCID lcid) #if _MSVCR_VER == 0 || _MSVCR_VER >= 100 for(i=0; i<ARRAY_SIZE(time_data); i++) { cur->wstr.wstr[i] = (wchar_t*)&cur->data[ret]; - ret += GetLocaleInfoW(lcid, time_data[i], + ret += GetLocaleInfoEx(sname, time_data[i], (wchar_t*)&cur->data[ret], size-ret)*sizeof(wchar_t); } #endif #if _MSVCR_VER >= 110 cur->locname = (wchar_t*)&cur->data[ret]; - LCIDToLocaleName(lcid, (wchar_t*)&cur->data[ret], (size-ret)/sizeof(wchar_t), 0); + wcsncpy((wchar_t *) &cur->data[ret], sname, size-ret); #else cur->lcid = lcid; #endif @@ -1248,25 +1236,23 @@ static pthreadlocinfo create_locinfo(int category, static const char numeric[] = "NUMERIC="; static const char time[] = "TIME=";
- pthreadlocinfo locinfo; - LCID lcid[6] = { 0 }; + pthreadlocinfo locinfo = NULL; unsigned short cp[6] = { 0 }; const char *locale_name[6] = { 0 }; + WCHAR *locale_sname[6] = { 0 }; int val, locale_len[6] = { 0 }; char buf[256]; BOOL sname_match; -#if _MSVCR_VER >= 100 wchar_t wbuf[256]; -#endif int i;
TRACE("(%d %s)\n", category, locale);
if(category<LC_MIN || category>LC_MAX || !locale) - return NULL; + goto fail;
if(locale[0]=='C' && !locale[1]) { - lcid[0] = 0; + locale_sname[0] = NULL; cp[0] = CP_ACP; } else if (locale[0] == 'L' && locale[1] == 'C' && locale[2] == '_') { const char *p; @@ -1290,29 +1276,25 @@ static pthreadlocinfo create_locinfo(int category, i = LC_TIME; locale += sizeof(time)-1; } else - return NULL; + goto fail;
p = strchr(locale, ';'); if(locale[0]=='C' && (locale[1]==';' || locale[1]=='\0')) { - lcid[i] = 0; + locale_sname[i] = NULL; cp[i] = CP_ACP; ok = TRUE; } else if(p) { - WCHAR wbuf[LOCALE_NAME_MAX_LENGTH] = { 0 }; - memcpy(buf, locale, p-locale); buf[p-locale] = '\0'; ok = locale_to_sname(buf, &cp[i], &sname_match, wbuf, LOCALE_NAME_MAX_LENGTH); - lcid[i] = LocaleNameToLCID(wbuf, LOCALE_ALLOW_NEUTRAL_NAMES); + locale_sname[i] = wcsdup(wbuf); if(sname_match) { locale_name[i] = locale; locale_len[i] = p-locale; } } else { - WCHAR wbuf[LOCALE_NAME_MAX_LENGTH] = { 0 }; - ok = locale_to_sname(buf, &cp[i], &sname_match, wbuf, LOCALE_NAME_MAX_LENGTH); - lcid[i] = LocaleNameToLCID(wbuf, LOCALE_ALLOW_NEUTRAL_NAMES); + locale_sname[i] = wcsdup(wbuf); if(sname_match) { locale_name[i] = locale; locale_len[i] = strlen(locale); @@ -1320,7 +1302,7 @@ static pthreadlocinfo create_locinfo(int category, }
if(!ok) - return NULL; + goto fail;
if(!p || *(p+1)!='L' || *(p+2)!='C' || *(p+3)!='_') break; @@ -1328,20 +1310,19 @@ static pthreadlocinfo create_locinfo(int category, locale = p+1; } } else { - WCHAR wbuf[LOCALE_NAME_MAX_LENGTH] = { 0 }; BOOL ok = FALSE;
ok = locale_to_sname(locale, &cp[0], &sname_match, wbuf, LOCALE_NAME_MAX_LENGTH); - lcid[0] = LocaleNameToLCID(wbuf, LOCALE_ALLOW_NEUTRAL_NAMES); + locale_sname[0] = wcsdup(wbuf); if(!ok) - return NULL; + goto fail; if(sname_match) { locale_name[0] = locale; locale_len[0] = strlen(locale); }
for(i=1; i<6; i++) { - lcid[i] = lcid[0]; + locale_sname[i] = wcsdup(locale_sname[0]); cp[i] = cp[0]; locale_name[i] = locale_name[0]; locale_len[i] = locale_len[0]; @@ -1353,16 +1334,16 @@ static pthreadlocinfo create_locinfo(int category, if(i==LC_CTYPE && cp[i]==CP_UTF8) { locale_name[i] = NULL; locale_len[i] = 0; - lcid[i] = old_locinfo ? old_locinfo->lc_handle[i] : 0; + locale_sname[i] = old_locinfo ? wcsdup(old_locinfo->lc_name[i]) : NULL; cp[i] = old_locinfo ? old_locinfo->lc_id[i].wCodePage : 0; } #endif if(category!=LC_ALL && category!=i) { if(old_locinfo) { - lcid[i] = old_locinfo->lc_handle[i]; + locale_sname[i] = old_locinfo ? wcsdup(old_locinfo->lc_name[i]) : NULL; cp[i] = old_locinfo->lc_id[i].wCodePage; } else { - lcid[i] = 0; + locale_sname[i] = NULL; cp[i] = 0; } } @@ -1370,7 +1351,7 @@ static pthreadlocinfo create_locinfo(int category,
locinfo = malloc(sizeof(threadlocinfo)); if(!locinfo) - return NULL; + goto fail;
memset(locinfo, 0, sizeof(threadlocinfo)); locinfo->refcount = 1; @@ -1378,38 +1359,34 @@ static pthreadlocinfo create_locinfo(int category, if(locale_name[LC_COLLATE] && !init_category_name(locale_name[LC_COLLATE], locale_len[LC_COLLATE], locinfo, LC_COLLATE)) { - free_locinfo(locinfo); - return NULL; + goto fail; }
if(!category_needs_update(LC_COLLATE, old_locinfo, - lcid[LC_COLLATE], cp[LC_COLLATE])) { + locale_sname[LC_COLLATE], cp[LC_COLLATE])) { copy_threadlocinfo_category(locinfo, old_locinfo, LC_COLLATE); locinfo->lc_collate_cp = old_locinfo->lc_collate_cp; - } else if(lcid[LC_COLLATE]) { - if(!update_threadlocinfo_category(lcid[LC_COLLATE], + } else if(locale_sname[LC_COLLATE]) { + if(!update_threadlocinfo_category(locale_sname[LC_COLLATE], cp[LC_COLLATE], locinfo, LC_COLLATE)) { - free_locinfo(locinfo); - return NULL; + goto fail; }
locinfo->lc_collate_cp = locinfo->lc_id[LC_COLLATE].wCodePage; } else { if(!init_category_name("C", 1, locinfo, LC_COLLATE)) { - free_locinfo(locinfo); - return NULL; + goto fail; } }
if(locale_name[LC_CTYPE] && !init_category_name(locale_name[LC_CTYPE], locale_len[LC_CTYPE], locinfo, LC_CTYPE)) { - free_locinfo(locinfo); - return NULL; + goto fail; }
if(!category_needs_update(LC_CTYPE, old_locinfo, - lcid[LC_CTYPE], cp[LC_CTYPE])) { + locale_sname[LC_CTYPE], cp[LC_CTYPE])) { copy_threadlocinfo_category(locinfo, old_locinfo, LC_CTYPE); locinfo->lc_codepage = old_locinfo->lc_codepage; locinfo->lc_clike = old_locinfo->lc_clike; @@ -1421,28 +1398,25 @@ static pthreadlocinfo create_locinfo(int category, locinfo->pcumap = old_locinfo->pcumap; if(locinfo->ctype1_refcount) InterlockedIncrement((LONG *)locinfo->ctype1_refcount); - } else if(lcid[LC_CTYPE]) { + } else if(locale_sname[LC_CTYPE]) { CPINFO cp_info; int j;
- if(!update_threadlocinfo_category(lcid[LC_CTYPE], + if(!update_threadlocinfo_category(locale_sname[LC_CTYPE], cp[LC_CTYPE], locinfo, LC_CTYPE)) { - free_locinfo(locinfo); - return NULL; + goto fail; }
locinfo->lc_codepage = locinfo->lc_id[LC_CTYPE].wCodePage; locinfo->lc_clike = 1; if(!GetCPInfo(locinfo->lc_codepage, &cp_info)) { - free_locinfo(locinfo); - return NULL; + goto fail; } locinfo->mb_cur_max = cp_info.MaxCharSize;
locinfo->ctype1_refcount = malloc(sizeof(int)); if(!locinfo->ctype1_refcount) { - free_locinfo(locinfo); - return NULL; + goto fail; } *locinfo->ctype1_refcount = 1;
@@ -1450,8 +1424,7 @@ static pthreadlocinfo create_locinfo(int category, locinfo->pclmap = malloc(sizeof(char[256])); locinfo->pcumap = malloc(sizeof(char[256])); if(!locinfo->ctype1 || !locinfo->pclmap || !locinfo->pcumap) { - free_locinfo(locinfo); - return NULL; + goto fail; }
locinfo->ctype1[0] = 0; @@ -1464,7 +1437,7 @@ static pthreadlocinfo create_locinfo(int category, /* builtin GetStringTypeA doesn't set output to 0 on invalid input */ locinfo->ctype1[i] = 0;
- GetStringTypeA(lcid[LC_CTYPE], CT_CTYPE1, buf, + GetStringTypeA(locinfo->lc_handle[LC_CTYPE], CT_CTYPE1, buf, 1, locinfo->ctype1+i); }
@@ -1479,9 +1452,9 @@ static pthreadlocinfo create_locinfo(int category, buf[i] = i; }
- LCMapStringA(lcid[LC_CTYPE], LCMAP_LOWERCASE, buf, 256, + LCMapStringA(locinfo->lc_handle[LC_CTYPE], LCMAP_LOWERCASE, buf, 256, (char*)locinfo->pclmap, 256); - LCMapStringA(lcid[LC_CTYPE], LCMAP_UPPERCASE, buf, 256, + LCMapStringA(locinfo->lc_handle[LC_CTYPE], LCMAP_UPPERCASE, buf, 256, (char*)locinfo->pcumap, 256); } else { locinfo->lc_clike = 1; @@ -1490,20 +1463,19 @@ static pthreadlocinfo create_locinfo(int category, locinfo->pclmap = cloc_clmap; locinfo->pcumap = cloc_cumap; if(!init_category_name("C", 1, locinfo, LC_CTYPE)) { - free_locinfo(locinfo); - return NULL; + goto fail; } }
if(!category_needs_update(LC_MONETARY, old_locinfo, - lcid[LC_MONETARY], cp[LC_MONETARY]) && + locale_sname[LC_MONETARY], cp[LC_MONETARY]) && !category_needs_update(LC_NUMERIC, old_locinfo, - lcid[LC_NUMERIC], cp[LC_NUMERIC])) { + locale_sname[LC_NUMERIC], cp[LC_NUMERIC])) { locinfo->lconv = old_locinfo->lconv; locinfo->lconv_intl_refcount = old_locinfo->lconv_intl_refcount; if(locinfo->lconv_intl_refcount) InterlockedIncrement((LONG *)locinfo->lconv_intl_refcount); - } else if(lcid[LC_MONETARY] || lcid[LC_NUMERIC]) { + } else if(locale_sname[LC_MONETARY] || locale_sname[LC_NUMERIC]) { locinfo->lconv = malloc(sizeof(struct lconv)); locinfo->lconv_intl_refcount = malloc(sizeof(int)); if(!locinfo->lconv || !locinfo->lconv_intl_refcount) { @@ -1511,8 +1483,7 @@ static pthreadlocinfo create_locinfo(int category, free(locinfo->lconv_intl_refcount); locinfo->lconv = NULL; locinfo->lconv_intl_refcount = NULL; - free_locinfo(locinfo); - return NULL; + goto fail; } memset(locinfo->lconv, 0, sizeof(struct lconv)); *locinfo->lconv_intl_refcount = 1; @@ -1523,12 +1494,11 @@ static pthreadlocinfo create_locinfo(int category, if(locale_name[LC_MONETARY] && !init_category_name(locale_name[LC_MONETARY], locale_len[LC_MONETARY], locinfo, LC_MONETARY)) { - free_locinfo(locinfo); - return NULL; + goto fail; }
if(!category_needs_update(LC_MONETARY, old_locinfo, - lcid[LC_MONETARY], cp[LC_MONETARY])) { + locale_sname[LC_MONETARY], cp[LC_MONETARY])) { copy_threadlocinfo_category(locinfo, old_locinfo, LC_MONETARY); locinfo->lconv_mon_refcount = old_locinfo->lconv_mon_refcount; if(locinfo->lconv_mon_refcount) @@ -1558,59 +1528,58 @@ static pthreadlocinfo create_locinfo(int category, locinfo->lconv->_W_negative_sign = old_locinfo->lconv->_W_negative_sign; #endif } - } else if(lcid[LC_MONETARY]) { - if(!update_threadlocinfo_category(lcid[LC_MONETARY], + } else if(locale_sname[LC_MONETARY]) { + if(!update_threadlocinfo_category(locale_sname[LC_MONETARY], cp[LC_MONETARY], locinfo, LC_MONETARY)) { - free_locinfo(locinfo); - return NULL; + goto fail; }
locinfo->lconv_mon_refcount = malloc(sizeof(int)); if(!locinfo->lconv_mon_refcount) { - free_locinfo(locinfo); - return NULL; + goto fail; }
*locinfo->lconv_mon_refcount = 1;
- i = GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_SINTLSYMBOL - |LOCALE_NOUSEROVERRIDE, buf, 256); + i = GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_SINTLSYMBOL + |LOCALE_NOUSEROVERRIDE, wbuf, 256); + i = WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, NULL, 0, NULL, NULL); if(i && (locinfo->lconv->int_curr_symbol = malloc(i))) - memcpy(locinfo->lconv->int_curr_symbol, buf, i); + WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, locinfo->lconv->int_curr_symbol, i, NULL, NULL); else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- i = GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_SCURRENCY - |LOCALE_NOUSEROVERRIDE, buf, 256); + i = GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_SCURRENCY + |LOCALE_NOUSEROVERRIDE, wbuf, 256); + i = WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, NULL, 0, NULL, NULL); if(i && (locinfo->lconv->currency_symbol = malloc(i))) - memcpy(locinfo->lconv->currency_symbol, buf, i); + WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, locinfo->lconv->currency_symbol, i, NULL, NULL); else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- i = GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_SMONDECIMALSEP - |LOCALE_NOUSEROVERRIDE, buf, 256); + i = GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_SMONDECIMALSEP + |LOCALE_NOUSEROVERRIDE, wbuf, 256); + i = WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, NULL, 0, NULL, NULL); if(i && (locinfo->lconv->mon_decimal_point = malloc(i))) - memcpy(locinfo->lconv->mon_decimal_point, buf, i); + WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, locinfo->lconv->mon_decimal_point, i, NULL, NULL); else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- i = GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_SMONTHOUSANDSEP - |LOCALE_NOUSEROVERRIDE, buf, 256); + i = GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_SMONTHOUSANDSEP + |LOCALE_NOUSEROVERRIDE, wbuf, 256); + i = WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, NULL, 0, NULL, NULL); if(i && (locinfo->lconv->mon_thousands_sep = malloc(i))) - memcpy(locinfo->lconv->mon_thousands_sep, buf, i); + WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, locinfo->lconv->mon_thousands_sep, i, NULL, NULL); else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- i = GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_SMONGROUPING - |LOCALE_NOUSEROVERRIDE, buf, 256); + i = GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_SMONGROUPING + |LOCALE_NOUSEROVERRIDE, wbuf, 256); + WideCharToMultiByte(CP_ACP, 0, wbuf, -1, buf, 256, NULL, NULL); if(i>1) i = i/2 + (buf[i-2]=='0'?0:1); if(i && (locinfo->lconv->mon_grouping = malloc(i))) { @@ -1620,145 +1589,130 @@ static pthreadlocinfo create_locinfo(int category, if(buf[i] != '0') locinfo->lconv->mon_grouping[i/2+1] = 127; } else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- i = GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_SPOSITIVESIGN - |LOCALE_NOUSEROVERRIDE, buf, 256); + i = GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_SPOSITIVESIGN + |LOCALE_NOUSEROVERRIDE, wbuf, 256); + i = WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, NULL, 0, NULL, NULL); if(i && (locinfo->lconv->positive_sign = malloc(i))) - memcpy(locinfo->lconv->positive_sign, buf, i); + WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, locinfo->lconv->positive_sign, i, NULL, NULL); else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- i = GetLocaleInfoA(lcid[LC_MONETARY], LOCALE_SNEGATIVESIGN - |LOCALE_NOUSEROVERRIDE, buf, 256); + i = GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_SNEGATIVESIGN + |LOCALE_NOUSEROVERRIDE, wbuf, 256); + i = WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, NULL, 0, NULL, NULL); if(i && (locinfo->lconv->negative_sign = malloc(i))) - memcpy(locinfo->lconv->negative_sign, buf, i); + WideCharToMultiByte(cp[LC_MONETARY], 0, wbuf, -1, locinfo->lconv->negative_sign, i, NULL, NULL); else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- if(GetLocaleInfoW(lcid[LC_MONETARY], LOCALE_IINTLCURRDIGITS + if(GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_IINTLCURRDIGITS |LOCALE_NOUSEROVERRIDE|LOCALE_RETURN_NUMBER, (WCHAR *)&val, 2)) locinfo->lconv->int_frac_digits = val; else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- if(GetLocaleInfoW(lcid[LC_MONETARY], LOCALE_ICURRDIGITS + if(GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_ICURRDIGITS |LOCALE_NOUSEROVERRIDE|LOCALE_RETURN_NUMBER, (WCHAR *)&val, 2)) locinfo->lconv->frac_digits = val; else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- if(GetLocaleInfoW(lcid[LC_MONETARY], LOCALE_IPOSSYMPRECEDES + if(GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_IPOSSYMPRECEDES |LOCALE_NOUSEROVERRIDE|LOCALE_RETURN_NUMBER, (WCHAR *)&val, 2)) locinfo->lconv->p_cs_precedes = val; else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- if(GetLocaleInfoW(lcid[LC_MONETARY], LOCALE_IPOSSEPBYSPACE + if(GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_IPOSSEPBYSPACE |LOCALE_NOUSEROVERRIDE|LOCALE_RETURN_NUMBER, (WCHAR *)&val, 2)) locinfo->lconv->p_sep_by_space = val; else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- if(GetLocaleInfoW(lcid[LC_MONETARY], LOCALE_INEGSYMPRECEDES + if(GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_INEGSYMPRECEDES |LOCALE_NOUSEROVERRIDE|LOCALE_RETURN_NUMBER, (WCHAR *)&val, 2)) locinfo->lconv->n_cs_precedes = val; else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- if(GetLocaleInfoW(lcid[LC_MONETARY], LOCALE_INEGSEPBYSPACE + if(GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_INEGSEPBYSPACE |LOCALE_NOUSEROVERRIDE|LOCALE_RETURN_NUMBER, (WCHAR *)&val, 2)) locinfo->lconv->n_sep_by_space = val; else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- if(GetLocaleInfoW(lcid[LC_MONETARY], LOCALE_IPOSSIGNPOSN + if(GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_IPOSSIGNPOSN |LOCALE_NOUSEROVERRIDE|LOCALE_RETURN_NUMBER, (WCHAR *)&val, 2)) locinfo->lconv->p_sign_posn = val; else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- if(GetLocaleInfoW(lcid[LC_MONETARY], LOCALE_INEGSIGNPOSN + if(GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_INEGSIGNPOSN |LOCALE_NOUSEROVERRIDE|LOCALE_RETURN_NUMBER, (WCHAR *)&val, 2)) locinfo->lconv->n_sign_posn = val; else { - free_locinfo(locinfo); - return NULL; + goto fail; }
#if _MSVCR_VER >= 100 - i = GetLocaleInfoW(lcid[LC_MONETARY], LOCALE_SINTLSYMBOL + i = GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_SINTLSYMBOL |LOCALE_NOUSEROVERRIDE, wbuf, 256); if(i && (locinfo->lconv->_W_int_curr_symbol = malloc(i * sizeof(wchar_t)))) memcpy(locinfo->lconv->_W_int_curr_symbol, wbuf, i * sizeof(wchar_t)); else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- i = GetLocaleInfoW(lcid[LC_MONETARY], LOCALE_SCURRENCY + i = GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_SCURRENCY |LOCALE_NOUSEROVERRIDE, wbuf, 256); if(i && (locinfo->lconv->_W_currency_symbol = malloc(i * sizeof(wchar_t)))) memcpy(locinfo->lconv->_W_currency_symbol, wbuf, i * sizeof(wchar_t)); else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- i = GetLocaleInfoW(lcid[LC_MONETARY], LOCALE_SMONDECIMALSEP + i = GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_SMONDECIMALSEP |LOCALE_NOUSEROVERRIDE, wbuf, 256); if(i && (locinfo->lconv->_W_mon_decimal_point = malloc(i * sizeof(wchar_t)))) memcpy(locinfo->lconv->_W_mon_decimal_point, wbuf, i * sizeof(wchar_t)); else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- i = GetLocaleInfoW(lcid[LC_MONETARY], LOCALE_SMONTHOUSANDSEP + i = GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_SMONTHOUSANDSEP |LOCALE_NOUSEROVERRIDE, wbuf, 256); if(i && (locinfo->lconv->_W_mon_thousands_sep = malloc(i * sizeof(wchar_t)))) memcpy(locinfo->lconv->_W_mon_thousands_sep, wbuf, i * sizeof(wchar_t)); else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- i = GetLocaleInfoW(lcid[LC_MONETARY], LOCALE_SPOSITIVESIGN + i = GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_SPOSITIVESIGN |LOCALE_NOUSEROVERRIDE, wbuf, 256); if(i && (locinfo->lconv->_W_positive_sign = malloc(i * sizeof(wchar_t)))) memcpy(locinfo->lconv->_W_positive_sign, wbuf, i * sizeof(wchar_t)); else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- i = GetLocaleInfoW(lcid[LC_MONETARY], LOCALE_SNEGATIVESIGN + i = GetLocaleInfoEx(locale_sname[LC_MONETARY], LOCALE_SNEGATIVESIGN |LOCALE_NOUSEROVERRIDE, wbuf, 256); if(i && (locinfo->lconv->_W_negative_sign = malloc(i * sizeof(wchar_t)))) memcpy(locinfo->lconv->_W_negative_sign, wbuf, i * sizeof(wchar_t)); else { - free_locinfo(locinfo); - return NULL; + goto fail; } #endif } else { @@ -1790,20 +1744,18 @@ static pthreadlocinfo create_locinfo(int category, }
if(!init_category_name("C", 1, locinfo, LC_MONETARY)) { - free_locinfo(locinfo); - return NULL; + goto fail; } }
if(locale_name[LC_NUMERIC] && !init_category_name(locale_name[LC_NUMERIC], locale_len[LC_NUMERIC], locinfo, LC_NUMERIC)) { - free_locinfo(locinfo); - return NULL; + goto fail; }
if(!category_needs_update(LC_NUMERIC, old_locinfo, - lcid[LC_NUMERIC], cp[LC_NUMERIC])) { + locale_sname[LC_NUMERIC], cp[LC_NUMERIC])) { copy_threadlocinfo_category(locinfo, old_locinfo, LC_NUMERIC); locinfo->lconv_num_refcount = old_locinfo->lconv_num_refcount; if(locinfo->lconv_num_refcount) @@ -1817,41 +1769,40 @@ static pthreadlocinfo create_locinfo(int category, locinfo->lconv->_W_thousands_sep = old_locinfo->lconv->_W_thousands_sep; #endif } - } else if(lcid[LC_NUMERIC]) { - if(!update_threadlocinfo_category(lcid[LC_NUMERIC], + } else if(locale_sname[LC_NUMERIC]) { + if(!update_threadlocinfo_category(locale_sname[LC_NUMERIC], cp[LC_NUMERIC], locinfo, LC_NUMERIC)) { - free_locinfo(locinfo); - return NULL; + goto fail; }
locinfo->lconv_num_refcount = malloc(sizeof(int)); if(!locinfo->lconv_num_refcount) { - free_locinfo(locinfo); - return NULL; + goto fail; }
*locinfo->lconv_num_refcount = 1;
- i = GetLocaleInfoA(lcid[LC_NUMERIC], LOCALE_SDECIMAL - |LOCALE_NOUSEROVERRIDE, buf, 256); + i = GetLocaleInfoEx(locale_sname[LC_NUMERIC], LOCALE_SDECIMAL + |LOCALE_NOUSEROVERRIDE, wbuf, 256); + i = WideCharToMultiByte(cp[LC_NUMERIC], 0, wbuf, -1, NULL, 0, NULL, NULL); if(i && (locinfo->lconv->decimal_point = malloc(i))) - memcpy(locinfo->lconv->decimal_point, buf, i); + WideCharToMultiByte(cp[LC_NUMERIC], 0, wbuf, -1, locinfo->lconv->decimal_point, i, NULL, NULL); else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- i = GetLocaleInfoA(lcid[LC_NUMERIC], LOCALE_STHOUSAND - |LOCALE_NOUSEROVERRIDE, buf, 256); + i = GetLocaleInfoEx(locale_sname[LC_NUMERIC], LOCALE_STHOUSAND + |LOCALE_NOUSEROVERRIDE, wbuf, 256); + i = WideCharToMultiByte(cp[LC_NUMERIC], 0, wbuf, -1, NULL, 0, NULL, NULL); if(i && (locinfo->lconv->thousands_sep = malloc(i))) - memcpy(locinfo->lconv->thousands_sep, buf, i); + WideCharToMultiByte(cp[LC_NUMERIC], 0, wbuf, -1, locinfo->lconv->thousands_sep, i, NULL, NULL); else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- i = GetLocaleInfoA(lcid[LC_NUMERIC], LOCALE_SGROUPING - |LOCALE_NOUSEROVERRIDE, buf, 256); + i = GetLocaleInfoEx(locale_sname[LC_NUMERIC], LOCALE_SGROUPING + |LOCALE_NOUSEROVERRIDE, wbuf, 256); + WideCharToMultiByte(cp[LC_NUMERIC], 0, wbuf, -1, buf, 256, NULL, NULL); if(i>1) i = i/2 + (buf[i-2]=='0'?0:1); if(i && (locinfo->lconv->grouping = malloc(i))) { @@ -1861,27 +1812,24 @@ static pthreadlocinfo create_locinfo(int category, if(buf[i] != '0') locinfo->lconv->grouping[i/2+1] = 127; } else { - free_locinfo(locinfo); - return NULL; + goto fail; }
#if _MSVCR_VER >= 100 - i = GetLocaleInfoW(lcid[LC_NUMERIC], LOCALE_SDECIMAL + i = GetLocaleInfoEx(locale_sname[LC_NUMERIC], LOCALE_SDECIMAL |LOCALE_NOUSEROVERRIDE, wbuf, 256); if(i && (locinfo->lconv->_W_decimal_point = malloc(i * sizeof(wchar_t)))) memcpy(locinfo->lconv->_W_decimal_point, wbuf, i * sizeof(wchar_t)); else { - free_locinfo(locinfo); - return NULL; + goto fail; }
- i = GetLocaleInfoW(lcid[LC_NUMERIC], LOCALE_STHOUSAND + i = GetLocaleInfoEx(locale_sname[LC_NUMERIC], LOCALE_STHOUSAND |LOCALE_NOUSEROVERRIDE, wbuf, 256); if(i && (locinfo->lconv->_W_thousands_sep = malloc(i * sizeof(wchar_t)))) memcpy(locinfo->lconv->_W_thousands_sep, wbuf, i * sizeof(wchar_t)); else { - free_locinfo(locinfo); - return NULL; + goto fail; } #endif } else { @@ -1897,45 +1845,48 @@ static pthreadlocinfo create_locinfo(int category, }
if (!init_category_name("C", 1, locinfo, LC_NUMERIC)) { - free_locinfo(locinfo); - return NULL; + goto fail; } }
if(locale_name[LC_TIME] && !init_category_name(locale_name[LC_TIME], locale_len[LC_TIME], locinfo, LC_TIME)) { - free_locinfo(locinfo); - return NULL; + goto fail; }
if(!category_needs_update(LC_TIME, old_locinfo, - lcid[LC_TIME], cp[LC_TIME])) { + locale_sname[LC_TIME], cp[LC_TIME])) { copy_threadlocinfo_category(locinfo, old_locinfo, LC_TIME); locinfo->lc_time_curr = old_locinfo->lc_time_curr; InterlockedIncrement(&locinfo->lc_time_curr->refcount); - } else if(lcid[LC_TIME]) { - if(!update_threadlocinfo_category(lcid[LC_TIME], + } else if(locale_sname[LC_TIME]) { + if(!update_threadlocinfo_category(locale_sname[LC_TIME], cp[LC_TIME], locinfo, LC_TIME)) { - free_locinfo(locinfo); - return NULL; + goto fail; }
- locinfo->lc_time_curr = create_time_data(lcid[LC_TIME]); + locinfo->lc_time_curr = create_time_data(locale_sname[LC_TIME]); if(!locinfo->lc_time_curr) { - free_locinfo(locinfo); - return NULL; + goto fail; } } else { if(!init_category_name("C", 1, locinfo, LC_TIME)) { - free_locinfo(locinfo); - return NULL; + goto fail; } locinfo->lc_time_curr = &cloc_time_data; InterlockedIncrement(&locinfo->lc_time_curr->refcount); }
return locinfo; + +fail: + free_locinfo(locinfo); + + for (i = 0; i < LC_MAX; i++) + free(locale_sname[i]); + + return NULL; }
/********************************************************************* diff --git a/dlls/msvcrt/tests/locale.c b/dlls/msvcrt/tests/locale.c index 56fe17f2f68..95c468bc140 100644 --- a/dlls/msvcrt/tests/locale.c +++ b/dlls/msvcrt/tests/locale.c @@ -114,14 +114,14 @@ static void test_setlocale(void) ret = setlocale(LC_ALL, "chinese"); ok(ret != NULL || broken (ret == NULL), "ret == NULL\n"); if(ret) - ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936") + todo_wine ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936") || !strcmp(ret, "Chinese (Simplified)_China.936") || broken(!strcmp(ret, "Chinese_Taiwan.950")), "ret = %s\n", ret);
ret = setlocale(LC_ALL, "chinese-simplified"); ok(ret != NULL || broken (ret == NULL), "ret == NULL\n"); if(ret) - ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936") + todo_wine ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936") || !strcmp(ret, "Chinese (Simplified)_China.936") || broken(!strcmp(ret, "Chinese_People's Republic of China.936")) || broken(!strcmp(ret, "Chinese_Taiwan.950")), "ret = %s\n", ret); @@ -135,7 +135,7 @@ static void test_setlocale(void) ret = setlocale(LC_ALL, "chs"); ok(ret != NULL || broken (ret == NULL), "ret == NULL\n"); if(ret) - ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936") + todo_wine ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936") || !strcmp(ret, "Chinese (Simplified)_China.936") || broken(!strcmp(ret, "Chinese_People's Republic of China.936")), "ret = %s\n", ret);
@@ -150,7 +150,7 @@ static void test_setlocale(void) if(ret) { trace("Chinese_China.936=%s\n", ret); - ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936") /* Vista - Win7 */ + todo_wine ok(!strcmp(ret, "Chinese (Simplified)_People's Republic of China.936") /* Vista - Win7 */ || !strcmp(ret, "Chinese (Simplified)_China.936") /* Win8 - Win10 */ || broken(!strcmp(ret, "Chinese_People's Republic of China.936")), "ret = %s\n", ret); } diff --git a/include/msvcrt/corecrt.h b/include/msvcrt/corecrt.h index 9ad707824ff..6b2d86b9acf 100644 --- a/include/msvcrt/corecrt.h +++ b/include/msvcrt/corecrt.h @@ -316,9 +316,7 @@ typedef struct threadlocaleinfostruct { const unsigned char *pclmap; const unsigned char *pcumap; struct __lc_time_data *lc_time_curr; -#if _MSVCR_VER >= 110 wchar_t *lc_name[6]; -#endif } threadlocinfo; #define _THREADLOCALEINFO #endif