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