ntdll: Return correct time zone names for Asia/Tokyo and Asia/Yakutsk.
Without this change, for Japan, Wine returns "Korea Standard Time",
not "Tokyo Standard Time" as seen in Bug 42719.
Actually, this is a regression by d666143f88
.
The new code relies on offsets from UTC and DST change timings. However,
Northeast Asia regions don't use daylight saving time. Thus, Wine can't
distinguish between these regions.
Signed-off-by: Akihiro Sagawa <sagawa.aki@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
87c3421ddb
commit
35d93e02d1
|
@ -53,6 +53,12 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
|
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
|
||||||
|
|
||||||
|
#define SHORT_TZ_NAME_MAX 8
|
||||||
|
struct tz_name_map {
|
||||||
|
WCHAR key_name[128];
|
||||||
|
char short_name[SHORT_TZ_NAME_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
static int init_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi);
|
static int init_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi);
|
||||||
|
|
||||||
static RTL_CRITICAL_SECTION TIME_tz_section;
|
static RTL_CRITICAL_SECTION TIME_tz_section;
|
||||||
|
@ -571,6 +577,42 @@ static BOOL match_tz_info(const RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, const RT
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int compare_tz_key(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const struct tz_name_map *map_a, *map_b;
|
||||||
|
map_a = (const struct tz_name_map *)a;
|
||||||
|
map_b = (const struct tz_name_map *)b;
|
||||||
|
return strcmpW(map_a->key_name, map_b->key_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL match_tz_name(const char* tz_name,
|
||||||
|
const RTL_DYNAMIC_TIME_ZONE_INFORMATION *reg_tzi)
|
||||||
|
{
|
||||||
|
static const struct tz_name_map mapping[] = {
|
||||||
|
{ {'K','o','r','e','a',' ','S','t','a','n','d','a','r','d',' ','T','i',
|
||||||
|
'm','e',0 },
|
||||||
|
"KST" },
|
||||||
|
{ {'T','o','k','y','o',' ','S','t','a','n','d','a','r','d',' ','T','i',
|
||||||
|
'm','e',0 },
|
||||||
|
"JST" },
|
||||||
|
{ {'Y','a','k','u','t','s','k',' ','S','t','a','n','d','a','r','d',' ',
|
||||||
|
'T','i','m','e',0 },
|
||||||
|
"+09" }, /* YAKST was used until tzdata 2016f */
|
||||||
|
};
|
||||||
|
struct tz_name_map *match, key;
|
||||||
|
|
||||||
|
if (reg_tzi->DaylightDate.wMonth)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
strcpyW(key.key_name, reg_tzi->TimeZoneKeyName);
|
||||||
|
match = bsearch(&key, mapping, sizeof(mapping)/sizeof(mapping[0]),
|
||||||
|
sizeof(mapping[0]), compare_tz_key);
|
||||||
|
if (!match)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return !strcmp(match->short_name, tz_name);
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL reg_query_value(HKEY hkey, LPCWSTR name, DWORD type, void *data, DWORD count)
|
static BOOL reg_query_value(HKEY hkey, LPCWSTR name, DWORD type, void *data, DWORD count)
|
||||||
{
|
{
|
||||||
UNICODE_STRING nameW;
|
UNICODE_STRING nameW;
|
||||||
|
@ -592,7 +634,7 @@ static BOOL reg_query_value(HKEY hkey, LPCWSTR name, DWORD type, void *data, DWO
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void find_reg_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, int year)
|
static void find_reg_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, const char* tz_name, int year)
|
||||||
{
|
{
|
||||||
static const WCHAR Time_ZonesW[] = { 'M','a','c','h','i','n','e','\\',
|
static const WCHAR Time_ZonesW[] = { 'M','a','c','h','i','n','e','\\',
|
||||||
'S','o','f','t','w','a','r','e','\\',
|
'S','o','f','t','w','a','r','e','\\',
|
||||||
|
@ -714,7 +756,8 @@ static void find_reg_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, int year)
|
||||||
|
|
||||||
NtClose(hSubkey);
|
NtClose(hSubkey);
|
||||||
|
|
||||||
if (match_tz_info(tzi, ®_tzi))
|
if (match_tz_info(tzi, ®_tzi)
|
||||||
|
&& match_tz_name(tz_name, ®_tzi))
|
||||||
{
|
{
|
||||||
*tzi = reg_tzi;
|
*tzi = reg_tzi;
|
||||||
NtClose(hkey);
|
NtClose(hkey);
|
||||||
|
@ -729,8 +772,8 @@ static void find_reg_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, int year)
|
||||||
NtClose(hkey);
|
NtClose(hkey);
|
||||||
|
|
||||||
FIXME("Can't find matching timezone information in the registry for "
|
FIXME("Can't find matching timezone information in the registry for "
|
||||||
"bias %d, std (d/m/y): %u/%02u/%04u, dlt (d/m/y): %u/%02u/%04u\n",
|
"%s, bias %d, std (d/m/y): %u/%02u/%04u, dlt (d/m/y): %u/%02u/%04u\n",
|
||||||
tzi->Bias,
|
tz_name, tzi->Bias,
|
||||||
tzi->StandardDate.wDay, tzi->StandardDate.wMonth, tzi->StandardDate.wYear,
|
tzi->StandardDate.wDay, tzi->StandardDate.wMonth, tzi->StandardDate.wYear,
|
||||||
tzi->DaylightDate.wDay, tzi->DaylightDate.wMonth, tzi->DaylightDate.wYear);
|
tzi->DaylightDate.wDay, tzi->DaylightDate.wMonth, tzi->DaylightDate.wYear);
|
||||||
}
|
}
|
||||||
|
@ -763,6 +806,7 @@ static int init_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi)
|
||||||
static RTL_DYNAMIC_TIME_ZONE_INFORMATION cached_tzi;
|
static RTL_DYNAMIC_TIME_ZONE_INFORMATION cached_tzi;
|
||||||
static int current_year = -1, current_bias = 65535;
|
static int current_year = -1, current_bias = 65535;
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
|
char tz_name[SHORT_TZ_NAME_MAX];
|
||||||
time_t year_start, year_end, tmp, dlt = 0, std = 0;
|
time_t year_start, year_end, tmp, dlt = 0, std = 0;
|
||||||
int is_dst, current_is_dst, bias;
|
int is_dst, current_is_dst, bias;
|
||||||
|
|
||||||
|
@ -782,6 +826,10 @@ static int init_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi)
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(tzi, 0, sizeof(*tzi));
|
memset(tzi, 0, sizeof(*tzi));
|
||||||
|
if (!strftime(tz_name, sizeof(tz_name), "%Z", tm)) {
|
||||||
|
/* not enough room or another error */
|
||||||
|
tz_name[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
TRACE("tz data will be valid through year %d, bias %d\n", tm->tm_year + 1900, bias);
|
TRACE("tz data will be valid through year %d, bias %d\n", tm->tm_year + 1900, bias);
|
||||||
current_year = tm->tm_year;
|
current_year = tm->tm_year;
|
||||||
|
@ -864,7 +912,7 @@ static int init_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi)
|
||||||
tzi->StandardBias);
|
tzi->StandardBias);
|
||||||
}
|
}
|
||||||
|
|
||||||
find_reg_tz_info(tzi, current_year + 1900);
|
find_reg_tz_info(tzi, tz_name, current_year + 1900);
|
||||||
cached_tzi = *tzi;
|
cached_tzi = *tzi;
|
||||||
|
|
||||||
RtlLeaveCriticalSection( &TIME_tz_section );
|
RtlLeaveCriticalSection( &TIME_tz_section );
|
||||||
|
|
Loading…
Reference in New Issue