Signed-off-by: Chip Davis cdavis@codeweavers.com --- v3: Fix a naive attempt at modifying a patch immediately before sending. --- dlls/msvcr90/tests/msvcr90.c | 16 +++++----- dlls/msvcrt/locale.c | 62 +++++++++++++++++++++--------------- 2 files changed, 45 insertions(+), 33 deletions(-)
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c index 693b8a30c5c1..038e16a1d326 100644 --- a/dlls/msvcr90/tests/msvcr90.c +++ b/dlls/msvcr90/tests/msvcr90.c @@ -2120,10 +2120,10 @@ static void test__get_current_locale(void) l->locinfo->lc_codepage, l2->locinfo->lc_codepage); ok(l->locinfo->lc_clike != l2->locinfo->lc_clike, "same lc_clike values %d, %d\n", l->locinfo->lc_clike, l2->locinfo->lc_clike); + ok(l->locinfo->lc_clike, "non-C locale is C-like\n"); } - ok(l->locinfo->lc_clike, "non-C locale is C-like\n"); + ok(!l2->locinfo->lc_clike, "C locale is not C-like\n"); todo_wine { - ok(!l2->locinfo->lc_clike, "C locale is not C-like\n"); ok(l->locinfo->ctype1 != l2->locinfo->ctype1, "same ctype1 pointers\n"); ok(l->locinfo->pclmap != l2->locinfo->pclmap, "same clmap pointers\n"); ok(l->locinfo->pcumap != l2->locinfo->pcumap, "same cumap pointers\n"); @@ -2195,10 +2195,10 @@ static void test__get_current_locale(void) l->locinfo->lc_codepage, l2->locinfo->lc_codepage); ok(l->locinfo->lc_clike != l2->locinfo->lc_clike, "same lc_clike values %d, %d\n", l->locinfo->lc_clike, l2->locinfo->lc_clike); + ok(l->locinfo->lc_clike, "non-C locale is C-like\n"); } - ok(l->locinfo->lc_clike, "non-C locale is C-like\n"); + ok(!l2->locinfo->lc_clike, "C locale is not C-like\n"); todo_wine { - ok(!l2->locinfo->lc_clike, "C locale is not C-like\n"); ok(l->locinfo->ctype1 != l2->locinfo->ctype1, "same ctype1 pointers\n"); ok(l->locinfo->pclmap != l2->locinfo->pclmap, "same clmap pointers\n"); ok(l->locinfo->pcumap != l2->locinfo->pcumap, "same cumap pointers\n"); @@ -2276,10 +2276,10 @@ static void test__get_current_locale(void) l->locinfo->lc_codepage, l2->locinfo->lc_codepage); ok(l->locinfo->lc_clike != l2->locinfo->lc_clike, "same lc_clike values %d, %d\n", l->locinfo->lc_clike, l2->locinfo->lc_clike); + ok(l->locinfo->lc_clike, "non-C locale is C-like\n"); } - ok(l->locinfo->lc_clike, "non-C locale is C-like\n"); + ok(!l2->locinfo->lc_clike, "C locale is not C-like\n"); todo_wine { - ok(!l2->locinfo->lc_clike, "C locale is not C-like\n"); ok(l->locinfo->ctype1 != l2->locinfo->ctype1, "same ctype1 pointers\n"); ok(l->locinfo->pclmap != l2->locinfo->pclmap, "same clmap pointers\n"); ok(l->locinfo->pcumap != l2->locinfo->pcumap, "same cumap pointers\n"); @@ -2352,10 +2352,10 @@ static void test__get_current_locale(void) l->locinfo->lc_codepage, l2->locinfo->lc_codepage); ok(l->locinfo->lc_clike != l2->locinfo->lc_clike, "same lc_clike values %d, %d\n", l->locinfo->lc_clike, l2->locinfo->lc_clike); + ok(l->locinfo->lc_clike, "non-C locale is C-like\n"); } - ok(l->locinfo->lc_clike, "non-C locale is C-like\n"); + ok(!l2->locinfo->lc_clike, "C locale is not C-like\n"); todo_wine { - ok(!l2->locinfo->lc_clike, "C locale is not C-like\n"); ok(l->locinfo->ctype1 != l2->locinfo->ctype1, "same ctype1 pointers\n"); ok(l->locinfo->pclmap != l2->locinfo->pclmap, "same clmap pointers\n"); ok(l->locinfo->pcumap != l2->locinfo->pcumap, "same cumap pointers\n"); diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index 3723c14d483b..47f7c60a445c 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -55,6 +55,9 @@ BOOL initial_locale = TRUE; #define MSVCRT_LEADBYTE 0x8000 #define MSVCRT_C1_DEFINED 0x200
+static unsigned char cloc_clmap[256]; +static unsigned char cloc_cumap[256]; + static const MSVCRT_wchar_t sun[] = {'S','u','n',0}; static const MSVCRT_wchar_t mon[] = {'M','o','n',0}; static const MSVCRT_wchar_t tue[] = {'T','u','e',0}; @@ -163,6 +166,16 @@ static const char * const _country_synonyms[] = "spanish-modern", "esn" };
+static BOOL WINAPI init_cloc_casemap(PINIT_ONCE once, void *param, void **context) +{ + int i; + for(i=0; i<256; i++) { + cloc_clmap[i] = (i>='A' && i<='Z' ? i-'A'+'a' : i); + cloc_cumap[i] = (i>='a' && i<='z' ? i-'a'+'A' : i); + } + return TRUE; +} + /* INTERNAL: Map a synonym to an ISO code */ static void remap_synonym(char *name) { @@ -926,11 +939,13 @@ void free_locinfo(MSVCRT_pthreadlocinfo locinfo) MSVCRT_free(locinfo->lconv_mon_refcount); MSVCRT_free(locinfo->lconv);
- MSVCRT_free(locinfo->ctype1_refcount); - MSVCRT_free(locinfo->ctype1); - - MSVCRT_free(locinfo->pclmap); - MSVCRT_free(locinfo->pcumap); + if(locinfo->ctype1_refcount + && !InterlockedDecrement(locinfo->ctype1_refcount)) { + MSVCRT_free(locinfo->ctype1_refcount); + MSVCRT_free(locinfo->ctype1); + MSVCRT_free(locinfo->pclmap); + MSVCRT_free(locinfo->pcumap); + }
if(locinfo->lc_time_curr != &cloc_time_data) MSVCRT_free(locinfo->lc_time_curr); @@ -1198,13 +1213,6 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, } memset(locinfo->lconv, 0, sizeof(struct MSVCRT_lconv));
- locinfo->pclmap = MSVCRT_malloc(sizeof(char[256])); - locinfo->pcumap = MSVCRT_malloc(sizeof(char[256])); - if(!locinfo->pclmap || !locinfo->pcumap) { - free_locinfo(locinfo); - return NULL; - } - if(locale_name[MSVCRT_LC_COLLATE] && !init_category_name(locale_name[MSVCRT_LC_COLLATE], locale_len[MSVCRT_LC_COLLATE], locinfo, MSVCRT_LC_COLLATE)) { @@ -1254,6 +1262,16 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, free_locinfo(locinfo); return NULL; } + locinfo->lc_codepage = old_locinfo->lc_codepage; + locinfo->lc_clike = old_locinfo->lc_clike; + locinfo->mb_cur_max = old_locinfo->mb_cur_max; + locinfo->ctype1 = old_locinfo->ctype1; + locinfo->ctype1_refcount = old_locinfo->ctype1_refcount; + locinfo->pctype = old_locinfo->pctype; + locinfo->pclmap = old_locinfo->pclmap; + locinfo->pcumap = old_locinfo->pcumap; + if(locinfo->ctype1_refcount) + InterlockedIncrement(locinfo->ctype1_refcount); } else if(lcid[MSVCRT_LC_CTYPE] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_CTYPE)) { CPINFO cp_info; int j; @@ -1274,7 +1292,9 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
locinfo->ctype1_refcount = MSVCRT_malloc(sizeof(int)); locinfo->ctype1 = MSVCRT_malloc(sizeof(short[257])); - if(!locinfo->ctype1_refcount || !locinfo->ctype1) { + locinfo->pclmap = MSVCRT_malloc(sizeof(char[256])); + locinfo->pcumap = MSVCRT_malloc(sizeof(char[256])); + if(!locinfo->ctype1_refcount || !locinfo->ctype1 || !locinfo->pclmap || !locinfo->pcumap) { free_locinfo(locinfo); return NULL; } @@ -1315,7 +1335,7 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, LCMapStringA(lcid[MSVCRT_LC_CTYPE], LCMAP_UPPERCASE, buf, 256, (char*)locinfo->pcumap, 256); } else { - locinfo->lc_clike = 1; + static INIT_ONCE once = INIT_ONCE_STATIC_INIT; locinfo->mb_cur_max = 1; locinfo->pctype = MSVCRT__ctype+1; if(!init_category_name("C", 1, locinfo, MSVCRT_LC_CTYPE)) { @@ -1323,17 +1343,9 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, return NULL; }
- for(i=0; i<256; i++) { - if(locinfo->pctype[i] & MSVCRT__LEADBYTE) - buf[i] = ' '; - else - buf[i] = i; - } - - for(i=0; i<256; i++) { - locinfo->pclmap[i] = (i>='A' && i<='Z' ? i-'A'+'a' : i); - locinfo->pcumap[i] = (i>='a' && i<='z' ? i-'a'+'A' : i); - } + InitOnceExecuteOnce(&once, init_cloc_casemap, NULL, NULL); + locinfo->pclmap = cloc_clmap; + locinfo->pcumap = cloc_cumap; }
if(locale_name[MSVCRT_LC_MONETARY] &&