mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-18 18:26:14 +01:00
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
This commit is contained in:
parent
dc774db608
commit
c868123c0a
143
glib/gtimezone.c
143
glib/gtimezone.c
@ -39,8 +39,10 @@
|
|||||||
#include "gdate.h"
|
#include "gdate.h"
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
|
|
||||||
#define STRICT
|
#define STRICT
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <wchar.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -602,10 +604,23 @@ copy_windows_systemtime (SYSTEMTIME *s_time, TimeZoneDate *tzdate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* UTC = local time + bias while local time = UTC + offset */
|
/* UTC = local time + bias while local time = UTC + offset */
|
||||||
static void
|
static gboolean
|
||||||
rule_from_windows_time_zone_info (TimeZoneRule *rule,
|
rule_from_windows_time_zone_info (TimeZoneRule *rule,
|
||||||
TIME_ZONE_INFORMATION *tzi)
|
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 */
|
/* Set offset */
|
||||||
if (tzi->StandardDate.wMonth)
|
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->DaylightDate), &(rule->dlt_start));
|
||||||
|
|
||||||
copy_windows_systemtime (&(tzi->StandardDate), &(rule->dlt_end));
|
copy_windows_systemtime (&(tzi->StandardDate), &(rule->dlt_end));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
@ -622,31 +636,41 @@ rule_from_windows_time_zone_info (TimeZoneRule *rule,
|
|||||||
rule->std_offset = -tzi->Bias * 60;
|
rule->std_offset = -tzi->Bias * 60;
|
||||||
rule->dlt_start.mon = 0;
|
rule->dlt_start.mon = 0;
|
||||||
}
|
}
|
||||||
strncpy (rule->std_name, (gchar*)tzi->StandardName, NAME_SIZE - 1);
|
strncpy (rule->std_name, std_name, NAME_SIZE - 1);
|
||||||
strncpy (rule->dlt_name, (gchar*)tzi->DaylightName, NAME_SIZE - 1);
|
strncpy (rule->dlt_name, dlt_name, NAME_SIZE - 1);
|
||||||
|
|
||||||
|
g_free (std_name);
|
||||||
|
g_free (dlt_name);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gchar*
|
static gchar*
|
||||||
windows_default_tzname (void)
|
windows_default_tzname (void)
|
||||||
{
|
{
|
||||||
const gchar *subkey =
|
const gunichar2 *subkey =
|
||||||
"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation";
|
L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation";
|
||||||
HKEY key;
|
HKEY key;
|
||||||
gchar *key_name = NULL;
|
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)
|
KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
DWORD size = 0;
|
DWORD size = 0;
|
||||||
if (RegQueryValueExA (key, "TimeZoneKeyName", NULL, NULL,
|
if (RegQueryValueExW (key, L"TimeZoneKeyName", NULL, NULL,
|
||||||
NULL, &size) == ERROR_SUCCESS)
|
NULL, &size) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
key_name = g_malloc ((gint)size);
|
key_name_w = g_malloc ((gint)size);
|
||||||
if (RegQueryValueExA (key, "TimeZoneKeyName", NULL, NULL,
|
|
||||||
(LPBYTE)key_name, &size) != ERROR_SUCCESS)
|
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;
|
key_name = NULL;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
key_name = g_utf16_to_utf8 (key_name_w, -1, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
RegCloseKey (key);
|
RegCloseKey (key);
|
||||||
}
|
}
|
||||||
@ -696,7 +720,8 @@ rules_from_windows_time_zone (const gchar *identifier,
|
|||||||
TimeZoneRule **rules)
|
TimeZoneRule **rules)
|
||||||
{
|
{
|
||||||
HKEY key;
|
HKEY key;
|
||||||
gchar *subkey, *subkey_dynamic;
|
gchar *subkey = NULL;
|
||||||
|
gchar *subkey_dynamic = NULL;
|
||||||
gchar *key_name = NULL;
|
gchar *key_name = NULL;
|
||||||
const gchar *reg_key =
|
const gchar *reg_key =
|
||||||
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\";
|
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\";
|
||||||
@ -704,6 +729,7 @@ rules_from_windows_time_zone (const gchar *identifier,
|
|||||||
DWORD size;
|
DWORD size;
|
||||||
guint rules_num = 0;
|
guint rules_num = 0;
|
||||||
RegTZI regtzi, regtzi_prev;
|
RegTZI regtzi, regtzi_prev;
|
||||||
|
gunichar2 *subkey_w, *subkey_dynamic_w;
|
||||||
|
|
||||||
g_assert (out_identifier != NULL);
|
g_assert (out_identifier != NULL);
|
||||||
g_assert (rules != NULL);
|
g_assert (rules != NULL);
|
||||||
@ -721,90 +747,118 @@ rules_from_windows_time_zone (const gchar *identifier,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
subkey = g_strconcat (reg_key, key_name, NULL);
|
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)
|
KEY_QUERY_VALUE, &key) != ERROR_SUCCESS)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
size = sizeof tzi.StandardName;
|
size = sizeof tzi.StandardName;
|
||||||
if (RegQueryValueExA (key, "Std", NULL, NULL,
|
if (RegQueryValueExW (key, L"Std", NULL, NULL,
|
||||||
(LPBYTE)&(tzi.StandardName), &size) != ERROR_SUCCESS)
|
(LPBYTE)&(tzi.StandardName), &size) != ERROR_SUCCESS)
|
||||||
goto failed;
|
goto registry_failed;
|
||||||
|
|
||||||
size = sizeof tzi.DaylightName;
|
size = sizeof tzi.DaylightName;
|
||||||
|
|
||||||
if (RegQueryValueExA (key, "Dlt", NULL, NULL,
|
if (RegQueryValueExW (key, L"Dlt", NULL, NULL,
|
||||||
(LPBYTE)&(tzi.DaylightName), &size) != ERROR_SUCCESS)
|
(LPBYTE)&(tzi.DaylightName), &size) != ERROR_SUCCESS)
|
||||||
goto failed;
|
goto registry_failed;
|
||||||
|
|
||||||
RegCloseKey (key);
|
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)
|
KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
DWORD first, last;
|
DWORD first, last;
|
||||||
int year, i;
|
int year, i;
|
||||||
gchar *s;
|
wchar_t s[12];
|
||||||
|
|
||||||
size = sizeof first;
|
size = sizeof first;
|
||||||
if (RegQueryValueExA (key, "FirstEntry", NULL, NULL,
|
if (RegQueryValueExW (key, L"FirstEntry", NULL, NULL,
|
||||||
(LPBYTE) &first, &size) != ERROR_SUCCESS)
|
(LPBYTE) &first, &size) != ERROR_SUCCESS)
|
||||||
goto failed;
|
goto registry_failed;
|
||||||
|
|
||||||
size = sizeof last;
|
size = sizeof last;
|
||||||
if (RegQueryValueExA (key, "LastEntry", NULL, NULL,
|
if (RegQueryValueExW (key, L"LastEntry", NULL, NULL,
|
||||||
(LPBYTE) &last, &size) != ERROR_SUCCESS)
|
(LPBYTE) &last, &size) != ERROR_SUCCESS)
|
||||||
goto failed;
|
goto registry_failed;
|
||||||
|
|
||||||
rules_num = last - first + 2;
|
rules_num = last - first + 2;
|
||||||
*rules = g_new0 (TimeZoneRule, rules_num);
|
*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 (!failed)
|
||||||
if (RegQueryValueExA (key, s, NULL, NULL,
|
{
|
||||||
(LPBYTE) ®tzi, &size) != ERROR_SUCCESS)
|
size = sizeof regtzi;
|
||||||
|
if (RegQueryValueExW (key, s, NULL, NULL,
|
||||||
|
(LPBYTE) ®tzi, &size) != ERROR_SUCCESS)
|
||||||
|
failed = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failed)
|
||||||
{
|
{
|
||||||
g_free (*rules);
|
g_free (*rules);
|
||||||
*rules = NULL;
|
*rules = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free (s);
|
|
||||||
|
|
||||||
if (year > first && memcmp (®tzi_prev, ®tzi, sizeof regtzi) == 0)
|
if (year > first && memcmp (®tzi_prev, ®tzi, sizeof regtzi) == 0)
|
||||||
continue;
|
continue;
|
||||||
else
|
else
|
||||||
memcpy (®tzi_prev, ®tzi, sizeof regtzi);
|
memcpy (®tzi_prev, ®tzi, sizeof regtzi);
|
||||||
|
|
||||||
register_tzi_to_tzi (®tzi, &tzi);
|
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)[i++].start_year = year;
|
||||||
}
|
}
|
||||||
|
|
||||||
rules_num = i + 1;
|
rules_num = i + 1;
|
||||||
|
|
||||||
failed:
|
registry_failed:
|
||||||
RegCloseKey (key);
|
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)
|
KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
size = sizeof regtzi;
|
size = sizeof regtzi;
|
||||||
if (RegQueryValueExA (key, "TZI", NULL, NULL,
|
if (RegQueryValueExW (key, L"TZI", NULL, NULL,
|
||||||
(LPBYTE) ®tzi, &size) == ERROR_SUCCESS)
|
(LPBYTE) ®tzi, &size) == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
rules_num = 2;
|
rules_num = 2;
|
||||||
*rules = g_new0 (TimeZoneRule, 2);
|
*rules = g_new0 (TimeZoneRule, 2);
|
||||||
register_tzi_to_tzi (®tzi, &tzi);
|
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);
|
RegCloseKey (key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utf16_conv_failed:
|
||||||
|
g_free (subkey_dynamic_w);
|
||||||
g_free (subkey_dynamic);
|
g_free (subkey_dynamic);
|
||||||
|
g_free (subkey_w);
|
||||||
g_free (subkey);
|
g_free (subkey);
|
||||||
|
|
||||||
if (*rules)
|
if (*rules)
|
||||||
@ -1518,15 +1572,16 @@ g_time_zone_new (const gchar *identifier)
|
|||||||
{
|
{
|
||||||
rules = g_new0 (TimeZoneRule, 2);
|
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);
|
rules[0].start_year = MIN_TZYEAR;
|
||||||
memset (rules[0].dlt_name, 0, NAME_SIZE);
|
rules[1].start_year = MAX_TZYEAR;
|
||||||
|
|
||||||
rules[0].start_year = MIN_TZYEAR;
|
init_zone_from_rules (tz, rules, 2, windows_default_tzname ());
|
||||||
rules[1].start_year = MAX_TZYEAR;
|
}
|
||||||
|
|
||||||
init_zone_from_rules (tz, rules, 2, windows_default_tzname ());
|
|
||||||
|
|
||||||
g_free (rules);
|
g_free (rules);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user