Fix 3 bugs in locale handling
Dmitry Timoshkov
dmitry at baikal.ru
Fri Jun 11 07:35:30 CDT 2004
Hello,
this patch fixes 3 bugs in locale handling:
1. If the locale has changed current code never refreshes win.ini
and registry values due to the following test done in GetLocaleInfoW:
/* first check for overrides in the registry */
if (!(lcflags & LOCALE_NOUSEROVERRIDE) && lcid == GetUserDefaultLCID())
{
lcid is always pointing to current user locale returned by GetUserDefaultLCID()
and therefore cached (old) values get returned.
I modified code to get data directly from kernel resources in that case.
Also I removed LOCALE_IDATE from the list of updated keys since SetLocaleInfoW
doesn't allow changing this key and uses heuristics parsing LOCALE_SSHORTDATE
and LOCALE_SLONGDATE.
2. This bug is related to the aforementioned heuristics with parsing
LOCALE_SSHORTDATE and LOCALE_SLONGDATE. The code erroneously used
LOCALE_SDATE instead of LOCALE_SSHORTDATE.
3. The code which parses LOCALE_SSHORTDATE and LOCALE_SLONGDATE does
its job very poorly. dlls/kernel/nls/enu.nls has the following format
string for LOCALE_SLONGDATE: "dddd, MMMM dd, yyyy" and this leads to
a confusion due to the leading 'dddd'.
I changed the code to parse the whole string, not just search for
the first character occurrence.
Changelog:
Dmitry Timoshkov <dmitry at codeweavers.com>
- Fix a bug causing locale data to be not properly refreshed on locale
change.
- Fix erroneous use of LOCALE_SDATE in the place of LOCALE_SSHORTDATE.
- Fix incorrect assumptions about format strings when parsing date
formats and setting LOCALE_IDATE and LOCALE_ILDATE values.
--- cvs/hq/wine/dlls/kernel/locale.c 2004-04-20 18:51:26.000000000 +0900
+++ wine/dlls/kernel/locale.c 2004-06-11 20:49:33.000000000 +0900
@@ -48,6 +48,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(nls);
#define LOCALE_LOCALEINFOFLAGSMASK (LOCALE_NOUSEROVERRIDE|LOCALE_USE_CP_ACP|LOCALE_RETURN_NUMBER)
+static INT get_resource_locale_info( LCID, LCTYPE, UINT, LPWSTR, INT );
+
/* current code pages */
static const union cptable *ansi_cptable;
static const union cptable *oem_cptable;
@@ -250,7 +252,6 @@ void LOCALE_InitRegistry(void)
LOCALE_STIME, LOCALE_ITIME,
LOCALE_ITLZERO,
LOCALE_SSHORTDATE,
- LOCALE_IDATE,
LOCALE_SLONGDATE,
LOCALE_SDATE,
LOCALE_SCURRENCY, LOCALE_ICURRENCY,
@@ -302,8 +303,7 @@ void LOCALE_InitRegistry(void)
for (i = 0; i < sizeof(updateValues)/sizeof(updateValues[0]); i++)
{
- GetLocaleInfoW( lcid, updateValues[i] | LOCALE_NOUSEROVERRIDE, bufferW,
- sizeof(bufferW)/sizeof(WCHAR) );
+ get_resource_locale_info( lcid, updateValues[i], 0, bufferW, sizeof(bufferW)/sizeof(WCHAR) );
SetLocaleInfoW( lcid, updateValues[i], bufferW );
}
}
@@ -829,6 +829,8 @@ INT WINAPI GetLocaleInfoA( LCID lcid, LC
WCHAR *bufferW;
INT lenW, ret;
+ TRACE( "(lcid=0x%lx,lctype=0x%lx,%p,%d)\n", lcid, lctype, buffer, len );
+
if (len < 0 || (len && !buffer))
{
SetLastError( ERROR_INVALID_PARAMETER );
@@ -879,13 +881,8 @@ INT WINAPI GetLocaleInfoA( LCID lcid, LC
*/
INT WINAPI GetLocaleInfoW( LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len )
{
- LANGID lang_id;
- HRSRC hrsrc;
- HGLOBAL hmem;
INT ret;
UINT lcflags;
- const WCHAR *p;
- unsigned int i;
if (len < 0 || (len && !buffer))
{
@@ -899,6 +896,8 @@ INT WINAPI GetLocaleInfoW( LCID lcid, LC
lcflags = lctype & LOCALE_LOCALEINFOFLAGSMASK;
lctype &= 0xffff;
+ TRACE( "(lcid=0x%lx,lctype=0x%lx,%p,%d)\n", lcid, lctype, buffer, len );
+
/* first check for overrides in the registry */
if (!(lcflags & LOCALE_NOUSEROVERRIDE) && lcid == GetUserDefaultLCID())
@@ -937,6 +936,25 @@ INT WINAPI GetLocaleInfoW( LCID lcid, LC
}
/* now load it from kernel resources */
+ ret = get_resource_locale_info( lcid, lctype, lcflags, buffer, len );
+
+ return ret;
+}
+
+
+/******************************************************************************
+ * get_resource_locale_info
+ *
+ * Retrieve locale info from kernel resources.
+ */
+static INT get_resource_locale_info( LCID lcid, LCTYPE lctype, UINT lcflags, LPWSTR buffer, INT len )
+{
+ INT ret;
+ LANGID lang_id;
+ HRSRC hrsrc;
+ HGLOBAL hmem;
+ const WCHAR *p;
+ unsigned int i;
lang_id = LANGIDFROMLCID( lcid );
@@ -1089,7 +1107,7 @@ BOOL WINAPI SetLocaleInfoW( LCID lcid, L
lcid, GetUserDefaultLCID());
}
- TRACE("setting %lx to %s\n", lctype, debugstr_w(data) );
+ TRACE("setting %lx (%s) to %s\n", lctype, debugstr_w(value), debugstr_w(data) );
/* FIXME: should check that data to set is sane */
@@ -1100,15 +1118,15 @@ BOOL WINAPI SetLocaleInfoW( LCID lcid, L
RtlInitUnicodeString( &valueW, value );
status = NtSetValueKey( hkey, &valueW, 0, REG_SZ, data, (strlenW(data)+1)*sizeof(WCHAR) );
- if (lctype == LOCALE_SDATE || lctype == LOCALE_SLONGDATE)
+ if (lctype == LOCALE_SSHORTDATE || lctype == LOCALE_SLONGDATE)
{
/* Set I-value from S value */
- WCHAR *lpD, *lpM, *lpY;
+ WCHAR *lpD, *lpM, *lpY, *p;
WCHAR szBuff[2];
- lpD = strchrW(data, 'd');
- lpM = strchrW(data, 'M');
- lpY = strchrW(data, 'y');
+ lpD = strchrW(data, 'd'); while ((p = strchrW(lpD+1, 'd'))) lpD = p;
+ lpM = strchrW(data, 'M'); while ((p = strchrW(lpM+1, 'M'))) lpM = p;
+ lpY = strchrW(data, 'y'); while ((p = strchrW(lpY+1, 'y'))) lpY = p;
if (lpD <= lpM)
{
@@ -1124,7 +1142,7 @@ BOOL WINAPI SetLocaleInfoW( LCID lcid, L
szBuff[1] = '\0';
- if (lctype == LOCALE_SDATE)
+ if (lctype == LOCALE_SSHORTDATE)
lctype = LOCALE_IDATE;
else
lctype = LOCALE_ILDATE;
More information about the wine-patches
mailing list