This patch series fixes management of _locale_t objects to align more with native. Some apps and libraries--most notably libc++--depend on this to behave properly.
The first patch contains tests demonstrating the proper behavior of _locale_t objects and their various members. Patches 2 through 6 copy various portions of the threadlocinfo struct from old to new when they aren't updated. This is all to clear the way for patch 7, which updates the locale pointer in msvcrt itself instead of the contents of the threadlocinfo struct. The last patch fixes the reference counting behavior of _get_current_locale() to match native.
Signed-off-by: Chip Davis cdavis@codeweavers.com --- v3: Fix implicit pointer-to-int cast warnings, because we haven't adopted the C99 _Bool type yet. --- 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..d51e3c985d63 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 --- v4: Update for changes in patch 1. --- dlls/msvcr90/tests/msvcr90.c | 64 ++++++++++------------------ dlls/msvcrt/locale.c | 81 ++++++++++++++++++++++++++++-------- 2 files changed, 85 insertions(+), 60 deletions(-)
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c index d51e3c985d63..693b8a30c5c1 100644 --- a/dlls/msvcr90/tests/msvcr90.c +++ b/dlls/msvcr90/tests/msvcr90.c @@ -2030,15 +2030,11 @@ static void test__get_current_locale(void) "same locale name pointers for LC_COLLATE\n"); ok(l->locinfo->lc_category[LC_COLLATE].refcount != l2->locinfo->lc_category[LC_COLLATE].refcount, "same refcount pointers for LC_COLLATE\n"); - ok(!!l->locinfo->lc_category[LC_COLLATE].refcount, "null refcount pointer for LC_COLLATE\n"); - if(l->locinfo->lc_category[LC_COLLATE].refcount) - ok(*l->locinfo->lc_category[LC_COLLATE].refcount == 1, "refcount = %d\n", - *l->locinfo->lc_category[LC_COLLATE].refcount); - ok(!!l2->locinfo->lc_category[LC_COLLATE].refcount, "null refcount pointer for LC_COLLATE\n"); - if(l2->locinfo->lc_category[LC_COLLATE].refcount) - ok(*l2->locinfo->lc_category[LC_COLLATE].refcount == 2, "refcount = %d\n", - *l2->locinfo->lc_category[LC_COLLATE].refcount); } + ok(*l->locinfo->lc_category[LC_COLLATE].refcount == 1, "refcount = %d\n", + *l->locinfo->lc_category[LC_COLLATE].refcount); + todo_wine ok(*l2->locinfo->lc_category[LC_COLLATE].refcount == 2, "refcount = %d\n", + *l2->locinfo->lc_category[LC_COLLATE].refcount); for(i = LC_CTYPE; i <= LC_MAX; i++) { ok(l->locinfo->lc_category[i].locale == l2->locinfo->lc_category[i].locale, "different locale name pointers for category %d\n", i); @@ -2101,15 +2097,11 @@ static void test__get_current_locale(void) "same locale name pointers for category %d\n", i); ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount, "same refcount pointers for category %d\n", i); - ok(!!l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i); - if(l->locinfo->lc_category[i].refcount) - ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n", - *l->locinfo->lc_category[i].refcount, i); - ok(!!l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i); - if(l2->locinfo->lc_category[i].refcount) - ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n", - *l2->locinfo->lc_category[i].refcount, i); } + ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n", + *l->locinfo->lc_category[i].refcount, i); + todo_wine ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n", + *l2->locinfo->lc_category[i].refcount, i); } for(i = LC_MONETARY; i <= LC_MAX; i++) { ok(l->locinfo->lc_category[i].locale == l2->locinfo->lc_category[i].locale, @@ -2180,15 +2172,11 @@ static void test__get_current_locale(void) "same locale name pointers for category %d\n", i); ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount, "same refcount pointers for category %d\n", i); - ok(!!l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i); - if(l->locinfo->lc_category[i].refcount) - ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n", - *l->locinfo->lc_category[i].refcount, i); - ok(!!l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i); - if(l2->locinfo->lc_category[i].refcount) - ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n", - *l2->locinfo->lc_category[i].refcount, i); } + ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n", + *l->locinfo->lc_category[i].refcount, i); + todo_wine ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n", + *l2->locinfo->lc_category[i].refcount, i); } for(i = LC_NUMERIC; i <= LC_MAX; i++) { ok(l->locinfo->lc_category[i].locale == l2->locinfo->lc_category[i].locale, @@ -2267,15 +2255,11 @@ static void test__get_current_locale(void) "same locale name pointers for category %d\n", i); ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount, "same refcount pointers for category %d\n", i); - ok(!!l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i); - if(l->locinfo->lc_category[i].refcount) - ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n", - *l->locinfo->lc_category[i].refcount, i); - ok(!!l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i); - if(l2->locinfo->lc_category[i].refcount) - ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n", - *l2->locinfo->lc_category[i].refcount, i); } + ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n", + *l->locinfo->lc_category[i].refcount, i); + todo_wine ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n", + *l2->locinfo->lc_category[i].refcount, i); } ok(l->locinfo->lc_category[LC_TIME].locale == l2->locinfo->lc_category[LC_TIME].locale, "different locale name pointers for LC_TIME\n"); @@ -2347,21 +2331,17 @@ static void test__get_current_locale(void) ok(l2->locinfo->refcount == 2, "refcount = %d\n", l2->locinfo->refcount); }
- todo_wine { - for(i = LC_MIN+1; i <= LC_MAX; i++) { + for(i = LC_MIN+1; i <= LC_MAX; i++) { + todo_wine { ok(l->locinfo->lc_category[i].locale != l2->locinfo->lc_category[i].locale, "same locale name pointers for category %d\n", i); ok(l->locinfo->lc_category[i].refcount != l2->locinfo->lc_category[i].refcount, "same refcount pointers for category %d\n", i); - ok(!!l->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i); - if(l->locinfo->lc_category[i].refcount) - ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n", - *l->locinfo->lc_category[i].refcount, i); - ok(!!l2->locinfo->lc_category[i].refcount, "null refcount pointer for category %d\n", i); - if(l2->locinfo->lc_category[i].refcount) - ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n", - *l2->locinfo->lc_category[i].refcount, i); } + ok(*l->locinfo->lc_category[i].refcount == 1, "refcount = %d for category %d\n", + *l->locinfo->lc_category[i].refcount, i); + todo_wine ok(*l2->locinfo->lc_category[i].refcount == 2, "refcount = %d for category %d\n", + *l2->locinfo->lc_category[i].refcount, i); }
todo_wine { diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index f6e7631b4f50..20004648ca79 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -418,6 +418,17 @@ static BOOL init_category_name(const char *name, int len, return TRUE; }
+/* INTERNAL: Copy lc_handle, lc_id, and lc_category from one threadlocinfo to another */ +static void copy_threadlocinfo_category(MSVCRT_pthreadlocinfo locinfo, MSVCRT_pthreadlocinfo old_locinfo, int category) +{ + locinfo->lc_handle[category] = old_locinfo->lc_handle[category]; + locinfo->lc_id[category] = old_locinfo->lc_id[category]; + if(!locinfo->lc_category[category].locale) { + locinfo->lc_category[category] = old_locinfo->lc_category[category]; + InterlockedIncrement(locinfo->lc_category[category].refcount); + } +} + /* INTERNAL: Set lc_handle, lc_id and lc_category in threadlocinfo struct */ static BOOL update_threadlocinfo_category(LCID lcid, unsigned short cp, MSVCRT_pthreadlocinfo locinfo, int category) @@ -878,11 +889,14 @@ void free_locinfo(MSVCRT_pthreadlocinfo locinfo) return;
for(i=MSVCRT_LC_MIN+1; i<=MSVCRT_LC_MAX; i++) { - MSVCRT_free(locinfo->lc_category[i].locale); - MSVCRT_free(locinfo->lc_category[i].refcount); #if _MSVCR_VER >= 110 MSVCRT_free(locinfo->lc_name[i]); #endif + if(!locinfo->lc_category[i].refcount + || InterlockedDecrement(locinfo->lc_category[i].refcount)) + continue; + MSVCRT_free(locinfo->lc_category[i].locale); + MSVCRT_free(locinfo->lc_category[i].refcount); }
if(locinfo->lconv) { @@ -1200,8 +1214,11 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_COLLATE, category, old_locinfo, lcid[MSVCRT_LC_COLLATE], cp[MSVCRT_LC_COLLATE])) { - locinfo->lc_handle[MSVCRT_LC_COLLATE] = old_locinfo->lc_handle[MSVCRT_LC_COLLATE]; - locinfo->lc_id[MSVCRT_LC_COLLATE].wCodePage = old_locinfo->lc_id[MSVCRT_LC_COLLATE].wCodePage; + copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_COLLATE); + if(!set_lc_locale_name(locinfo, MSVCRT_LC_COLLATE)) { + free_locinfo(locinfo); + return NULL; + } } else if(lcid[MSVCRT_LC_COLLATE] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_COLLATE)) { if(!update_threadlocinfo_category(lcid[MSVCRT_LC_COLLATE], cp[MSVCRT_LC_COLLATE], locinfo, MSVCRT_LC_COLLATE)) { @@ -1215,8 +1232,12 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, free_locinfo(locinfo); return NULL; } - } else - locinfo->lc_category[MSVCRT_LC_COLLATE].locale = MSVCRT__strdup("C"); + } else { + if(!init_category_name("C", 1, locinfo, MSVCRT_LC_COLLATE)) { + free_locinfo(locinfo); + return NULL; + } + }
if(locale_name[MSVCRT_LC_CTYPE] && !init_category_name(locale_name[MSVCRT_LC_CTYPE], @@ -1227,8 +1248,11 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_CTYPE, category, old_locinfo, lcid[MSVCRT_LC_CTYPE], cp[MSVCRT_LC_CTYPE])) { - locinfo->lc_handle[MSVCRT_LC_CTYPE] = old_locinfo->lc_handle[MSVCRT_LC_CTYPE]; - locinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage = old_locinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage; + copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_CTYPE); + if(!set_lc_locale_name(locinfo, MSVCRT_LC_CTYPE)) { + free_locinfo(locinfo); + return NULL; + } } else if(lcid[MSVCRT_LC_CTYPE] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_CTYPE)) { CPINFO cp_info; int j; @@ -1293,7 +1317,10 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, locinfo->lc_clike = 1; locinfo->mb_cur_max = 1; locinfo->pctype = MSVCRT__ctype+1; - locinfo->lc_category[MSVCRT_LC_CTYPE].locale = MSVCRT__strdup("C"); + if(!init_category_name("C", 1, locinfo, MSVCRT_LC_CTYPE)) { + free_locinfo(locinfo); + return NULL; + }
for(i=0; i<256; i++) { if(locinfo->pctype[i] & MSVCRT__LEADBYTE) @@ -1317,8 +1344,11 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_MONETARY, category, old_locinfo, lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY])) { - locinfo->lc_handle[MSVCRT_LC_MONETARY] = old_locinfo->lc_handle[MSVCRT_LC_MONETARY]; - locinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage = old_locinfo->lc_id[MSVCRT_LC_MONETARY].wCodePage; + copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_MONETARY); + if(!set_lc_locale_name(locinfo, MSVCRT_LC_MONETARY)) { + free_locinfo(locinfo); + return NULL; + } } else if(lcid[MSVCRT_LC_MONETARY] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_MONETARY)) { if(!update_threadlocinfo_category(lcid[MSVCRT_LC_MONETARY], cp[MSVCRT_LC_MONETARY], locinfo, MSVCRT_LC_MONETARY)) { @@ -1585,7 +1615,10 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, locinfo->lconv->_W_negative_sign[0] = '\0'; #endif
- locinfo->lc_category[MSVCRT_LC_MONETARY].locale = MSVCRT__strdup("C"); + if(!init_category_name("C", 1, locinfo, MSVCRT_LC_MONETARY)) { + free_locinfo(locinfo); + return NULL; + } }
if(locale_name[MSVCRT_LC_NUMERIC] && @@ -1597,8 +1630,11 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_NUMERIC, category, old_locinfo, lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC])) { - locinfo->lc_handle[MSVCRT_LC_NUMERIC] = old_locinfo->lc_handle[MSVCRT_LC_NUMERIC]; - locinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage = old_locinfo->lc_id[MSVCRT_LC_NUMERIC].wCodePage; + copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_NUMERIC); + if(!set_lc_locale_name(locinfo, MSVCRT_LC_NUMERIC)) { + free_locinfo(locinfo); + return NULL; + } } else if(lcid[MSVCRT_LC_NUMERIC] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_NUMERIC)) { if(!update_threadlocinfo_category(lcid[MSVCRT_LC_NUMERIC], cp[MSVCRT_LC_NUMERIC], locinfo, MSVCRT_LC_NUMERIC)) { @@ -1703,7 +1739,10 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, locinfo->lconv->_W_thousands_sep[0] = '\0'; #endif
- locinfo->lc_category[MSVCRT_LC_NUMERIC].locale = MSVCRT__strdup("C"); + if (!init_category_name("C", 1, locinfo, MSVCRT_LC_NUMERIC)) { + free_locinfo(locinfo); + return NULL; + } }
if(locale_name[MSVCRT_LC_TIME] && @@ -1715,8 +1754,11 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category,
if(!category_needs_update(MSVCRT_LC_TIME, category, old_locinfo, lcid[MSVCRT_LC_TIME], cp[MSVCRT_LC_TIME])) { - locinfo->lc_handle[MSVCRT_LC_TIME] = old_locinfo->lc_handle[MSVCRT_LC_TIME]; - locinfo->lc_id[MSVCRT_LC_TIME].wCodePage = old_locinfo->lc_id[MSVCRT_LC_TIME].wCodePage; + copy_threadlocinfo_category(locinfo, old_locinfo, MSVCRT_LC_TIME); + if(!set_lc_locale_name(locinfo, MSVCRT_LC_TIME)) { + free_locinfo(locinfo); + return NULL; + } } else if(lcid[MSVCRT_LC_TIME] && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_TIME)) { if(!update_threadlocinfo_category(lcid[MSVCRT_LC_TIME], cp[MSVCRT_LC_TIME], locinfo, MSVCRT_LC_TIME)) { @@ -1735,7 +1777,10 @@ static MSVCRT_pthreadlocinfo create_locinfo(int category, return NULL; } } else { - locinfo->lc_category[MSVCRT_LC_TIME].locale = MSVCRT__strdup("C"); + if(!init_category_name("C", 1, locinfo, MSVCRT_LC_TIME)) { + free_locinfo(locinfo); + return NULL; + } locinfo->lc_time_curr = &cloc_time_data; }
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 693b8a30c5c1..038e16a1d326 100644 --- a/dlls/msvcr90/tests/msvcr90.c +++ b/dlls/msvcr90/tests/msvcr90.c @@ -2120,10 +2120,10 @@ static void test__get_current_locale(void) l->locinfo->lc_codepage, l2->locinfo->lc_codepage); ok(l->locinfo->lc_clike != l2->locinfo->lc_clike, "same lc_clike values %d, %d\n", l->locinfo->lc_clike, l2->locinfo->lc_clike); + ok(l->locinfo->lc_clike, "non-C locale is C-like\n"); } - ok(l->locinfo->lc_clike, "non-C locale is C-like\n"); + ok(!l2->locinfo->lc_clike, "C locale is not C-like\n"); todo_wine { - ok(!l2->locinfo->lc_clike, "C locale is not C-like\n"); ok(l->locinfo->ctype1 != l2->locinfo->ctype1, "same ctype1 pointers\n"); ok(l->locinfo->pclmap != l2->locinfo->pclmap, "same clmap pointers\n"); ok(l->locinfo->pcumap != l2->locinfo->pcumap, "same cumap pointers\n"); @@ -2195,10 +2195,10 @@ static void test__get_current_locale(void) l->locinfo->lc_codepage, l2->locinfo->lc_codepage); ok(l->locinfo->lc_clike != l2->locinfo->lc_clike, "same lc_clike values %d, %d\n", l->locinfo->lc_clike, l2->locinfo->lc_clike); + ok(l->locinfo->lc_clike, "non-C locale is C-like\n"); } - ok(l->locinfo->lc_clike, "non-C locale is C-like\n"); + ok(!l2->locinfo->lc_clike, "C locale is not C-like\n"); todo_wine { - ok(!l2->locinfo->lc_clike, "C locale is not C-like\n"); ok(l->locinfo->ctype1 != l2->locinfo->ctype1, "same ctype1 pointers\n"); ok(l->locinfo->pclmap != l2->locinfo->pclmap, "same clmap pointers\n"); ok(l->locinfo->pcumap != l2->locinfo->pcumap, "same cumap pointers\n"); @@ -2276,10 +2276,10 @@ static void test__get_current_locale(void) l->locinfo->lc_codepage, l2->locinfo->lc_codepage); ok(l->locinfo->lc_clike != l2->locinfo->lc_clike, "same lc_clike values %d, %d\n", l->locinfo->lc_clike, l2->locinfo->lc_clike); + ok(l->locinfo->lc_clike, "non-C locale is C-like\n"); } - ok(l->locinfo->lc_clike, "non-C locale is C-like\n"); + ok(!l2->locinfo->lc_clike, "C locale is not C-like\n"); todo_wine { - ok(!l2->locinfo->lc_clike, "C locale is not C-like\n"); ok(l->locinfo->ctype1 != l2->locinfo->ctype1, "same ctype1 pointers\n"); ok(l->locinfo->pclmap != l2->locinfo->pclmap, "same clmap pointers\n"); ok(l->locinfo->pcumap != l2->locinfo->pcumap, "same cumap pointers\n"); @@ -2352,10 +2352,10 @@ static void test__get_current_locale(void) l->locinfo->lc_codepage, l2->locinfo->lc_codepage); ok(l->locinfo->lc_clike != l2->locinfo->lc_clike, "same lc_clike values %d, %d\n", l->locinfo->lc_clike, l2->locinfo->lc_clike); + ok(l->locinfo->lc_clike, "non-C locale is C-like\n"); } - ok(l->locinfo->lc_clike, "non-C locale is C-like\n"); + ok(!l2->locinfo->lc_clike, "C locale is not C-like\n"); todo_wine { - ok(!l2->locinfo->lc_clike, "C locale is not C-like\n"); ok(l->locinfo->ctype1 != l2->locinfo->ctype1, "same ctype1 pointers\n"); ok(l->locinfo->pclmap != l2->locinfo->pclmap, "same clmap pointers\n"); ok(l->locinfo->pcumap != l2->locinfo->pcumap, "same cumap pointers\n"); diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c index 3723c14d483b..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 --- v3: Fix a spot I missed. --- 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 | 5 +++-- 5 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c index 038e16a1d326..18c9c3c15cc3 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..280fcc8a829d 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]; @@ -1154,7 +1155,7 @@ static void test_strftime(void) { "day1", "day2", "day3", "day4", "day5", "day6", "day7" }, { "m1", "m2", "m3", "m4", "m5", "m6", "m7", "m8", "m9", "m10", "m11", "m12" }, { "mon1", "mon2", "mon3", "mon4", "mon5", "mon6", "mon7", "mon8", "mon9", "mon10", "mon11", "mon12" }, - "tam", "tpm", 0, 0, 0, { 1, 0 }, + "tam", "tpm", 0, 0, 0, 1, 0, { L"D1", L"D2", L"D3", L"D4", L"D5", L"D6", L"D7" }, { L"Day1", L"Day2", L"Day3", L"Day4", L"Day5", L"Day6", L"Day7" }, { L"M1", L"M2", L"M3", L"M4", L"M5", L"M6", L"M7", L"M8", L"M9", L"M10", L"M11", L"M12" },
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 --- v4: Update for changes in patch 1. --- 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 18c9c3c15cc3..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; }