From: Jactry Zeng jzeng@codeweavers.com
--- dlls/msvcrt/locale.c | 29 ++++++++++++++++++++++++++--- dlls/msvcrt/tests/string.c | 6 +++--- 2 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index 013b6b10ed8..febb972ac47 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -243,6 +243,7 @@ static BOOL remap_synonym(char *name) typedef struct { WCHAR search_language[MAX_ELEM_LEN]; WCHAR search_country[MAX_ELEM_LEN]; + WCHAR search_codepage[MAX_ELEM_LEN]; WCHAR found_lang_sname[LOCALE_NAME_MAX_LENGTH]; unsigned int match_flags; BOOL allow_sname; @@ -280,6 +281,14 @@ find_best_locale_proc( WCHAR *name, DWORD locale_flags, LPARAM lParam ) WCHAR buff[MAX_ELEM_LEN]; unsigned int flags = 0;
+ if (*res->search_codepage && compare_info(name, LOCALE_IDEFAULTANSICODEPAGE, buff, res->search_codepage, TRUE)) + { + TRACE("Found locale %s by codepage %s.\n", wine_dbgstr_w(name), wine_dbgstr_w(res->search_codepage)); + res->match_flags = FOUND_SNAME; + wcscpy(res->found_lang_sname, name); + return STOP_LOOKING; + } + if (res->allow_sname && compare_info(name,LOCALE_SNAME,buff,res->search_language, TRUE)) { TRACE(":Found locale: %s->%s\n", wine_dbgstr_w(res->search_language), wine_dbgstr_w(buff)); @@ -1275,6 +1284,18 @@ static __lc_time_data* create_time_data(WCHAR *sname) return cur; }
+static LCID lcid_from_codepage(int codepage) +{ + locale_search_t search; + + memset(&search, 0, sizeof(locale_search_t)); + _itow(codepage, search.search_codepage, 10); + EnumSystemLocalesEx(find_best_locale_proc, LOCALE_NEUTRALDATA, (LPARAM)&search, NULL); + if (search.match_flags & FOUND_SNAME) + return LocaleNameToLCID(search.found_lang_sname, LCID_CONVERSION_FLAGS); + return 0; +} + static pthreadlocinfo create_locinfo(int category, const char *locale, const threadlocinfo *old_locinfo) { @@ -1483,6 +1504,7 @@ static pthreadlocinfo create_locinfo(int category, InterlockedIncrement((LONG *)locinfo->ctype1_refcount); } else if(locale_sname[LC_CTYPE]) { CPINFO cp_info; + LCID cp_lcid; int j;
if(!update_threadlocinfo_category(locale_sname[LC_CTYPE], @@ -1513,6 +1535,7 @@ static pthreadlocinfo create_locinfo(int category, locinfo->ctype1[0] = 0; locinfo->pctype = locinfo->ctype1+1;
+ cp_lcid = lcid_from_codepage(locinfo->lc_codepage); buf[1] = buf[2] = '\0'; for(i=1; i<257; i++) { buf[0] = i-1; @@ -1520,7 +1543,7 @@ static pthreadlocinfo create_locinfo(int category, /* builtin GetStringTypeA doesn't set output to 0 on invalid input */ locinfo->ctype1[i] = 0;
- GetStringTypeA(locinfo->lc_handle[LC_CTYPE], CT_CTYPE1, buf, + GetStringTypeA(cp_lcid ? cp_lcid : locinfo->lc_handle[LC_CTYPE], CT_CTYPE1, buf, 1, locinfo->ctype1+i); }
@@ -1535,9 +1558,9 @@ static pthreadlocinfo create_locinfo(int category, buf[i] = i; }
- LCMapStringA(locinfo->lc_handle[LC_CTYPE], LCMAP_LOWERCASE, buf, 256, + LCMapStringA(cp_lcid ? cp_lcid : locinfo->lc_handle[LC_CTYPE], LCMAP_LOWERCASE, buf, 256, (char*)locinfo->pclmap, 256); - LCMapStringA(locinfo->lc_handle[LC_CTYPE], LCMAP_UPPERCASE, buf, 256, + LCMapStringA(cp_lcid ? cp_lcid : locinfo->lc_handle[LC_CTYPE], LCMAP_UPPERCASE, buf, 256, (char*)locinfo->pcumap, 256); } else { locinfo->lc_clike = 1; diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c index 54b15b577c4..edce8bf3ae4 100644 --- a/dlls/msvcrt/tests/string.c +++ b/dlls/msvcrt/tests/string.c @@ -5057,11 +5057,11 @@ static void test_locale_info(void) ok(!!ret, "Got locale name %s vs %s.\n", locinfo->lc_category[LC_CTYPE].locale, locinfo2->lc_category[LC_CTYPE].locale); ret = memcmp(locinfo->ctype1, locinfo2->ctype1, 257 * sizeof(*locinfo->ctype1)); - todo_wine ok(!ret, "Got wrong ctype1 data.\n"); + ok(!ret, "Got wrong ctype1 data.\n"); ret = memcmp(locinfo->pclmap, locinfo2->pclmap, 256 * sizeof(*locinfo->pclmap)); - todo_wine ok(!ret, "Got wrong pclmap data.\n"); + ok(!ret, "Got wrong pclmap data.\n"); ret = memcmp(locinfo->pcumap, locinfo2->pcumap, 256 * sizeof(*locinfo->pcumap)); - todo_wine ok(!ret, "Got wrong pcumap data.\n"); + ok(!ret, "Got wrong pcumap data.\n"); ok(locinfo->lc_handle[LC_CTYPE] != locinfo2->lc_handle[LC_CTYPE], "Got wrong LC_CTYPE %#lx vs %#lx.\n", locinfo->lc_handle[LC_CTYPE], locinfo2->lc_handle[LC_CTYPE]);