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 a1f269e01cf4..b577260edc98 100644 --- a/dlls/msvcrt/locale.c +++ b/dlls/msvcrt/locale.c @@ -921,6 +921,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) { @@ -929,9 +950,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]); @@ -993,6 +1011,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); }
@@ -1017,9 +1038,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; }