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 +#include #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_dynamic = g_strconcat (subkey, "\\Dynamic DST", NULL); + subkey_w = g_utf8_to_utf16 (subkey, -1, NULL, NULL, NULL); + if (subkey_w == NULL) + goto utf16_conv_failed; - if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, subkey, 0, + 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 (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) ®tzi, &size) != ERROR_SUCCESS) + if (!failed) + { + size = sizeof regtzi; + if (RegQueryValueExW (key, s, NULL, NULL, + (LPBYTE) ®tzi, &size) != ERROR_SUCCESS) + failed = TRUE; + } + + if (failed) { g_free (*rules); *rules = NULL; break; } - g_free (s); - if (year > first && memcmp (®tzi_prev, ®tzi, sizeof regtzi) == 0) continue; else memcpy (®tzi_prev, ®tzi, sizeof regtzi); register_tzi_to_tzi (®tzi, &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) ®tzi, &size) == ERROR_SUCCESS) { rules_num = 2; *rules = g_new0 (TimeZoneRule, 2); register_tzi_to_tzi (®tzi, &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); + 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); - 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); }