Signed-off-by: Chip Davis cdavis@codeweavers.com --- v2: Bail if setlocale() fails. Mark a result as broken(). --- dlls/msvcr90/tests/msvcr90.c | 466 +++++++++++++++++++++++++++++++++++ 1 file changed, 466 insertions(+)
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c index c8a49f25492d..c81f4410d60b 100644 --- a/dlls/msvcr90/tests/msvcr90.c +++ b/dlls/msvcr90/tests/msvcr90.c @@ -139,6 +139,22 @@ static int (__cdecl *p_swscanf)(const wchar_t *str, const wchar_t* format, ...); static int (__cdecl *p____mb_cur_max_l_func)(_locale_t locale); static _locale_t (__cdecl *p__create_locale)(int, const char*); static void (__cdecl *p__free_locale)(_locale_t); +static _locale_t (__cdecl *p__get_current_locale)(void); + +struct __lc_time_data { + const char *short_wday[7]; + const char *wday[7]; + const char *short_mon[12]; + const char *mon[12]; + const char *am; + const char *pm; + const char *short_date; + const char *date; + const char *time; + LCID lcid; + int unk; + int refcount; +};
/* make sure we use the correct errno */ #undef errno @@ -408,6 +424,7 @@ static BOOL init(void) SET(p____mb_cur_max_l_func, "___mb_cur_max_l_func"); SET(p__create_locale, "_create_locale"); SET(p__free_locale, "_free_locale"); + SET(p__get_current_locale, "_get_current_locale");
if (sizeof(void *) == 8) { @@ -1961,6 +1978,454 @@ static void test____mb_cur_max_l_func(void) p__free_locale(l); }
+static void test__get_current_locale(void) +{ + _locale_t l = p__get_current_locale(), l2 = p__get_current_locale(); + int i; +#define lc_str(lc, s) \ + ok(!strcmp(l->locinfo->lc_category[lc].locale, s), #lc " = "%s"\n", \ + l->locinfo->lc_category[lc].locale) + lc_str(LC_COLLATE, "C"); + lc_str(LC_CTYPE, "C"); + lc_str(LC_MONETARY, "C"); + lc_str(LC_NUMERIC, "C"); + lc_str(LC_TIME, "C"); + + ok(l->locinfo->refcount == 3, "refcount = %d\n", l->locinfo->refcount); + + if(!p_setlocale(LC_ALL, "english")) { + win_skip("English locale not available\n"); + p__free_locale(l); + p__free_locale(l2); + return; + } + + todo_wine { + lc_str(LC_COLLATE, "C"); + lc_str(LC_CTYPE, "C"); + lc_str(LC_MONETARY, "C"); + lc_str(LC_NUMERIC, "C"); + lc_str(LC_TIME, "C"); + } +#undef lc_str + + todo_wine ok(l->locinfo->refcount == 2, "refcount = %d\n", l->locinfo->refcount); + ok(l->locinfo == l2->locinfo, "different locinfo pointers\n"); + ok(l->mbcinfo == l2->mbcinfo, "different mbcinfo pointers\n"); + + p__free_locale(l); + p__free_locale(l2); + + l = p__get_current_locale(); + p_setlocale(LC_COLLATE, "C"); + l2 = p__get_current_locale(); + + todo_wine { + ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount); + ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount); + } + + todo_wine { + ok(l->locinfo->lc_category[LC_COLLATE].locale != l2->locinfo->lc_category[LC_COLLATE].locale, + "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); + } + 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); + ok(l->locinfo->lc_category[i].refcount == l2->locinfo->lc_category[i].refcount, + "different refcount pointers for category %d\n", i); + todo_wine ok(*l->locinfo->lc_category[i].refcount == 3, "refcount = %d for category %d\n", + *l->locinfo->lc_category[i].refcount, i); + } + + todo_wine ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n", + l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp); + + ok(l->locinfo->lc_codepage == l2->locinfo->lc_codepage, "different lc_codepages %u, %u\n", + l->locinfo->lc_codepage, l2->locinfo->lc_codepage); + ok(l->locinfo->lc_clike == l2->locinfo->lc_clike, "different lc_clike values %d, %d\n", + l->locinfo->lc_clike, l2->locinfo->lc_clike); + /* The meaning of this member seems to be reversed--go figure */ + ok(l->locinfo->lc_clike, "non-C locale is C-like\n"); + ok(l->locinfo->ctype1 == l2->locinfo->ctype1, "different ctype1 pointers\n"); + ok(l->locinfo->pclmap == l2->locinfo->pclmap, "different clmap pointers\n"); + ok(l->locinfo->pcumap == l2->locinfo->pcumap, "different cumap pointers\n"); + ok(l->locinfo->ctype1_refcount == l2->locinfo->ctype1_refcount, "different ctype1_refcount pointers\n"); + todo_wine ok(*l->locinfo->ctype1_refcount == 3, "refcount = %d\n", *l->locinfo->ctype1_refcount); + + ok(l->locinfo->lconv == l2->locinfo->lconv, "different lconv pointers\n"); + ok(l->locinfo->lconv_intl_refcount == l2->locinfo->lconv_intl_refcount, "different lconv_intl_refcount pointers\n"); + todo_wine ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n"); + if(l->locinfo->lconv_intl_refcount) + todo_wine ok(*l->locinfo->lconv_intl_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_intl_refcount); + + ok(l->locinfo->lconv->decimal_point == l2->locinfo->lconv->decimal_point, "different LC_NUMERIC pointers\n"); + ok(l->locinfo->lconv_num_refcount == l2->locinfo->lconv_num_refcount, "different lconv_num_refcount pointers\n"); + todo_wine ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n"); + if(l->locinfo->lconv_num_refcount) + todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount); + + ok(l->locinfo->lconv->currency_symbol == l2->locinfo->lconv->currency_symbol, "different LC_MONETARY pointers\n"); + ok(l->locinfo->lconv_mon_refcount == l2->locinfo->lconv_mon_refcount, "different lconv_mon_refcount pointers\n"); + todo_wine ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n"); + if(l->locinfo->lconv_mon_refcount) + todo_wine ok(*l->locinfo->lconv_mon_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_mon_refcount); + + ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n"); + todo_wine ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); + todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount); + + p__free_locale(l2); + + p_setlocale(LC_CTYPE, "C"); + l2 = p__get_current_locale(); + + todo_wine { + ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount); + ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount); + } + + for(i = LC_COLLATE; i < LC_MONETARY; 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); + } + } + for(i = LC_MONETARY; 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); + ok(l->locinfo->lc_category[i].refcount == l2->locinfo->lc_category[i].refcount, + "different refcount pointers for category %d\n", i); + todo_wine ok(*l->locinfo->lc_category[i].refcount == 3, "refcount = %d for category %d\n", + *l->locinfo->lc_category[i].refcount, i); + } + + todo_wine { + ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n", + l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp); + + ok(l->locinfo->lc_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n", + 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"); + 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"); + ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n"); + ok(l->locinfo->ctype1_refcount, "null refcount pointer for non-C locale\n"); + if(l->locinfo->ctype1_refcount) + ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount); + } + ok(!l2->locinfo->ctype1_refcount, "nonnull refcount pointer for C locale\n"); + + ok(l->locinfo->lconv == l2->locinfo->lconv, "different lconv pointers\n"); + ok(l->locinfo->lconv_intl_refcount == l2->locinfo->lconv_intl_refcount, "different lconv_intl_refcount pointers\n"); + todo_wine ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n"); + if(l->locinfo->lconv_intl_refcount) + todo_wine ok(*l->locinfo->lconv_intl_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_intl_refcount); + + ok(l->locinfo->lconv->decimal_point == l2->locinfo->lconv->decimal_point, "different LC_NUMERIC pointers\n"); + ok(l->locinfo->lconv_num_refcount == l2->locinfo->lconv_num_refcount, "different lconv_num_refcount pointers\n"); + todo_wine ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n"); + if(l->locinfo->lconv_num_refcount) + todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount); + + ok(l->locinfo->lconv->currency_symbol == l2->locinfo->lconv->currency_symbol, "different LC_MONETARY pointers\n"); + ok(l->locinfo->lconv_mon_refcount == l2->locinfo->lconv_mon_refcount, "different lconv_mon_refcount pointers\n"); + todo_wine ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n"); + if(l->locinfo->lconv_mon_refcount) + todo_wine ok(*l->locinfo->lconv_mon_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_mon_refcount); + + ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n"); + todo_wine ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); + todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount); + + p__free_locale(l2); + + p_setlocale(LC_MONETARY, "C"); + l2 = p__get_current_locale(); + + todo_wine { + ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount); + ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount); + } + + for(i = LC_COLLATE; i <= LC_MONETARY; 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); + } + } + for(i = LC_NUMERIC; 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); + ok(l->locinfo->lc_category[i].refcount == l2->locinfo->lc_category[i].refcount, + "different refcount pointers for category %d\n", i); + todo_wine ok(*l->locinfo->lc_category[i].refcount == 3, "refcount = %d for category %d\n", + *l->locinfo->lc_category[i].refcount, i); + } + + todo_wine { + ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n", + l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp); + + ok(l->locinfo->lc_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n", + 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"); + 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"); + ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n"); + ok(l->locinfo->ctype1_refcount, "null refcount pointer for non-C locale\n"); + if(l->locinfo->ctype1_refcount) + ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount); + } + ok(!l2->locinfo->ctype1_refcount, "nonnull refcount pointer for C locale\n"); + + todo_wine { + ok(l->locinfo->lconv != l2->locinfo->lconv, "same lconv pointers\n"); + ok(l->locinfo->lconv_intl_refcount != l2->locinfo->lconv_intl_refcount, "same lconv_intl_refcount pointers\n"); + ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n"); + if(l->locinfo->lconv_intl_refcount) + ok(*l->locinfo->lconv_intl_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_intl_refcount); + ok(l2->locinfo->lconv_intl_refcount, "null refcount pointer for C locale\n"); + if(l2->locinfo->lconv_intl_refcount) + ok(*l2->locinfo->lconv_intl_refcount == 2, "refcount = %d\n", *l2->locinfo->lconv_intl_refcount); + } + + ok(l->locinfo->lconv->decimal_point == l2->locinfo->lconv->decimal_point, "different LC_NUMERIC pointers\n"); + ok(l->locinfo->lconv_num_refcount == l2->locinfo->lconv_num_refcount, "different lconv_num_refcount pointers\n"); + todo_wine ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n"); + if(l->locinfo->lconv_num_refcount) + todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount); + + todo_wine { + ok(l->locinfo->lconv->currency_symbol != l2->locinfo->lconv->currency_symbol, "same LC_MONETARY pointers\n"); + ok(l->locinfo->lconv_mon_refcount != l2->locinfo->lconv_mon_refcount, "same lconv_mon_refcount pointers\n"); + ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n"); + if(l->locinfo->lconv_mon_refcount) + ok(*l->locinfo->lconv_mon_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_mon_refcount); + } + ok(!l2->locinfo->lconv_mon_refcount, "nonnull refcount pointer for C locale\n"); + + ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n"); + todo_wine ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); + todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount); + + p__free_locale(l2); + + p_setlocale(LC_NUMERIC, "C"); + l2 = p__get_current_locale(); + + todo_wine { + ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount); + ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount); + } + + for(i = LC_COLLATE; i <= LC_NUMERIC; 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[LC_TIME].locale == l2->locinfo->lc_category[LC_TIME].locale, + "different locale name pointers for LC_TIME\n"); + ok(l->locinfo->lc_category[LC_TIME].refcount == l2->locinfo->lc_category[LC_TIME].refcount, + "different refcount pointers for LC_TIME\n"); + todo_wine ok(*l->locinfo->lc_category[LC_TIME].refcount == 3, "refcount = %d\n", + *l->locinfo->lc_category[LC_TIME].refcount); + + todo_wine { + ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n", + l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp); + + ok(l->locinfo->lc_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n", + 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"); + 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"); + ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n"); + ok(l->locinfo->ctype1_refcount, "null refcount pointer for non-C locale\n"); + if(l->locinfo->ctype1_refcount) + ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount); + } + ok(!l2->locinfo->ctype1_refcount, "nonnull refcount pointer for C locale\n"); + + todo_wine { + ok(l->locinfo->lconv != l2->locinfo->lconv, "same lconv pointers\n"); + ok(l->locinfo->lconv_intl_refcount != l2->locinfo->lconv_intl_refcount, "same lconv_intl_refcount pointers\n"); + ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n"); + if(l->locinfo->lconv_intl_refcount) + ok(*l->locinfo->lconv_intl_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_intl_refcount); + } + ok(!l2->locinfo->lconv_intl_refcount, "nonnull refcount pointer for C locale\n"); + + todo_wine { + ok(l->locinfo->lconv->decimal_point != l2->locinfo->lconv->decimal_point, "same LC_NUMERIC pointers\n"); + ok(l->locinfo->lconv_num_refcount != l2->locinfo->lconv_num_refcount, "same lconv_num_refcount pointers\n"); + ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n"); + if(l->locinfo->lconv_num_refcount) + ok(*l->locinfo->lconv_num_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_num_refcount); + } + ok(!l2->locinfo->lconv_num_refcount, "nonnull refcount pointer for C locale\n"); + + todo_wine { + ok(l->locinfo->lconv->currency_symbol != l2->locinfo->lconv->currency_symbol, "same LC_MONETARY pointers\n"); + ok(l->locinfo->lconv_mon_refcount != l2->locinfo->lconv_mon_refcount, "same lconv_mon_refcount pointers\n"); + ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n"); + if(l->locinfo->lconv_mon_refcount) + ok(*l->locinfo->lconv_mon_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_mon_refcount); + } + ok(!l2->locinfo->lconv_mon_refcount, "nonnull refcount pointer for C locale\n"); + + ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n"); + todo_wine ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); + todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount); + + p__free_locale(l2); + + p_setlocale(LC_TIME, "C"); + l2 = p__get_current_locale(); + + todo_wine { + ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount); + ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount); + } + + todo_wine { + for(i = LC_MIN+1; i <= LC_MAX; i++) { + 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); + } + } + + todo_wine { + ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n", + l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp); + + ok(l->locinfo->lc_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n", + 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"); + 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"); + ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n"); + ok(l->locinfo->ctype1_refcount, "null refcount pointer for non-C locale\n"); + if(l->locinfo->ctype1_refcount) + ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount); + } + ok(!l2->locinfo->ctype1_refcount, "nonnull refcount pointer for C locale\n"); + + todo_wine { + ok(l->locinfo->lconv != l2->locinfo->lconv, "same lconv pointers\n"); + ok(l->locinfo->lconv_intl_refcount != l2->locinfo->lconv_intl_refcount, "same lconv_intl_refcount pointers\n"); + ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n"); + if(l->locinfo->lconv_intl_refcount) + ok(*l->locinfo->lconv_intl_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_intl_refcount); + } + ok(!l2->locinfo->lconv_intl_refcount, "nonnull refcount pointer for C locale\n"); + + todo_wine { + ok(l->locinfo->lconv->decimal_point != l2->locinfo->lconv->decimal_point, "same LC_NUMERIC pointers\n"); + ok(l->locinfo->lconv_num_refcount != l2->locinfo->lconv_num_refcount, "same lconv_num_refcount pointers\n"); + ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n"); + if(l->locinfo->lconv_num_refcount) + ok(*l->locinfo->lconv_num_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_num_refcount); + } + ok(!l2->locinfo->lconv_num_refcount, "nonnull refcount pointer for C locale\n"); + + todo_wine { + ok(l->locinfo->lconv->currency_symbol != l2->locinfo->lconv->currency_symbol, "same LC_MONETARY pointers\n"); + ok(l->locinfo->lconv_mon_refcount != l2->locinfo->lconv_mon_refcount, "same lconv_mon_refcount pointers\n"); + ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n"); + if(l->locinfo->lconv_mon_refcount) + ok(*l->locinfo->lconv_mon_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_mon_refcount); + } + ok(!l2->locinfo->lconv_mon_refcount, "nonnull refcount pointer for C locale\n"); + + todo_wine ok(l->locinfo->lc_time_curr != l2->locinfo->lc_time_curr, "same lc_time_curr pointers\n"); + ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); + todo_wine ok(l->locinfo->lc_time_curr->refcount == 1, "refcount = %d\n", l->locinfo->lc_time_curr->refcount); + ok(l2->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l2->locinfo->lc_time_curr->unk); + todo_wine ok(l2->locinfo->lc_time_curr->refcount == 3 || broken(l2->locinfo->lc_time_curr->refcount == 2), + "refcount = %d\n", l2->locinfo->lc_time_curr->refcount); + + p__free_locale(l2); + + p__free_locale(l); + p_setlocale(LC_ALL, "C"); +} + START_TEST(msvcr90) { if(!init()) @@ -2001,4 +2466,5 @@ START_TEST(msvcr90) test___strncnt(); test_swscanf(); test____mb_cur_max_l_func(); + test__get_current_locale(); }
Signed-off-by: Chip Davis cdavis@codeweavers.com --- v3: Don't overwrite a locale name that was already set. --- 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 c81f4410d60b..f4ece2e10c93 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; }
Signed-off-by: Chip Davis cdavis@codeweavers.com --- dlls/msvcrt/locale.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index 20004648ca79..3723c14d483b 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -1219,6 +1219,7 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, free_locinfo(locinfo); return NULL; } + locinfo->lc_collate_cp = old_locinfo->lc_collate_cp; } 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)) {
Signed-off-by: Chip Davis cdavis@codeweavers.com --- dlls/msvcr90/tests/msvcr90.c | 16 +++++----- dlls/msvcrt/locale.c | 59 +++++++++++++++++++++--------------- 2 files changed, 42 insertions(+), 33 deletions(-)
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c index f4ece2e10c93..db8770e23b88 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..849ba352ddb3 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 char cloc_clmap[256]; +static 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,15 @@ 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); + } +} + /* INTERNAL: Map a synonym to an ISO code */ static void remap_synonym(char *name) { @@ -926,11 +938,11 @@ 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); + }
if(locinfo->lc_time_curr != &cloc_time_data) MSVCRT_free(locinfo->lc_time_curr); @@ -1198,13 +1210,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 +1259,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 +1289,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 +1332,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 +1340,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] &&
Signed-off-by: Chip Davis cdavis@codeweavers.com --- v3: Add a missing swap_pointers() call needed to keep tests happy. --- dlls/msvcrt/locale.c | 438 +++++++++++++++++++++++++------------------ 1 file changed, 257 insertions(+), 181 deletions(-)
diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index 849ba352ddb3..7c4d66ab87d3 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -58,6 +58,21 @@ BOOL initial_locale = TRUE; static char cloc_clmap[256]; static char cloc_cumap[256];
+#if _MSVCR_VER >= 100 +static const MSVCRT_wchar_t emptyW[] = {0}; +static const MSVCRT_wchar_t cloc_dec_point[] = {'.', 0}; +#endif +static struct MSVCRT_lconv cloc_lconv = +{ + ".", "", "", + "", "", "", "", "", "", "", CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX +#if _MSVCR_VER >= 100 + , + cloc_dec_point, emptyW, + emptyW, emptyW, emptyW, emptyW, emptyW, emptyW +#endif +}; + 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}; @@ -852,6 +867,14 @@ int CDECL __lconv_init(void) { /* this is used to make chars unsigned */ charmax = 255; + cloc_lconv.int_frac_digits = charmax; + cloc_lconv.frac_digits = charmax; + cloc_lconv.p_cs_precedes = charmax; + cloc_lconv.p_sep_by_space = charmax; + cloc_lconv.n_cs_precedes = charmax; + cloc_lconv.n_sep_by_space = charmax; + cloc_lconv.p_sign_posn = charmax; + cloc_lconv.n_sign_posn = charmax; return 0; }
@@ -912,31 +935,42 @@ void free_locinfo(MSVCRT_pthreadlocinfo locinfo) }
if(locinfo->lconv) { - MSVCRT_free(locinfo->lconv->decimal_point); - MSVCRT_free(locinfo->lconv->thousands_sep); - MSVCRT_free(locinfo->lconv->grouping); - MSVCRT_free(locinfo->lconv->int_curr_symbol); - MSVCRT_free(locinfo->lconv->currency_symbol); - MSVCRT_free(locinfo->lconv->mon_decimal_point); - MSVCRT_free(locinfo->lconv->mon_thousands_sep); - MSVCRT_free(locinfo->lconv->mon_grouping); - MSVCRT_free(locinfo->lconv->positive_sign); - MSVCRT_free(locinfo->lconv->negative_sign); + if(locinfo->lconv_num_refcount + && !InterlockedDecrement(locinfo->lconv_num_refcount)) { + MSVCRT_free(locinfo->lconv->decimal_point); + MSVCRT_free(locinfo->lconv->thousands_sep); + MSVCRT_free(locinfo->lconv->grouping); #if _MSVCR_VER >= 100 - MSVCRT_free(locinfo->lconv->_W_decimal_point); - MSVCRT_free(locinfo->lconv->_W_thousands_sep); - MSVCRT_free(locinfo->lconv->_W_int_curr_symbol); - MSVCRT_free(locinfo->lconv->_W_currency_symbol); - MSVCRT_free(locinfo->lconv->_W_mon_decimal_point); - MSVCRT_free(locinfo->lconv->_W_mon_thousands_sep); - MSVCRT_free(locinfo->lconv->_W_positive_sign); - MSVCRT_free(locinfo->lconv->_W_negative_sign); + MSVCRT_free(locinfo->lconv->_W_decimal_point); + MSVCRT_free(locinfo->lconv->_W_thousands_sep); #endif + MSVCRT_free(locinfo->lconv_num_refcount); + } + if(locinfo->lconv_mon_refcount + && !InterlockedDecrement(locinfo->lconv_mon_refcount)) { + MSVCRT_free(locinfo->lconv->int_curr_symbol); + MSVCRT_free(locinfo->lconv->currency_symbol); + MSVCRT_free(locinfo->lconv->mon_decimal_point); + MSVCRT_free(locinfo->lconv->mon_thousands_sep); + MSVCRT_free(locinfo->lconv->mon_grouping); + MSVCRT_free(locinfo->lconv->positive_sign); + MSVCRT_free(locinfo->lconv->negative_sign); +#if _MSVCR_VER >= 100 + MSVCRT_free(locinfo->lconv->_W_int_curr_symbol); + MSVCRT_free(locinfo->lconv->_W_currency_symbol); + MSVCRT_free(locinfo->lconv->_W_mon_decimal_point); + MSVCRT_free(locinfo->lconv->_W_mon_thousands_sep); + MSVCRT_free(locinfo->lconv->_W_positive_sign); + MSVCRT_free(locinfo->lconv->_W_negative_sign); +#endif + MSVCRT_free(locinfo->lconv_mon_refcount); + } + if(locinfo->lconv_intl_refcount + && !InterlockedDecrement(locinfo->lconv_intl_refcount)) { + MSVCRT_free(locinfo->lconv_intl_refcount); + MSVCRT_free(locinfo->lconv); + } } - MSVCRT_free(locinfo->lconv_intl_refcount); - MSVCRT_free(locinfo->lconv_num_refcount); - MSVCRT_free(locinfo->lconv_mon_refcount); - MSVCRT_free(locinfo->lconv);
if(locinfo->ctype1_refcount && !InterlockedDecrement(locinfo->ctype1_refcount)) { @@ -1203,13 +1237,6 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, memset(locinfo, 0, sizeof(MSVCRT_threadlocinfo)); locinfo->refcount = 1;
- locinfo->lconv = MSVCRT_malloc(sizeof(struct MSVCRT_lconv)); - if(!locinfo->lconv) { - free_locinfo(locinfo); - return NULL; - } - memset(locinfo->lconv, 0, sizeof(struct MSVCRT_lconv)); - if(locale_name[MSVCRT_LC_COLLATE] && !init_category_name(locale_name[MSVCRT_LC_COLLATE], locale_len[MSVCRT_LC_COLLATE], locinfo, MSVCRT_LC_COLLATE)) { @@ -1345,6 +1372,38 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, locinfo->pcumap = cloc_cumap; }
+ if(!category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo, + lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY]) + && !category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo, + lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC])) { + locinfo->lconv = old_locinfo->lconv; + locinfo->lconv_intl_refcount = old_locinfo->lconv_intl_refcount; + if(locinfo->lconv_intl_refcount) + InterlockedIncrement(locinfo->lconv_intl_refcount); + } else if((lcid[MSVCRT_LC_MONETARY] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_MONETARY)) + || (lcid[MSVCRT_LC_NUMERIC] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_NUMERIC)) + || (!category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo, + lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY]) + && old_locinfo->lc_handle[MSVCRT_LC_MONETARY]) + || (!category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo, + lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC]) + && old_locinfo->lc_handle[MSVCRT_LC_NUMERIC])) { + locinfo->lconv = MSVCRT_malloc(sizeof(struct MSVCRT_lconv)); + locinfo->lconv_intl_refcount = MSVCRT_malloc(sizeof(int)); + if(!locinfo->lconv || !locinfo->lconv_intl_refcount) { + MSVCRT_free(locinfo->lconv); + MSVCRT_free(locinfo->lconv_intl_refcount); + locinfo->lconv = NULL; + locinfo->lconv_intl_refcount = NULL; + free_locinfo(locinfo); + return NULL; + } + memset(locinfo->lconv, 0, sizeof(struct MSVCRT_lconv)); + *locinfo->lconv_intl_refcount = 1; + } else { + locinfo->lconv = &cloc_lconv; + } + if(locale_name[MSVCRT_LC_MONETARY] && !init_category_name(locale_name[MSVCRT_LC_MONETARY], locale_len[MSVCRT_LC_MONETARY], locinfo, MSVCRT_LC_MONETARY)) { @@ -1359,6 +1418,35 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, free_locinfo(locinfo); return NULL; } + locinfo->lconv_mon_refcount = old_locinfo->lconv_mon_refcount; + if(locinfo->lconv_mon_refcount) + InterlockedIncrement(locinfo->lconv_mon_refcount); + if(category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo, + lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC])) { + locinfo->lconv->int_curr_symbol = old_locinfo->lconv->int_curr_symbol; + locinfo->lconv->currency_symbol = old_locinfo->lconv->currency_symbol; + locinfo->lconv->mon_decimal_point = old_locinfo->lconv->mon_decimal_point; + locinfo->lconv->mon_thousands_sep = old_locinfo->lconv->mon_thousands_sep; + locinfo->lconv->mon_grouping = old_locinfo->lconv->mon_grouping; + locinfo->lconv->positive_sign = old_locinfo->lconv->positive_sign; + locinfo->lconv->negative_sign = old_locinfo->lconv->negative_sign; + locinfo->lconv->int_frac_digits = old_locinfo->lconv->int_frac_digits; + locinfo->lconv->frac_digits = old_locinfo->lconv->frac_digits; + locinfo->lconv->p_cs_precedes = old_locinfo->lconv->p_cs_precedes; + locinfo->lconv->p_sep_by_space = old_locinfo->lconv->p_sep_by_space; + locinfo->lconv->n_cs_precedes = old_locinfo->lconv->n_cs_precedes; + locinfo->lconv->n_sep_by_space = old_locinfo->lconv->n_sep_by_space; + locinfo->lconv->p_sign_posn = old_locinfo->lconv->p_sign_posn; + locinfo->lconv->n_sign_posn = old_locinfo->lconv->n_sign_posn; +#if _MSVCR_VER >= 100 + locinfo->lconv->_W_int_curr_symbol = old_locinfo->lconv->_W_int_curr_symbol; + locinfo->lconv->_W_currency_symbol = old_locinfo->lconv->_W_currency_symbol; + locinfo->lconv->_W_mon_decimal_point = old_locinfo->lconv->_W_mon_decimal_point; + locinfo->lconv->_W_mon_thousands_sep = old_locinfo->lconv->_W_mon_thousands_sep; + locinfo->lconv->_W_positive_sign = old_locinfo->lconv->_W_positive_sign; + locinfo->lconv->_W_negative_sign = old_locinfo->lconv->_W_negative_sign; +#endif + } } 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)) { @@ -1366,14 +1454,12 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, return NULL; }
- locinfo->lconv_intl_refcount = MSVCRT_malloc(sizeof(int)); locinfo->lconv_mon_refcount = MSVCRT_malloc(sizeof(int)); - if(!locinfo->lconv_intl_refcount || !locinfo->lconv_mon_refcount) { + if(!locinfo->lconv_mon_refcount) { free_locinfo(locinfo); return NULL; }
- *locinfo->lconv_intl_refcount = 1; *locinfo->lconv_mon_refcount = 1;
i = GetLocaleInfoA(lcid[MSVCRT_LC_MONETARY], LOCALE_SINTLSYMBOL @@ -1570,60 +1656,33 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, return NULL; } } else { - locinfo->lconv->int_curr_symbol = MSVCRT_malloc(sizeof(char)); - locinfo->lconv->currency_symbol = MSVCRT_malloc(sizeof(char)); - locinfo->lconv->mon_decimal_point = MSVCRT_malloc(sizeof(char)); - locinfo->lconv->mon_thousands_sep = MSVCRT_malloc(sizeof(char)); - locinfo->lconv->mon_grouping = MSVCRT_malloc(sizeof(char)); - locinfo->lconv->positive_sign = MSVCRT_malloc(sizeof(char)); - locinfo->lconv->negative_sign = MSVCRT_malloc(sizeof(char)); - - if(!locinfo->lconv->int_curr_symbol || !locinfo->lconv->currency_symbol - || !locinfo->lconv->mon_decimal_point || !locinfo->lconv->mon_thousands_sep - || !locinfo->lconv->mon_grouping || !locinfo->lconv->positive_sign - || !locinfo->lconv->negative_sign) { - free_locinfo(locinfo); - return NULL; - } - - locinfo->lconv->int_curr_symbol[0] = '\0'; - locinfo->lconv->currency_symbol[0] = '\0'; - locinfo->lconv->mon_decimal_point[0] = '\0'; - locinfo->lconv->mon_thousands_sep[0] = '\0'; - locinfo->lconv->mon_grouping[0] = '\0'; - locinfo->lconv->positive_sign[0] = '\0'; - locinfo->lconv->negative_sign[0] = '\0'; - locinfo->lconv->int_frac_digits = charmax; - locinfo->lconv->frac_digits = charmax; - locinfo->lconv->p_cs_precedes = charmax; - locinfo->lconv->p_sep_by_space = charmax; - locinfo->lconv->n_cs_precedes = charmax; - locinfo->lconv->n_sep_by_space = charmax; - locinfo->lconv->p_sign_posn = charmax; - locinfo->lconv->n_sign_posn = charmax; + if(!category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo, + lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC])) { + locinfo->lconv->int_curr_symbol = ""; + locinfo->lconv->currency_symbol = ""; + locinfo->lconv->mon_decimal_point = ""; + locinfo->lconv->mon_thousands_sep = ""; + locinfo->lconv->mon_grouping = ""; + locinfo->lconv->positive_sign = ""; + locinfo->lconv->negative_sign = ""; + locinfo->lconv->int_frac_digits = charmax; + locinfo->lconv->frac_digits = charmax; + locinfo->lconv->p_cs_precedes = charmax; + locinfo->lconv->p_sep_by_space = charmax; + locinfo->lconv->n_cs_precedes = charmax; + locinfo->lconv->n_sep_by_space = charmax; + locinfo->lconv->p_sign_posn = charmax; + locinfo->lconv->n_sign_posn = charmax;
#if _MSVCR_VER >= 100 - locinfo->lconv->_W_int_curr_symbol = MSVCRT_malloc(sizeof(MSVCRT_wchar_t)); - locinfo->lconv->_W_currency_symbol = MSVCRT_malloc(sizeof(MSVCRT_wchar_t)); - locinfo->lconv->_W_mon_decimal_point = MSVCRT_malloc(sizeof(MSVCRT_wchar_t)); - locinfo->lconv->_W_mon_thousands_sep = MSVCRT_malloc(sizeof(MSVCRT_wchar_t)); - locinfo->lconv->_W_positive_sign = MSVCRT_malloc(sizeof(MSVCRT_wchar_t)); - locinfo->lconv->_W_negative_sign = MSVCRT_malloc(sizeof(MSVCRT_wchar_t)); - - if(!locinfo->lconv->_W_int_curr_symbol || !locinfo->lconv->_W_currency_symbol - || !locinfo->lconv->_W_mon_decimal_point || !locinfo->lconv->_W_mon_thousands_sep - || !locinfo->lconv->positive_sign || !locinfo->lconv->negative_sign) { - free_locinfo(locinfo); - return NULL; - } - - locinfo->lconv->_W_int_curr_symbol[0] = '\0'; - locinfo->lconv->_W_currency_symbol[0] = '\0'; - locinfo->lconv->_W_mon_decimal_point[0] = '\0'; - locinfo->lconv->_W_mon_thousands_sep[0] = '\0'; - locinfo->lconv->_W_positive_sign[0] = '\0'; - locinfo->lconv->_W_negative_sign[0] = '\0'; + locinfo->lconv->_W_int_curr_symbol = emptyW; + locinfo->lconv->_W_currency_symbol = emptyW; + locinfo->lconv->_W_mon_decimal_point = emptyW; + locinfo->lconv->_W_mon_thousands_sep = emptyW; + locinfo->lconv->_W_positive_sign = emptyW; + locinfo->lconv->_W_negative_sign = emptyW; #endif + }
if(!init_category_name("C", 1, locinfo, MSVCRT_LC_MONETARY)) { free_locinfo(locinfo); @@ -1645,6 +1704,19 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, free_locinfo(locinfo); return NULL; } + locinfo->lconv_num_refcount = old_locinfo->lconv_num_refcount; + if(locinfo->lconv_num_refcount) + InterlockedIncrement(locinfo->lconv_num_refcount); + if(category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo, + lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY])) { + locinfo->lconv->decimal_point = old_locinfo->lconv->decimal_point; + locinfo->lconv->thousands_sep = old_locinfo->lconv->thousands_sep; + locinfo->lconv->grouping = old_locinfo->lconv->grouping; +#if _MSVCR_VER >= 100 + locinfo->lconv->_W_decimal_point = old_locinfo->lconv->_W_decimal_point; + locinfo->lconv->_W_thousands_sep = old_locinfo->lconv->_W_thousands_sep; +#endif + } } 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)) { @@ -1652,15 +1724,12 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, return NULL; }
- if(!locinfo->lconv_intl_refcount) - locinfo->lconv_intl_refcount = MSVCRT_malloc(sizeof(int)); locinfo->lconv_num_refcount = MSVCRT_malloc(sizeof(int)); - if(!locinfo->lconv_intl_refcount || !locinfo->lconv_num_refcount) { + if(!locinfo->lconv_num_refcount) { free_locinfo(locinfo); return NULL; }
- *locinfo->lconv_intl_refcount = 1; *locinfo->lconv_num_refcount = 1;
i = GetLocaleInfoA(lcid[MSVCRT_LC_NUMERIC], LOCALE_SDECIMAL @@ -1721,33 +1790,17 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, return NULL; } } else { - locinfo->lconv->decimal_point = MSVCRT_malloc(sizeof(char[2])); - locinfo->lconv->thousands_sep = MSVCRT_malloc(sizeof(char)); - locinfo->lconv->grouping = MSVCRT_malloc(sizeof(char)); - if(!locinfo->lconv->decimal_point || !locinfo->lconv->thousands_sep - || !locinfo->lconv->grouping) { - free_locinfo(locinfo); - return NULL; - } - - locinfo->lconv->decimal_point[0] = '.'; - locinfo->lconv->decimal_point[1] = '\0'; - locinfo->lconv->thousands_sep[0] = '\0'; - locinfo->lconv->grouping[0] = '\0'; + if(!category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo, + lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY])) { + locinfo->lconv->decimal_point = "."; + locinfo->lconv->thousands_sep = ""; + locinfo->lconv->grouping = "";
#if _MSVCR_VER >= 100 - locinfo->lconv->_W_decimal_point = MSVCRT_malloc(sizeof(MSVCRT_wchar_t[2])); - locinfo->lconv->_W_thousands_sep = MSVCRT_malloc(sizeof(MSVCRT_wchar_t)); - - if(!locinfo->lconv->_W_decimal_point || !locinfo->lconv->_W_thousands_sep) { - free_locinfo(locinfo); - return NULL; - } - - locinfo->lconv->_W_decimal_point[0] = '.'; - locinfo->lconv->_W_decimal_point[1] = '\0'; - locinfo->lconv->_W_thousands_sep[0] = '\0'; + locinfo->lconv->_W_decimal_point = cloc_dec_point; + locinfo->lconv->_W_thousands_sep = emptyW; #endif + }
if (!init_category_name("C", 1, locinfo, MSVCRT_LC_NUMERIC)) { free_locinfo(locinfo); @@ -1949,95 +2002,118 @@ char* CDECL MSVCRT_setlocale(int category, const char* locale) (void**)&newlocinfo->lc_category[MSVCRT_LC_CTYPE].refcount); }
- if(locinfo->lc_handle[MSVCRT_LC_MONETARY]!=newlocinfo->lc_handle[MSVCRT_LC_MONETARY] - || locinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage!=newlocinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage) { + if(newlocinfo->lc_category[MSVCRT_LC_MONETARY].locale) { + swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_MONETARY].locale, + (void**)&newlocinfo->lc_category[MSVCRT_LC_MONETARY].locale); + swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_MONETARY].refcount, + (void**)&newlocinfo->lc_category[MSVCRT_LC_MONETARY].refcount); + } + + if(newlocinfo->lc_category[MSVCRT_LC_NUMERIC].locale) { + swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_NUMERIC].locale, + (void**)&newlocinfo->lc_category[MSVCRT_LC_NUMERIC].locale); + swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_NUMERIC].refcount, + (void**)&newlocinfo->lc_category[MSVCRT_LC_NUMERIC].refcount); + } + + if((locinfo->lc_handle[MSVCRT_LC_MONETARY]!=newlocinfo->lc_handle[MSVCRT_LC_MONETARY] + || locinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage!=newlocinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage) + && (locinfo->lc_handle[MSVCRT_LC_NUMERIC]!=newlocinfo->lc_handle[MSVCRT_LC_NUMERIC] + || locinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage!=newlocinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage)) { locinfo->lc_handle[MSVCRT_LC_MONETARY] = newlocinfo->lc_handle[MSVCRT_LC_MONETARY]; locinfo->lc_id[MSVCRT_LC_MONETARY] = newlocinfo->lc_id[MSVCRT_LC_MONETARY]; - - swap_pointers((void**)&locinfo->lconv->int_curr_symbol, - (void**)&newlocinfo->lconv->int_curr_symbol); - swap_pointers((void**)&locinfo->lconv->currency_symbol, - (void**)&newlocinfo->lconv->currency_symbol); - swap_pointers((void**)&locinfo->lconv->mon_decimal_point, - (void**)&newlocinfo->lconv->mon_decimal_point); - swap_pointers((void**)&locinfo->lconv->mon_thousands_sep, - (void**)&newlocinfo->lconv->mon_thousands_sep); - swap_pointers((void**)&locinfo->lconv->mon_grouping, - (void**)&newlocinfo->lconv->mon_grouping); - swap_pointers((void**)&locinfo->lconv->positive_sign, - (void**)&newlocinfo->lconv->positive_sign); - swap_pointers((void**)&locinfo->lconv->negative_sign, - (void**)&newlocinfo->lconv->negative_sign); + locinfo->lc_handle[MSVCRT_LC_NUMERIC] = + newlocinfo->lc_handle[MSVCRT_LC_NUMERIC]; + locinfo->lc_id[MSVCRT_LC_NUMERIC] = + newlocinfo->lc_id[MSVCRT_LC_NUMERIC]; + swap_pointers((void**)&locinfo->lconv, (void**)&newlocinfo->lconv); +#if _MSVCR_VER >= 110 + swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_MONETARY], + (void**)&newlocinfo->lc_name[MSVCRT_LC_MONETARY]); + swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_NUMERIC], + (void**)&newlocinfo->lc_name[MSVCRT_LC_NUMERIC]); +#endif + } else { + if(locinfo->lc_handle[MSVCRT_LC_MONETARY]!=newlocinfo->lc_handle[MSVCRT_LC_MONETARY] + || locinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage!=newlocinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage) { + locinfo->lc_handle[MSVCRT_LC_MONETARY] = + newlocinfo->lc_handle[MSVCRT_LC_MONETARY]; + locinfo->lc_id[MSVCRT_LC_MONETARY] = + newlocinfo->lc_id[MSVCRT_LC_MONETARY]; + + swap_pointers((void**)&locinfo->lconv->int_curr_symbol, + (void**)&newlocinfo->lconv->int_curr_symbol); + swap_pointers((void**)&locinfo->lconv->currency_symbol, + (void**)&newlocinfo->lconv->currency_symbol); + swap_pointers((void**)&locinfo->lconv->mon_decimal_point, + (void**)&newlocinfo->lconv->mon_decimal_point); + swap_pointers((void**)&locinfo->lconv->mon_thousands_sep, + (void**)&newlocinfo->lconv->mon_thousands_sep); + swap_pointers((void**)&locinfo->lconv->mon_grouping, + (void**)&newlocinfo->lconv->mon_grouping); + swap_pointers((void**)&locinfo->lconv->positive_sign, + (void**)&newlocinfo->lconv->positive_sign); + swap_pointers((void**)&locinfo->lconv->negative_sign, + (void**)&newlocinfo->lconv->negative_sign);
#if _MSVCR_VER >= 100 - swap_pointers((void**)&locinfo->lconv->_W_int_curr_symbol, - (void**)&newlocinfo->lconv->_W_int_curr_symbol); - swap_pointers((void**)&locinfo->lconv->_W_currency_symbol, - (void**)&newlocinfo->lconv->_W_currency_symbol); - swap_pointers((void**)&locinfo->lconv->_W_mon_decimal_point, - (void**)&newlocinfo->lconv->_W_mon_decimal_point); - swap_pointers((void**)&locinfo->lconv->_W_mon_thousands_sep, - (void**)&newlocinfo->lconv->_W_mon_thousands_sep); - swap_pointers((void**)&locinfo->lconv->_W_positive_sign, - (void**)&newlocinfo->lconv->_W_positive_sign); - swap_pointers((void**)&locinfo->lconv->_W_negative_sign, - (void**)&newlocinfo->lconv->_W_negative_sign); + swap_pointers((void**)&locinfo->lconv->_W_int_curr_symbol, + (void**)&newlocinfo->lconv->_W_int_curr_symbol); + swap_pointers((void**)&locinfo->lconv->_W_currency_symbol, + (void**)&newlocinfo->lconv->_W_currency_symbol); + swap_pointers((void**)&locinfo->lconv->_W_mon_decimal_point, + (void**)&newlocinfo->lconv->_W_mon_decimal_point); + swap_pointers((void**)&locinfo->lconv->_W_mon_thousands_sep, + (void**)&newlocinfo->lconv->_W_mon_thousands_sep); + swap_pointers((void**)&locinfo->lconv->_W_positive_sign, + (void**)&newlocinfo->lconv->_W_positive_sign); + swap_pointers((void**)&locinfo->lconv->_W_negative_sign, + (void**)&newlocinfo->lconv->_W_negative_sign); #endif
- locinfo->lconv->int_frac_digits = newlocinfo->lconv->int_frac_digits; - locinfo->lconv->frac_digits = newlocinfo->lconv->frac_digits; - locinfo->lconv->p_cs_precedes = newlocinfo->lconv->p_cs_precedes; - locinfo->lconv->p_sep_by_space = newlocinfo->lconv->p_sep_by_space; - locinfo->lconv->n_cs_precedes = newlocinfo->lconv->n_cs_precedes; - locinfo->lconv->n_sep_by_space = newlocinfo->lconv->n_sep_by_space; - locinfo->lconv->p_sign_posn = newlocinfo->lconv->p_sign_posn; - locinfo->lconv->n_sign_posn = newlocinfo->lconv->n_sign_posn; + locinfo->lconv->int_frac_digits = newlocinfo->lconv->int_frac_digits; + locinfo->lconv->frac_digits = newlocinfo->lconv->frac_digits; + locinfo->lconv->p_cs_precedes = newlocinfo->lconv->p_cs_precedes; + locinfo->lconv->p_sep_by_space = newlocinfo->lconv->p_sep_by_space; + locinfo->lconv->n_cs_precedes = newlocinfo->lconv->n_cs_precedes; + locinfo->lconv->n_sep_by_space = newlocinfo->lconv->n_sep_by_space; + locinfo->lconv->p_sign_posn = newlocinfo->lconv->p_sign_posn; + locinfo->lconv->n_sign_posn = newlocinfo->lconv->n_sign_posn;
#if _MSVCR_VER >= 110 - swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_MONETARY], - (void**)&newlocinfo->lc_name[MSVCRT_LC_MONETARY]); + swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_MONETARY], + (void**)&newlocinfo->lc_name[MSVCRT_LC_MONETARY]); #endif - } - if(newlocinfo->lc_category[MSVCRT_LC_MONETARY].locale) { - swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_MONETARY].locale, - (void**)&newlocinfo->lc_category[MSVCRT_LC_MONETARY].locale); - swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_MONETARY].refcount, - (void**)&newlocinfo->lc_category[MSVCRT_LC_MONETARY].refcount); - } + }
- if(locinfo->lc_handle[MSVCRT_LC_NUMERIC]!=newlocinfo->lc_handle[MSVCRT_LC_NUMERIC] - || locinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage!=newlocinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage) { - locinfo->lc_handle[MSVCRT_LC_NUMERIC] = - newlocinfo->lc_handle[MSVCRT_LC_NUMERIC]; - locinfo->lc_id[MSVCRT_LC_NUMERIC] = - newlocinfo->lc_id[MSVCRT_LC_NUMERIC]; + if(locinfo->lc_handle[MSVCRT_LC_NUMERIC]!=newlocinfo->lc_handle[MSVCRT_LC_NUMERIC] + || locinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage!=newlocinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage) { + locinfo->lc_handle[MSVCRT_LC_NUMERIC] = + newlocinfo->lc_handle[MSVCRT_LC_NUMERIC]; + locinfo->lc_id[MSVCRT_LC_NUMERIC] = + newlocinfo->lc_id[MSVCRT_LC_NUMERIC];
- swap_pointers((void**)&locinfo->lconv->decimal_point, - (void**)&newlocinfo->lconv->decimal_point); - swap_pointers((void**)&locinfo->lconv->thousands_sep, - (void**)&newlocinfo->lconv->thousands_sep); - swap_pointers((void**)&locinfo->lconv->grouping, - (void**)&newlocinfo->lconv->grouping); + swap_pointers((void**)&locinfo->lconv->decimal_point, + (void**)&newlocinfo->lconv->decimal_point); + swap_pointers((void**)&locinfo->lconv->thousands_sep, + (void**)&newlocinfo->lconv->thousands_sep); + swap_pointers((void**)&locinfo->lconv->grouping, + (void**)&newlocinfo->lconv->grouping);
#if _MSVCR_VER >= 100 - swap_pointers((void**)&locinfo->lconv->_W_decimal_point, - (void**)&newlocinfo->lconv->_W_decimal_point); - swap_pointers((void**)&locinfo->lconv->_W_thousands_sep, - (void**)&newlocinfo->lconv->_W_thousands_sep); + swap_pointers((void**)&locinfo->lconv->_W_decimal_point, + (void**)&newlocinfo->lconv->_W_decimal_point); + swap_pointers((void**)&locinfo->lconv->_W_thousands_sep, + (void**)&newlocinfo->lconv->_W_thousands_sep); #endif
#if _MSVCR_VER >= 110 - swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_NUMERIC], - (void**)&newlocinfo->lc_name[MSVCRT_LC_NUMERIC]); + swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_NUMERIC], + (void**)&newlocinfo->lc_name[MSVCRT_LC_NUMERIC]); #endif - } - if(newlocinfo->lc_category[MSVCRT_LC_NUMERIC].locale) { - swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_NUMERIC].locale, - (void**)&newlocinfo->lc_category[MSVCRT_LC_NUMERIC].locale); - swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_NUMERIC].refcount, - (void**)&newlocinfo->lc_category[MSVCRT_LC_NUMERIC].refcount); + } }
if(locinfo->lc_handle[MSVCRT_LC_TIME]!=newlocinfo->lc_handle[MSVCRT_LC_TIME]
My testing shows that unk[1] is some sort of refcount. I've updated a few places with this knowledge.
Signed-off-by: Chip Davis cdavis@codeweavers.com --- v2: Don't give cloc_time_data an initial refcount of 1. I misjudged where the extra ref came from. --- dlls/msvcr90/tests/msvcr90.c | 8 ++++---- dlls/msvcrt/locale.c | 10 ++++++++-- dlls/msvcrt/msvcrt.h | 3 ++- dlls/msvcrt/tests/time.c | 7 ++++--- dlls/ucrtbase/tests/misc.c | 3 ++- 5 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c index db8770e23b88..4d0de35749b3 100644 --- a/dlls/msvcr90/tests/msvcr90.c +++ b/dlls/msvcr90/tests/msvcr90.c @@ -2078,7 +2078,7 @@ static void test__get_current_locale(void) todo_wine ok(*l->locinfo->lconv_mon_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_mon_refcount);
ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n"); - todo_wine ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); + ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
p__free_locale(l2); @@ -2153,7 +2153,7 @@ static void test__get_current_locale(void) todo_wine ok(*l->locinfo->lconv_mon_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_mon_refcount);
ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n"); - todo_wine ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); + ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
p__free_locale(l2); @@ -2236,7 +2236,7 @@ static void test__get_current_locale(void) ok(!l2->locinfo->lconv_mon_refcount, "nonnull refcount pointer for C locale\n");
ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n"); - todo_wine ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); + ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
p__free_locale(l2); @@ -2318,7 +2318,7 @@ static void test__get_current_locale(void) ok(!l2->locinfo->lconv_mon_refcount, "nonnull refcount pointer for C locale\n");
ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n"); - todo_wine ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); + ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
p__free_locale(l2); diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index 7c4d66ab87d3..5f7df5b661ce 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -131,7 +131,7 @@ MSVCRT___lc_time_data cloc_time_data = #if _MSVCR_VER < 110 MAKELCID(LANG_ENGLISH, SORT_DEFAULT), #endif - {1, 0}, + 1, 0, {{sun, mon, tue, wed, thu, fri, sat, sunday, monday, tuesday, wednesday, thursday, friday, saturday, jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec, @@ -978,7 +978,8 @@ void free_locinfo(MSVCRT_pthreadlocinfo locinfo) MSVCRT_free(locinfo->ctype1); }
- if(locinfo->lc_time_curr != &cloc_time_data) + if(!InterlockedDecrement(&locinfo->lc_time_curr->refcount) + && locinfo->lc_time_curr != &cloc_time_data) MSVCRT_free(locinfo->lc_time_curr);
MSVCRT_free(locinfo); @@ -1119,6 +1120,8 @@ static MSVCRT___lc_time_data* create_time_data(LCID lcid) #else cur->lcid = lcid; #endif + cur->unk = 1; + cur->refcount = 1;
return cur; } @@ -1822,6 +1825,8 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, free_locinfo(locinfo); return NULL; } + locinfo->lc_time_curr = old_locinfo->lc_time_curr; + InterlockedIncrement(&locinfo->lc_time_curr->refcount); } 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)) { @@ -1845,6 +1850,7 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, return NULL; } locinfo->lc_time_curr = &cloc_time_data; + InterlockedIncrement(&locinfo->lc_time_curr->refcount); }
return locinfo; diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h index 244df7d23ccc..e5a22c68ee8b 100644 --- a/dlls/msvcrt/msvcrt.h +++ b/dlls/msvcrt/msvcrt.h @@ -146,7 +146,8 @@ typedef struct { #if _MSVCR_VER < 110 LCID lcid; #endif - int unk[2]; + int unk; + int refcount; union { const MSVCRT_wchar_t *wstr[43]; struct { diff --git a/dlls/msvcrt/tests/time.c b/dlls/msvcrt/tests/time.c index 45ed971ca89a..20212d19bfa5 100644 --- a/dlls/msvcrt/tests/time.c +++ b/dlls/msvcrt/tests/time.c @@ -47,7 +47,8 @@ typedef struct { const char *date; const char *time; LCID lcid; - int unk[2]; + int unk; + int refcount; } __lc_time_data;
static __time32_t (__cdecl *p_mkgmtime32)(struct tm*); @@ -824,8 +825,8 @@ static void test_strftime(void) return; }
- /* TODO: find meaning of unk[0] */ - time_data.unk[0] = 1; + /* TODO: find meaning of unk */ + time_data.unk = 1; for (i=0; i<ARRAY_SIZE(tests_td); i++) { time_data.short_date = tests_td[i].short_date; diff --git a/dlls/ucrtbase/tests/misc.c b/dlls/ucrtbase/tests/misc.c index c9b04b7dd473..f39182b684f6 100644 --- a/dlls/ucrtbase/tests/misc.c +++ b/dlls/ucrtbase/tests/misc.c @@ -116,7 +116,8 @@ typedef struct { const char *short_date; const char *date; const char *time; - int unk[2]; + int unk; + int refcount; const wchar_t *short_wdayW[7]; const wchar_t *wdayW[7]; const wchar_t *short_monW[12];
Do this instead of swapping their contents. This way, the result of _get_current_locale(), which references the current threadlocinfo, won't change after a setlocale() call.
Signed-off-by: Chip Davis cdavis@codeweavers.com --- v3: More updates for changes to previous patches. --- dlls/msvcr90/tests/msvcr90.c | 334 +++++++++++++---------------------- dlls/msvcrt/locale.c | 202 ++------------------- 2 files changed, 132 insertions(+), 404 deletions(-)
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c index 4d0de35749b3..eda774210c7b 100644 --- a/dlls/msvcr90/tests/msvcr90.c +++ b/dlls/msvcr90/tests/msvcr90.c @@ -2000,16 +2000,14 @@ static void test__get_current_locale(void) return; }
- todo_wine { - lc_str(LC_COLLATE, "C"); - lc_str(LC_CTYPE, "C"); - lc_str(LC_MONETARY, "C"); - lc_str(LC_NUMERIC, "C"); - lc_str(LC_TIME, "C"); - } + lc_str(LC_COLLATE, "C"); + lc_str(LC_CTYPE, "C"); + lc_str(LC_MONETARY, "C"); + lc_str(LC_NUMERIC, "C"); + lc_str(LC_TIME, "C"); #undef lc_str
- todo_wine ok(l->locinfo->refcount == 2, "refcount = %d\n", l->locinfo->refcount); + ok(l->locinfo->refcount == 2, "refcount = %d\n", l->locinfo->refcount); ok(l->locinfo == l2->locinfo, "different locinfo pointers\n"); ok(l->mbcinfo == l2->mbcinfo, "different mbcinfo pointers\n");
@@ -2020,17 +2018,13 @@ static void test__get_current_locale(void) p_setlocale(LC_COLLATE, "C"); l2 = p__get_current_locale();
- todo_wine { - ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount); - ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount); - } + ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount); + ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount);
- todo_wine { - ok(l->locinfo->lc_category[LC_COLLATE].locale != l2->locinfo->lc_category[LC_COLLATE].locale, - "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].locale != l2->locinfo->lc_category[LC_COLLATE].locale, + "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 == 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", @@ -2044,7 +2038,7 @@ static void test__get_current_locale(void) *l->locinfo->lc_category[i].refcount, i); }
- todo_wine ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n", + ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n", l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp);
ok(l->locinfo->lc_codepage == l2->locinfo->lc_codepage, "different lc_codepages %u, %u\n", @@ -2061,21 +2055,15 @@ static void test__get_current_locale(void)
ok(l->locinfo->lconv == l2->locinfo->lconv, "different lconv pointers\n"); ok(l->locinfo->lconv_intl_refcount == l2->locinfo->lconv_intl_refcount, "different lconv_intl_refcount pointers\n"); - todo_wine ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n"); - if(l->locinfo->lconv_intl_refcount) - todo_wine ok(*l->locinfo->lconv_intl_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_intl_refcount); + todo_wine ok(*l->locinfo->lconv_intl_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_intl_refcount);
ok(l->locinfo->lconv->decimal_point == l2->locinfo->lconv->decimal_point, "different LC_NUMERIC pointers\n"); ok(l->locinfo->lconv_num_refcount == l2->locinfo->lconv_num_refcount, "different lconv_num_refcount pointers\n"); - todo_wine ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n"); - if(l->locinfo->lconv_num_refcount) - todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount); + todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount);
ok(l->locinfo->lconv->currency_symbol == l2->locinfo->lconv->currency_symbol, "different LC_MONETARY pointers\n"); ok(l->locinfo->lconv_mon_refcount == l2->locinfo->lconv_mon_refcount, "different lconv_mon_refcount pointers\n"); - todo_wine ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n"); - if(l->locinfo->lconv_mon_refcount) - todo_wine ok(*l->locinfo->lconv_mon_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_mon_refcount); + todo_wine ok(*l->locinfo->lconv_mon_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_mon_refcount);
ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n"); ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); @@ -2086,18 +2074,14 @@ static void test__get_current_locale(void) p_setlocale(LC_CTYPE, "C"); l2 = p__get_current_locale();
- todo_wine { - ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount); - ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount); - } + ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount); + ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount);
for(i = LC_COLLATE; i < LC_MONETARY; 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].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 == 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", @@ -2112,45 +2096,33 @@ static void test__get_current_locale(void) *l->locinfo->lc_category[i].refcount, i); }
- todo_wine { - ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n", - l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp); + ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n", + l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp);
- ok(l->locinfo->lc_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n", - 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_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n", + 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(!l2->locinfo->lc_clike, "C locale is not C-like\n"); - todo_wine { - 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"); - ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n"); - ok(l->locinfo->ctype1_refcount, "null refcount pointer for non-C locale\n"); - if(l->locinfo->ctype1_refcount) - ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount); - } + 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"); + ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n"); + ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount); ok(!l2->locinfo->ctype1_refcount, "nonnull refcount pointer for C locale\n");
ok(l->locinfo->lconv == l2->locinfo->lconv, "different lconv pointers\n"); ok(l->locinfo->lconv_intl_refcount == l2->locinfo->lconv_intl_refcount, "different lconv_intl_refcount pointers\n"); - todo_wine ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n"); - if(l->locinfo->lconv_intl_refcount) - todo_wine ok(*l->locinfo->lconv_intl_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_intl_refcount); + todo_wine ok(*l->locinfo->lconv_intl_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_intl_refcount);
ok(l->locinfo->lconv->decimal_point == l2->locinfo->lconv->decimal_point, "different LC_NUMERIC pointers\n"); ok(l->locinfo->lconv_num_refcount == l2->locinfo->lconv_num_refcount, "different lconv_num_refcount pointers\n"); - todo_wine ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n"); - if(l->locinfo->lconv_num_refcount) - todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount); + todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount);
ok(l->locinfo->lconv->currency_symbol == l2->locinfo->lconv->currency_symbol, "different LC_MONETARY pointers\n"); ok(l->locinfo->lconv_mon_refcount == l2->locinfo->lconv_mon_refcount, "different lconv_mon_refcount pointers\n"); - todo_wine ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n"); - if(l->locinfo->lconv_mon_refcount) - todo_wine ok(*l->locinfo->lconv_mon_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_mon_refcount); + todo_wine ok(*l->locinfo->lconv_mon_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_mon_refcount);
ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n"); ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); @@ -2161,18 +2133,14 @@ static void test__get_current_locale(void) p_setlocale(LC_MONETARY, "C"); l2 = p__get_current_locale();
- todo_wine { - ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount); - ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount); - } + ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount); + ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount);
for(i = LC_COLLATE; i <= LC_MONETARY; 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].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 == 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", @@ -2187,52 +2155,34 @@ static void test__get_current_locale(void) *l->locinfo->lc_category[i].refcount, i); }
- todo_wine { - ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n", - l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp); + ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n", + l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp);
- ok(l->locinfo->lc_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n", - 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_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n", + 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(!l2->locinfo->lc_clike, "C locale is not C-like\n"); - todo_wine { - 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"); - ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n"); - ok(l->locinfo->ctype1_refcount, "null refcount pointer for non-C locale\n"); - if(l->locinfo->ctype1_refcount) - ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount); - } + 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"); + ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n"); + ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount); ok(!l2->locinfo->ctype1_refcount, "nonnull refcount pointer for C locale\n");
- todo_wine { - ok(l->locinfo->lconv != l2->locinfo->lconv, "same lconv pointers\n"); - ok(l->locinfo->lconv_intl_refcount != l2->locinfo->lconv_intl_refcount, "same lconv_intl_refcount pointers\n"); - ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n"); - if(l->locinfo->lconv_intl_refcount) - ok(*l->locinfo->lconv_intl_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_intl_refcount); - ok(l2->locinfo->lconv_intl_refcount, "null refcount pointer for C locale\n"); - if(l2->locinfo->lconv_intl_refcount) - ok(*l2->locinfo->lconv_intl_refcount == 2, "refcount = %d\n", *l2->locinfo->lconv_intl_refcount); - } + ok(l->locinfo->lconv != l2->locinfo->lconv, "same lconv pointers\n"); + ok(l->locinfo->lconv_intl_refcount != l2->locinfo->lconv_intl_refcount, "same lconv_intl_refcount pointers\n"); + ok(*l->locinfo->lconv_intl_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_intl_refcount); + todo_wine ok(*l2->locinfo->lconv_intl_refcount == 2, "refcount = %d\n", *l2->locinfo->lconv_intl_refcount);
ok(l->locinfo->lconv->decimal_point == l2->locinfo->lconv->decimal_point, "different LC_NUMERIC pointers\n"); ok(l->locinfo->lconv_num_refcount == l2->locinfo->lconv_num_refcount, "different lconv_num_refcount pointers\n"); - todo_wine ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n"); - if(l->locinfo->lconv_num_refcount) - todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount); - - todo_wine { - ok(l->locinfo->lconv->currency_symbol != l2->locinfo->lconv->currency_symbol, "same LC_MONETARY pointers\n"); - ok(l->locinfo->lconv_mon_refcount != l2->locinfo->lconv_mon_refcount, "same lconv_mon_refcount pointers\n"); - ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n"); - if(l->locinfo->lconv_mon_refcount) - ok(*l->locinfo->lconv_mon_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_mon_refcount); - } + todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount); + + ok(l->locinfo->lconv->currency_symbol != l2->locinfo->lconv->currency_symbol, "same LC_MONETARY pointers\n"); + ok(l->locinfo->lconv_mon_refcount != l2->locinfo->lconv_mon_refcount, "same lconv_mon_refcount pointers\n"); + ok(*l->locinfo->lconv_mon_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_mon_refcount); ok(!l2->locinfo->lconv_mon_refcount, "nonnull refcount pointer for C locale\n");
ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n"); @@ -2244,18 +2194,14 @@ static void test__get_current_locale(void) p_setlocale(LC_NUMERIC, "C"); l2 = p__get_current_locale();
- todo_wine { - ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount); - ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount); - } + ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount); + ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount);
for(i = LC_COLLATE; i <= LC_NUMERIC; 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].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 == 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", @@ -2268,53 +2214,35 @@ static void test__get_current_locale(void) todo_wine ok(*l->locinfo->lc_category[LC_TIME].refcount == 3, "refcount = %d\n", *l->locinfo->lc_category[LC_TIME].refcount);
- todo_wine { - ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n", - l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp); + ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n", + l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp);
- ok(l->locinfo->lc_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n", - 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_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n", + 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(!l2->locinfo->lc_clike, "C locale is not C-like\n"); - todo_wine { - 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"); - ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n"); - ok(l->locinfo->ctype1_refcount, "null refcount pointer for non-C locale\n"); - if(l->locinfo->ctype1_refcount) - ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount); - } + 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"); + ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n"); + ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount); ok(!l2->locinfo->ctype1_refcount, "nonnull refcount pointer for C locale\n");
- todo_wine { - ok(l->locinfo->lconv != l2->locinfo->lconv, "same lconv pointers\n"); - ok(l->locinfo->lconv_intl_refcount != l2->locinfo->lconv_intl_refcount, "same lconv_intl_refcount pointers\n"); - ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n"); - if(l->locinfo->lconv_intl_refcount) - ok(*l->locinfo->lconv_intl_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_intl_refcount); - } + ok(l->locinfo->lconv != l2->locinfo->lconv, "same lconv pointers\n"); + ok(l->locinfo->lconv_intl_refcount != l2->locinfo->lconv_intl_refcount, "same lconv_intl_refcount pointers\n"); + ok(*l->locinfo->lconv_intl_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_intl_refcount); ok(!l2->locinfo->lconv_intl_refcount, "nonnull refcount pointer for C locale\n");
- todo_wine { - ok(l->locinfo->lconv->decimal_point != l2->locinfo->lconv->decimal_point, "same LC_NUMERIC pointers\n"); - ok(l->locinfo->lconv_num_refcount != l2->locinfo->lconv_num_refcount, "same lconv_num_refcount pointers\n"); - ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n"); - if(l->locinfo->lconv_num_refcount) - ok(*l->locinfo->lconv_num_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_num_refcount); - } + ok(l->locinfo->lconv->decimal_point != l2->locinfo->lconv->decimal_point, "same LC_NUMERIC pointers\n"); + ok(l->locinfo->lconv_num_refcount != l2->locinfo->lconv_num_refcount, "same lconv_num_refcount pointers\n"); + ok(*l->locinfo->lconv_num_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_num_refcount); ok(!l2->locinfo->lconv_num_refcount, "nonnull refcount pointer for C locale\n");
- todo_wine { - ok(l->locinfo->lconv->currency_symbol != l2->locinfo->lconv->currency_symbol, "same LC_MONETARY pointers\n"); - ok(l->locinfo->lconv_mon_refcount != l2->locinfo->lconv_mon_refcount, "same lconv_mon_refcount pointers\n"); - ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n"); - if(l->locinfo->lconv_mon_refcount) - ok(*l->locinfo->lconv_mon_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_mon_refcount); - } + ok(l->locinfo->lconv->currency_symbol != l2->locinfo->lconv->currency_symbol, "same LC_MONETARY pointers\n"); + ok(l->locinfo->lconv_mon_refcount != l2->locinfo->lconv_mon_refcount, "same lconv_mon_refcount pointers\n"); + ok(*l->locinfo->lconv_mon_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_mon_refcount); ok(!l2->locinfo->lconv_mon_refcount, "nonnull refcount pointer for C locale\n");
ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n"); @@ -2326,76 +2254,54 @@ static void test__get_current_locale(void) p_setlocale(LC_TIME, "C"); l2 = p__get_current_locale();
- todo_wine { - ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount); - ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount); - } + ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount); + ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount);
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].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 == 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 { - ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n", - l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp); + ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n", + l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp);
- ok(l->locinfo->lc_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n", - 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_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n", + 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(!l2->locinfo->lc_clike, "C locale is not C-like\n"); - todo_wine { - 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"); - ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n"); - ok(l->locinfo->ctype1_refcount, "null refcount pointer for non-C locale\n"); - if(l->locinfo->ctype1_refcount) - ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount); - } + 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"); + ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n"); + ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount); ok(!l2->locinfo->ctype1_refcount, "nonnull refcount pointer for C locale\n");
- todo_wine { - ok(l->locinfo->lconv != l2->locinfo->lconv, "same lconv pointers\n"); - ok(l->locinfo->lconv_intl_refcount != l2->locinfo->lconv_intl_refcount, "same lconv_intl_refcount pointers\n"); - ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n"); - if(l->locinfo->lconv_intl_refcount) - ok(*l->locinfo->lconv_intl_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_intl_refcount); - } + ok(l->locinfo->lconv != l2->locinfo->lconv, "same lconv pointers\n"); + ok(l->locinfo->lconv_intl_refcount != l2->locinfo->lconv_intl_refcount, "same lconv_intl_refcount pointers\n"); + ok(*l->locinfo->lconv_intl_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_intl_refcount); ok(!l2->locinfo->lconv_intl_refcount, "nonnull refcount pointer for C locale\n");
- todo_wine { - ok(l->locinfo->lconv->decimal_point != l2->locinfo->lconv->decimal_point, "same LC_NUMERIC pointers\n"); - ok(l->locinfo->lconv_num_refcount != l2->locinfo->lconv_num_refcount, "same lconv_num_refcount pointers\n"); - ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n"); - if(l->locinfo->lconv_num_refcount) - ok(*l->locinfo->lconv_num_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_num_refcount); - } + ok(l->locinfo->lconv->decimal_point != l2->locinfo->lconv->decimal_point, "same LC_NUMERIC pointers\n"); + ok(l->locinfo->lconv_num_refcount != l2->locinfo->lconv_num_refcount, "same lconv_num_refcount pointers\n"); + ok(*l->locinfo->lconv_num_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_num_refcount); ok(!l2->locinfo->lconv_num_refcount, "nonnull refcount pointer for C locale\n");
- todo_wine { - ok(l->locinfo->lconv->currency_symbol != l2->locinfo->lconv->currency_symbol, "same LC_MONETARY pointers\n"); - ok(l->locinfo->lconv_mon_refcount != l2->locinfo->lconv_mon_refcount, "same lconv_mon_refcount pointers\n"); - ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n"); - if(l->locinfo->lconv_mon_refcount) - ok(*l->locinfo->lconv_mon_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_mon_refcount); - } + ok(l->locinfo->lconv->currency_symbol != l2->locinfo->lconv->currency_symbol, "same LC_MONETARY pointers\n"); + ok(l->locinfo->lconv_mon_refcount != l2->locinfo->lconv_mon_refcount, "same lconv_mon_refcount pointers\n"); + ok(*l->locinfo->lconv_mon_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_mon_refcount); ok(!l2->locinfo->lconv_mon_refcount, "nonnull refcount pointer for C locale\n");
- todo_wine ok(l->locinfo->lc_time_curr != l2->locinfo->lc_time_curr, "same lc_time_curr pointers\n"); + ok(l->locinfo->lc_time_curr != l2->locinfo->lc_time_curr, "same lc_time_curr pointers\n"); ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); - todo_wine ok(l->locinfo->lc_time_curr->refcount == 1, "refcount = %d\n", l->locinfo->lc_time_curr->refcount); + ok(l->locinfo->lc_time_curr->refcount == 1, "refcount = %d\n", l->locinfo->lc_time_curr->refcount); ok(l2->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l2->locinfo->lc_time_curr->unk); todo_wine ok(l2->locinfo->lc_time_curr->refcount == 3 || broken(l2->locinfo->lc_time_curr->refcount == 2), "refcount = %d\n", l2->locinfo->lc_time_curr->refcount); diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index 5f7df5b661ce..88cefcefc17e 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -512,17 +512,22 @@ static inline void swap_pointers(void **p1, void **p2) { *p2 = hlp; }
-/* INTERNAL: returns pthreadlocinfo struct */ -MSVCRT_pthreadlocinfo get_locinfo(void) { +/* INTERNAL: returns pointer to pointer to threadlocinfo struct */ +static MSVCRT_pthreadlocinfo *get_locinfo_ptr(void) { thread_data_t *data = msvcrt_get_thread_data();
if(!data || !data->have_locale) - return MSVCRT_locale->locinfo; + return &MSVCRT_locale->locinfo; + + return &data->locinfo; +}
- return data->locinfo; +/* INTERNAL: returns threadlocinfo struct */ +MSVCRT_pthreadlocinfo get_locinfo(void) { + return *get_locinfo_ptr(); }
-/* INTERNAL: returns pthreadlocinfo struct */ +/* INTERNAL: returns threadmbcinfo struct */ MSVCRT_pthreadmbcinfo get_mbcinfo(void) { thread_data_t *data = msvcrt_get_thread_data();
@@ -1958,191 +1963,8 @@ char* CDECL MSVCRT_setlocale(int category, const char* locale) if(locale[0] != 'C' || locale[1] != '\0') initial_locale = FALSE;
- if(locinfo->lc_handle[MSVCRT_LC_COLLATE]!=newlocinfo->lc_handle[MSVCRT_LC_COLLATE] - || locinfo->lc_id[MSVCRT_LC_COLLATE].wCodePage!=newlocinfo->lc_id[MSVCRT_LC_COLLATE].wCodePage) { - locinfo->lc_collate_cp = newlocinfo->lc_collate_cp; - locinfo->lc_handle[MSVCRT_LC_COLLATE] = - newlocinfo->lc_handle[MSVCRT_LC_COLLATE]; - locinfo->lc_id[MSVCRT_LC_COLLATE] = - newlocinfo->lc_id[MSVCRT_LC_COLLATE]; - -#if _MSVCR_VER >= 110 - swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_COLLATE], - (void**)&newlocinfo->lc_name[MSVCRT_LC_COLLATE]); -#endif - } - if(newlocinfo->lc_category[MSVCRT_LC_COLLATE].locale) { - swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_COLLATE].locale, - (void**)&newlocinfo->lc_category[MSVCRT_LC_COLLATE].locale); - swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_COLLATE].refcount, - (void**)&newlocinfo->lc_category[MSVCRT_LC_COLLATE].refcount); - } - - if(locinfo->lc_handle[MSVCRT_LC_CTYPE]!=newlocinfo->lc_handle[MSVCRT_LC_CTYPE] - || locinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage!=newlocinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage) { - locinfo->lc_handle[MSVCRT_LC_CTYPE] = - newlocinfo->lc_handle[MSVCRT_LC_CTYPE]; - locinfo->lc_id[MSVCRT_LC_CTYPE] = - newlocinfo->lc_id[MSVCRT_LC_CTYPE]; - - locinfo->lc_codepage = newlocinfo->lc_codepage; - locinfo->lc_clike = newlocinfo->lc_clike; - locinfo->mb_cur_max = newlocinfo->mb_cur_max; - - swap_pointers((void**)&locinfo->ctype1_refcount, - (void**)&newlocinfo->ctype1_refcount); - swap_pointers((void**)&locinfo->ctype1, (void**)&newlocinfo->ctype1); - swap_pointers((void**)&locinfo->pctype, (void**)&newlocinfo->pctype); - swap_pointers((void**)&locinfo->pclmap, (void**)&newlocinfo->pclmap); - swap_pointers((void**)&locinfo->pcumap, (void**)&newlocinfo->pcumap); - -#if _MSVCR_VER >= 110 - swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_CTYPE], - (void**)&newlocinfo->lc_name[MSVCRT_LC_CTYPE]); -#endif - } - if(newlocinfo->lc_category[MSVCRT_LC_CTYPE].locale) { - swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_CTYPE].locale, - (void**)&newlocinfo->lc_category[MSVCRT_LC_CTYPE].locale); - swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_CTYPE].refcount, - (void**)&newlocinfo->lc_category[MSVCRT_LC_CTYPE].refcount); - } - - if(newlocinfo->lc_category[MSVCRT_LC_MONETARY].locale) { - swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_MONETARY].locale, - (void**)&newlocinfo->lc_category[MSVCRT_LC_MONETARY].locale); - swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_MONETARY].refcount, - (void**)&newlocinfo->lc_category[MSVCRT_LC_MONETARY].refcount); - } - - if(newlocinfo->lc_category[MSVCRT_LC_NUMERIC].locale) { - swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_NUMERIC].locale, - (void**)&newlocinfo->lc_category[MSVCRT_LC_NUMERIC].locale); - swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_NUMERIC].refcount, - (void**)&newlocinfo->lc_category[MSVCRT_LC_NUMERIC].refcount); - } - - if((locinfo->lc_handle[MSVCRT_LC_MONETARY]!=newlocinfo->lc_handle[MSVCRT_LC_MONETARY] - || locinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage!=newlocinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage) - && (locinfo->lc_handle[MSVCRT_LC_NUMERIC]!=newlocinfo->lc_handle[MSVCRT_LC_NUMERIC] - || locinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage!=newlocinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage)) { - locinfo->lc_handle[MSVCRT_LC_MONETARY] = - newlocinfo->lc_handle[MSVCRT_LC_MONETARY]; - locinfo->lc_id[MSVCRT_LC_MONETARY] = - newlocinfo->lc_id[MSVCRT_LC_MONETARY]; - locinfo->lc_handle[MSVCRT_LC_NUMERIC] = - newlocinfo->lc_handle[MSVCRT_LC_NUMERIC]; - locinfo->lc_id[MSVCRT_LC_NUMERIC] = - newlocinfo->lc_id[MSVCRT_LC_NUMERIC]; - swap_pointers((void**)&locinfo->lconv, (void**)&newlocinfo->lconv); -#if _MSVCR_VER >= 110 - swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_MONETARY], - (void**)&newlocinfo->lc_name[MSVCRT_LC_MONETARY]); - swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_NUMERIC], - (void**)&newlocinfo->lc_name[MSVCRT_LC_NUMERIC]); -#endif - } else { - if(locinfo->lc_handle[MSVCRT_LC_MONETARY]!=newlocinfo->lc_handle[MSVCRT_LC_MONETARY] - || locinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage!=newlocinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage) { - locinfo->lc_handle[MSVCRT_LC_MONETARY] = - newlocinfo->lc_handle[MSVCRT_LC_MONETARY]; - locinfo->lc_id[MSVCRT_LC_MONETARY] = - newlocinfo->lc_id[MSVCRT_LC_MONETARY]; - - swap_pointers((void**)&locinfo->lconv->int_curr_symbol, - (void**)&newlocinfo->lconv->int_curr_symbol); - swap_pointers((void**)&locinfo->lconv->currency_symbol, - (void**)&newlocinfo->lconv->currency_symbol); - swap_pointers((void**)&locinfo->lconv->mon_decimal_point, - (void**)&newlocinfo->lconv->mon_decimal_point); - swap_pointers((void**)&locinfo->lconv->mon_thousands_sep, - (void**)&newlocinfo->lconv->mon_thousands_sep); - swap_pointers((void**)&locinfo->lconv->mon_grouping, - (void**)&newlocinfo->lconv->mon_grouping); - swap_pointers((void**)&locinfo->lconv->positive_sign, - (void**)&newlocinfo->lconv->positive_sign); - swap_pointers((void**)&locinfo->lconv->negative_sign, - (void**)&newlocinfo->lconv->negative_sign); - -#if _MSVCR_VER >= 100 - swap_pointers((void**)&locinfo->lconv->_W_int_curr_symbol, - (void**)&newlocinfo->lconv->_W_int_curr_symbol); - swap_pointers((void**)&locinfo->lconv->_W_currency_symbol, - (void**)&newlocinfo->lconv->_W_currency_symbol); - swap_pointers((void**)&locinfo->lconv->_W_mon_decimal_point, - (void**)&newlocinfo->lconv->_W_mon_decimal_point); - swap_pointers((void**)&locinfo->lconv->_W_mon_thousands_sep, - (void**)&newlocinfo->lconv->_W_mon_thousands_sep); - swap_pointers((void**)&locinfo->lconv->_W_positive_sign, - (void**)&newlocinfo->lconv->_W_positive_sign); - swap_pointers((void**)&locinfo->lconv->_W_negative_sign, - (void**)&newlocinfo->lconv->_W_negative_sign); -#endif - - locinfo->lconv->int_frac_digits = newlocinfo->lconv->int_frac_digits; - locinfo->lconv->frac_digits = newlocinfo->lconv->frac_digits; - locinfo->lconv->p_cs_precedes = newlocinfo->lconv->p_cs_precedes; - locinfo->lconv->p_sep_by_space = newlocinfo->lconv->p_sep_by_space; - locinfo->lconv->n_cs_precedes = newlocinfo->lconv->n_cs_precedes; - locinfo->lconv->n_sep_by_space = newlocinfo->lconv->n_sep_by_space; - locinfo->lconv->p_sign_posn = newlocinfo->lconv->p_sign_posn; - locinfo->lconv->n_sign_posn = newlocinfo->lconv->n_sign_posn; - -#if _MSVCR_VER >= 110 - swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_MONETARY], - (void**)&newlocinfo->lc_name[MSVCRT_LC_MONETARY]); -#endif - } - - if(locinfo->lc_handle[MSVCRT_LC_NUMERIC]!=newlocinfo->lc_handle[MSVCRT_LC_NUMERIC] - || locinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage!=newlocinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage) { - locinfo->lc_handle[MSVCRT_LC_NUMERIC] = - newlocinfo->lc_handle[MSVCRT_LC_NUMERIC]; - locinfo->lc_id[MSVCRT_LC_NUMERIC] = - newlocinfo->lc_id[MSVCRT_LC_NUMERIC]; - - swap_pointers((void**)&locinfo->lconv->decimal_point, - (void**)&newlocinfo->lconv->decimal_point); - swap_pointers((void**)&locinfo->lconv->thousands_sep, - (void**)&newlocinfo->lconv->thousands_sep); - swap_pointers((void**)&locinfo->lconv->grouping, - (void**)&newlocinfo->lconv->grouping); - -#if _MSVCR_VER >= 100 - swap_pointers((void**)&locinfo->lconv->_W_decimal_point, - (void**)&newlocinfo->lconv->_W_decimal_point); - swap_pointers((void**)&locinfo->lconv->_W_thousands_sep, - (void**)&newlocinfo->lconv->_W_thousands_sep); -#endif - -#if _MSVCR_VER >= 110 - swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_NUMERIC], - (void**)&newlocinfo->lc_name[MSVCRT_LC_NUMERIC]); -#endif - } - } - - if(locinfo->lc_handle[MSVCRT_LC_TIME]!=newlocinfo->lc_handle[MSVCRT_LC_TIME] - || locinfo->lc_id[MSVCRT_LC_TIME].wCodePage!=newlocinfo->lc_id[MSVCRT_LC_TIME].wCodePage) { - locinfo->lc_handle[MSVCRT_LC_TIME] = - newlocinfo->lc_handle[MSVCRT_LC_TIME]; - locinfo->lc_id[MSVCRT_LC_TIME] = - newlocinfo->lc_id[MSVCRT_LC_TIME]; - swap_pointers((void**)&locinfo->lc_time_curr, - (void**)&newlocinfo->lc_time_curr); - -#if _MSVCR_VER >= 110 - swap_pointers((void**)&locinfo->lc_name[MSVCRT_LC_TIME], - (void**)&newlocinfo->lc_name[MSVCRT_LC_TIME]); -#endif - } - if(newlocinfo->lc_category[MSVCRT_LC_TIME].locale) { - swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_TIME].locale, - (void**)&newlocinfo->lc_category[MSVCRT_LC_TIME].locale); - swap_pointers((void**)&locinfo->lc_category[MSVCRT_LC_TIME].refcount, - (void**)&newlocinfo->lc_category[MSVCRT_LC_TIME].refcount); - } - + locinfo = newlocinfo; + swap_pointers(get_locinfo_ptr(), &newlocinfo); free_locinfo(newlocinfo); _unlock_locales();
Signed-off-by: Chip Davis cdavis@codeweavers.com --- v3: Make sure we decrement refcounts, too. --- dlls/msvcr90/tests/msvcr90.c | 46 ++++++++++++++++++------------------ dlls/msvcrt/locale.c | 30 +++++++++++++++++++---- 2 files changed, 48 insertions(+), 28 deletions(-)
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c index eda774210c7b..c2cf14f37e4c 100644 --- a/dlls/msvcr90/tests/msvcr90.c +++ b/dlls/msvcr90/tests/msvcr90.c @@ -2027,14 +2027,14 @@ static void test__get_current_locale(void) "same refcount pointers for LC_COLLATE\n"); 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", + 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); ok(l->locinfo->lc_category[i].refcount == l2->locinfo->lc_category[i].refcount, "different refcount pointers for category %d\n", i); - todo_wine ok(*l->locinfo->lc_category[i].refcount == 3, "refcount = %d for category %d\n", + ok(*l->locinfo->lc_category[i].refcount == 3, "refcount = %d for category %d\n", *l->locinfo->lc_category[i].refcount, i); }
@@ -2051,23 +2051,23 @@ static void test__get_current_locale(void) ok(l->locinfo->pclmap == l2->locinfo->pclmap, "different clmap pointers\n"); ok(l->locinfo->pcumap == l2->locinfo->pcumap, "different cumap pointers\n"); ok(l->locinfo->ctype1_refcount == l2->locinfo->ctype1_refcount, "different ctype1_refcount pointers\n"); - todo_wine ok(*l->locinfo->ctype1_refcount == 3, "refcount = %d\n", *l->locinfo->ctype1_refcount); + ok(*l->locinfo->ctype1_refcount == 3, "refcount = %d\n", *l->locinfo->ctype1_refcount);
ok(l->locinfo->lconv == l2->locinfo->lconv, "different lconv pointers\n"); ok(l->locinfo->lconv_intl_refcount == l2->locinfo->lconv_intl_refcount, "different lconv_intl_refcount pointers\n"); - todo_wine ok(*l->locinfo->lconv_intl_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_intl_refcount); + ok(*l->locinfo->lconv_intl_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_intl_refcount);
ok(l->locinfo->lconv->decimal_point == l2->locinfo->lconv->decimal_point, "different LC_NUMERIC pointers\n"); ok(l->locinfo->lconv_num_refcount == l2->locinfo->lconv_num_refcount, "different lconv_num_refcount pointers\n"); - todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount); + ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount);
ok(l->locinfo->lconv->currency_symbol == l2->locinfo->lconv->currency_symbol, "different LC_MONETARY pointers\n"); ok(l->locinfo->lconv_mon_refcount == l2->locinfo->lconv_mon_refcount, "different lconv_mon_refcount pointers\n"); - todo_wine ok(*l->locinfo->lconv_mon_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_mon_refcount); + ok(*l->locinfo->lconv_mon_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_mon_refcount);
ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n"); ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); - todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount); + ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
p__free_locale(l2);
@@ -2084,7 +2084,7 @@ static void test__get_current_locale(void) "same refcount pointers for category %d\n", 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", + 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++) { @@ -2092,7 +2092,7 @@ static void test__get_current_locale(void) "different locale name pointers for category %d\n", i); ok(l->locinfo->lc_category[i].refcount == l2->locinfo->lc_category[i].refcount, "different refcount pointers for category %d\n", i); - todo_wine ok(*l->locinfo->lc_category[i].refcount == 3, "refcount = %d for category %d\n", + ok(*l->locinfo->lc_category[i].refcount == 3, "refcount = %d for category %d\n", *l->locinfo->lc_category[i].refcount, i); }
@@ -2114,19 +2114,19 @@ static void test__get_current_locale(void)
ok(l->locinfo->lconv == l2->locinfo->lconv, "different lconv pointers\n"); ok(l->locinfo->lconv_intl_refcount == l2->locinfo->lconv_intl_refcount, "different lconv_intl_refcount pointers\n"); - todo_wine ok(*l->locinfo->lconv_intl_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_intl_refcount); + ok(*l->locinfo->lconv_intl_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_intl_refcount);
ok(l->locinfo->lconv->decimal_point == l2->locinfo->lconv->decimal_point, "different LC_NUMERIC pointers\n"); ok(l->locinfo->lconv_num_refcount == l2->locinfo->lconv_num_refcount, "different lconv_num_refcount pointers\n"); - todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount); + ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount);
ok(l->locinfo->lconv->currency_symbol == l2->locinfo->lconv->currency_symbol, "different LC_MONETARY pointers\n"); ok(l->locinfo->lconv_mon_refcount == l2->locinfo->lconv_mon_refcount, "different lconv_mon_refcount pointers\n"); - todo_wine ok(*l->locinfo->lconv_mon_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_mon_refcount); + ok(*l->locinfo->lconv_mon_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_mon_refcount);
ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n"); ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); - todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount); + ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
p__free_locale(l2);
@@ -2143,7 +2143,7 @@ static void test__get_current_locale(void) "same refcount pointers for category %d\n", 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", + 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++) { @@ -2151,7 +2151,7 @@ static void test__get_current_locale(void) "different locale name pointers for category %d\n", i); ok(l->locinfo->lc_category[i].refcount == l2->locinfo->lc_category[i].refcount, "different refcount pointers for category %d\n", i); - todo_wine ok(*l->locinfo->lc_category[i].refcount == 3, "refcount = %d for category %d\n", + ok(*l->locinfo->lc_category[i].refcount == 3, "refcount = %d for category %d\n", *l->locinfo->lc_category[i].refcount, i); }
@@ -2174,11 +2174,11 @@ static void test__get_current_locale(void) ok(l->locinfo->lconv != l2->locinfo->lconv, "same lconv pointers\n"); ok(l->locinfo->lconv_intl_refcount != l2->locinfo->lconv_intl_refcount, "same lconv_intl_refcount pointers\n"); ok(*l->locinfo->lconv_intl_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_intl_refcount); - todo_wine ok(*l2->locinfo->lconv_intl_refcount == 2, "refcount = %d\n", *l2->locinfo->lconv_intl_refcount); + ok(*l2->locinfo->lconv_intl_refcount == 2, "refcount = %d\n", *l2->locinfo->lconv_intl_refcount);
ok(l->locinfo->lconv->decimal_point == l2->locinfo->lconv->decimal_point, "different LC_NUMERIC pointers\n"); ok(l->locinfo->lconv_num_refcount == l2->locinfo->lconv_num_refcount, "different lconv_num_refcount pointers\n"); - todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount); + ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount);
ok(l->locinfo->lconv->currency_symbol != l2->locinfo->lconv->currency_symbol, "same LC_MONETARY pointers\n"); ok(l->locinfo->lconv_mon_refcount != l2->locinfo->lconv_mon_refcount, "same lconv_mon_refcount pointers\n"); @@ -2187,7 +2187,7 @@ static void test__get_current_locale(void)
ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n"); ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); - todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount); + ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
p__free_locale(l2);
@@ -2204,14 +2204,14 @@ static void test__get_current_locale(void) "same refcount pointers for category %d\n", 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", + 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"); ok(l->locinfo->lc_category[LC_TIME].refcount == l2->locinfo->lc_category[LC_TIME].refcount, "different refcount pointers for LC_TIME\n"); - todo_wine ok(*l->locinfo->lc_category[LC_TIME].refcount == 3, "refcount = %d\n", + ok(*l->locinfo->lc_category[LC_TIME].refcount == 3, "refcount = %d\n", *l->locinfo->lc_category[LC_TIME].refcount);
ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n", @@ -2247,7 +2247,7 @@ static void test__get_current_locale(void)
ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n"); ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); - todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount); + ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
p__free_locale(l2);
@@ -2264,7 +2264,7 @@ static void test__get_current_locale(void) "same refcount pointers for category %d\n", 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", + ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n", *l2->locinfo->lc_category[i].refcount, i); }
@@ -2303,7 +2303,7 @@ static void test__get_current_locale(void) ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk); ok(l->locinfo->lc_time_curr->refcount == 1, "refcount = %d\n", l->locinfo->lc_time_curr->refcount); ok(l2->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l2->locinfo->lc_time_curr->unk); - todo_wine ok(l2->locinfo->lc_time_curr->refcount == 3 || broken(l2->locinfo->lc_time_curr->refcount == 2), + ok(l2->locinfo->lc_time_curr->refcount == 3 || broken(l2->locinfo->lc_time_curr->refcount == 2), "refcount = %d\n", l2->locinfo->lc_time_curr->refcount);
p__free_locale(l2); diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index 88cefcefc17e..ecaf51231ec1 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -917,6 +917,27 @@ int CDECL ___lc_collate_cp_func(void) return get_locinfo()->lc_collate_cp; }
+/* INTERNAL: increases all reference counts in threadlocinfo struct */ +MSVCRT_pthreadlocinfo grab_locinfo(MSVCRT_pthreadlocinfo locinfo) +{ + int i; + + InterlockedIncrement(&locinfo->refcount); + for(i=MSVCRT_LC_MIN+1; i<=MSVCRT_LC_MAX; i++) + InterlockedIncrement(locinfo->lc_category[i].refcount); + if(locinfo->lconv_intl_refcount) + InterlockedIncrement(locinfo->lconv_intl_refcount); + if(locinfo->lconv_num_refcount) + InterlockedIncrement(locinfo->lconv_num_refcount); + if(locinfo->lconv_mon_refcount) + InterlockedIncrement(locinfo->lconv_mon_refcount); + if(locinfo->ctype1_refcount) + InterlockedIncrement(locinfo->ctype1_refcount); + InterlockedIncrement(&locinfo->lc_time_curr->refcount); + + return locinfo; +} + /* INTERNAL: frees MSVCRT_pthreadlocinfo struct */ void free_locinfo(MSVCRT_pthreadlocinfo locinfo) { @@ -925,9 +946,6 @@ void free_locinfo(MSVCRT_pthreadlocinfo locinfo) if(!locinfo) return;
- if(InterlockedDecrement(&locinfo->refcount)) - return; - for(i=MSVCRT_LC_MIN+1; i<=MSVCRT_LC_MAX; i++) { #if _MSVCR_VER >= 110 MSVCRT_free(locinfo->lc_name[i]); @@ -987,6 +1005,9 @@ void free_locinfo(MSVCRT_pthreadlocinfo locinfo) && locinfo->lc_time_curr != &cloc_time_data) MSVCRT_free(locinfo->lc_time_curr);
+ if(InterlockedDecrement(&locinfo->refcount)) + return; + MSVCRT_free(locinfo); }
@@ -1011,9 +1032,8 @@ MSVCRT__locale_t CDECL MSVCRT__get_current_locale(void) if(!loc) return NULL;
- loc->locinfo = get_locinfo(); + loc->locinfo = grab_locinfo(get_locinfo()); loc->mbcinfo = get_mbcinfo(); - InterlockedIncrement(&loc->locinfo->refcount); InterlockedIncrement(&loc->mbcinfo->refcount); return loc; }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=64355
Your paranoid android.
=== debian10 (32 bit report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x7e8fb54a).
Report errors: ucrtbase:misc crashed (c0000005)
=== debian10 (32 bit Chinese:China report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x7eb7554a).
Report errors: ucrtbase:misc crashed (c0000005)
=== debian10 (32 bit WoW report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x7e8fb54a).
Report errors: ucrtbase:misc crashed (c0000005)
=== debian10 (64 bit WoW report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x7e8fb54a).
Report errors: ucrtbase:misc crashed (c0000005)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=64354
Your paranoid android.
=== debian10 (32 bit report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x7e8fb4aa).
Report errors: ucrtbase:misc crashed (c0000005)
=== debian10 (32 bit Chinese:China report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x7eb754aa).
Report errors: ucrtbase:misc crashed (c0000005)
=== debian10 (32 bit WoW report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x7e8fb4aa).
Report errors: ucrtbase:misc crashed (c0000005)
=== debian10 (64 bit WoW report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x7e8fb4aa).
Report errors: ucrtbase:misc crashed (c0000005)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=64353
Your paranoid android.
=== w2008s64 (32 bit report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" 0390:misc: unhandled exception c0000005 at 744FB1D1
=== w7u (32 bit report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" 0c28:misc: unhandled exception c0000005 at 6C4BC8F1
=== w1064v1507 (32 bit report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" 0fa8:misc: unhandled exception c0000005 at 728B7849
=== w1064v1809 (32 bit report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" 18ec:misc: unhandled exception c0000005 at 7658283D
=== w1064v1809_2scr (32 bit report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" 1964:misc: unhandled exception c0000005 at 7656283D
=== w1064v1809_ar (32 bit report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" 0b34:misc: unhandled exception c0000005 at 759C287F
=== w1064v1809_he (32 bit report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" 0be8:misc: unhandled exception c0000005 at 768F287F
=== w1064v1809_ja (32 bit report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" 190c:misc: unhandled exception c0000005 at 7565287F
=== w1064v1809_zh_CN (32 bit report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" 0768:misc: unhandled exception c0000005 at 750F287F
=== w2008s64 (64 bit report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" 0390:misc: unhandled exception c0000005 at 000007FEF709569C
=== w1064v1507 (64 bit report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" 0fb4:misc: unhandled exception c0000005 at 00007FF8BCB13AFC
=== w1064v1809 (64 bit report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" 189c:misc: unhandled exception c0000005 at 00007FF870D36F9C
=== debian10 (32 bit report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x7e8fa9aa).
Report errors: ucrtbase:misc crashed (c0000005)
=== debian10 (32 bit French report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x7eb749aa).
Report errors: ucrtbase:misc crashed (c0000005)
=== debian10 (32 bit Japanese:Japan report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x7eb749aa).
Report errors: ucrtbase:misc crashed (c0000005)
=== debian10 (32 bit Chinese:China report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x7eb749aa).
Report errors: ucrtbase:misc crashed (c0000005)
=== debian10 (32 bit WoW report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x7e8fa9aa).
Report errors: ucrtbase:misc crashed (c0000005)
=== debian10 (64 bit WoW report) ===
ucrtbase: misc.c:1174: Test failed: 2) buf = "Mon1", expected "M1" Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x7e8fa9aa).
Report errors: ucrtbase:misc crashed (c0000005)
Hi Chip,
On 2/2/20 11:55 PM, Chip Davis wrote:
--- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -1219,6 +1219,7 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, free_locinfo(locinfo); return NULL; }
locinfo->lc_collate_cp = old_locinfo->lc_collate_cp;
Why do you need this? It should not be needed taking in account that this category is not being updated.
Thanks, Piotr
February 3, 2020 10:51 AM, "Piotr Caban" piotr.caban@gmail.com wrote:
Hi Chip,
On 2/2/20 11:55 PM, Chip Davis wrote:
--- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -1219,6 +1219,7 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, free_locinfo(locinfo); return NULL; }
- locinfo->lc_collate_cp = old_locinfo->lc_collate_cp;
Why do you need this? It should not be needed taking in account that this category is not being updated.
In patch 7, we stop updating the *contents* of the old locinfo, and instead update the locinfo pointer itself. This is needed so that the result of a _get_current_locale() call before a setlocale() call is unaffected by the setlocale() call. I needed that, in turn, because libc++ (from llvm-mingw) often calls _get_current_locale() before temporarily updating the global locale using setlocale(), and this bug was screwing up restoring the old locale. Demonstrating this is the case was the point of patch 1. For that to work, we have to copy the data for the un-updated parts from the old locinfo to the new one.
(Hmm... Perhaps I should've written a cover letter for this series.)
Chip
Hi Chip,
On 2/2/20 11:55 PM, Chip Davis wrote:
+/* 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) {
Why are you checking locinfo->lc_category[category].locale here?
Thanks, Piotr
February 3, 2020 10:40 AM, "Piotr Caban" piotr.caban@gmail.com wrote:
Hi Chip,
On 2/2/20 11:55 PM, Chip Davis wrote:
+/* 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) {
Why are you checking locinfo->lc_category[category].locale here?
To avoid overwriting it and leaking it in case it was set by init_category_name() earlier. Also, if I don't do this, the msvcr110 tests fail.
Thanks, Piotr
Chip
Hi Chip,
The patch is causing lots of compilation warnings like e.g.: msvcr90.c: In function ‘test__get_current_locale’: msvcr90.c:2064:28: warning: passing argument 1 of ‘winetest_ok’ makes integer from pointer without a cast [-Wint-conversion] 2064 | todo_wine ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n"); | ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~ | | | int *
Thanks, Piotr
On 2/2/20 11:55 PM, Chip Davis wrote:
Signed-off-by: Chip Davis cdavis@codeweavers.com
v2: Bail if setlocale() fails. Mark a result as broken().
dlls/msvcr90/tests/msvcr90.c | 466 +++++++++++++++++++++++++++++++++++ 1 file changed, 466 insertions(+)
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c index c8a49f25492d..c81f4410d60b 100644 --- a/dlls/msvcr90/tests/msvcr90.c +++ b/dlls/msvcr90/tests/msvcr90.c @@ -139,6 +139,22 @@ static int (__cdecl *p_swscanf)(const wchar_t *str, const wchar_t* format, ...); static int (__cdecl *p____mb_cur_max_l_func)(_locale_t locale); static _locale_t (__cdecl *p__create_locale)(int, const char*); static void (__cdecl *p__free_locale)(_locale_t); +static _locale_t (__cdecl *p__get_current_locale)(void);
+struct __lc_time_data {
- const char *short_wday[7];
- const char *wday[7];
- const char *short_mon[12];
- const char *mon[12];
- const char *am;
- const char *pm;
- const char *short_date;
- const char *date;
- const char *time;
- LCID lcid;
- int unk;
- int refcount;
+};
/* make sure we use the correct errno */ #undef errno @@ -408,6 +424,7 @@ static BOOL init(void) SET(p____mb_cur_max_l_func, "___mb_cur_max_l_func"); SET(p__create_locale, "_create_locale"); SET(p__free_locale, "_free_locale");
SET(p__get_current_locale, "_get_current_locale");
if (sizeof(void *) == 8) {
@@ -1961,6 +1978,454 @@ static void test____mb_cur_max_l_func(void) p__free_locale(l); }
+static void test__get_current_locale(void) +{
- _locale_t l = p__get_current_locale(), l2 = p__get_current_locale();
- int i;
+#define lc_str(lc, s) \
- ok(!strcmp(l->locinfo->lc_category[lc].locale, s), #lc " = "%s"\n", \
l->locinfo->lc_category[lc].locale)
- lc_str(LC_COLLATE, "C");
- lc_str(LC_CTYPE, "C");
- lc_str(LC_MONETARY, "C");
- lc_str(LC_NUMERIC, "C");
- lc_str(LC_TIME, "C");
- ok(l->locinfo->refcount == 3, "refcount = %d\n", l->locinfo->refcount);
- if(!p_setlocale(LC_ALL, "english")) {
win_skip("English locale not available\n");
p__free_locale(l);
p__free_locale(l2);
return;
- }
- todo_wine {
lc_str(LC_COLLATE, "C");
lc_str(LC_CTYPE, "C");
lc_str(LC_MONETARY, "C");
lc_str(LC_NUMERIC, "C");
lc_str(LC_TIME, "C");
- }
+#undef lc_str
- todo_wine ok(l->locinfo->refcount == 2, "refcount = %d\n", l->locinfo->refcount);
- ok(l->locinfo == l2->locinfo, "different locinfo pointers\n");
- ok(l->mbcinfo == l2->mbcinfo, "different mbcinfo pointers\n");
- p__free_locale(l);
- p__free_locale(l2);
- l = p__get_current_locale();
- p_setlocale(LC_COLLATE, "C");
- l2 = p__get_current_locale();
- todo_wine {
ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount);
ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount);
- }
- todo_wine {
ok(l->locinfo->lc_category[LC_COLLATE].locale != l2->locinfo->lc_category[LC_COLLATE].locale,
"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);
- }
- 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);
ok(l->locinfo->lc_category[i].refcount == l2->locinfo->lc_category[i].refcount,
"different refcount pointers for category %d\n", i);
todo_wine ok(*l->locinfo->lc_category[i].refcount == 3, "refcount = %d for category %d\n",
*l->locinfo->lc_category[i].refcount, i);
- }
- todo_wine ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n",
l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp);
- ok(l->locinfo->lc_codepage == l2->locinfo->lc_codepage, "different lc_codepages %u, %u\n",
l->locinfo->lc_codepage, l2->locinfo->lc_codepage);
- ok(l->locinfo->lc_clike == l2->locinfo->lc_clike, "different lc_clike values %d, %d\n",
l->locinfo->lc_clike, l2->locinfo->lc_clike);
- /* The meaning of this member seems to be reversed--go figure */
- ok(l->locinfo->lc_clike, "non-C locale is C-like\n");
- ok(l->locinfo->ctype1 == l2->locinfo->ctype1, "different ctype1 pointers\n");
- ok(l->locinfo->pclmap == l2->locinfo->pclmap, "different clmap pointers\n");
- ok(l->locinfo->pcumap == l2->locinfo->pcumap, "different cumap pointers\n");
- ok(l->locinfo->ctype1_refcount == l2->locinfo->ctype1_refcount, "different ctype1_refcount pointers\n");
- todo_wine ok(*l->locinfo->ctype1_refcount == 3, "refcount = %d\n", *l->locinfo->ctype1_refcount);
- ok(l->locinfo->lconv == l2->locinfo->lconv, "different lconv pointers\n");
- ok(l->locinfo->lconv_intl_refcount == l2->locinfo->lconv_intl_refcount, "different lconv_intl_refcount pointers\n");
- todo_wine ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n");
- if(l->locinfo->lconv_intl_refcount)
todo_wine ok(*l->locinfo->lconv_intl_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_intl_refcount);
- ok(l->locinfo->lconv->decimal_point == l2->locinfo->lconv->decimal_point, "different LC_NUMERIC pointers\n");
- ok(l->locinfo->lconv_num_refcount == l2->locinfo->lconv_num_refcount, "different lconv_num_refcount pointers\n");
- todo_wine ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n");
- if(l->locinfo->lconv_num_refcount)
todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount);
- ok(l->locinfo->lconv->currency_symbol == l2->locinfo->lconv->currency_symbol, "different LC_MONETARY pointers\n");
- ok(l->locinfo->lconv_mon_refcount == l2->locinfo->lconv_mon_refcount, "different lconv_mon_refcount pointers\n");
- todo_wine ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n");
- if(l->locinfo->lconv_mon_refcount)
todo_wine ok(*l->locinfo->lconv_mon_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_mon_refcount);
- ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n");
- todo_wine ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk);
- todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
- p__free_locale(l2);
- p_setlocale(LC_CTYPE, "C");
- l2 = p__get_current_locale();
- todo_wine {
ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount);
ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount);
- }
- for(i = LC_COLLATE; i < LC_MONETARY; 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);
}
- }
- for(i = LC_MONETARY; 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);
ok(l->locinfo->lc_category[i].refcount == l2->locinfo->lc_category[i].refcount,
"different refcount pointers for category %d\n", i);
todo_wine ok(*l->locinfo->lc_category[i].refcount == 3, "refcount = %d for category %d\n",
*l->locinfo->lc_category[i].refcount, i);
- }
- todo_wine {
ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n",
l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp);
ok(l->locinfo->lc_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n",
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");
- 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");
ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n");
ok(l->locinfo->ctype1_refcount, "null refcount pointer for non-C locale\n");
if(l->locinfo->ctype1_refcount)
ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount);
- }
- ok(!l2->locinfo->ctype1_refcount, "nonnull refcount pointer for C locale\n");
- ok(l->locinfo->lconv == l2->locinfo->lconv, "different lconv pointers\n");
- ok(l->locinfo->lconv_intl_refcount == l2->locinfo->lconv_intl_refcount, "different lconv_intl_refcount pointers\n");
- todo_wine ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n");
- if(l->locinfo->lconv_intl_refcount)
todo_wine ok(*l->locinfo->lconv_intl_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_intl_refcount);
- ok(l->locinfo->lconv->decimal_point == l2->locinfo->lconv->decimal_point, "different LC_NUMERIC pointers\n");
- ok(l->locinfo->lconv_num_refcount == l2->locinfo->lconv_num_refcount, "different lconv_num_refcount pointers\n");
- todo_wine ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n");
- if(l->locinfo->lconv_num_refcount)
todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount);
- ok(l->locinfo->lconv->currency_symbol == l2->locinfo->lconv->currency_symbol, "different LC_MONETARY pointers\n");
- ok(l->locinfo->lconv_mon_refcount == l2->locinfo->lconv_mon_refcount, "different lconv_mon_refcount pointers\n");
- todo_wine ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n");
- if(l->locinfo->lconv_mon_refcount)
todo_wine ok(*l->locinfo->lconv_mon_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_mon_refcount);
- ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n");
- todo_wine ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk);
- todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
- p__free_locale(l2);
- p_setlocale(LC_MONETARY, "C");
- l2 = p__get_current_locale();
- todo_wine {
ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount);
ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount);
- }
- for(i = LC_COLLATE; i <= LC_MONETARY; 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);
}
- }
- for(i = LC_NUMERIC; 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);
ok(l->locinfo->lc_category[i].refcount == l2->locinfo->lc_category[i].refcount,
"different refcount pointers for category %d\n", i);
todo_wine ok(*l->locinfo->lc_category[i].refcount == 3, "refcount = %d for category %d\n",
*l->locinfo->lc_category[i].refcount, i);
- }
- todo_wine {
ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n",
l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp);
ok(l->locinfo->lc_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n",
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");
- 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");
ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n");
ok(l->locinfo->ctype1_refcount, "null refcount pointer for non-C locale\n");
if(l->locinfo->ctype1_refcount)
ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount);
- }
- ok(!l2->locinfo->ctype1_refcount, "nonnull refcount pointer for C locale\n");
- todo_wine {
ok(l->locinfo->lconv != l2->locinfo->lconv, "same lconv pointers\n");
ok(l->locinfo->lconv_intl_refcount != l2->locinfo->lconv_intl_refcount, "same lconv_intl_refcount pointers\n");
ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n");
if(l->locinfo->lconv_intl_refcount)
ok(*l->locinfo->lconv_intl_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_intl_refcount);
ok(l2->locinfo->lconv_intl_refcount, "null refcount pointer for C locale\n");
if(l2->locinfo->lconv_intl_refcount)
ok(*l2->locinfo->lconv_intl_refcount == 2, "refcount = %d\n", *l2->locinfo->lconv_intl_refcount);
- }
- ok(l->locinfo->lconv->decimal_point == l2->locinfo->lconv->decimal_point, "different LC_NUMERIC pointers\n");
- ok(l->locinfo->lconv_num_refcount == l2->locinfo->lconv_num_refcount, "different lconv_num_refcount pointers\n");
- todo_wine ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n");
- if(l->locinfo->lconv_num_refcount)
todo_wine ok(*l->locinfo->lconv_num_refcount == 3, "refcount = %d\n", *l->locinfo->lconv_num_refcount);
- todo_wine {
ok(l->locinfo->lconv->currency_symbol != l2->locinfo->lconv->currency_symbol, "same LC_MONETARY pointers\n");
ok(l->locinfo->lconv_mon_refcount != l2->locinfo->lconv_mon_refcount, "same lconv_mon_refcount pointers\n");
ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n");
if(l->locinfo->lconv_mon_refcount)
ok(*l->locinfo->lconv_mon_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_mon_refcount);
- }
- ok(!l2->locinfo->lconv_mon_refcount, "nonnull refcount pointer for C locale\n");
- ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n");
- todo_wine ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk);
- todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
- p__free_locale(l2);
- p_setlocale(LC_NUMERIC, "C");
- l2 = p__get_current_locale();
- todo_wine {
ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount);
ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount);
- }
- for(i = LC_COLLATE; i <= LC_NUMERIC; 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[LC_TIME].locale == l2->locinfo->lc_category[LC_TIME].locale,
"different locale name pointers for LC_TIME\n");
- ok(l->locinfo->lc_category[LC_TIME].refcount == l2->locinfo->lc_category[LC_TIME].refcount,
"different refcount pointers for LC_TIME\n");
- todo_wine ok(*l->locinfo->lc_category[LC_TIME].refcount == 3, "refcount = %d\n",
*l->locinfo->lc_category[LC_TIME].refcount);
- todo_wine {
ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n",
l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp);
ok(l->locinfo->lc_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n",
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");
- 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");
ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n");
ok(l->locinfo->ctype1_refcount, "null refcount pointer for non-C locale\n");
if(l->locinfo->ctype1_refcount)
ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount);
- }
- ok(!l2->locinfo->ctype1_refcount, "nonnull refcount pointer for C locale\n");
- todo_wine {
ok(l->locinfo->lconv != l2->locinfo->lconv, "same lconv pointers\n");
ok(l->locinfo->lconv_intl_refcount != l2->locinfo->lconv_intl_refcount, "same lconv_intl_refcount pointers\n");
ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n");
if(l->locinfo->lconv_intl_refcount)
ok(*l->locinfo->lconv_intl_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_intl_refcount);
- }
- ok(!l2->locinfo->lconv_intl_refcount, "nonnull refcount pointer for C locale\n");
- todo_wine {
ok(l->locinfo->lconv->decimal_point != l2->locinfo->lconv->decimal_point, "same LC_NUMERIC pointers\n");
ok(l->locinfo->lconv_num_refcount != l2->locinfo->lconv_num_refcount, "same lconv_num_refcount pointers\n");
ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n");
if(l->locinfo->lconv_num_refcount)
ok(*l->locinfo->lconv_num_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_num_refcount);
- }
- ok(!l2->locinfo->lconv_num_refcount, "nonnull refcount pointer for C locale\n");
- todo_wine {
ok(l->locinfo->lconv->currency_symbol != l2->locinfo->lconv->currency_symbol, "same LC_MONETARY pointers\n");
ok(l->locinfo->lconv_mon_refcount != l2->locinfo->lconv_mon_refcount, "same lconv_mon_refcount pointers\n");
ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n");
if(l->locinfo->lconv_mon_refcount)
ok(*l->locinfo->lconv_mon_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_mon_refcount);
- }
- ok(!l2->locinfo->lconv_mon_refcount, "nonnull refcount pointer for C locale\n");
- ok(l->locinfo->lc_time_curr == l2->locinfo->lc_time_curr, "different lc_time_curr pointers\n");
- todo_wine ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk);
- todo_wine ok(l->locinfo->lc_time_curr->refcount == 3, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
- p__free_locale(l2);
- p_setlocale(LC_TIME, "C");
- l2 = p__get_current_locale();
- todo_wine {
ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount);
ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount);
- }
- todo_wine {
for(i = LC_MIN+1; i <= LC_MAX; i++) {
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);
}
- }
- todo_wine {
ok(l->locinfo->lc_collate_cp != l2->locinfo->lc_collate_cp, "same lc_collate_cp %u, %u\n",
l->locinfo->lc_collate_cp, l2->locinfo->lc_collate_cp);
ok(l->locinfo->lc_codepage != l2->locinfo->lc_codepage, "same lc_codepages %u, %u\n",
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");
- 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");
ok(l->locinfo->ctype1_refcount != l2->locinfo->ctype1_refcount, "same ctype1_refcount pointers\n");
ok(l->locinfo->ctype1_refcount, "null refcount pointer for non-C locale\n");
if(l->locinfo->ctype1_refcount)
ok(*l->locinfo->ctype1_refcount == 1, "refcount = %d\n", *l->locinfo->ctype1_refcount);
- }
- ok(!l2->locinfo->ctype1_refcount, "nonnull refcount pointer for C locale\n");
- todo_wine {
ok(l->locinfo->lconv != l2->locinfo->lconv, "same lconv pointers\n");
ok(l->locinfo->lconv_intl_refcount != l2->locinfo->lconv_intl_refcount, "same lconv_intl_refcount pointers\n");
ok(l->locinfo->lconv_intl_refcount, "null refcount pointer in non-C locale\n");
if(l->locinfo->lconv_intl_refcount)
ok(*l->locinfo->lconv_intl_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_intl_refcount);
- }
- ok(!l2->locinfo->lconv_intl_refcount, "nonnull refcount pointer for C locale\n");
- todo_wine {
ok(l->locinfo->lconv->decimal_point != l2->locinfo->lconv->decimal_point, "same LC_NUMERIC pointers\n");
ok(l->locinfo->lconv_num_refcount != l2->locinfo->lconv_num_refcount, "same lconv_num_refcount pointers\n");
ok(l->locinfo->lconv_num_refcount, "null refcount pointer in non-C locale\n");
if(l->locinfo->lconv_num_refcount)
ok(*l->locinfo->lconv_num_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_num_refcount);
- }
- ok(!l2->locinfo->lconv_num_refcount, "nonnull refcount pointer for C locale\n");
- todo_wine {
ok(l->locinfo->lconv->currency_symbol != l2->locinfo->lconv->currency_symbol, "same LC_MONETARY pointers\n");
ok(l->locinfo->lconv_mon_refcount != l2->locinfo->lconv_mon_refcount, "same lconv_mon_refcount pointers\n");
ok(l->locinfo->lconv_mon_refcount, "null refcount pointer in non-C locale\n");
if(l->locinfo->lconv_mon_refcount)
ok(*l->locinfo->lconv_mon_refcount == 1, "refcount = %d\n", *l->locinfo->lconv_mon_refcount);
- }
- ok(!l2->locinfo->lconv_mon_refcount, "nonnull refcount pointer for C locale\n");
- todo_wine ok(l->locinfo->lc_time_curr != l2->locinfo->lc_time_curr, "same lc_time_curr pointers\n");
- ok(l->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l->locinfo->lc_time_curr->unk);
- todo_wine ok(l->locinfo->lc_time_curr->refcount == 1, "refcount = %d\n", l->locinfo->lc_time_curr->refcount);
- ok(l2->locinfo->lc_time_curr->unk == 1, "unk = %d\n", l2->locinfo->lc_time_curr->unk);
- todo_wine ok(l2->locinfo->lc_time_curr->refcount == 3 || broken(l2->locinfo->lc_time_curr->refcount == 2),
"refcount = %d\n", l2->locinfo->lc_time_curr->refcount);
- p__free_locale(l2);
- p__free_locale(l);
- p_setlocale(LC_ALL, "C");
+}
- START_TEST(msvcr90) { if(!init())
@@ -2001,4 +2466,5 @@ START_TEST(msvcr90) test___strncnt(); test_swscanf(); test____mb_cur_max_l_func();
- test__get_current_locale(); }