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