[PATCH v2 0/8] MR10134: ntdll: Fix various issues with mapping Unix timezone to Windows timezone.
-- v2: ntdll: Accept 30min shift in match_tz_date(). ntdll: Better search for DST change in find_dst_change(). ntdll: Drop additional TZ matching with match_tz_name(). ntdll: Try to determine system time zone to Windows zone by name. ntdll: Factor out read_reg_tz_info(). ntdll: Fix get_timezone_info() for timezones defined with inverse DST on Unix. server: FIx timezone bias for timezones defined with inverse DST on Unix. https://gitlab.winehq.org/wine/wine/-/merge_requests/10134
From: Paul Gofman <pgofman@codeweavers.com> --- dlls/ntdll/unix/system.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index d9b276acb46..3559ba6a212 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -2925,6 +2925,20 @@ static time_t find_dst_change(time_t start, time_t end, int *is_dst) return min; } +static LONG64 get_current_tz_bias(void) +{ + ULONG high, low; + + do + { + high = user_shared_data->TimeZoneBias.High1Time; + low = user_shared_data->TimeZoneBias.LowPart; + } + while (high != user_shared_data->TimeZoneBias.High2Time); + + return ((LONG64)high << 32) | low; +} + static void get_timezone_info( RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi ) { static RTL_DYNAMIC_TIME_ZONE_INFORMATION cached_tzi; @@ -3227,27 +3241,10 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class, case SystemTimeOfDayInformation: /* 3 */ { - static LONGLONG last_bias; - static time_t last_utc; - struct tm *tm; - time_t utc; SYSTEM_TIMEOFDAY_INFORMATION sti = {{{ 0 }}}; sti.BootTime.QuadPart = server_start_time; - - utc = time( NULL ); - pthread_mutex_lock( &timezone_mutex ); - if (utc != last_utc) - { - last_utc = utc; - tm = gmtime( &utc ); - last_bias = mktime( tm ) - utc; - tm = localtime( &utc ); - if (tm->tm_isdst) last_bias -= 3600; - last_bias *= TICKSPERSEC; - } - sti.TimeZoneBias.QuadPart = last_bias; - pthread_mutex_unlock( &timezone_mutex ); + sti.TimeZoneBias.QuadPart = get_current_tz_bias(); NtQuerySystemTime( &sti.SystemTime ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10134
From: Paul Gofman <pgofman@codeweavers.com> --- server/fd.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/server/fd.c b/server/fd.c index f70bec354a3..414172ac6dd 100644 --- a/server/fd.c +++ b/server/fd.c @@ -382,7 +382,7 @@ static void set_user_shared_data_time(void) timeout_t tick_count = monotonic_time / 10000; static timeout_t last_timezone_update; timeout_t timezone_bias; - struct tm *tm; + struct tm *tm, tm1, tm2; time_t now; if (monotonic_time - last_timezone_update > TICKS_PER_SEC) @@ -391,7 +391,13 @@ static void set_user_shared_data_time(void) tm = gmtime( &now ); timezone_bias = mktime( tm ) - now; tm = localtime( &now ); - if (tm->tm_isdst) timezone_bias -= 3600; + if (tm->tm_isdst) + { + tm1 = tm2 = *tm; + tm1.tm_isdst = 0; + tm2.tm_isdst = 1; + timezone_bias += mktime(&tm1) < mktime(&tm2) ? 3600 : -3600; + } timezone_bias *= TICKS_PER_SEC; atomic_store_long(&user_shared_data->TimeZoneBias.High2Time, timezone_bias >> 32); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10134
From: Paul Gofman <pgofman@codeweavers.com> --- dlls/ntdll/unix/system.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index 3559ba6a212..c2476a20d47 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -2676,6 +2676,7 @@ static int weekday_to_mday(int year, int day, int mon, int day_of_week) do { date.tm_mday++; + date.tm_isdst = -1; tmp = mktime(&date); } while (date.tm_wday != day_of_week || date.tm_mon != mon); @@ -2688,6 +2689,7 @@ static int weekday_to_mday(int year, int day, int mon, int day_of_week) struct tm *tm; date.tm_mday += 7; + date.tm_isdst = -1; tmp = mktime(&date); tm = localtime(&tmp); if (tm->tm_mon != mon) @@ -2943,10 +2945,11 @@ static void get_timezone_info( RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi ) { static RTL_DYNAMIC_TIME_ZONE_INFORMATION cached_tzi; static int current_year = -1, current_bias = 65535; - struct tm *tm; + struct tm *tm, tm1, tm2; char tz_name[16]; time_t year_start, year_end, tmp, dlt = 0, std = 0; int is_dst, bias; + BOOL inverted_dst; mutex_lock( &timezone_mutex ); @@ -2955,6 +2958,12 @@ static void get_timezone_info( RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi ) bias = (LONG)(mktime(tm) - year_start) / 60; tm = localtime(&year_start); + tm1 = tm2 = *tm; + tm1.tm_isdst = 0; + tm2.tm_isdst = 1; + inverted_dst = mktime(&tm1) < mktime(&tm2); + if (inverted_dst) bias += 60; + if (current_year == tm->tm_year && current_bias == bias) { *tzi = cached_tzi; @@ -2968,18 +2977,19 @@ static void get_timezone_info( RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi ) 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, inverted_dst %d\n", tm->tm_year + 1900, bias, inverted_dst); current_year = tm->tm_year; current_bias = bias; tzi->Bias = bias; - tm->tm_isdst = 0; + tm->tm_isdst = inverted_dst; tm->tm_mday = 1; tm->tm_mon = tm->tm_hour = tm->tm_min = tm->tm_sec = tm->tm_wday = tm->tm_yday = 0; year_start = mktime(tm); TRACE("year_start: %s", ctime(&year_start)); + tm->tm_isdst = inverted_dst; tm->tm_mday = tm->tm_wday = tm->tm_yday = 0; tm->tm_mon = 12; tm->tm_hour = 23; @@ -2988,12 +2998,14 @@ static void get_timezone_info( RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi ) TRACE("year_end: %s", ctime(&year_end)); tmp = find_dst_change(year_start, year_end, &is_dst); + if (inverted_dst) is_dst = !is_dst; if (is_dst) dlt = tmp; else std = tmp; tmp = find_dst_change(tmp, year_end, &is_dst); + if (inverted_dst) is_dst = !is_dst; if (is_dst) dlt = tmp; else -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10134
From: Paul Gofman <pgofman@codeweavers.com> --- dlls/ntdll/unix/system.c | 116 ++++++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 51 deletions(-) diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index c2476a20d47..2fe54090d56 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -2791,13 +2791,75 @@ static BOOL reg_query_value( HKEY key, LPCWSTR name, DWORD type, void *data, DWO return TRUE; } -static void find_reg_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, const char* tz_name, int year) +static BOOL read_reg_tz_info( HANDLE key, UNICODE_STRING *zone_key_name, int year, RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi ) { static const WCHAR stdW[] = { 'S','t','d',0 }; static const WCHAR dltW[] = { 'D','l','t',0 }; static const WCHAR mui_stdW[] = { 'M','U','I','_','S','t','d',0 }; static const WCHAR mui_dltW[] = { 'M','U','I','_','D','l','t',0 }; static const WCHAR tziW[] = { 'T','Z','I',0 }; + static const WCHAR Dynamic_DstW[] = { 'D','y','n','a','m','i','c',' ','D','S','T',0 }; + HANDLE subkey, subkey_dyn; + OBJECT_ATTRIBUTES attr; + struct tz_reg_data + { + LONG bias; + LONG std_bias; + LONG dlt_bias; + RTL_SYSTEM_TIME std_date; + RTL_SYSTEM_TIME dlt_date; + } tz_data; + BOOL is_dynamic = FALSE; + UNICODE_STRING name; + BOOL ret = FALSE; + char buffer[16]; + WCHAR yearW[16]; + + InitializeObjectAttributes( &attr, zone_key_name, 0, key, NULL ); + if (NtOpenKey( &subkey, KEY_READ, &attr )) return FALSE; + + memset( tzi, 0, sizeof(*tzi) ); + memcpy(tzi->TimeZoneKeyName, zone_key_name->Buffer, zone_key_name->Length); + tzi->TimeZoneKeyName[zone_key_name->Length / sizeof(WCHAR)] = 0; + + if (!reg_query_value(subkey, mui_stdW, REG_SZ, tzi->StandardName, sizeof(tzi->StandardName)) && + !reg_query_value(subkey, stdW, REG_SZ, tzi->StandardName, sizeof(tzi->StandardName))) + goto done; + + if (!reg_query_value(subkey, mui_dltW, REG_SZ, tzi->DaylightName, sizeof(tzi->DaylightName)) && + !reg_query_value(subkey, dltW, REG_SZ, tzi->DaylightName, sizeof(tzi->DaylightName))) + goto done; + + /* Check for Dynamic DST entry first */ + name.Buffer = (WCHAR *)Dynamic_DstW; + name.Length = sizeof(Dynamic_DstW) - sizeof(WCHAR); + attr.RootDirectory = subkey; + attr.ObjectName = &name; + if (!NtOpenKey( &subkey_dyn, KEY_READ, &attr )) + { + snprintf( buffer, sizeof(buffer), "%u", year ); + ascii_to_unicode( yearW, buffer, strlen(buffer) + 1 ); + is_dynamic = reg_query_value( subkey_dyn, yearW, REG_BINARY, &tz_data, sizeof(tz_data) ); + NtClose( subkey_dyn ); + } + if (!is_dynamic && !reg_query_value( subkey, tziW, REG_BINARY, &tz_data, sizeof(tz_data) )) + goto done; + + tzi->Bias = tz_data.bias; + tzi->StandardBias = tz_data.std_bias; + tzi->DaylightBias = tz_data.dlt_bias; + tzi->StandardDate = tz_data.std_date; + tzi->DaylightDate = tz_data.dlt_date; + + ret = TRUE; + +done: + NtClose( subkey ); + return ret; +} + +static void find_reg_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, const char* tz_name, int year) +{ static const WCHAR Time_ZonesW[] = { '\\','R','e','g','i','s','t','r','y','\\', 'M','a','c','h','i','n','e','\\', 'S','o','f','t','w','a','r','e','\\', @@ -2805,18 +2867,14 @@ static void find_reg_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, const char* 'W','i','n','d','o','w','s',' ','N','T','\\', 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 'T','i','m','e',' ','Z','o','n','e','s',0 }; - static const WCHAR Dynamic_DstW[] = { 'D','y','n','a','m','i','c',' ','D','S','T',0 }; RTL_DYNAMIC_TIME_ZONE_INFORMATION reg_tzi; - HANDLE key, subkey, subkey_dyn = 0; + HANDLE key; ULONG idx, len; OBJECT_ATTRIBUTES attr; UNICODE_STRING nameW; - WCHAR yearW[16]; char buffer[128]; KEY_BASIC_INFORMATION *info = (KEY_BASIC_INFORMATION *)buffer; - snprintf( buffer, sizeof(buffer), "%u", year ); - ascii_to_unicode( yearW, buffer, strlen(buffer) + 1 ); init_unicode_string( &nameW, Time_ZonesW ); InitializeObjectAttributes( &attr, &nameW, 0, 0, NULL ); if (NtOpenKey( &key, KEY_READ, &attr )) return; @@ -2824,50 +2882,9 @@ static void find_reg_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, const char* idx = 0; while (!NtEnumerateKey( key, idx++, KeyBasicInformation, buffer, sizeof(buffer), &len )) { - struct tz_reg_data - { - LONG bias; - LONG std_bias; - LONG dlt_bias; - RTL_SYSTEM_TIME std_date; - RTL_SYSTEM_TIME dlt_date; - } tz_data; - BOOL is_dynamic = FALSE; - nameW.Buffer = info->Name; nameW.Length = info->NameLength; - attr.RootDirectory = key; - if (NtOpenKey( &subkey, KEY_READ, &attr )) continue; - - memset( ®_tzi, 0, sizeof(reg_tzi) ); - memcpy(reg_tzi.TimeZoneKeyName, nameW.Buffer, nameW.Length); - reg_tzi.TimeZoneKeyName[nameW.Length/sizeof(WCHAR)] = 0; - - if (!reg_query_value(subkey, mui_stdW, REG_SZ, reg_tzi.StandardName, sizeof(reg_tzi.StandardName)) && - !reg_query_value(subkey, stdW, REG_SZ, reg_tzi.StandardName, sizeof(reg_tzi.StandardName))) - goto next; - - if (!reg_query_value(subkey, mui_dltW, REG_SZ, reg_tzi.DaylightName, sizeof(reg_tzi.DaylightName)) && - !reg_query_value(subkey, dltW, REG_SZ, reg_tzi.DaylightName, sizeof(reg_tzi.DaylightName))) - goto next; - - /* Check for Dynamic DST entry first */ - nameW.Buffer = (WCHAR *)Dynamic_DstW; - nameW.Length = sizeof(Dynamic_DstW) - sizeof(WCHAR); - attr.RootDirectory = subkey; - if (!NtOpenKey( &subkey_dyn, KEY_READ, &attr )) - { - is_dynamic = reg_query_value( subkey_dyn, yearW, REG_BINARY, &tz_data, sizeof(tz_data) ); - NtClose( subkey_dyn ); - } - if (!is_dynamic && !reg_query_value( subkey, tziW, REG_BINARY, &tz_data, sizeof(tz_data) )) - goto next; - - reg_tzi.Bias = tz_data.bias; - reg_tzi.StandardBias = tz_data.std_bias; - reg_tzi.DaylightBias = tz_data.dlt_bias; - reg_tzi.StandardDate = tz_data.std_date; - reg_tzi.DaylightDate = tz_data.dlt_date; + if (!read_reg_tz_info( key, &nameW, year, ®_tzi )) continue; TRACE("%s: bias %d\n", debugstr_us(&nameW), reg_tzi.Bias); TRACE("std (d/m/y): %u/%02u/%04u day of week %u %u:%02u:%02u.%03u bias %d\n", @@ -2886,12 +2903,9 @@ static void find_reg_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, const char* if (match_tz_info( tzi, ®_tzi ) && match_tz_name( tz_name, ®_tzi )) { *tzi = reg_tzi; - NtClose( subkey ); NtClose( key ); return; } - next: - NtClose( subkey ); } NtClose( key ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10134
From: Paul Gofman <pgofman@codeweavers.com> --- dlls/kernelbase/kernelbase.rgs | 454 +++++++++++++++++++++++++++++++++ dlls/ntdll/unix/system.c | 97 ++++++- tools/make_unicode | 24 +- 3 files changed, 564 insertions(+), 11 deletions(-) diff --git a/dlls/kernelbase/kernelbase.rgs b/dlls/kernelbase/kernelbase.rgs index ac1820d5c79..0a01ee5580f 100644 --- a/dlls/kernelbase/kernelbase.rgs +++ b/dlls/kernelbase/kernelbase.rgs @@ -3255,6 +3255,460 @@ HKLM } } } + NoRemove Wine + { + 'Time Zones' + { + 'TZ Mapping' + { + val 'Africa/Abidjan' = s 'Greenwich Standard Time' + val 'Africa/Accra' = s 'Greenwich Standard Time' + val 'Africa/Addis_Ababa' = s 'E. Africa Standard Time' + val 'Africa/Algiers' = s 'W. Central Africa Standard Time' + val 'Africa/Asmera' = s 'E. Africa Standard Time' + val 'Africa/Bamako' = s 'Greenwich Standard Time' + val 'Africa/Bangui' = s 'W. Central Africa Standard Time' + val 'Africa/Banjul' = s 'Greenwich Standard Time' + val 'Africa/Bissau' = s 'Greenwich Standard Time' + val 'Africa/Blantyre' = s 'South Africa Standard Time' + val 'Africa/Brazzaville' = s 'W. Central Africa Standard Time' + val 'Africa/Bujumbura' = s 'South Africa Standard Time' + val 'Africa/Cairo' = s 'Egypt Standard Time' + val 'Africa/Casablanca' = s 'Morocco Standard Time' + val 'Africa/Ceuta' = s 'Romance Standard Time' + val 'Africa/Conakry' = s 'Greenwich Standard Time' + val 'Africa/Dakar' = s 'Greenwich Standard Time' + val 'Africa/Dar_es_Salaam' = s 'E. Africa Standard Time' + val 'Africa/Djibouti' = s 'E. Africa Standard Time' + val 'Africa/Douala' = s 'W. Central Africa Standard Time' + val 'Africa/El_Aaiun' = s 'Morocco Standard Time' + val 'Africa/Freetown' = s 'Greenwich Standard Time' + val 'Africa/Gaborone' = s 'South Africa Standard Time' + val 'Africa/Harare' = s 'South Africa Standard Time' + val 'Africa/Johannesburg' = s 'South Africa Standard Time' + val 'Africa/Juba' = s 'South Sudan Standard Time' + val 'Africa/Kampala' = s 'E. Africa Standard Time' + val 'Africa/Khartoum' = s 'Sudan Standard Time' + val 'Africa/Kigali' = s 'South Africa Standard Time' + val 'Africa/Kinshasa' = s 'W. Central Africa Standard Time' + val 'Africa/Lagos' = s 'W. Central Africa Standard Time' + val 'Africa/Libreville' = s 'W. Central Africa Standard Time' + val 'Africa/Lome' = s 'Greenwich Standard Time' + val 'Africa/Luanda' = s 'W. Central Africa Standard Time' + val 'Africa/Lubumbashi' = s 'South Africa Standard Time' + val 'Africa/Lusaka' = s 'South Africa Standard Time' + val 'Africa/Malabo' = s 'W. Central Africa Standard Time' + val 'Africa/Maputo' = s 'South Africa Standard Time' + val 'Africa/Maseru' = s 'South Africa Standard Time' + val 'Africa/Mbabane' = s 'South Africa Standard Time' + val 'Africa/Mogadishu' = s 'E. Africa Standard Time' + val 'Africa/Monrovia' = s 'Greenwich Standard Time' + val 'Africa/Nairobi' = s 'E. Africa Standard Time' + val 'Africa/Ndjamena' = s 'W. Central Africa Standard Time' + val 'Africa/Niamey' = s 'W. Central Africa Standard Time' + val 'Africa/Nouakchott' = s 'Greenwich Standard Time' + val 'Africa/Ouagadougou' = s 'Greenwich Standard Time' + val 'Africa/Porto-Novo' = s 'W. Central Africa Standard Time' + val 'Africa/Sao_Tome' = s 'Sao Tome Standard Time' + val 'Africa/Tripoli' = s 'Libya Standard Time' + val 'Africa/Tunis' = s 'W. Central Africa Standard Time' + val 'Africa/Windhoek' = s 'Namibia Standard Time' + val 'America/Adak' = s 'Aleutian Standard Time' + val 'America/Anchorage' = s 'Alaskan Standard Time' + val 'America/Anguilla' = s 'SA Western Standard Time' + val 'America/Antigua' = s 'SA Western Standard Time' + val 'America/Araguaina' = s 'Tocantins Standard Time' + val 'America/Argentina/La_Rioja' = s 'Argentina Standard Time' + val 'America/Argentina/Rio_Gallegos' = s 'Argentina Standard Time' + val 'America/Argentina/Salta' = s 'Argentina Standard Time' + val 'America/Argentina/San_Juan' = s 'Argentina Standard Time' + val 'America/Argentina/San_Luis' = s 'Argentina Standard Time' + val 'America/Argentina/Tucuman' = s 'Argentina Standard Time' + val 'America/Argentina/Ushuaia' = s 'Argentina Standard Time' + val 'America/Aruba' = s 'SA Western Standard Time' + val 'America/Asuncion' = s 'Paraguay Standard Time' + val 'America/Bahia' = s 'Bahia Standard Time' + val 'America/Bahia_Banderas' = s 'Central Standard Time (Mexico)' + val 'America/Barbados' = s 'SA Western Standard Time' + val 'America/Belem' = s 'SA Eastern Standard Time' + val 'America/Belize' = s 'Central America Standard Time' + val 'America/Blanc-Sablon' = s 'SA Western Standard Time' + val 'America/Boa_Vista' = s 'SA Western Standard Time' + val 'America/Bogota' = s 'SA Pacific Standard Time' + val 'America/Boise' = s 'Mountain Standard Time' + val 'America/Buenos_Aires' = s 'Argentina Standard Time' + val 'America/Cambridge_Bay' = s 'Mountain Standard Time' + val 'America/Campo_Grande' = s 'Central Brazilian Standard Time' + val 'America/Cancun' = s 'Eastern Standard Time (Mexico)' + val 'America/Caracas' = s 'Venezuela Standard Time' + val 'America/Catamarca' = s 'Argentina Standard Time' + val 'America/Cayenne' = s 'SA Eastern Standard Time' + val 'America/Cayman' = s 'SA Pacific Standard Time' + val 'America/Chicago' = s 'Central Standard Time' + val 'America/Chihuahua' = s 'Central Standard Time (Mexico)' + val 'America/Ciudad_Juarez' = s 'Mountain Standard Time' + val 'America/Coral_Harbour' = s 'SA Pacific Standard Time' + val 'America/Cordoba' = s 'Argentina Standard Time' + val 'America/Costa_Rica' = s 'Central America Standard Time' + val 'America/Coyhaique' = s 'Magallanes Standard Time' + val 'America/Creston' = s 'US Mountain Standard Time' + val 'America/Cuiaba' = s 'Central Brazilian Standard Time' + val 'America/Curacao' = s 'SA Western Standard Time' + val 'America/Danmarkshavn' = s 'Greenwich Standard Time' + val 'America/Dawson' = s 'Yukon Standard Time' + val 'America/Dawson_Creek' = s 'US Mountain Standard Time' + val 'America/Denver' = s 'Mountain Standard Time' + val 'America/Detroit' = s 'Eastern Standard Time' + val 'America/Dominica' = s 'SA Western Standard Time' + val 'America/Edmonton' = s 'Mountain Standard Time' + val 'America/Eirunepe' = s 'SA Pacific Standard Time' + val 'America/El_Salvador' = s 'Central America Standard Time' + val 'America/Fort_Nelson' = s 'US Mountain Standard Time' + val 'America/Fortaleza' = s 'SA Eastern Standard Time' + val 'America/Glace_Bay' = s 'Atlantic Standard Time' + val 'America/Godthab' = s 'Greenland Standard Time' + val 'America/Goose_Bay' = s 'Atlantic Standard Time' + val 'America/Grand_Turk' = s 'Turks And Caicos Standard Time' + val 'America/Grenada' = s 'SA Western Standard Time' + val 'America/Guadeloupe' = s 'SA Western Standard Time' + val 'America/Guatemala' = s 'Central America Standard Time' + val 'America/Guayaquil' = s 'SA Pacific Standard Time' + val 'America/Guyana' = s 'SA Western Standard Time' + val 'America/Halifax' = s 'Atlantic Standard Time' + val 'America/Havana' = s 'Cuba Standard Time' + val 'America/Hermosillo' = s 'US Mountain Standard Time' + val 'America/Indiana/Knox' = s 'Central Standard Time' + val 'America/Indiana/Marengo' = s 'US Eastern Standard Time' + val 'America/Indiana/Petersburg' = s 'Eastern Standard Time' + val 'America/Indiana/Tell_City' = s 'Central Standard Time' + val 'America/Indiana/Vevay' = s 'US Eastern Standard Time' + val 'America/Indiana/Vincennes' = s 'Eastern Standard Time' + val 'America/Indiana/Winamac' = s 'Eastern Standard Time' + val 'America/Indianapolis' = s 'US Eastern Standard Time' + val 'America/Inuvik' = s 'Mountain Standard Time' + val 'America/Iqaluit' = s 'Eastern Standard Time' + val 'America/Jamaica' = s 'SA Pacific Standard Time' + val 'America/Jujuy' = s 'Argentina Standard Time' + val 'America/Juneau' = s 'Alaskan Standard Time' + val 'America/Kentucky/Monticello' = s 'Eastern Standard Time' + val 'America/Kralendijk' = s 'SA Western Standard Time' + val 'America/La_Paz' = s 'SA Western Standard Time' + val 'America/Lima' = s 'SA Pacific Standard Time' + val 'America/Los_Angeles' = s 'Pacific Standard Time' + val 'America/Louisville' = s 'Eastern Standard Time' + val 'America/Lower_Princes' = s 'SA Western Standard Time' + val 'America/Maceio' = s 'SA Eastern Standard Time' + val 'America/Managua' = s 'Central America Standard Time' + val 'America/Manaus' = s 'SA Western Standard Time' + val 'America/Marigot' = s 'SA Western Standard Time' + val 'America/Martinique' = s 'SA Western Standard Time' + val 'America/Matamoros' = s 'Central Standard Time' + val 'America/Mazatlan' = s 'Mountain Standard Time (Mexico)' + val 'America/Mendoza' = s 'Argentina Standard Time' + val 'America/Menominee' = s 'Central Standard Time' + val 'America/Merida' = s 'Central Standard Time (Mexico)' + val 'America/Metlakatla' = s 'Alaskan Standard Time' + val 'America/Mexico_City' = s 'Central Standard Time (Mexico)' + val 'America/Miquelon' = s 'Saint Pierre Standard Time' + val 'America/Moncton' = s 'Atlantic Standard Time' + val 'America/Monterrey' = s 'Central Standard Time (Mexico)' + val 'America/Montevideo' = s 'Montevideo Standard Time' + val 'America/Montserrat' = s 'SA Western Standard Time' + val 'America/Nassau' = s 'Eastern Standard Time' + val 'America/New_York' = s 'Eastern Standard Time' + val 'America/Nome' = s 'Alaskan Standard Time' + val 'America/Noronha' = s 'UTC-02' + val 'America/North_Dakota/Beulah' = s 'Central Standard Time' + val 'America/North_Dakota/Center' = s 'Central Standard Time' + val 'America/North_Dakota/New_Salem' = s 'Central Standard Time' + val 'America/Ojinaga' = s 'Central Standard Time' + val 'America/Panama' = s 'SA Pacific Standard Time' + val 'America/Paramaribo' = s 'SA Eastern Standard Time' + val 'America/Phoenix' = s 'US Mountain Standard Time' + val 'America/Port-au-Prince' = s 'Haiti Standard Time' + val 'America/Port_of_Spain' = s 'SA Western Standard Time' + val 'America/Porto_Velho' = s 'SA Western Standard Time' + val 'America/Puerto_Rico' = s 'SA Western Standard Time' + val 'America/Punta_Arenas' = s 'Magallanes Standard Time' + val 'America/Rankin_Inlet' = s 'Central Standard Time' + val 'America/Recife' = s 'SA Eastern Standard Time' + val 'America/Regina' = s 'Canada Central Standard Time' + val 'America/Resolute' = s 'Central Standard Time' + val 'America/Rio_Branco' = s 'SA Pacific Standard Time' + val 'America/Santarem' = s 'SA Eastern Standard Time' + val 'America/Santiago' = s 'Pacific SA Standard Time' + val 'America/Santo_Domingo' = s 'SA Western Standard Time' + val 'America/Sao_Paulo' = s 'E. South America Standard Time' + val 'America/Scoresbysund' = s 'Azores Standard Time' + val 'America/Sitka' = s 'Alaskan Standard Time' + val 'America/St_Barthelemy' = s 'SA Western Standard Time' + val 'America/St_Johns' = s 'Newfoundland Standard Time' + val 'America/St_Kitts' = s 'SA Western Standard Time' + val 'America/St_Lucia' = s 'SA Western Standard Time' + val 'America/St_Thomas' = s 'SA Western Standard Time' + val 'America/St_Vincent' = s 'SA Western Standard Time' + val 'America/Swift_Current' = s 'Canada Central Standard Time' + val 'America/Tegucigalpa' = s 'Central America Standard Time' + val 'America/Thule' = s 'Atlantic Standard Time' + val 'America/Tijuana' = s 'Pacific Standard Time (Mexico)' + val 'America/Toronto' = s 'Eastern Standard Time' + val 'America/Tortola' = s 'SA Western Standard Time' + val 'America/Vancouver' = s 'Pacific Standard Time' + val 'America/Whitehorse' = s 'Yukon Standard Time' + val 'America/Winnipeg' = s 'Central Standard Time' + val 'America/Yakutat' = s 'Alaskan Standard Time' + val 'Antarctica/Casey' = s 'Central Pacific Standard Time' + val 'Antarctica/Davis' = s 'SE Asia Standard Time' + val 'Antarctica/DumontDUrville' = s 'West Pacific Standard Time' + val 'Antarctica/Macquarie' = s 'Tasmania Standard Time' + val 'Antarctica/Mawson' = s 'West Asia Standard Time' + val 'Antarctica/McMurdo' = s 'New Zealand Standard Time' + val 'Antarctica/Palmer' = s 'SA Eastern Standard Time' + val 'Antarctica/Rothera' = s 'SA Eastern Standard Time' + val 'Antarctica/Syowa' = s 'E. Africa Standard Time' + val 'Antarctica/Vostok' = s 'Central Asia Standard Time' + val 'Arctic/Longyearbyen' = s 'W. Europe Standard Time' + val 'Asia/Aden' = s 'Arab Standard Time' + val 'Asia/Almaty' = s 'West Asia Standard Time' + val 'Asia/Amman' = s 'Jordan Standard Time' + val 'Asia/Anadyr' = s 'Russia Time Zone 11' + val 'Asia/Aqtau' = s 'West Asia Standard Time' + val 'Asia/Aqtobe' = s 'West Asia Standard Time' + val 'Asia/Ashgabat' = s 'West Asia Standard Time' + val 'Asia/Atyrau' = s 'West Asia Standard Time' + val 'Asia/Baghdad' = s 'Arabic Standard Time' + val 'Asia/Bahrain' = s 'Arab Standard Time' + val 'Asia/Baku' = s 'Azerbaijan Standard Time' + val 'Asia/Bangkok' = s 'SE Asia Standard Time' + val 'Asia/Barnaul' = s 'Altai Standard Time' + val 'Asia/Beirut' = s 'Middle East Standard Time' + val 'Asia/Bishkek' = s 'Central Asia Standard Time' + val 'Asia/Brunei' = s 'Singapore Standard Time' + val 'Asia/Calcutta' = s 'India Standard Time' + val 'Asia/Chita' = s 'Transbaikal Standard Time' + val 'Asia/Colombo' = s 'Sri Lanka Standard Time' + val 'Asia/Damascus' = s 'Syria Standard Time' + val 'Asia/Dhaka' = s 'Bangladesh Standard Time' + val 'Asia/Dili' = s 'Tokyo Standard Time' + val 'Asia/Dubai' = s 'Arabian Standard Time' + val 'Asia/Dushanbe' = s 'West Asia Standard Time' + val 'Asia/Famagusta' = s 'GTB Standard Time' + val 'Asia/Gaza' = s 'West Bank Standard Time' + val 'Asia/Hebron' = s 'West Bank Standard Time' + val 'Asia/Hong_Kong' = s 'China Standard Time' + val 'Asia/Hovd' = s 'W. Mongolia Standard Time' + val 'Asia/Irkutsk' = s 'North Asia East Standard Time' + val 'Asia/Jakarta' = s 'SE Asia Standard Time' + val 'Asia/Jayapura' = s 'Tokyo Standard Time' + val 'Asia/Jerusalem' = s 'Israel Standard Time' + val 'Asia/Kabul' = s 'Afghanistan Standard Time' + val 'Asia/Kamchatka' = s 'Russia Time Zone 11' + val 'Asia/Karachi' = s 'Pakistan Standard Time' + val 'Asia/Katmandu' = s 'Nepal Standard Time' + val 'Asia/Khandyga' = s 'Yakutsk Standard Time' + val 'Asia/Krasnoyarsk' = s 'North Asia Standard Time' + val 'Asia/Kuala_Lumpur' = s 'Singapore Standard Time' + val 'Asia/Kuching' = s 'Singapore Standard Time' + val 'Asia/Kuwait' = s 'Arab Standard Time' + val 'Asia/Macau' = s 'China Standard Time' + val 'Asia/Magadan' = s 'Magadan Standard Time' + val 'Asia/Makassar' = s 'Singapore Standard Time' + val 'Asia/Manila' = s 'Singapore Standard Time' + val 'Asia/Muscat' = s 'Arabian Standard Time' + val 'Asia/Nicosia' = s 'GTB Standard Time' + val 'Asia/Novokuznetsk' = s 'North Asia Standard Time' + val 'Asia/Novosibirsk' = s 'N. Central Asia Standard Time' + val 'Asia/Omsk' = s 'Omsk Standard Time' + val 'Asia/Oral' = s 'West Asia Standard Time' + val 'Asia/Phnom_Penh' = s 'SE Asia Standard Time' + val 'Asia/Pontianak' = s 'SE Asia Standard Time' + val 'Asia/Pyongyang' = s 'North Korea Standard Time' + val 'Asia/Qatar' = s 'Arab Standard Time' + val 'Asia/Qostanay' = s 'West Asia Standard Time' + val 'Asia/Qyzylorda' = s 'Qyzylorda Standard Time' + val 'Asia/Rangoon' = s 'Myanmar Standard Time' + val 'Asia/Riyadh' = s 'Arab Standard Time' + val 'Asia/Saigon' = s 'SE Asia Standard Time' + val 'Asia/Sakhalin' = s 'Sakhalin Standard Time' + val 'Asia/Samarkand' = s 'West Asia Standard Time' + val 'Asia/Seoul' = s 'Korea Standard Time' + val 'Asia/Shanghai' = s 'China Standard Time' + val 'Asia/Singapore' = s 'Singapore Standard Time' + val 'Asia/Srednekolymsk' = s 'Russia Time Zone 10' + val 'Asia/Taipei' = s 'Taipei Standard Time' + val 'Asia/Tashkent' = s 'West Asia Standard Time' + val 'Asia/Tbilisi' = s 'Georgian Standard Time' + val 'Asia/Tehran' = s 'Iran Standard Time' + val 'Asia/Thimphu' = s 'Bangladesh Standard Time' + val 'Asia/Tokyo' = s 'Tokyo Standard Time' + val 'Asia/Tomsk' = s 'Tomsk Standard Time' + val 'Asia/Ulaanbaatar' = s 'Ulaanbaatar Standard Time' + val 'Asia/Urumqi' = s 'Central Asia Standard Time' + val 'Asia/Ust-Nera' = s 'Vladivostok Standard Time' + val 'Asia/Vientiane' = s 'SE Asia Standard Time' + val 'Asia/Vladivostok' = s 'Vladivostok Standard Time' + val 'Asia/Yakutsk' = s 'Yakutsk Standard Time' + val 'Asia/Yekaterinburg' = s 'Ekaterinburg Standard Time' + val 'Asia/Yerevan' = s 'Caucasus Standard Time' + val 'Atlantic/Azores' = s 'Azores Standard Time' + val 'Atlantic/Bermuda' = s 'Atlantic Standard Time' + val 'Atlantic/Canary' = s 'GMT Standard Time' + val 'Atlantic/Cape_Verde' = s 'Cape Verde Standard Time' + val 'Atlantic/Faeroe' = s 'GMT Standard Time' + val 'Atlantic/Madeira' = s 'GMT Standard Time' + val 'Atlantic/Reykjavik' = s 'Greenwich Standard Time' + val 'Atlantic/South_Georgia' = s 'UTC-02' + val 'Atlantic/St_Helena' = s 'Greenwich Standard Time' + val 'Atlantic/Stanley' = s 'SA Eastern Standard Time' + val 'Australia/Adelaide' = s 'Cen. Australia Standard Time' + val 'Australia/Brisbane' = s 'E. Australia Standard Time' + val 'Australia/Broken_Hill' = s 'Cen. Australia Standard Time' + val 'Australia/Darwin' = s 'AUS Central Standard Time' + val 'Australia/Eucla' = s 'Aus Central W. Standard Time' + val 'Australia/Hobart' = s 'Tasmania Standard Time' + val 'Australia/Lindeman' = s 'E. Australia Standard Time' + val 'Australia/Lord_Howe' = s 'Lord Howe Standard Time' + val 'Australia/Melbourne' = s 'AUS Eastern Standard Time' + val 'Australia/Perth' = s 'W. Australia Standard Time' + val 'Australia/Sydney' = s 'AUS Eastern Standard Time' + val 'Etc/GMT' = s 'UTC' + val 'Etc/GMT+1' = s 'Cape Verde Standard Time' + val 'Etc/GMT+10' = s 'Hawaiian Standard Time' + val 'Etc/GMT+11' = s 'UTC-11' + val 'Etc/GMT+12' = s 'Dateline Standard Time' + val 'Etc/GMT+2' = s 'UTC-02' + val 'Etc/GMT+3' = s 'SA Eastern Standard Time' + val 'Etc/GMT+4' = s 'SA Western Standard Time' + val 'Etc/GMT+5' = s 'SA Pacific Standard Time' + val 'Etc/GMT+6' = s 'Central America Standard Time' + val 'Etc/GMT+7' = s 'US Mountain Standard Time' + val 'Etc/GMT+8' = s 'UTC-08' + val 'Etc/GMT+9' = s 'UTC-09' + val 'Etc/GMT-1' = s 'W. Central Africa Standard Time' + val 'Etc/GMT-10' = s 'West Pacific Standard Time' + val 'Etc/GMT-11' = s 'Central Pacific Standard Time' + val 'Etc/GMT-12' = s 'UTC+12' + val 'Etc/GMT-13' = s 'UTC+13' + val 'Etc/GMT-14' = s 'Line Islands Standard Time' + val 'Etc/GMT-2' = s 'South Africa Standard Time' + val 'Etc/GMT-3' = s 'E. Africa Standard Time' + val 'Etc/GMT-4' = s 'Arabian Standard Time' + val 'Etc/GMT-5' = s 'West Asia Standard Time' + val 'Etc/GMT-6' = s 'Central Asia Standard Time' + val 'Etc/GMT-7' = s 'SE Asia Standard Time' + val 'Etc/GMT-8' = s 'Singapore Standard Time' + val 'Etc/GMT-9' = s 'Tokyo Standard Time' + val 'Etc/UTC' = s 'UTC' + val 'Europe/Amsterdam' = s 'W. Europe Standard Time' + val 'Europe/Andorra' = s 'W. Europe Standard Time' + val 'Europe/Astrakhan' = s 'Astrakhan Standard Time' + val 'Europe/Athens' = s 'GTB Standard Time' + val 'Europe/Belgrade' = s 'Central Europe Standard Time' + val 'Europe/Berlin' = s 'W. Europe Standard Time' + val 'Europe/Bratislava' = s 'Central Europe Standard Time' + val 'Europe/Brussels' = s 'Romance Standard Time' + val 'Europe/Bucharest' = s 'GTB Standard Time' + val 'Europe/Budapest' = s 'Central Europe Standard Time' + val 'Europe/Busingen' = s 'W. Europe Standard Time' + val 'Europe/Chisinau' = s 'E. Europe Standard Time' + val 'Europe/Copenhagen' = s 'Romance Standard Time' + val 'Europe/Dublin' = s 'GMT Standard Time' + val 'Europe/Gibraltar' = s 'W. Europe Standard Time' + val 'Europe/Guernsey' = s 'GMT Standard Time' + val 'Europe/Helsinki' = s 'FLE Standard Time' + val 'Europe/Isle_of_Man' = s 'GMT Standard Time' + val 'Europe/Istanbul' = s 'Turkey Standard Time' + val 'Europe/Jersey' = s 'GMT Standard Time' + val 'Europe/Kaliningrad' = s 'Kaliningrad Standard Time' + val 'Europe/Kiev' = s 'FLE Standard Time' + val 'Europe/Kirov' = s 'Russian Standard Time' + val 'Europe/Lisbon' = s 'GMT Standard Time' + val 'Europe/Ljubljana' = s 'Central Europe Standard Time' + val 'Europe/London' = s 'GMT Standard Time' + val 'Europe/Luxembourg' = s 'W. Europe Standard Time' + val 'Europe/Madrid' = s 'Romance Standard Time' + val 'Europe/Malta' = s 'W. Europe Standard Time' + val 'Europe/Mariehamn' = s 'FLE Standard Time' + val 'Europe/Minsk' = s 'Belarus Standard Time' + val 'Europe/Monaco' = s 'W. Europe Standard Time' + val 'Europe/Moscow' = s 'Russian Standard Time' + val 'Europe/Oslo' = s 'W. Europe Standard Time' + val 'Europe/Paris' = s 'Romance Standard Time' + val 'Europe/Podgorica' = s 'Central Europe Standard Time' + val 'Europe/Prague' = s 'Central Europe Standard Time' + val 'Europe/Riga' = s 'FLE Standard Time' + val 'Europe/Rome' = s 'W. Europe Standard Time' + val 'Europe/Samara' = s 'Russia Time Zone 3' + val 'Europe/San_Marino' = s 'W. Europe Standard Time' + val 'Europe/Sarajevo' = s 'Central European Standard Time' + val 'Europe/Saratov' = s 'Saratov Standard Time' + val 'Europe/Simferopol' = s 'Russian Standard Time' + val 'Europe/Skopje' = s 'Central European Standard Time' + val 'Europe/Sofia' = s 'FLE Standard Time' + val 'Europe/Stockholm' = s 'W. Europe Standard Time' + val 'Europe/Tallinn' = s 'FLE Standard Time' + val 'Europe/Tirane' = s 'Central Europe Standard Time' + val 'Europe/Ulyanovsk' = s 'Astrakhan Standard Time' + val 'Europe/Vaduz' = s 'W. Europe Standard Time' + val 'Europe/Vatican' = s 'W. Europe Standard Time' + val 'Europe/Vienna' = s 'W. Europe Standard Time' + val 'Europe/Vilnius' = s 'FLE Standard Time' + val 'Europe/Volgograd' = s 'Volgograd Standard Time' + val 'Europe/Warsaw' = s 'Central European Standard Time' + val 'Europe/Zagreb' = s 'Central European Standard Time' + val 'Europe/Zurich' = s 'W. Europe Standard Time' + val 'Indian/Antananarivo' = s 'E. Africa Standard Time' + val 'Indian/Chagos' = s 'Central Asia Standard Time' + val 'Indian/Christmas' = s 'SE Asia Standard Time' + val 'Indian/Cocos' = s 'Myanmar Standard Time' + val 'Indian/Comoro' = s 'E. Africa Standard Time' + val 'Indian/Kerguelen' = s 'West Asia Standard Time' + val 'Indian/Mahe' = s 'Mauritius Standard Time' + val 'Indian/Maldives' = s 'West Asia Standard Time' + val 'Indian/Mauritius' = s 'Mauritius Standard Time' + val 'Indian/Mayotte' = s 'E. Africa Standard Time' + val 'Indian/Reunion' = s 'Mauritius Standard Time' + val 'Pacific/Apia' = s 'Samoa Standard Time' + val 'Pacific/Auckland' = s 'New Zealand Standard Time' + val 'Pacific/Bougainville' = s 'Bougainville Standard Time' + val 'Pacific/Chatham' = s 'Chatham Islands Standard Time' + val 'Pacific/Easter' = s 'Easter Island Standard Time' + val 'Pacific/Efate' = s 'Central Pacific Standard Time' + val 'Pacific/Enderbury' = s 'UTC+13' + val 'Pacific/Fakaofo' = s 'UTC+13' + val 'Pacific/Fiji' = s 'Fiji Standard Time' + val 'Pacific/Funafuti' = s 'UTC+12' + val 'Pacific/Galapagos' = s 'Central America Standard Time' + val 'Pacific/Gambier' = s 'UTC-09' + val 'Pacific/Guadalcanal' = s 'Central Pacific Standard Time' + val 'Pacific/Guam' = s 'West Pacific Standard Time' + val 'Pacific/Honolulu' = s 'Hawaiian Standard Time' + val 'Pacific/Kiritimati' = s 'Line Islands Standard Time' + val 'Pacific/Kosrae' = s 'Central Pacific Standard Time' + val 'Pacific/Kwajalein' = s 'UTC+12' + val 'Pacific/Majuro' = s 'UTC+12' + val 'Pacific/Marquesas' = s 'Marquesas Standard Time' + val 'Pacific/Midway' = s 'UTC-11' + val 'Pacific/Nauru' = s 'UTC+12' + val 'Pacific/Niue' = s 'UTC-11' + val 'Pacific/Norfolk' = s 'Norfolk Standard Time' + val 'Pacific/Noumea' = s 'Central Pacific Standard Time' + val 'Pacific/Pago_Pago' = s 'UTC-11' + val 'Pacific/Palau' = s 'Tokyo Standard Time' + val 'Pacific/Pitcairn' = s 'UTC-08' + val 'Pacific/Ponape' = s 'Central Pacific Standard Time' + val 'Pacific/Port_Moresby' = s 'West Pacific Standard Time' + val 'Pacific/Rarotonga' = s 'Hawaiian Standard Time' + val 'Pacific/Saipan' = s 'West Pacific Standard Time' + val 'Pacific/Tahiti' = s 'Hawaiian Standard Time' + val 'Pacific/Tarawa' = s 'UTC+12' + val 'Pacific/Tongatapu' = s 'Tonga Standard Time' + val 'Pacific/Truk' = s 'West Pacific Standard Time' + val 'Pacific/Wake' = s 'UTC+12' + val 'Pacific/Wallis' = s 'UTC+12' + } + } + } } NoRemove SYSTEM { diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index 2fe54090d56..ec8ae15e665 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -264,6 +264,15 @@ static ULONG_PTR system_cpu_mask; static pthread_mutex_t timezone_mutex = PTHREAD_MUTEX_INITIALIZER; +static const char default_tzinfo_dir[] = "/usr/share/zoneinfo"; +static const WCHAR Time_ZonesW[] = { '\\','R','e','g','i','s','t','r','y','\\', + 'M','a','c','h','i','n','e','\\', + 'S','o','f','t','w','a','r','e','\\', + 'M','i','c','r','o','s','o','f','t','\\', + 'W','i','n','d','o','w','s',' ','N','T','\\', + 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', + 'T','i','m','e',' ','Z','o','n','e','s',0 }; + /******************************************************************************* * Architecture specific feature detection for CPUs * @@ -2860,13 +2869,6 @@ done: static void find_reg_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, const char* tz_name, int year) { - static const WCHAR Time_ZonesW[] = { '\\','R','e','g','i','s','t','r','y','\\', - 'M','a','c','h','i','n','e','\\', - 'S','o','f','t','w','a','r','e','\\', - 'M','i','c','r','o','s','o','f','t','\\', - 'W','i','n','d','o','w','s',' ','N','T','\\', - 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', - 'T','i','m','e',' ','Z','o','n','e','s',0 }; RTL_DYNAMIC_TIME_ZONE_INFORMATION reg_tzi; HANDLE key; ULONG idx, len; @@ -2941,6 +2943,76 @@ static time_t find_dst_change(time_t start, time_t end, int *is_dst) return min; } +static BOOL get_tz_info_from_zoneinfo_name( RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, const char *name, int year ) +{ + static const WCHAR wine_tz_map[] = { '\\','R','e','g','i','s','t','r','y','\\', + 'M','a','c','h','i','n','e','\\', + 'S','o','f','t','w','a','r','e','\\', + 'W','i','n','e','\\', + 'T','i','m','e',' ','Z','o','n','e','s','\\', + 'T','Z',' ','M','a','p','p','i','n','g', + 0 }; + + const char *tzinfo_dir = getenv( "TZDIR" ); + UNICODE_STRING key_name, win_name; + WCHAR nameW[64], win_nameW[64]; + OBJECT_ATTRIBUTES attr; + char buf[MAX_PATH]; + HANDLE key; + BOOL ret; + FILE *f; + + TRACE( "name %s.\n", debugstr_a( name )); + + if (strlen(name) >= ARRAY_SIZE(nameW)) return FALSE; + + if (!tzinfo_dir) tzinfo_dir = default_tzinfo_dir; + snprintf( buf, sizeof(buf), "%s/%s", tzinfo_dir, name ); + + if (!(f = fopen( buf, "r" ))) + { + WARN( "Could not open %s.\n", debugstr_a( buf )); + return FALSE; + } + fclose( f ); + + init_unicode_string( &key_name, wine_tz_map ); + InitializeObjectAttributes( &attr, &key_name, 0, NULL, NULL ); + if (NtOpenKey( &key, KEY_READ, &attr )) return FALSE; + + ascii_to_unicode( nameW, name, strlen( name ) + 1 ); + ret = reg_query_value( key, nameW, REG_SZ, win_nameW, sizeof(win_nameW) ); + NtClose( key ); + if (!ret) return FALSE; + TRACE( "got %s for %s.\n", debugstr_w(win_nameW), debugstr_a( name ) ); + + init_unicode_string( &key_name, Time_ZonesW ); + if (NtOpenKey( &key, KEY_READ, &attr )) return FALSE; + init_unicode_string( &win_name, win_nameW ); + ret = read_reg_tz_info( key, &win_name, year, tzi ); + NtClose( key ); + return ret; +} + +static BOOL get_system_config_tz_info( RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, int year ) +{ + char path[PATH_MAX]; + const char *str; + int len; + + if ((str = getenv( "TZ" ))) + { + if (*str == ':') ++str; + return get_tz_info_from_zoneinfo_name( tzi, str, year ); + } + + if (!realpath( "/etc/localtime", path )) return FALSE; + len = sizeof( default_tzinfo_dir ) - 1; + if (strncmp( path, default_tzinfo_dir, len )) return FALSE; + if (path[len] != '/') return FALSE; + return get_tz_info_from_zoneinfo_name( tzi, path + len + 1, year ); +} + static LONG64 get_current_tz_bias(void) { ULONG high, low; @@ -2959,6 +3031,7 @@ static void get_timezone_info( RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi ) { static RTL_DYNAMIC_TIME_ZONE_INFORMATION cached_tzi; static int current_year = -1, current_bias = 65535; + RTL_DYNAMIC_TIME_ZONE_INFORMATION reg_tzi; struct tm *tm, tm1, tm2; char tz_name[16]; time_t year_start, year_end, tmp, dlt = 0, std = 0; @@ -3075,6 +3148,16 @@ static void get_timezone_info( RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi ) tzi->StandardBias); } + if (get_system_config_tz_info( ®_tzi, current_year + 1900 )) + { + if (match_tz_info( tzi, ®_tzi ) && match_tz_name( tz_name, ®_tzi )) + { + cached_tzi = *tzi = reg_tzi; + mutex_unlock( &timezone_mutex ); + return; + } + WARN( "System config TZ info didn't match guessed parameters, falling back to search.\n" ); + } find_reg_tz_info(tzi, tz_name, current_year + 1900); cached_tzi = *tzi; mutex_unlock( &timezone_mutex ); diff --git a/tools/make_unicode b/tools/make_unicode index f7ccbd8131d..3cb4ab80c4a 100755 --- a/tools/make_unicode +++ b/tools/make_unicode @@ -71,6 +71,7 @@ my $MAX_CHAR = 0x10ffff; my $nlskey = "-SYSTEM\\-CurrentControlSet\\-Control\\-Nls"; my $zonekey = "-Software\\-Microsoft\\-Windows NT\\-CurrentVersion\\Time Zones"; +my $winezonekey = "-Software\\-Wine\\Time Zones"; my @allfiles = ( @@ -5501,6 +5502,7 @@ sub load_windows_zones() { my $current_name; my %names; + my %mapping; my $base = "cldr-release-$CLDRVERSION"; my $INPUT = open_data_file( "cldr", "$base/common/supplemental/windowsZones.xml" ); while (<$INPUT>) @@ -5513,9 +5515,16 @@ sub load_windows_zones() { $names{$1} = [ $current_name, $2 ]; } + if (/<mapZone other="(.*)" territory=(.*) type="(.*)"\/>/) + { + foreach my $name (split ' ', $3) + { + $mapping{$name} = $1; + } + } } close $INPUT; - return %names; + return (\%names, \%mapping); } @@ -5638,7 +5647,7 @@ sub dump_timezones($@) my $FIRST_YEAR = 2000; my $LAST_YEAR = 2030; - my %names = load_windows_zones(); + my ($names, $mapping) = load_windows_zones(); my %zones; my %rules; my %links; @@ -5694,9 +5703,10 @@ sub dump_timezones($@) close $FILE; } - foreach my $name (sort { uc($a) cmp uc($b) } keys %names) + foreach my $name (sort { uc($a) cmp uc($b) } keys %{$names}) { - my ($display, $zone) = @{$names{$name}}; + my ($display, $zone) = @{%{$names}{$name}}; + $zone = $links{$zone} if defined $links{$zone}; # build list of transitions @@ -5865,6 +5875,12 @@ sub dump_timezones($@) add_registry_dword_value( $zonekey, "$name\\Dynamic DST", "LastEntry", $last_year ); } + foreach my $map (sort { uc($a) cmp uc($b) } keys %{$mapping}) + { + my $name = %{$mapping}{$map}; + add_registry_string_value( $winezonekey, "TZ Mapping", $map, $name ); + } + print OUTPUT "}\n"; close OUTPUT; save_file($filename); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10134
From: Paul Gofman <pgofman@codeweavers.com> Fixes matching timezones Asia/Dili, Asia/Jayapura, Etc/GMT-9, Pacific/Palau. --- dlls/ntdll/unix/system.c | 60 ++++------------------------------------ 1 file changed, 6 insertions(+), 54 deletions(-) diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index ec8ae15e665..cb30d2208d6 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -2740,48 +2740,6 @@ static BOOL match_tz_info( const RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, match_tz_date(&tzi->DaylightDate, ®_tzi->DaylightDate)); } -static BOOL match_past_tz_bias( time_t past_time, LONG past_bias ) -{ - LONG bias; - struct tm *tm; - if (!past_time) return TRUE; - - tm = gmtime( &past_time ); - bias = (LONG)(mktime(tm) - past_time) / 60; - return bias == past_bias; -} - -static BOOL match_tz_name( const char *tz_name, const RTL_DYNAMIC_TIME_ZONE_INFORMATION *reg_tzi ) -{ - static const struct { - WCHAR key_name[32]; - const char *short_name; - time_t past_time; - LONG past_bias; - } - mapping[] = - { - { {'N','o','r','t','h',' ','K','o','r','e','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e',0 }, - "KST", 1451606400 /* 2016-01-01 00:00:00 UTC */, -510 }, - { {'K','o','r','e','a',' ','S','t','a','n','d','a','r','d',' ','T','i','m','e',0 }, - "KST", 1451606400 /* 2016-01-01 00:00:00 UTC */, -540 }, - { {'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 */ - }; - unsigned int i; - - if (reg_tzi->DaylightDate.wMonth) return TRUE; - for (i = 0; i < ARRAY_SIZE(mapping); i++) - { - if (!wcscmp( mapping[i].key_name, reg_tzi->TimeZoneKeyName )) - return !strcmp( mapping[i].short_name, tz_name ) - && match_past_tz_bias( mapping[i].past_time, mapping[i].past_bias ); - } - return TRUE; -} - static BOOL reg_query_value( HKEY key, LPCWSTR name, DWORD type, void *data, DWORD count ) { char buf[256]; @@ -2867,7 +2825,7 @@ done: return ret; } -static void find_reg_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, const char* tz_name, int year) +static void find_reg_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, int year) { RTL_DYNAMIC_TIME_ZONE_INFORMATION reg_tzi; HANDLE key; @@ -2902,7 +2860,7 @@ static void find_reg_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, const char* reg_tzi.DaylightDate.wSecond, reg_tzi.DaylightDate.wMilliseconds, reg_tzi.DaylightBias); - if (match_tz_info( tzi, ®_tzi ) && match_tz_name( tz_name, ®_tzi )) + if (match_tz_info( tzi, ®_tzi )) { *tzi = reg_tzi; NtClose( key ); @@ -2914,8 +2872,8 @@ static void find_reg_tz_info(RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi, const char* if (idx == 1) return; /* registry info not initialized yet */ FIXME("Can't find matching timezone information in the registry for " - "%s, bias %d, std (d/m/y): %u/%02u/%04u, dlt (d/m/y): %u/%02u/%04u\n", - tz_name, tzi->Bias, + "bias %d, std (d/m/y): %u/%02u/%04u, dlt (d/m/y): %u/%02u/%04u\n", + tzi->Bias, tzi->StandardDate.wDay, tzi->StandardDate.wMonth, tzi->StandardDate.wYear, tzi->DaylightDate.wDay, tzi->DaylightDate.wMonth, tzi->DaylightDate.wYear); } @@ -3033,7 +2991,6 @@ static void get_timezone_info( RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi ) static int current_year = -1, current_bias = 65535; RTL_DYNAMIC_TIME_ZONE_INFORMATION reg_tzi; struct tm *tm, tm1, tm2; - char tz_name[16]; time_t year_start, year_end, tmp, dlt = 0, std = 0; int is_dst, bias; BOOL inverted_dst; @@ -3059,11 +3016,6 @@ static void get_timezone_info( RTL_DYNAMIC_TIME_ZONE_INFORMATION *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, inverted_dst %d\n", tm->tm_year + 1900, bias, inverted_dst); current_year = tm->tm_year; current_bias = bias; @@ -3150,7 +3102,7 @@ static void get_timezone_info( RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi ) if (get_system_config_tz_info( ®_tzi, current_year + 1900 )) { - if (match_tz_info( tzi, ®_tzi ) && match_tz_name( tz_name, ®_tzi )) + if (match_tz_info( tzi, ®_tzi )) { cached_tzi = *tzi = reg_tzi; mutex_unlock( &timezone_mutex ); @@ -3158,7 +3110,7 @@ static void get_timezone_info( RTL_DYNAMIC_TIME_ZONE_INFORMATION *tzi ) } WARN( "System config TZ info didn't match guessed parameters, falling back to search.\n" ); } - find_reg_tz_info(tzi, tz_name, current_year + 1900); + find_reg_tz_info(tzi, current_year + 1900); cached_tzi = *tzi; mutex_unlock( &timezone_mutex ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10134
From: Paul Gofman <pgofman@codeweavers.com> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50532 --- dlls/ntdll/unix/system.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index cb30d2208d6..0f3740d216e 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -2883,14 +2883,25 @@ static time_t find_dst_change(time_t start, time_t end, int *is_dst) struct tm *tm; ULONGLONG min = (sizeof(time_t) == sizeof(int)) ? (ULONG)start : start; ULONGLONG max = (sizeof(time_t) == sizeof(int)) ? (ULONG)end : end; + time_t pos; tm = localtime(&start); *is_dst = !tm->tm_isdst; TRACE("starting date isdst %d, %s", !*is_dst, ctime(&start)); + for (pos = min; pos <= max; pos += 30 * 24 * 3600) + { + tm = localtime(&pos); + if (tm->tm_isdst == *is_dst) + { + max = pos; + break; + } + } + while (min <= max) { - time_t pos = (min + max) / 2; + pos = (min + max) / 2; tm = localtime(&pos); if (tm->tm_isdst != *is_dst) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10134
From: Paul Gofman <pgofman@codeweavers.com> Fixes Australia/Lord_Howe timezone match. --- dlls/ntdll/unix/system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index 0f3740d216e..5723c3774da 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -2727,7 +2727,7 @@ static BOOL match_tz_date( const RTL_SYSTEM_TIME *st, const RTL_SYSTEM_TIME *reg return (st->wDay == wDay && st->wHour == reg_st->wHour && - st->wMinute == reg_st->wMinute && + (st->wMinute == reg_st->wMinute || (st->wMinute == 30 && !reg_st->wMinute)) && st->wSecond == reg_st->wSecond && st->wMilliseconds == reg_st->wMilliseconds); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10134
v2: - Fix timezone bias estimation for the period within 1 hour around DST change time. The result of mktime(tm) with tm_isdst is set to -1 on input and determined by the system (or tm_isdst after mktime) can only be realied upon when tm has local time, otherwise the DST detection may be used at the wrong time point. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10134#note_129969
The Mac build error is: ``` error: failed to write to /var/tmp/builds/wine/wine/usr/local/lib/wine/x86_64-windows/tmp699885c7/ws2_32.dll : No space left on device ``` -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10134#note_129981
participants (2)
-
Paul Gofman -
Paul Gofman (@gofman)