From: Victor Chiletto vchiletto@codeweavers.com
--- dlls/msvcrt/locale.c | 66 +++++++++++++++++++++++++------------------- dlls/msvcrt/mbcs.c | 3 +- dlls/msvcrt/msvcrt.h | 5 ++-- 3 files changed, 42 insertions(+), 32 deletions(-)
diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index 7fd14f6ee7f..8a617d0212d 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -314,28 +314,27 @@ find_best_locale_proc( WCHAR *name, DWORD locale_flags, LPARAM lParam ) return CONTINUE_LOOKING; }
-/* Internal: Find the LCID for a locale specification */ -LCID locale_to_LCID(const char *locale, unsigned short *codepage, BOOL *sname) +/* Internal: Find the sname for a locale specification */ +BOOL locale_to_sname(const char *locale, unsigned short *codepage, BOOL *sname_match, WCHAR *sname, int sname_size) { thread_data_t *data = msvcrt_get_thread_data(); const char *cp, *region; BOOL is_sname = FALSE; DWORD locale_cp; - LCID lcid;
if (!strcmp(locale, data->cached_locale)) { if (codepage) *codepage = data->cached_cp; if (sname) - *sname = data->cached_sname; - return data->cached_lcid; + wcsncpy(sname, data->cached_sname, sname_size); + return TRUE; }
cp = strchr(locale, '.'); region = strchr(locale, '_');
if(!locale[0] || (cp == locale && !region)) { - lcid = GetUserDefaultLCID(); + GetUserDefaultLocaleName(sname, sname_size); } else { locale_search_t search; char search_language_buf[MAX_ELEM_LEN] = { 0 }, search_country_buf[MAX_ELEM_LEN] = { 0 }; @@ -368,26 +367,26 @@ LCID locale_to_LCID(const char *locale, unsigned short *codepage, BOOL *sname) EnumSystemLocalesEx( find_best_locale_proc, 0, (LPARAM)&search, NULL);
if (!search.match_flags) - return -1; + return FALSE;
/* If we were given something that didn't match, fail */ if (search.search_language[0] && !(search.match_flags & (FOUND_SNAME | FOUND_LANGUAGE))) - return -1; + return FALSE; if (search.search_country[0] && !(search.match_flags & FOUND_COUNTRY)) - return -1; + return FALSE;
- lcid = LocaleNameToLCID(search.found_lang_sname, LOCALE_ALLOW_NEUTRAL_NAMES); + wcsncpy(sname, search.found_lang_sname, sname_size); is_sname = (search.match_flags & FOUND_SNAME) != 0; }
/* Obtain code page */ if (!cp || !cp[1] || !_strnicmp(cp, ".ACP", 4)) { - GetLocaleInfoW(lcid, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, + GetLocaleInfoEx(sname, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER, (WCHAR *)&locale_cp, sizeof(DWORD)/sizeof(WCHAR)); if (!locale_cp) locale_cp = GetACP(); } else if (!_strnicmp(cp, ".OCP", 4)) { - GetLocaleInfoW(lcid, LOCALE_IDEFAULTCODEPAGE | LOCALE_RETURN_NUMBER, + GetLocaleInfoEx(sname, LOCALE_IDEFAULTCODEPAGE | LOCALE_RETURN_NUMBER, (WCHAR *)&locale_cp, sizeof(DWORD)/sizeof(WCHAR)); #if _MSVCR_VER >= 140 } else if (!_strnicmp(cp, ".UTF-8", 6) @@ -398,24 +397,23 @@ LCID locale_to_LCID(const char *locale, unsigned short *codepage, BOOL *sname) locale_cp = atoi(cp + 1); } if (!IsValidCodePage(locale_cp)) - return -1; + return FALSE;
if (!locale_cp) - return -1; + return FALSE;
if (codepage) *codepage = locale_cp; - if (sname) - *sname = is_sname; + if (sname_match) + *sname_match = is_sname;
if (strlen(locale) < sizeof(data->cached_locale)) { strcpy(data->cached_locale, locale); - data->cached_lcid = lcid; data->cached_cp = locale_cp; - data->cached_sname = is_sname; + wcscpy(data->cached_sname, sname); }
- return lcid; + return TRUE; }
static void copy_threadlocinfo_category(pthreadlocinfo locinfo, @@ -1256,7 +1254,7 @@ static pthreadlocinfo create_locinfo(int category, const char *locale_name[6] = { 0 }; int val, locale_len[6] = { 0 }; char buf[256]; - BOOL sname; + BOOL sname_match; #if _MSVCR_VER >= 100 wchar_t wbuf[256]; #endif @@ -1274,6 +1272,7 @@ static pthreadlocinfo create_locinfo(int category, const char *p;
while(1) { + BOOL ok = FALSE; locale += 3; /* LC_ */ if(!memcmp(locale, collate, sizeof(collate)-1)) { i = LC_COLLATE; @@ -1297,23 +1296,30 @@ static pthreadlocinfo create_locinfo(int category, if(locale[0]=='C' && (locale[1]==';' || locale[1]=='\0')) { lcid[i] = 0; 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'; - lcid[i] = locale_to_LCID(buf, &cp[i], &sname); - if(sname) { + ok = locale_to_sname(buf, &cp[i], &sname_match, wbuf, LOCALE_NAME_MAX_LENGTH); + lcid[i] = LocaleNameToLCID(wbuf, LOCALE_ALLOW_NEUTRAL_NAMES); + if(sname_match) { locale_name[i] = locale; locale_len[i] = p-locale; } } else { - lcid[i] = locale_to_LCID(locale, &cp[i], &sname); - if(sname) { + 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); + if(sname_match) { locale_name[i] = locale; locale_len[i] = strlen(locale); } }
- if(lcid[i] == -1) + if(!ok) return NULL;
if(!p || *(p+1)!='L' || *(p+2)!='C' || *(p+3)!='_') @@ -1322,10 +1328,14 @@ static pthreadlocinfo create_locinfo(int category, locale = p+1; } } else { - lcid[0] = locale_to_LCID(locale, &cp[0], &sname); - if(lcid[0] == -1) + 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); + if(!ok) return NULL; - if(sname) { + if(sname_match) { locale_name[0] = locale; locale_len[0] = strlen(locale); } diff --git a/dlls/msvcrt/mbcs.c b/dlls/msvcrt/mbcs.c index 16c5c378be7..8598bceb029 100644 --- a/dlls/msvcrt/mbcs.c +++ b/dlls/msvcrt/mbcs.c @@ -252,8 +252,9 @@ threadmbcinfo* create_mbcinfo(int cp, LCID lcid, threadmbcinfo *old_mbcinfo) }
if(lcid == -1) { + WCHAR wbuf[LOCALE_NAME_MAX_LENGTH]; sprintf(bufA, ".%d", newcp); - mbcinfo->mblcid = locale_to_LCID(bufA, NULL, NULL); + mbcinfo->mblcid = locale_to_sname(bufA, NULL, NULL, wbuf, LOCALE_NAME_MAX_LENGTH) ? LocaleNameToLCID(wbuf, LOCALE_ALLOW_NEUTRAL_NAMES) : -1; } else { mbcinfo->mblcid = lcid; } diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h index 1d2db6a4d87..42c41c2200c 100644 --- a/dlls/msvcrt/msvcrt.h +++ b/dlls/msvcrt/msvcrt.h @@ -170,8 +170,7 @@ struct __thread_data { int processing_throw; frame_info *frame_info_head; void *unk8[6]; - LCID cached_lcid; - BOOL cached_sname; + WCHAR cached_sname[LOCALE_NAME_MAX_LENGTH]; int unk9[2]; DWORD cached_cp; char cached_locale[131]; @@ -186,7 +185,7 @@ typedef struct __thread_data thread_data_t;
extern thread_data_t *CDECL msvcrt_get_thread_data(void) DECLSPEC_HIDDEN;
-LCID locale_to_LCID(const char*, unsigned short*, BOOL*) DECLSPEC_HIDDEN; +BOOL locale_to_sname(const char*, unsigned short*, BOOL*, WCHAR*, int) DECLSPEC_HIDDEN; extern _locale_t MSVCRT_locale DECLSPEC_HIDDEN; extern __lc_time_data cloc_time_data DECLSPEC_HIDDEN; extern unsigned int MSVCRT___lc_codepage;