msvcrt: Don't overwrite threadmbcinfostruct structure in _setmbcp.

Signed-off-by: Piotr Caban <piotr@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Piotr Caban 2020-11-19 18:57:48 +01:00 committed by Alexandre Julliard
parent e84394764a
commit 35a8f15361
4 changed files with 63 additions and 26 deletions

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}
/*********************************************************************

View file

@ -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