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