[glib/win32-enhance-gtimezone: 5/9] glib/gtimezone.c: Use Unicode versions of Windows Registry API



commit c868123c0a499bbbbd9fffd966422a9e16be5419
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Thu Feb 27 14:19:02 2014 +0800

    glib/gtimezone.c: Use Unicode versions of Windows Registry API
    
    We are going to use RegLoadMUIStringW() in the next commit, since there
    is no real RegLoadMUIStringA() function (it exists as a stub only).
    This is done so that we are consistent along the way
    
    Also fix rule_from_windows_time_zone_info() as we can't just do a strncpy()
    of tzi->StandardName and tzi->DaylightName directly, as they are wchar_t/
    gunichar2 strings, where we must convert to UTF-8 first.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=719344

 glib/gtimezone.c | 141 ++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 98 insertions(+), 43 deletions(-)
---
diff --git a/glib/gtimezone.c b/glib/gtimezone.c
index 970b4b1a5..751a925a1 100644
--- a/glib/gtimezone.c
+++ b/glib/gtimezone.c
@@ -39,8 +39,10 @@
 #include "gdate.h"
 
 #ifdef G_OS_WIN32
+
 #define STRICT
 #include <windows.h>
+#include <wchar.h>
 #endif
 
 /**
@@ -602,10 +604,23 @@ copy_windows_systemtime (SYSTEMTIME *s_time, TimeZoneDate *tzdate)
 }
 
 /* UTC = local time + bias while local time = UTC + offset */
-static void
+static gboolean
 rule_from_windows_time_zone_info (TimeZoneRule *rule,
                                   TIME_ZONE_INFORMATION *tzi)
 {
+  gchar *std_name, *dlt_name;
+
+  std_name = g_utf16_to_utf8 ((gunichar2 *)tzi->StandardName, -1, NULL, NULL, NULL);
+  if (std_name == NULL)
+    return FALSE;
+
+  dlt_name = g_utf16_to_utf8 ((gunichar2 *)tzi->DaylightName, -1, NULL, NULL, NULL);
+  if (dlt_name == NULL)
+    {
+      g_free (std_name);
+      return FALSE;
+    }
+
   /* Set offset */
   if (tzi->StandardDate.wMonth)
     {
@@ -614,7 +629,6 @@ rule_from_windows_time_zone_info (TimeZoneRule *rule,
       copy_windows_systemtime (&(tzi->DaylightDate), &(rule->dlt_start));
 
       copy_windows_systemtime (&(tzi->StandardDate), &(rule->dlt_end));
-
     }
 
   else
@@ -622,31 +636,41 @@ rule_from_windows_time_zone_info (TimeZoneRule *rule,
       rule->std_offset = -tzi->Bias * 60;
       rule->dlt_start.mon = 0;
     }
-  strncpy (rule->std_name, (gchar*)tzi->StandardName, NAME_SIZE - 1);
-  strncpy (rule->dlt_name, (gchar*)tzi->DaylightName, NAME_SIZE - 1);
+  strncpy (rule->std_name, std_name, NAME_SIZE - 1);
+  strncpy (rule->dlt_name, dlt_name, NAME_SIZE - 1);
+
+  g_free (std_name);
+  g_free (dlt_name);
+
+  return TRUE;
 }
 
 static gchar*
 windows_default_tzname (void)
 {
-  const gchar *subkey =
-    "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation";
+  const gunichar2 *subkey =
+    L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation";
   HKEY key;
   gchar *key_name = NULL;
-  if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, subkey, 0,
+  gunichar2 *key_name_w = NULL;
+  if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, subkey, 0,
                      KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
     {
       DWORD size = 0;
-      if (RegQueryValueExA (key, "TimeZoneKeyName", NULL, NULL,
+      if (RegQueryValueExW (key, L"TimeZoneKeyName", NULL, NULL,
                             NULL, &size) == ERROR_SUCCESS)
         {
-          key_name = g_malloc ((gint)size);
-          if (RegQueryValueExA (key, "TimeZoneKeyName", NULL, NULL,
-                                (LPBYTE)key_name, &size) != ERROR_SUCCESS)
+          key_name_w = g_malloc ((gint)size);
+
+          if (key_name_w == NULL ||
+              RegQueryValueExW (key, L"TimeZoneKeyName", NULL, NULL,
+                                (LPBYTE)key_name_w, &size) != ERROR_SUCCESS)
             {
-              g_free (key_name);
+              g_free (key_name_w);
               key_name = NULL;
             }
+          else
+            key_name = g_utf16_to_utf8 (key_name_w, -1, NULL, NULL, NULL);
         }
       RegCloseKey (key);
     }
@@ -696,7 +720,8 @@ rules_from_windows_time_zone (const gchar   *identifier,
                               TimeZoneRule **rules)
 {
   HKEY key;
-  gchar *subkey, *subkey_dynamic;
+  gchar *subkey = NULL;
+  gchar *subkey_dynamic = NULL;
   gchar *key_name = NULL;
   const gchar *reg_key =
     "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\";
@@ -704,6 +729,7 @@ rules_from_windows_time_zone (const gchar   *identifier,
   DWORD size;
   guint rules_num = 0;
   RegTZI regtzi, regtzi_prev;
+  gunichar2 *subkey_w, *subkey_dynamic_w;
 
   g_assert (out_identifier != NULL);
   g_assert (rules != NULL);
@@ -721,90 +747,118 @@ rules_from_windows_time_zone (const gchar   *identifier,
     return 0;
 
   subkey = g_strconcat (reg_key, key_name, NULL);
+  subkey_w = g_utf8_to_utf16 (subkey, -1, NULL, NULL, NULL);
+  if (subkey_w == NULL)
+    goto utf16_conv_failed;
+
   subkey_dynamic = g_strconcat (subkey, "\\Dynamic DST", NULL);
+  subkey_dynamic_w = g_utf8_to_utf16 (subkey_dynamic, -1, NULL, NULL, NULL);
+  if (subkey_dynamic_w == NULL)
+    goto utf16_conv_failed;
 
-  if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, subkey, 0,
+  if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, subkey_w, 0,
                      KEY_QUERY_VALUE, &key) != ERROR_SUCCESS)
       return 0;
+
   size = sizeof tzi.StandardName;
-  if (RegQueryValueExA (key, "Std", NULL, NULL,
+  if (RegQueryValueExW (key, L"Std", NULL, NULL,
                         (LPBYTE)&(tzi.StandardName), &size) != ERROR_SUCCESS)
-    goto failed;
+    goto registry_failed;
 
   size = sizeof tzi.DaylightName;
 
-  if (RegQueryValueExA (key, "Dlt", NULL, NULL,
+  if (RegQueryValueExW (key, L"Dlt", NULL, NULL,
                         (LPBYTE)&(tzi.DaylightName), &size) != ERROR_SUCCESS)
-    goto failed;
+    goto registry_failed;
 
   RegCloseKey (key);
-  if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, subkey_dynamic, 0,
+  if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, subkey_dynamic_w, 0,
                      KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
     {
       DWORD first, last;
       int year, i;
-      gchar *s;
+      wchar_t s[12];
 
       size = sizeof first;
-      if (RegQueryValueExA (key, "FirstEntry", NULL, NULL,
+      if (RegQueryValueExW (key, L"FirstEntry", NULL, NULL,
                             (LPBYTE) &first, &size) != ERROR_SUCCESS)
-        goto failed;
+        goto registry_failed;
 
       size = sizeof last;
-      if (RegQueryValueExA (key, "LastEntry", NULL, NULL,
+      if (RegQueryValueExW (key, L"LastEntry", NULL, NULL,
                             (LPBYTE) &last, &size) != ERROR_SUCCESS)
-        goto failed;
+        goto registry_failed;
 
       rules_num = last - first + 2;
       *rules = g_new0 (TimeZoneRule, rules_num);
 
-      for (year = first, i = 0; year <= last; year++)
+      for (year = first, i = 0; *rules != NULL && year <= last; year++)
         {
-          s = g_strdup_printf ("%d", year);
+          gboolean failed = FALSE;
+          swprintf_s (s, 11, L"%d", year);
 
-          size = sizeof regtzi;
-          if (RegQueryValueExA (key, s, NULL, NULL,
-                            (LPBYTE) &regtzi, &size) != ERROR_SUCCESS)
+          if (!failed)
+            {
+              size = sizeof regtzi;
+              if (RegQueryValueExW (key, s, NULL, NULL,
+                                    (LPBYTE) &regtzi, &size) != ERROR_SUCCESS)
+                failed = TRUE;
+            }
+
+          if (failed)
             {
               g_free (*rules);
               *rules = NULL;
               break;
             }
 
-          g_free (s);
-
           if (year > first && memcmp (&regtzi_prev, &regtzi, sizeof regtzi) == 0)
               continue;
           else
             memcpy (&regtzi_prev, &regtzi, sizeof regtzi);
 
           register_tzi_to_tzi (&regtzi, &tzi);
-          rule_from_windows_time_zone_info (&(*rules)[i], &tzi);
+
+          if (!rule_from_windows_time_zone_info (&(*rules)[i], &tzi))
+            {
+              g_free (*rules);
+              *rules = NULL;
+              break;
+            }
+
           (*rules)[i++].start_year = year;
         }
 
       rules_num = i + 1;
 
-failed:
+registry_failed:
       RegCloseKey (key);
     }
-  else if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, subkey, 0,
+  else if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, subkey_w, 0,
                           KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
     {
       size = sizeof regtzi;
-      if (RegQueryValueExA (key, "TZI", NULL, NULL,
+      if (RegQueryValueExW (key, L"TZI", NULL, NULL,
                             (LPBYTE) &regtzi, &size) == ERROR_SUCCESS)
         {
           rules_num = 2;
           *rules = g_new0 (TimeZoneRule, 2);
           register_tzi_to_tzi (&regtzi, &tzi);
-          rule_from_windows_time_zone_info (&(*rules)[0], &tzi);
+
+          if (!rule_from_windows_time_zone_info (&(*rules)[0], &tzi))
+            {
+              g_free (*rules);
+              *rules = NULL;
+            }
         }
 
       RegCloseKey (key);
     }
 
+utf16_conv_failed:
+  g_free (subkey_dynamic_w);
   g_free (subkey_dynamic);
+  g_free (subkey_w);
   g_free (subkey);
 
   if (*rules)
@@ -1518,15 +1572,16 @@ g_time_zone_new (const gchar *identifier)
             {
               rules = g_new0 (TimeZoneRule, 2);
 
-              rule_from_windows_time_zone_info (&rules[0], &tzi);
-
-              memset (rules[0].std_name, 0, NAME_SIZE);
-              memset (rules[0].dlt_name, 0, NAME_SIZE);
+              if (rule_from_windows_time_zone_info (&rules[0], &tzi))
+                {
+                  memset (rules[0].std_name, 0, NAME_SIZE);
+                  memset (rules[0].dlt_name, 0, NAME_SIZE);
 
-              rules[0].start_year = MIN_TZYEAR;
-              rules[1].start_year = MAX_TZYEAR;
+                  rules[0].start_year = MIN_TZYEAR;
+                  rules[1].start_year = MAX_TZYEAR;
 
-              init_zone_from_rules (tz, rules, 2, windows_default_tzname ());
+                  init_zone_from_rules (tz, rules, 2, windows_default_tzname ());
+                }
 
               g_free (rules);
             }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]