Piotr Caban : msvcrt: Return thread locale copy in get_locinfo and get_mbcinfo.
Alexandre Julliard
julliard at winehq.org
Wed Nov 25 15:58:54 CST 2020
Module: wine
Branch: master
Commit: bcd0096d09e0cb0a6a2fb2ec9ffe3f4c72ec341a
URL: https://source.winehq.org/git/wine.git/?a=commit;h=bcd0096d09e0cb0a6a2fb2ec9ffe3f4c72ec341a
Author: Piotr Caban <piotr at codeweavers.com>
Date: Wed Nov 25 20:24:34 2020 +0100
msvcrt: Return thread locale copy in get_locinfo and get_mbcinfo.
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/msvcr90/tests/msvcr90.c | 4 +-
dlls/msvcrt/locale.c | 107 +++++++++++++++++++++++++++----------------
2 files changed, 70 insertions(+), 41 deletions(-)
diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c
index deca9be47fe..35967b2831c 100644
--- a/dlls/msvcr90/tests/msvcr90.c
+++ b/dlls/msvcr90/tests/msvcr90.c
@@ -1210,9 +1210,9 @@ static void test_getptd(void)
ok(p_fpecode() == &ptd->fpecode, "ptd->fpecode is incorrect\n");
mbcinfo = ptd->mbcinfo;
locinfo = ptd->locinfo;
- todo_wine ok(ptd->have_locale == 1, "ptd->have_locale = %x\n", ptd->have_locale);
+ ok(ptd->have_locale == 1, "ptd->have_locale = %x\n", ptd->have_locale);
p_configthreadlocale(1);
- todo_wine ok(mbcinfo == ptd->mbcinfo, "ptd->mbcinfo != mbcinfo\n");
+ ok(mbcinfo == ptd->mbcinfo, "ptd->mbcinfo != mbcinfo\n");
ok(locinfo == ptd->locinfo, "ptd->locinfo != locinfo\n");
ok(ptd->have_locale == 3, "ptd->have_locale = %x\n", ptd->have_locale);
ok(p_get_terminate() == ptd->terminate_handler, "ptd->terminate_handler != _get_terminate()\n");
diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c
index 82a499c5637..3925678a9fd 100644
--- a/dlls/msvcrt/locale.c
+++ b/dlls/msvcrt/locale.c
@@ -585,6 +585,22 @@ static BOOL update_threadlocinfo_category(LCID lcid, unsigned short cp,
return TRUE;
}
+/*********************************************************************
+ * _lock_locales (UCRTBASE.@)
+ */
+void CDECL _lock_locales(void)
+{
+ _lock(_SETLOCALE_LOCK);
+}
+
+/*********************************************************************
+ * _unlock_locales (UCRTBASE.@)
+ */
+void CDECL _unlock_locales(void)
+{
+ _unlock(_SETLOCALE_LOCK);
+}
+
static MSVCRT_pthreadlocinfo* CDECL get_locinfo_ptr(void) {
thread_data_t *data = msvcrt_get_thread_data();
@@ -594,18 +610,64 @@ static MSVCRT_pthreadlocinfo* CDECL get_locinfo_ptr(void) {
return &data->locinfo;
}
+static void CDECL 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->lc_category[i].wrefcount)
+ InterlockedIncrement(locinfo->lc_category[i].wrefcount);
+ }
+ 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);
+}
+
+static void CDECL update_thread_locale(thread_data_t *data)
+{
+ if((data->locale_flags & LOCALE_FREE) && ((data->locale_flags & LOCALE_THREAD) ||
+ (data->locinfo == MSVCRT_locale->locinfo && data->mbcinfo == MSVCRT_locale->mbcinfo)))
+ return;
+
+ if(data->locale_flags & LOCALE_FREE)
+ {
+ free_locinfo(data->locinfo);
+ free_mbcinfo(data->mbcinfo);
+ }
+
+ _lock_locales();
+ data->locinfo = MSVCRT_locale->locinfo;
+ grab_locinfo(data->locinfo);
+ _unlock_locales();
+
+ _lock(_MB_CP_LOCK);
+ data->mbcinfo = MSVCRT_locale->mbcinfo;
+ InterlockedIncrement(&data->mbcinfo->refcount);
+ _unlock(_MB_CP_LOCK);
+
+ data->locale_flags |= LOCALE_FREE;
+}
+
/* INTERNAL: returns threadlocinfo struct */
MSVCRT_pthreadlocinfo CDECL get_locinfo(void) {
- return *get_locinfo_ptr();
+ thread_data_t *data = msvcrt_get_thread_data();
+ update_thread_locale(data);
+ return data->locinfo;
}
/* INTERNAL: returns pthreadmbcinfo struct */
MSVCRT_pthreadmbcinfo CDECL get_mbcinfo(void) {
thread_data_t *data = msvcrt_get_thread_data();
-
- if(!data || !(data->locale_flags & LOCALE_THREAD))
- return MSVCRT_locale->mbcinfo;
-
+ update_thread_locale(data);
return data->mbcinfo;
}
@@ -1117,26 +1179,9 @@ void free_mbcinfo(MSVCRT_pthreadmbcinfo mbcinfo)
MSVCRT_free(mbcinfo);
}
-/*********************************************************************
- * _lock_locales (UCRTBASE.@)
- */
-void CDECL _lock_locales(void)
-{
- _lock(_SETLOCALE_LOCK);
-}
-
-/*********************************************************************
- * _unlock_locales (UCRTBASE.@)
- */
-void CDECL _unlock_locales(void)
-{
- _unlock(_SETLOCALE_LOCK);
-}
-
MSVCRT__locale_t CDECL get_current_locale_noalloc(MSVCRT__locale_t locale)
{
thread_data_t *data = msvcrt_get_thread_data();
- int i;
if(!data || !(data->locale_flags & LOCALE_THREAD))
{
@@ -1149,25 +1194,9 @@ MSVCRT__locale_t CDECL get_current_locale_noalloc(MSVCRT__locale_t locale)
locale->mbcinfo = data->mbcinfo;
}
- InterlockedIncrement(&locale->locinfo->refcount);
- for(i=MSVCRT_LC_MIN+1; i<=MSVCRT_LC_MAX; i++)
- {
- InterlockedIncrement(locale->locinfo->lc_category[i].refcount);
- if(locale->locinfo->lc_category[i].wrefcount)
- InterlockedIncrement(locale->locinfo->lc_category[i].wrefcount);
- }
- if(locale->locinfo->lconv_intl_refcount)
- InterlockedIncrement(locale->locinfo->lconv_intl_refcount);
- if(locale->locinfo->lconv_num_refcount)
- InterlockedIncrement(locale->locinfo->lconv_num_refcount);
- if(locale->locinfo->lconv_mon_refcount)
- InterlockedIncrement(locale->locinfo->lconv_mon_refcount);
- if(locale->locinfo->ctype1_refcount)
- InterlockedIncrement(locale->locinfo->ctype1_refcount);
- InterlockedIncrement(&locale->locinfo->lc_time_curr->refcount);
+ grab_locinfo(locale->locinfo);
if(locale->locinfo == MSVCRT_locale->locinfo)
_unlock_locales();
-
InterlockedIncrement(&locale->mbcinfo->refcount);
return locale;
}
More information about the wine-cvs
mailing list