diff options
author | Chun-wei Fan <fanchunwei@src.gnome.org> | 2014-02-27 14:19:02 +0800 |
---|---|---|
committer | Chun-wei Fan <fanchunwei@src.gnome.org> | 2019-06-13 17:08:09 +0800 |
commit | 3b038b8978c0df4cd76b5fd873feb992052186c1 (patch) | |
tree | df866e0c7ad698335b0ce43b84a0c2a3659812f5 | |
parent | 23a6173e4eea20ba1e4c8ff8ebed7afb9980e232 (diff) | |
download | glib-3b038b8978c0df4cd76b5fd873feb992052186c1.tar.gz |
Fix and enhance GTimeZone for Windows
Use RegLoadMUIStringW() to query MUI_Std and MUI_Dlt when possible,
as this has the advantage to retrieve a specific string for the timezone
name and abbreviation in a specific language, rather than being
hard-connected to the language version of Windows where the program is
being run on (i.e. the Std and Dlt entries for a given time zone name).
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, and use the wide variants of RegOpenKeyEx()/
RegQueryValueEx() throughout so that we acquire tzi->StandardName and
tzi->DaylightName consistently on all the supported versions of Windows.
https://bugzilla.gnome.org/show_bug.cgi?id=719344
-rw-r--r-- | glib/gtimezone.c | 86 |
1 files changed, 63 insertions, 23 deletions
diff --git a/glib/gtimezone.c b/glib/gtimezone.c index 3d38b17bf..279a78875 100644 --- a/glib/gtimezone.c +++ b/glib/gtimezone.c @@ -39,6 +39,7 @@ #include "gdate.h" #ifdef G_OS_WIN32 + #define STRICT #include <windows.h> #endif @@ -606,6 +607,10 @@ static void rule_from_windows_time_zone_info (TimeZoneRule *rule, TIME_ZONE_INFORMATION *tzi) { + gchar *stdName, *dltName; + + stdName = g_utf16_to_utf8 ((gunichar2 *)tzi->StandardName, -1, NULL, NULL, NULL); + dltName = g_utf16_to_utf8 ((gunichar2 *)tzi->DaylightName, -1, NULL, NULL, NULL); /* Set offset */ if (tzi->StandardDate.wMonth) { @@ -622,31 +627,36 @@ 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, stdName, NAME_SIZE - 1); + strncpy (rule->dlt_name, dltName, NAME_SIZE - 1); + g_free (stdName); + g_free (dltName); } 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 (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); } @@ -704,6 +714,13 @@ rules_from_windows_time_zone (const gchar *identifier, DWORD size; gint rules_num = 0; RegTZI regtzi, regtzi_prev; + WCHAR winsyspath[MAX_PATH]; + gunichar2 *subkey_w, *subkey_dynamic_w; + int n; + + n = GetSystemDirectoryW (winsyspath, MAX_PATH); + if (n == 0) + return 0; g_assert (out_identifier != NULL); g_assert (rules != NULL); @@ -723,35 +740,54 @@ rules_from_windows_time_zone (const gchar *identifier, subkey = g_strconcat (reg_key, key_name, NULL); subkey_dynamic = g_strconcat (subkey, "\\Dynamic DST", NULL); - if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, subkey, 0, + subkey_w = g_utf8_to_utf16 (subkey, -1, NULL, NULL, NULL); + subkey_dynamic_w = g_utf8_to_utf16 (subkey_dynamic, -1, NULL, NULL, NULL); + + 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, - (LPBYTE)&(tzi.StandardName), &size) != ERROR_SUCCESS) - goto failed; + /* use RegLoadMUIStringW() to query MUI_Std from the registry if possible, otherwise + fallback to querying Std */ + if (RegLoadMUIStringW (key, L"MUI_Std", tzi.StandardName, + size, &size, 0, winsyspath) != ERROR_SUCCESS) + { + size = sizeof tzi.StandardName; + if (RegQueryValueExW (key, L"Std", NULL, NULL, + (LPBYTE)&(tzi.StandardName), &size) != ERROR_SUCCESS) + goto failed; + } size = sizeof tzi.DaylightName; - if (RegQueryValueExA (key, "Dlt", NULL, NULL, - (LPBYTE)&(tzi.DaylightName), &size) != ERROR_SUCCESS) - goto failed; + /* use RegLoadMUIStringW() to query MUI_Dlt from the registry if possible, otherwise + fallback to querying Dlt */ + if (RegLoadMUIStringW (key, L"MUI_Dlt", tzi.DaylightName, + size, &size, 0, winsyspath) != ERROR_SUCCESS) + { + size = sizeof tzi.DaylightName; + if (RegQueryValueExW (key, L"Dlt", NULL, NULL, + (LPBYTE)&(tzi.DaylightName), &size) != ERROR_SUCCESS) + goto 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; + gunichar2 *s_w; size = sizeof first; - if (RegQueryValueExA (key, "FirstEntry", NULL, NULL, + if (RegQueryValueExW (key, L"FirstEntry", NULL, NULL, (LPBYTE) &first, &size) != ERROR_SUCCESS) goto failed; size = sizeof last; - if (RegQueryValueExA (key, "LastEntry", NULL, NULL, + if (RegQueryValueExW (key, L"LastEntry", NULL, NULL, (LPBYTE) &last, &size) != ERROR_SUCCESS) goto failed; @@ -761,9 +797,10 @@ rules_from_windows_time_zone (const gchar *identifier, for (year = first, i = 0; year <= last; year++) { s = g_strdup_printf ("%d", year); + s_w = g_utf8_to_utf16 (s, -1, NULL, NULL, NULL); size = sizeof regtzi; - if (RegQueryValueExA (key, s, NULL, NULL, + if (RegQueryValueExW (key, s_w, NULL, NULL, (LPBYTE) ®tzi, &size) != ERROR_SUCCESS) { g_free (*rules); @@ -771,6 +808,7 @@ rules_from_windows_time_zone (const gchar *identifier, break; } + g_free (s_w); g_free (s); if (year > first && memcmp (®tzi_prev, ®tzi, sizeof regtzi) == 0) @@ -788,11 +826,11 @@ rules_from_windows_time_zone (const gchar *identifier, 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; @@ -804,6 +842,8 @@ failed: RegCloseKey (key); } + g_free (subkey_dynamic_w); + g_free (subkey_w); g_free (subkey_dynamic); g_free (subkey); |