Piotr Caban : msvcrt: Don't overwrite threadmbcinfostruct structure in _setmbcp.

Alexandre Julliard julliard at winehq.org
Thu Nov 19 16:10:23 CST 2020


Module: wine
Branch: master
Commit: 35a8f15361022d9195bd141aa67b22e06007fa16
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=35a8f15361022d9195bd141aa67b22e06007fa16

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Thu Nov 19 18:57:48 2020 +0100

msvcrt: Don't overwrite threadmbcinfostruct structure in _setmbcp.

Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/msvcr90/tests/msvcr90.c | 25 +++++++++++++++++++++----
 dlls/msvcrt/locale.c         | 19 ++++++++++---------
 dlls/msvcrt/mbcs.c           | 42 ++++++++++++++++++++++++++++++------------
 dlls/msvcrt/msvcrt.h         |  3 ++-
 4 files changed, 63 insertions(+), 26 deletions(-)

diff --git a/dlls/msvcr90/tests/msvcr90.c b/dlls/msvcr90/tests/msvcr90.c
index ca5349e3387..08eb4a7ac64 100644
--- a/dlls/msvcr90/tests/msvcr90.c
+++ b/dlls/msvcr90/tests/msvcr90.c
@@ -130,6 +130,7 @@ static int (__cdecl *p_fflush_nolock)(FILE*);
 static size_t (__cdecl *p_mbstowcs)(wchar_t*, const char*, size_t);
 static size_t (__cdecl *p_wcstombs)(char*, const wchar_t*, size_t);
 static char* (__cdecl *p_setlocale)(int, const char*);
+static int (__cdecl *p__setmbcp)(int);
 static int (__cdecl *p__fpieee_flt)(ULONG, EXCEPTION_POINTERS*, int (__cdecl *handler)(_FPIEEE_RECORD*));
 static int (__cdecl *p__memicmp)(const char*, const char*, size_t);
 static int (__cdecl *p__memicmp_l)(const char*, const char*, size_t, _locale_t);
@@ -160,6 +161,16 @@ struct __lc_time_data {
 #undef errno
 #define errno (*p_errno())
 
+typedef struct threadmbcinfostruct {
+    int refcount;
+    int mbcodepage;
+    int ismbcodepage;
+    int mblcid;
+    unsigned short mbulinfo[6];
+    unsigned char mbctype[257];
+    unsigned char mbcasemap[256];
+} threadmbcinfo;
+
 /* type info */
 typedef struct __type_info
 {
@@ -415,6 +426,7 @@ static BOOL init(void)
     SET(p_mbstowcs, "mbstowcs");
     SET(p_wcstombs, "wcstombs");
     SET(p_setlocale, "setlocale");
+    SET(p__setmbcp, "_setmbcp");
     SET(p__fpieee_flt, "_fpieee_flt");
     SET(p__memicmp, "_memicmp");
     SET(p__memicmp_l, "_memicmp_l");
@@ -1979,9 +1991,13 @@ static void test____mb_cur_max_l_func(void)
 
 static void test__get_current_locale(void)
 {
-    _locale_t l = p__get_current_locale(), l2 = p__get_current_locale();
+    _locale_t l, l2;
     int i;
 
+    ok(!p__setmbcp(1252), "_setmbcp failed\n");
+    l = p__get_current_locale();
+    l2 = p__get_current_locale();
+
     ok(!strcmp(l->locinfo->lc_category[LC_COLLATE].locale, "C"),
             "LC_COLLATE = \"%s\"\n", l->locinfo->lc_category[LC_COLLATE].locale);
     ok(!strcmp(l->locinfo->lc_category[LC_CTYPE].locale, "C"),
@@ -1992,6 +2008,7 @@ static void test__get_current_locale(void)
             "LC_NUMERIC = \"%s\"\n", l->locinfo->lc_category[LC_NUMERIC].locale);
     ok(!strcmp(l->locinfo->lc_category[LC_TIME].locale, "C"),
             "LC_TIME = \"%s\"\n", l->locinfo->lc_category[LC_TIME].locale);
+    ok(l->mbcinfo->mbcodepage == 1252, "mbcodepage = %d\n", l->mbcinfo->mbcodepage);
 
     ok(l->locinfo->refcount == 3, "refcount = %d\n", l->locinfo->refcount);
 
@@ -2001,6 +2018,7 @@ static void test__get_current_locale(void)
         p__free_locale(l2);
         return;
     }
+    ok(!p__setmbcp(932), "_setmbcp failed\n");
 
     ok(!strcmp(l->locinfo->lc_category[LC_COLLATE].locale, "C"),
             "LC_COLLATE = \"%s\"\n", l->locinfo->lc_category[LC_COLLATE].locale);
@@ -2012,6 +2030,7 @@ static void test__get_current_locale(void)
             "LC_NUMERIC = \"%s\"\n", l->locinfo->lc_category[LC_NUMERIC].locale);
     ok(!strcmp(l->locinfo->lc_category[LC_TIME].locale, "C"),
             "LC_TIME = \"%s\"\n", l->locinfo->lc_category[LC_TIME].locale);
+    ok(l->mbcinfo->mbcodepage == 1252, "mbcodepage = %d\n", l->mbcinfo->mbcodepage);
 
     ok(l->locinfo->refcount == 2, "refcount = %d\n", l->locinfo->refcount);
     ok(l->locinfo == l2->locinfo, "different locinfo pointers\n");
@@ -2143,9 +2162,7 @@ static void test__get_current_locale(void)
 
     p__free_locale(l2);
 
-    trace("before: %s\n", p_setlocale(LC_ALL, NULL));
-    trace("current locale is: %s\n", p_setlocale(LC_MONETARY, "C"));
-    trace("after: %s\n", p_setlocale(LC_ALL, NULL));
+    p_setlocale(LC_MONETARY, "C");
     l2 = p__get_current_locale();
 
     ok(l->locinfo->refcount == 1, "refcount = %d\n", l->locinfo->refcount);
diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c
index 8543b3f1713..2cedc89530e 100644
--- a/dlls/msvcrt/locale.c
+++ b/dlls/msvcrt/locale.c
@@ -597,14 +597,18 @@ MSVCRT_pthreadlocinfo CDECL get_locinfo(void) {
     return *get_locinfo_ptr();
 }
 
-/* INTERNAL: returns pthreadmbcinfo struct */
-MSVCRT_pthreadmbcinfo CDECL get_mbcinfo(void) {
+MSVCRT_pthreadmbcinfo* CDECL get_mbcinfo_ptr(void) {
     thread_data_t *data = msvcrt_get_thread_data();
 
     if(!data || !data->have_locale)
-        return MSVCRT_locale->mbcinfo;
+        return &MSVCRT_locale->mbcinfo;
 
-    return data->mbcinfo;
+    return &data->mbcinfo;
+}
+
+/* INTERNAL: returns pthreadmbcinfo struct */
+MSVCRT_pthreadmbcinfo CDECL get_mbcinfo(void) {
+    return *get_mbcinfo_ptr();
 }
 
 /* INTERNAL: constructs string returned by setlocale */
@@ -1964,16 +1968,13 @@ MSVCRT__locale_t CDECL MSVCRT__create_locale(int category, const char *locale)
         return NULL;
     }
 
-    loc->mbcinfo = MSVCRT_malloc(sizeof(MSVCRT_threadmbcinfo));
+    loc->mbcinfo = create_mbcinfo(loc->locinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage,
+            loc->locinfo->lc_handle[MSVCRT_LC_CTYPE], NULL);
     if(!loc->mbcinfo) {
         free_locinfo(loc->locinfo);
         MSVCRT_free(loc);
         return NULL;
     }
-
-    loc->mbcinfo->refcount = 1;
-    _setmbcp_l(loc->locinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage,
-            loc->locinfo->lc_handle[MSVCRT_LC_CTYPE], loc->mbcinfo);
     return loc;
 }
 
diff --git a/dlls/msvcrt/mbcs.c b/dlls/msvcrt/mbcs.c
index f9a38184436..1454004610d 100644
--- a/dlls/msvcrt/mbcs.c
+++ b/dlls/msvcrt/mbcs.c
@@ -211,10 +211,9 @@ int CDECL ___mb_cur_max_l_func(MSVCRT__locale_t locale)
 /*********************************************************************
  * INTERNAL: _setmbcp_l
  */
-int _setmbcp_l(int cp, LCID lcid, MSVCRT_pthreadmbcinfo mbcinfo)
+MSVCRT_threadmbcinfo* create_mbcinfo(int cp, LCID lcid, MSVCRT_threadmbcinfo *old_mbcinfo)
 {
-  const char format[] = ".%d";
-
+  MSVCRT_threadmbcinfo *mbcinfo;
   int newcp;
   CPINFO cpi;
   BYTE *bytes;
@@ -225,8 +224,16 @@ int _setmbcp_l(int cp, LCID lcid, MSVCRT_pthreadmbcinfo mbcinfo)
   int ret;
   int i;
 
+  if(old_mbcinfo && cp==old_mbcinfo->mbcodepage
+          && (lcid==-1 || lcid==old_mbcinfo->mblcid)) {
+    InterlockedIncrement(&old_mbcinfo->refcount);
+    return old_mbcinfo;
+  }
+
+  mbcinfo = MSVCRT_malloc(sizeof(MSVCRT_threadmbcinfo));
   if(!mbcinfo)
-      mbcinfo = get_mbcinfo();
+    return NULL;
+  mbcinfo->refcount = 1;
 
   switch (cp)
   {
@@ -250,7 +257,7 @@ int _setmbcp_l(int cp, LCID lcid, MSVCRT_pthreadmbcinfo mbcinfo)
   }
 
   if(lcid == -1) {
-    MSVCRT_sprintf(bufA, format, newcp);
+    MSVCRT_sprintf(bufA, ".%d", newcp);
     mbcinfo->mblcid = MSVCRT_locale_to_LCID(bufA, NULL, NULL);
   } else {
     mbcinfo->mblcid = lcid;
@@ -265,8 +272,8 @@ int _setmbcp_l(int cp, LCID lcid, MSVCRT_pthreadmbcinfo mbcinfo)
   if (!GetCPInfo(newcp, &cpi))
   {
     WARN("Codepage %d not found\n", newcp);
-    *MSVCRT__errno() = MSVCRT_EINVAL;
-    return -1;
+    MSVCRT_free(mbcinfo);
+    return NULL;
   }
 
   /* setup the _mbctype */
@@ -370,10 +377,7 @@ int _setmbcp_l(int cp, LCID lcid, MSVCRT_pthreadmbcinfo mbcinfo)
   }
 
   mbcinfo->mbcodepage = newcp;
-  if(MSVCRT_locale && mbcinfo == MSVCRT_locale->mbcinfo)
-    memcpy(MSVCRT_mbctype, MSVCRT_locale->mbcinfo->mbctype, sizeof(MSVCRT_mbctype));
-
-  return 0;
+  return mbcinfo;
 }
 
 /*********************************************************************
@@ -381,7 +385,21 @@ int _setmbcp_l(int cp, LCID lcid, MSVCRT_pthreadmbcinfo mbcinfo)
  */
 int CDECL _setmbcp(int cp)
 {
-    return _setmbcp_l(cp, -1, NULL);
+    MSVCRT_threadmbcinfo **old_mbcinfo = get_mbcinfo_ptr();
+    MSVCRT_threadmbcinfo *mbcinfo;
+
+    mbcinfo = create_mbcinfo(cp, -1, *old_mbcinfo);
+    if(!mbcinfo) {
+        *MSVCRT__errno() = MSVCRT_EINVAL;
+        return -1;
+    }
+
+    free_mbcinfo(*old_mbcinfo);
+    *old_mbcinfo = mbcinfo;
+
+    if(mbcinfo == MSVCRT_locale->mbcinfo)
+        memcpy(MSVCRT_mbctype, MSVCRT_locale->mbcinfo->mbctype, sizeof(MSVCRT_mbctype));
+    return 0;
 }
 
 /*********************************************************************
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h
index 503aea33bd0..6c103ee3ca2 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -1136,10 +1136,11 @@ MSVCRT__locale_t CDECL get_current_locale_noalloc(MSVCRT__locale_t locale) DECLS
 void CDECL free_locale_noalloc(MSVCRT__locale_t locale) DECLSPEC_HIDDEN;
 MSVCRT_pthreadlocinfo CDECL get_locinfo(void) DECLSPEC_HIDDEN;
 MSVCRT_pthreadmbcinfo CDECL get_mbcinfo(void) DECLSPEC_HIDDEN;
+MSVCRT_pthreadmbcinfo* CDECL get_mbcinfo_ptr(void) DECLSPEC_HIDDEN;
 void __cdecl MSVCRT__free_locale(MSVCRT__locale_t);
+MSVCRT_threadmbcinfo* create_mbcinfo(int, LCID, MSVCRT_threadmbcinfo*) DECLSPEC_HIDDEN;
 void free_locinfo(MSVCRT_pthreadlocinfo) DECLSPEC_HIDDEN;
 void free_mbcinfo(MSVCRT_pthreadmbcinfo) DECLSPEC_HIDDEN;
-int _setmbcp_l(int, LCID, MSVCRT_pthreadmbcinfo) DECLSPEC_HIDDEN;
 int __cdecl __crtLCMapStringA(LCID, DWORD, const char*, int, char*, int, unsigned int, int) DECLSPEC_HIDDEN;
 
 #ifndef __WINE_MSVCRT_TEST




More information about the wine-cvs mailing list