Signed-off-by: Chip Davis cdavis@codeweavers.com --- v4: Update for changes in patch 1. --- dlls/msvcr90/tests/msvcr90.c | 64 ++++++++++------------------ dlls/msvcrt/locale.c | 81 ++++++++++++++++++++++++++++-------- 2 files changed, 85 insertions(+), 60 deletions(-)
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c index d51e3c985d63..693b8a30c5c1 100644 --- a/dlls/msvcr90/tests/msvcr90.c +++ b/dlls/msvcr90/tests/msvcr90.c @@ -2030,15 +2030,11 @@ static void test__get_current_locale(void) "same locale name pointers for LC_COLLATE\n"); ok(l->locinfo->lc_category[LC_COLLATE].refcount != l2->locinfo->lc_category[LC_COLLATE].refcount, "same refcount pointers for LC_COLLATE\n"); - ok(!!l->locinfo->lc_category[LC_COLLATE].refcount, "null refcount pointer for LC_COLLATE\n"); - if(l->locinfo->lc_category[LC_COLLATE].refcount) - ok(*l->locinfo->lc_category[LC_COLLATE].refcount == 1, "refcount = %d\n", - *l->locinfo->lc_category[LC_COLLATE].refcount); - ok(!!l2->locinfo->lc_category[LC_COLLATE].refcount, "null refcount pointer for LC_COLLATE\n"); - if(l2->locinfo->lc_category[LC_COLLATE].refcount) - ok(*l2->locinfo->lc_category[LC_COLLATE].refcount == 2, "refcount = %d\n", - *l2->locinfo->lc_category[LC_COLLATE].refcount); } + ok(*l->locinfo->lc_category[LC_COLLATE].refcount == 1, "refcount = %d\n", + *l->locinfo->lc_category[LC_COLLATE].refcount); + todo_wine ok(*l2->locinfo->lc_category[LC_COLLATE].refcount == 2, "refcount = %d\n", + *l2->locinfo->lc_category[LC_COLLATE].refcount); for(i = LC_CTYPE; i <= LC_MAX; i++) { ok(l->locinfo->lc_category[i].locale == l2->locinfo->lc_category[i].locale, "different locale name pointers for category %d\n", i); @@ -2101,15 +2097,11 @@ static void test__get_current_locale(void) "same locale name pointers for category %d\n", i); ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount, "same refcount pointers for category %d\n", i); - ok(!!l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i); - if(l->locinfo->lc_category[i].refcount) - ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n", - *l->locinfo->lc_category[i].refcount, i); - ok(!!l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i); - if(l2->locinfo->lc_category[i].refcount) - ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n", - *l2->locinfo->lc_category[i].refcount, i); } + ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n", + *l->locinfo->lc_category[i].refcount, i); + todo_wine ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n", + *l2->locinfo->lc_category[i].refcount, i); } for(i = LC_MONETARY; i <= LC_MAX; i++) { ok(l->locinfo->lc_category[i].locale == l2->locinfo->lc_category[i].locale, @@ -2180,15 +2172,11 @@ static void test__get_current_locale(void) "same locale name pointers for category %d\n", i); ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount, "same refcount pointers for category %d\n", i); - ok(!!l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i); - if(l->locinfo->lc_category[i].refcount) - ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n", - *l->locinfo->lc_category[i].refcount, i); - ok(!!l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i); - if(l2->locinfo->lc_category[i].refcount) - ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n", - *l2->locinfo->lc_category[i].refcount, i); } + ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n", + *l->locinfo->lc_category[i].refcount, i); + todo_wine ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n", + *l2->locinfo->lc_category[i].refcount, i); } for(i = LC_NUMERIC; i <= LC_MAX; i++) { ok(l->locinfo->lc_category[i].locale == l2->locinfo->lc_category[i].locale, @@ -2267,15 +2255,11 @@ static void test__get_current_locale(void) "same locale name pointers for category %d\n", i); ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount, "same refcount pointers for category %d\n", i); - ok(!!l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i); - if(l->locinfo->lc_category[i].refcount) - ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n", - *l->locinfo->lc_category[i].refcount, i); - ok(!!l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i); - if(l2->locinfo->lc_category[i].refcount) - ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n", - *l2->locinfo->lc_category[i].refcount, i); } + ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n", + *l->locinfo->lc_category[i].refcount, i); + todo_wine ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n", + *l2->locinfo->lc_category[i].refcount, i); } ok(l->locinfo->lc_category[LC_TIME].locale == l2->locinfo->lc_category[LC_TIME].locale, "different locale name pointers for LC_TIME\n"); @@ -2347,21 +2331,17 @@ static void test__get_current_locale(void) ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount); }
- todo_wine { - for(i = LC_MIN+1; i <= LC_MAX; i++) { + for(i = LC_MIN+1; i <= LC_MAX; i++) { + todo_wine { ok(l->locinfo->lc_category[i].locale != l2->locinfo->lc_category[i].locale, "same locale name pointers for category %d\n", i); ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount, "same refcount pointers for category %d\n", i); - ok(!!l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i); - if(l->locinfo->lc_category[i].refcount) - ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n", - *l->locinfo->lc_category[i].refcount, i); - ok(!!l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i); - if(l2->locinfo->lc_category[i].refcount) - ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n", - *l2->locinfo->lc_category[i].refcount, i); } + ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n", + *l->locinfo->lc_category[i].refcount, i); + todo_wine ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n", + *l2->locinfo->lc_category[i].refcount, i); }
todo_wine { diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index f6e7631b4f50..20004648ca79 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -418,6 +418,17 @@ static BOOL init_category_name(const char *name, int len, return TRUE; }
+/* INTERNAL: Copy lc_handle, lc_id, and lc_category from one threadlocinfo to another */ +static void copy_threadlocinfo_category(MSVCRT_pthreadlocinfo locinfo, MSVCRT_pthreadlocinfo old_locinfo, int category) +{ + locinfo->lc_handle[category] = old_locinfo->lc_handle[category]; + locinfo->lc_id[category] = old_locinfo->lc_id[category]; + if(!locinfo->lc_category[category].locale) { + locinfo->lc_category[category] = old_locinfo->lc_category[category]; + InterlockedIncrement(locinfo->lc_category[category].refcount); + } +} + /* INTERNAL: Set lc_handle, lc_id and lc_category in threadlocinfo struct */ static BOOL update_threadlocinfo_category(LCID lcid, unsigned short cp, MSVCRT_pthreadlocinfo locinfo, int category) @@ -878,11 +889,14 @@ void free_locinfo(MSVCRT_pthreadlocinfo locinfo) return;
for(i=MSVCRT_LC_MIN+1; i<=MSVCRT_LC_MAX; i++) { - MSVCRT_free(locinfo->lc_category[i].locale); - MSVCRT_free(locinfo->lc_category[i].refcount); #if _MSVCR_VER >= 110 MSVCRT_free(locinfo->lc_name[i]); #endif + if(!locinfo->lc_category[i].refcount + || InterlockedDecrement(locinfo->lc_category[i].refcount)) + continue; + MSVCRT_free(locinfo->lc_category[i].locale); + MSVCRT_free(locinfo->lc_category[i].refcount); }
if(locinfo->lconv) { @@ -1200,8 +1214,11 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_COLLATE, category, old_locinfo, lcid[MSVCRT_LC_COLLATE], cp[MSVCRT_LC_COLLATE])) { - locinfo->lc_handle[MSVCRT_LC_COLLATE] = old_locinfo->lc_handle[MSVCRT_LC_COLLATE]; - locinfo->lc_id[MSVCRT_LC_COLLATE].wCodePage = old_locinfo->lc_id[MSVCRT_LC_COLLATE].wCodePage; + copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_COLLATE); + if(!set_lc_locale_name(locinfo, MSVCRT_LC_COLLATE)) { + free_locinfo(locinfo); + return NULL; + } } else if(lcid[MSVCRT_LC_COLLATE] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_COLLATE)) { if(!update_threadlocinfo_category(lcid[MSVCRT_LC_COLLATE], cp[MSVCRT_LC_COLLATE], locinfo, MSVCRT_LC_COLLATE)) { @@ -1215,8 +1232,12 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, free_locinfo(locinfo); return NULL; } - } else - locinfo->lc_category[MSVCRT_LC_COLLATE].locale = MSVCRT__strdup("C"); + } else { + if(!init_category_name("C", 1, locinfo, MSVCRT_LC_COLLATE)) { + free_locinfo(locinfo); + return NULL; + } + }
if(locale_name[MSVCRT_LC_CTYPE] && !init_category_name(locale_name[MSVCRT_LC_CTYPE], @@ -1227,8 +1248,11 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_CTYPE, category, old_locinfo, lcid[MSVCRT_LC_CTYPE], cp[MSVCRT_LC_CTYPE])) { - locinfo->lc_handle[MSVCRT_LC_CTYPE] = old_locinfo->lc_handle[MSVCRT_LC_CTYPE]; - locinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage = old_locinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage; + copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_CTYPE); + if(!set_lc_locale_name(locinfo, MSVCRT_LC_CTYPE)) { + free_locinfo(locinfo); + return NULL; + } } else if(lcid[MSVCRT_LC_CTYPE] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_CTYPE)) { CPINFO cp_info; int j; @@ -1293,7 +1317,10 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, locinfo->lc_clike = 1; locinfo->mb_cur_max = 1; locinfo->pctype = MSVCRT__ctype+1; - locinfo->lc_category[MSVCRT_LC_CTYPE].locale = MSVCRT__strdup("C"); + if(!init_category_name("C", 1, locinfo, MSVCRT_LC_CTYPE)) { + free_locinfo(locinfo); + return NULL; + }
for(i=0; i<256; i++) { if(locinfo->pctype[i] & MSVCRT__LEADBYTE) @@ -1317,8 +1344,11 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo, lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY])) { - locinfo->lc_handle[MSVCRT_LC_MONETARY] = old_locinfo->lc_handle[MSVCRT_LC_MONETARY]; - locinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage = old_locinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage; + copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_MONETARY); + if(!set_lc_locale_name(locinfo, MSVCRT_LC_MONETARY)) { + free_locinfo(locinfo); + return NULL; + } } else if(lcid[MSVCRT_LC_MONETARY] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_MONETARY)) { if(!update_threadlocinfo_category(lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY], locinfo, MSVCRT_LC_MONETARY)) { @@ -1585,7 +1615,10 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, locinfo->lconv->_W_negative_sign[0] = '\0'; #endif
- locinfo->lc_category[MSVCRT_LC_MONETARY].locale = MSVCRT__strdup("C"); + if(!init_category_name("C", 1, locinfo, MSVCRT_LC_MONETARY)) { + free_locinfo(locinfo); + return NULL; + } }
if(locale_name[MSVCRT_LC_NUMERIC] && @@ -1597,8 +1630,11 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo, lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC])) { - locinfo->lc_handle[MSVCRT_LC_NUMERIC] = old_locinfo->lc_handle[MSVCRT_LC_NUMERIC]; - locinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage = old_locinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage; + copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_NUMERIC); + if(!set_lc_locale_name(locinfo, MSVCRT_LC_NUMERIC)) { + free_locinfo(locinfo); + return NULL; + } } else if(lcid[MSVCRT_LC_NUMERIC] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_NUMERIC)) { if(!update_threadlocinfo_category(lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC], locinfo, MSVCRT_LC_NUMERIC)) { @@ -1703,7 +1739,10 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, locinfo->lconv->_W_thousands_sep[0] = '\0'; #endif
- locinfo->lc_category[MSVCRT_LC_NUMERIC].locale = MSVCRT__strdup("C"); + if (!init_category_name("C", 1, locinfo, MSVCRT_LC_NUMERIC)) { + free_locinfo(locinfo); + return NULL; + } }
if(locale_name[MSVCRT_LC_TIME] && @@ -1715,8 +1754,11 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_TIME, category, old_locinfo, lcid[MSVCRT_LC_TIME], cp[MSVCRT_LC_TIME])) { - locinfo->lc_handle[MSVCRT_LC_TIME] = old_locinfo->lc_handle[MSVCRT_LC_TIME]; - locinfo->lc_id[MSVCRT_LC_TIME].wCodePage = old_locinfo->lc_id[MSVCRT_LC_TIME].wCodePage; + copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_TIME); + if(!set_lc_locale_name(locinfo, MSVCRT_LC_TIME)) { + free_locinfo(locinfo); + return NULL; + } } else if(lcid[MSVCRT_LC_TIME] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_TIME)) { if(!update_threadlocinfo_category(lcid[MSVCRT_LC_TIME], cp[MSVCRT_LC_TIME], locinfo, MSVCRT_LC_TIME)) { @@ -1735,7 +1777,10 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, return NULL; } } else { - locinfo->lc_category[MSVCRT_LC_TIME].locale = MSVCRT__strdup("C"); + if(!init_category_name("C", 1, locinfo, MSVCRT_LC_TIME)) { + free_locinfo(locinfo); + return NULL; + } locinfo->lc_time_curr = &cloc_time_data; }