msvcrt: Added implemenatation of _create_locale and _free_locale.
diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec
index b8876a4..9a27a8b 100644
--- a/dlls/msvcr80/msvcr80.spec
+++ b/dlls/msvcr80/msvcr80.spec
@@ -338,7 +338,7 @@
@ cdecl _cputs(str) msvcrt._cputs
@ stub _cputws
@ cdecl _creat(str long) msvcrt._creat
-@ stub _create_locale
+@ cdecl _create_locale(long str) msvcrt._create_locale
@ stub _crt_debugger_hook
@ varargs _cscanf(str) msvcrt._cscanf
@ stub _cscanf_l
@@ -428,7 +428,7 @@
@ cdecl _fputwchar(long) msvcrt._fputwchar
@ stub _fread_nolock
@ stub _fread_nolock_s
-@ stub _free_locale
+@ cdecl _free_locale(ptr) msvcrt._free_locale
@ stub _freea
@ stub _freea_s
@ stub _freefls
diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec
index dfb951c..7f8cdc0 100644
--- a/dlls/msvcr90/msvcr90.spec
+++ b/dlls/msvcr90/msvcr90.spec
@@ -330,7 +330,7 @@
@ cdecl _cputs(str) msvcrt._cputs
@ stub _cputws
@ cdecl _creat(str long) msvcrt._creat
-@ stub _create_locale
+@ cdecl _create_locale(long str) msvcrt._create_locale
@ stub _crt_debugger_hook
@ varargs _cscanf(str) msvcrt._cscanf
@ stub _cscanf_l
@@ -420,7 +420,7 @@
@ cdecl _fputwchar(long) msvcrt._fputwchar
@ stub _fread_nolock
@ stub _fread_nolock_s
-@ stub _free_locale
+@ cdecl _free_locale(ptr) msvcrt._free_locale
@ stub _freea
@ stub _freea_s
@ stub _freefls
diff --git a/dlls/msvcrt/locale.c b/dlls/msvcrt/locale.c
index c60b80d..b5bbe74 100644
--- a/dlls/msvcrt/locale.c
+++ b/dlls/msvcrt/locale.c
@@ -227,7 +227,7 @@
GetLocaleInfoA(lcid, LOCALE_IDEFAULTCODEPAGE,
locale->found_codepage, MAX_ELEM_LEN);
}
- if (strcasecmp(locale->search_codepage,"ACP"))
+ else if (strcasecmp(locale->search_codepage,"ACP"))
{
GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE,
locale->found_codepage, MAX_ELEM_LEN);
@@ -297,6 +297,59 @@
}
}
+/* INTERNAL: Set lc_handle, lc_id and lc_category in threadlocinfo struct */
+BOOL update_threadlocinfo_category(LCID lcid, MSVCRT__locale_t loc, int category)
+{
+ char buf[256], *p;
+ int len;
+
+ if(GetLocaleInfoA(lcid, LOCALE_ILANGUAGE, buf, 256)) {
+ p = buf;
+
+ loc->locinfo->lc_id[category].wLanguage = 0;
+ while(*p) {
+ loc->locinfo->lc_id[category].wLanguage *= 16;
+
+ if(*p <= '9')
+ loc->locinfo->lc_id[category].wLanguage += *p-'0';
+ else
+ loc->locinfo->lc_id[category].wLanguage += *p-'a'+10;
+
+ p++;
+ }
+
+ loc->locinfo->lc_id[category].wCountry =
+ loc->locinfo->lc_id[category].wLanguage;
+ }
+
+ if(GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE, buf, 256))
+ loc->locinfo->lc_id[category].wCodePage = atoi(buf);
+
+ loc->locinfo->lc_handle[category] = lcid;
+
+ len = 0;
+ len += GetLocaleInfoA(lcid, LOCALE_SLANGUAGE, buf, 256);
+ buf[len-1] = '_';
+ len += GetLocaleInfoA(lcid, LOCALE_SCOUNTRY, &buf[len], 256-len);
+ buf[len-1] = '.';
+ len += GetLocaleInfoA(lcid, LOCALE_IDEFAULTANSICODEPAGE, &buf[len], 256-len);
+
+ loc->locinfo->lc_category[category].locale = MSVCRT_malloc(sizeof(char[len]));
+ loc->locinfo->lc_category[category].refcount = MSVCRT_malloc(sizeof(int));
+ if(!loc->locinfo->lc_category[category].locale
+ || !loc->locinfo->lc_category[category].refcount) {
+ MSVCRT_free(loc->locinfo->lc_category[category].locale);
+ MSVCRT_free(loc->locinfo->lc_category[category].refcount);
+ loc->locinfo->lc_category[category].locale = NULL;
+ loc->locinfo->lc_category[category].refcount = NULL;
+ return TRUE;
+ }
+ memcpy(loc->locinfo->lc_category[category].locale, buf, sizeof(char[len]));
+ *loc->locinfo->lc_category[category].refcount = 1;
+
+ return FALSE;
+}
+
/*********************************************************************
* setlocale (MSVCRT.@)
@@ -641,3 +694,451 @@
{
return MSVCRT___lc_collate_cp;
}
+
+/* _free_locale - not exported in native msvcrt */
+void CDECL _free_locale(MSVCRT__locale_t locale)
+{
+ int i;
+ BOOL localeC = TRUE;
+
+ for(i=MSVCRT_LC_MIN+1; i<=MSVCRT_LC_MAX; i++) {
+ if(locale->locinfo->lc_category[i].refcount) {
+ MSVCRT_free(locale->locinfo->lc_category[i].locale);
+ MSVCRT_free(locale->locinfo->lc_category[i].refcount);
+ } else if(localeC) {
+ MSVCRT_free(locale->locinfo->lc_category[i].locale);
+ localeC = FALSE;
+ }
+ }
+
+ if(locale->locinfo->lconv) {
+ MSVCRT_free(locale->locinfo->lconv->decimal_point);
+ MSVCRT_free(locale->locinfo->lconv->thousands_sep);
+ MSVCRT_free(locale->locinfo->lconv->grouping);
+ MSVCRT_free(locale->locinfo->lconv->int_curr_symbol);
+ MSVCRT_free(locale->locinfo->lconv->currency_symbol);
+ MSVCRT_free(locale->locinfo->lconv->mon_decimal_point);
+ MSVCRT_free(locale->locinfo->lconv->mon_thousands_sep);
+ MSVCRT_free(locale->locinfo->lconv->mon_grouping);
+ MSVCRT_free(locale->locinfo->lconv->positive_sign);
+ MSVCRT_free(locale->locinfo->lconv->negative_sign);
+ }
+ MSVCRT_free(locale->locinfo->lconv_intl_refcount);
+ MSVCRT_free(locale->locinfo->lconv_num_refcount);
+ MSVCRT_free(locale->locinfo->lconv_mon_refcount);
+ MSVCRT_free(locale->locinfo->lconv);
+
+ MSVCRT_free(locale->locinfo->ctype1_refcount);
+ MSVCRT_free(locale->locinfo->ctype1);
+
+ MSVCRT_free(locale->locinfo->pclmap);
+ MSVCRT_free(locale->locinfo->pcumap);
+
+ MSVCRT_free(locale->locinfo);
+ MSVCRT_free(locale->mbcinfo);
+ MSVCRT_free(locale);
+}
+
+/* _create_locale - not exported in native msvcrt */
+MSVCRT__locale_t _create_locale(int category, const char *locale)
+{
+ MSVCRT__locale_t loc;
+ LCID lcid;
+ char buf[256], *localeC;
+ int i;
+
+ TRACE("(%d %s)\n", category, locale);
+
+ if(category<MSVCRT_LC_MIN || category>MSVCRT_LC_MAX || !locale)
+ return NULL;
+
+ if(locale[0]=='C' && !locale[1])
+ lcid = CP_ACP;
+ else if(!locale[0])
+ lcid = GetSystemDefaultLCID();
+ else {
+ locale_search_t search;
+ char *cp, *region;
+
+ memset(&search, 0, sizeof(locale_search_t));
+
+ cp = strchr(locale, '.');
+ region = strchr(locale, '_');
+
+ lstrcpynA(search.search_language, locale, MAX_ELEM_LEN);
+ if(region) {
+ lstrcpynA(search.search_country, region+1, MAX_ELEM_LEN);
+ if(region-locale < MAX_ELEM_LEN)
+ search.search_language[region-locale] = '\0';
+ } else
+ search.search_country[0] = '\0';
+
+ if(cp) {
+ lstrcpynA(search.search_codepage, cp+1, MAX_ELEM_LEN);
+ if(cp-region < MAX_ELEM_LEN)
+ search.search_country[cp-region] = '\0';
+ if(cp-locale < MAX_ELEM_LEN)
+ search.search_language[cp-locale] = '\0';
+ } else
+ search.search_codepage[0] = '\0';
+
+ lcid = MSVCRT_locale_to_LCID(&search);
+ if(!lcid)
+ return NULL;
+ }
+
+ loc = MSVCRT_malloc(sizeof(MSVCRT__locale_tstruct));
+ if(!loc)
+ return NULL;
+
+ loc->locinfo = MSVCRT_malloc(sizeof(MSVCRT_threadlocinfo));
+ if(!loc->locinfo) {
+ MSVCRT_free(loc);
+ return NULL;
+ }
+
+ loc->mbcinfo = MSVCRT_malloc(sizeof(MSVCRT_threadmbcinfo));
+ if(!loc->mbcinfo) {
+ MSVCRT_free(loc->locinfo);
+ MSVCRT_free(loc);
+ return NULL;
+ }
+
+ memset(loc->locinfo, 0, sizeof(MSVCRT_threadlocinfo));
+ memset(loc->mbcinfo, 0, sizeof(MSVCRT_threadmbcinfo));
+
+ if(category!=MSVCRT_LC_ALL || !lcid) {
+ localeC = MSVCRT_malloc(sizeof(char[2]));
+
+ if(localeC) {
+ localeC[0] = 'C';
+ localeC[1] = '\0';
+
+ for(i=MSVCRT_LC_ALL+1; i<=MSVCRT_LC_MAX; i++)
+ loc->locinfo->lc_category[i].locale = localeC;
+ } else {
+ _free_locale(loc);
+ return NULL;
+ }
+ }
+
+ loc->locinfo->lconv = MSVCRT_malloc(sizeof(struct MSVCRT_lconv));
+ if(!loc->locinfo->lconv) {
+ _free_locale(loc);
+ return NULL;
+ }
+ memset(loc->locinfo->lconv, 0, sizeof(struct MSVCRT_lconv));
+
+ loc->locinfo->pclmap = MSVCRT_malloc(sizeof(char[256]));
+ loc->locinfo->pcumap = MSVCRT_malloc(sizeof(char[256]));
+ if(!loc->locinfo->pclmap || !loc->locinfo->pcumap) {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ loc->locinfo->refcount = 1;
+
+ if(lcid && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_COLLATE)) {
+ if(update_threadlocinfo_category(lcid, loc, MSVCRT_LC_COLLATE)) {
+ _free_locale(loc);
+ return NULL;
+ }
+ }
+
+ if(lcid && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_CTYPE)) {
+ CPINFO cp;
+
+ if(update_threadlocinfo_category(lcid, loc, MSVCRT_LC_CTYPE)) {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ loc->locinfo->lc_codepage = loc->locinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage;
+ loc->locinfo->lc_clike = 1;
+ if(!GetCPInfo(loc->locinfo->lc_codepage, &cp)) {
+ _free_locale(loc);
+ return NULL;
+ }
+ loc->locinfo->mb_cur_max = cp.MaxCharSize;
+
+ loc->locinfo->ctype1_refcount = MSVCRT_malloc(sizeof(int));
+ loc->locinfo->ctype1 = MSVCRT_malloc(sizeof(short[257]));
+ if(!loc->locinfo->ctype1_refcount || !loc->locinfo->ctype1) {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ *loc->locinfo->ctype1_refcount = 1;
+ loc->locinfo->ctype1[0] = 0;
+ loc->locinfo->pctype = loc->locinfo->ctype1+1;
+
+ buf[1] = buf[2] = '\0';
+ for(i=1; i<257; i++) {
+ buf[0] = i-1;
+
+ GetStringTypeA(lcid, CT_CTYPE1, buf, 1, loc->locinfo->ctype1+i);
+ loc->locinfo->ctype1[i] |= 0x200;
+ }
+ } else {
+ loc->locinfo->lc_clike = 1;
+ loc->locinfo->mb_cur_max = 1;
+ loc->locinfo->pctype = MSVCRT__ctype+1;
+ }
+
+ for(i=0; i<256; i++)
+ buf[i] = i;
+
+ LCMapStringA(lcid, LCMAP_LOWERCASE, buf, 256, (char*)loc->locinfo->pclmap, 256);
+ LCMapStringA(lcid, LCMAP_UPPERCASE, buf, 256, (char*)loc->locinfo->pcumap, 256);
+
+ loc->mbcinfo->refcount = 1;
+ loc->mbcinfo->mbcodepage = loc->locinfo->lc_id[MSVCRT_LC_CTYPE].wCodePage;
+
+ for(i=0; i<256; i++) {
+ if(loc->locinfo->pclmap[i] != i) {
+ loc->mbcinfo->mbctype[i+1] |= 0x10;
+ loc->mbcinfo->mbcasemap[i] = loc->locinfo->pclmap[i];
+ } else if(loc->locinfo->pcumap[i] != i) {
+ loc->mbcinfo->mbctype[i+1] |= 0x20;
+ loc->mbcinfo->mbcasemap[i] = loc->locinfo->pcumap[i];
+ }
+ }
+
+ if(lcid && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_MONETARY)) {
+ if(update_threadlocinfo_category(lcid, loc, MSVCRT_LC_MONETARY)) {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ loc->locinfo->lconv_intl_refcount = MSVCRT_malloc(sizeof(int));
+ loc->locinfo->lconv_mon_refcount = MSVCRT_malloc(sizeof(int));
+ if(!loc->locinfo->lconv_intl_refcount || !loc->locinfo->lconv_mon_refcount) {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ *loc->locinfo->lconv_intl_refcount = 1;
+ *loc->locinfo->lconv_mon_refcount = 1;
+
+ i = GetLocaleInfoA(lcid, LOCALE_SINTLSYMBOL, buf, 256);
+ if(i && (loc->locinfo->lconv->int_curr_symbol = MSVCRT_malloc(sizeof(char[i]))))
+ memcpy(loc->locinfo->lconv->int_curr_symbol, buf, sizeof(char[i]));
+ else {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ i = GetLocaleInfoA(lcid, LOCALE_SCURRENCY, buf, 256);
+ if(i && (loc->locinfo->lconv->currency_symbol = MSVCRT_malloc(sizeof(char[i]))))
+ memcpy(loc->locinfo->lconv->currency_symbol, buf, sizeof(char[i]));
+ else {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ i = GetLocaleInfoA(lcid, LOCALE_SMONDECIMALSEP, buf, 256);
+ if(i && (loc->locinfo->lconv->mon_decimal_point = MSVCRT_malloc(sizeof(char[i]))))
+ memcpy(loc->locinfo->lconv->mon_decimal_point, buf, sizeof(char[i]));
+ else {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ i = GetLocaleInfoA(lcid, LOCALE_SMONTHOUSANDSEP, buf, 256);
+ if(i && (loc->locinfo->lconv->mon_thousands_sep = MSVCRT_malloc(sizeof(char[i]))))
+ memcpy(loc->locinfo->lconv->mon_thousands_sep, buf, sizeof(char[i]));
+ else {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ i = GetLocaleInfoA(lcid, LOCALE_SMONGROUPING, buf, 256);
+ if(i>1)
+ i = i/2 + (buf[i-2]=='0'?0:1);
+ if(i && (loc->locinfo->lconv->mon_grouping = MSVCRT_malloc(sizeof(char[i])))) {
+ for(i=0; buf[i+1]==';'; i+=2)
+ loc->locinfo->lconv->mon_grouping[i/2] = buf[i]-'0';
+ loc->locinfo->lconv->mon_grouping[i/2] = buf[i]-'0';
+ if(buf[i] != '0')
+ loc->locinfo->lconv->mon_grouping[i/2+1] = 127;
+ } else {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ i = GetLocaleInfoA(lcid, LOCALE_SPOSITIVESIGN, buf, 256);
+ if(i && (loc->locinfo->lconv->positive_sign = MSVCRT_malloc(sizeof(char[i]))))
+ memcpy(loc->locinfo->lconv->positive_sign, buf, sizeof(char[i]));
+ else {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ i = GetLocaleInfoA(lcid, LOCALE_SNEGATIVESIGN, buf, 256);
+ if(i && (loc->locinfo->lconv->negative_sign = MSVCRT_malloc(sizeof(char[i]))))
+ memcpy(loc->locinfo->lconv->negative_sign, buf, sizeof(char[i]));
+ else {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ if(GetLocaleInfoA(lcid, LOCALE_IINTLCURRDIGITS, buf, 256))
+ loc->locinfo->lconv->int_frac_digits = atoi(buf);
+ else {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ if(GetLocaleInfoA(lcid, LOCALE_ICURRDIGITS, buf, 256))
+ loc->locinfo->lconv->frac_digits = atoi(buf);
+ else {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ if(GetLocaleInfoA(lcid, LOCALE_IPOSSYMPRECEDES, buf, 256))
+ loc->locinfo->lconv->p_cs_precedes = atoi(buf);
+ else {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ if(GetLocaleInfoA(lcid, LOCALE_IPOSSEPBYSPACE, buf, 256))
+ loc->locinfo->lconv->p_sep_by_space = atoi(buf);
+ else {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ if(GetLocaleInfoA(lcid, LOCALE_INEGSYMPRECEDES, buf, 256))
+ loc->locinfo->lconv->n_cs_precedes = atoi(buf);
+ else {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ if(GetLocaleInfoA(lcid, LOCALE_INEGSEPBYSPACE, buf, 256))
+ loc->locinfo->lconv->n_sep_by_space = atoi(buf);
+ else {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ if(GetLocaleInfoA(lcid, LOCALE_IPOSSIGNPOSN, buf, 256))
+ loc->locinfo->lconv->p_sign_posn = atoi(buf);
+ else {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ if(GetLocaleInfoA(lcid, LOCALE_INEGSIGNPOSN, buf, 256))
+ loc->locinfo->lconv->n_sign_posn = atoi(buf);
+ else {
+ _free_locale(loc);
+ return NULL;
+ }
+ } else {
+ loc->locinfo->lconv->int_curr_symbol = MSVCRT_malloc(sizeof(char));
+ loc->locinfo->lconv->currency_symbol = MSVCRT_malloc(sizeof(char));
+ loc->locinfo->lconv->mon_decimal_point = MSVCRT_malloc(sizeof(char));
+ loc->locinfo->lconv->mon_thousands_sep = MSVCRT_malloc(sizeof(char));
+ loc->locinfo->lconv->mon_grouping = MSVCRT_malloc(sizeof(char));
+ loc->locinfo->lconv->positive_sign = MSVCRT_malloc(sizeof(char));
+ loc->locinfo->lconv->negative_sign = MSVCRT_malloc(sizeof(char));
+
+ if(!loc->locinfo->lconv->int_curr_symbol || !loc->locinfo->lconv->currency_symbol
+ || !loc->locinfo->lconv->mon_decimal_point || !loc->locinfo->lconv->mon_thousands_sep
+ || !loc->locinfo->lconv->mon_grouping || !loc->locinfo->lconv->positive_sign
+ || !loc->locinfo->lconv->negative_sign) {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ loc->locinfo->lconv->int_curr_symbol[0] = '\0';
+ loc->locinfo->lconv->currency_symbol[0] = '\0';
+ loc->locinfo->lconv->mon_decimal_point[0] = '\0';
+ loc->locinfo->lconv->mon_thousands_sep[0] = '\0';
+ loc->locinfo->lconv->mon_grouping[0] = '\0';
+ loc->locinfo->lconv->positive_sign[0] = '\0';
+ loc->locinfo->lconv->negative_sign[0] = '\0';
+ loc->locinfo->lconv->int_frac_digits = 127;
+ loc->locinfo->lconv->frac_digits = 127;
+ loc->locinfo->lconv->p_cs_precedes = 127;
+ loc->locinfo->lconv->p_sep_by_space = 127;
+ loc->locinfo->lconv->n_cs_precedes = 127;
+ loc->locinfo->lconv->n_sep_by_space = 127;
+ loc->locinfo->lconv->p_sign_posn = 127;
+ loc->locinfo->lconv->n_sign_posn = 127;
+ }
+
+ if(lcid && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_NUMERIC)) {
+ if(update_threadlocinfo_category(lcid, loc, MSVCRT_LC_NUMERIC)) {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ if(!loc->locinfo->lconv_intl_refcount)
+ loc->locinfo->lconv_intl_refcount = MSVCRT_malloc(sizeof(int));
+ loc->locinfo->lconv_num_refcount = MSVCRT_malloc(sizeof(int));
+ if(!loc->locinfo->lconv_intl_refcount || !loc->locinfo->lconv_num_refcount) {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ *loc->locinfo->lconv_intl_refcount = 1;
+ *loc->locinfo->lconv_num_refcount = 1;
+
+ i = GetLocaleInfoA(lcid, LOCALE_SDECIMAL, buf, 256);
+ if(i && (loc->locinfo->lconv->decimal_point = MSVCRT_malloc(sizeof(char[i]))))
+ memcpy(loc->locinfo->lconv->decimal_point, buf, sizeof(char[i]));
+ else {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ i = GetLocaleInfoA(lcid, LOCALE_STHOUSAND, buf, 256);
+ if(i && (loc->locinfo->lconv->thousands_sep = MSVCRT_malloc(sizeof(char[i]))))
+ memcpy(loc->locinfo->lconv->thousands_sep, buf, sizeof(char[i]));
+ else {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ i = GetLocaleInfoA(lcid, LOCALE_SGROUPING, buf, 256);
+ if(i>1)
+ i = i/2 + (buf[i-2]=='0'?0:1);
+ if(i && (loc->locinfo->lconv->grouping = MSVCRT_malloc(sizeof(char[i])))) {
+ for(i=0; buf[i+1]==';'; i+=2)
+ loc->locinfo->lconv->grouping[i/2] = buf[i]-'0';
+ loc->locinfo->lconv->grouping[i/2] = buf[i]-'0';
+ if(buf[i] != '0')
+ loc->locinfo->lconv->grouping[i/2+1] = 127;
+ } else {
+ _free_locale(loc);
+ return NULL;
+ }
+ } else {
+ loc->locinfo->lconv->decimal_point = MSVCRT_malloc(sizeof(char[2]));
+ loc->locinfo->lconv->thousands_sep = MSVCRT_malloc(sizeof(char));
+ loc->locinfo->lconv->grouping = MSVCRT_malloc(sizeof(char));
+ if(!loc->locinfo->lconv->decimal_point || !loc->locinfo->lconv->thousands_sep
+ || !loc->locinfo->lconv->grouping) {
+ _free_locale(loc);
+ return NULL;
+ }
+
+ loc->locinfo->lconv->decimal_point[0] = '.';
+ loc->locinfo->lconv->decimal_point[1] = '\0';
+ loc->locinfo->lconv->thousands_sep[0] = '\0';
+ loc->locinfo->lconv->grouping[0] = '\0';
+ }
+
+ if(lcid && (category==MSVCRT_LC_ALL || category==MSVCRT_LC_TIME)) {
+ if(update_threadlocinfo_category(lcid, loc, MSVCRT_LC_TIME)) {
+ _free_locale(loc);
+ return NULL;
+ }
+ }
+
+ return loc;
+}
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h
index 3f231ac..6c298d3 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -765,15 +765,25 @@
int *lconv_intl_refcount;
int *lconv_num_refcount;
int *lconv_mon_refcount;
- struct lconv *lconv;
+ struct MSVCRT_lconv *lconv;
int *ctype1_refcount;
unsigned short *ctype1;
- const unsigned short *pctype;
- const unsigned char *pclmap;
- const unsigned char *pcumap;
- struct __lc_time_data *lc_time_curr;
+ unsigned short *pctype;
+ unsigned char *pclmap;
+ unsigned char *pcumap;
+ struct MSVCRT___lc_time_data *lc_time_curr;
} MSVCRT_threadlocinfo;
+typedef struct MSVCRT_threadmbcinfostruct {
+ int refcount;
+ int mbcodepage;
+ int ismbcodepage;
+ int mblcid;
+ unsigned short mbulinfo[6];
+ char mbctype[257];
+ char mbcasemap[256];
+} MSVCRT_threadmbcinfo;
+
typedef struct MSVCRT_threadlocaleinfostruct *MSVCRT_pthreadlocinfo;
typedef struct MSVCRT_threadmbcinfostruct *MSVCRT_pthreadmbcinfo;
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index 7205bd6..8692e7d 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -1413,3 +1413,5 @@
# Functions not exported in native dll:
@ cdecl _get_invalid_parameter_handler()
@ cdecl _set_invalid_parameter_handler(ptr)
+@ cdecl _create_locale(long str)
+@ cdecl _free_locale(ptr)