mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-18 19:25:49 +00:00
ICU-444 add Win32-specific host timezone detection code
X-SVN-Rev: 11764
This commit is contained in:
parent
d00a183d4e
commit
e914485397
1 changed files with 492 additions and 0 deletions
|
@ -656,6 +656,491 @@ static char* u_bottomNBytesOfDouble(double* d, int n)
|
|||
platform with new implementations.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/* Win32 time zone detection ------------------------------------------------ */
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
/*
|
||||
This code attempts to detect the Windows time zone, as set in the
|
||||
Windows Date and Time control panel. It attempts to work on
|
||||
multiple flavors of Windows (9x, Me, NT, 2000, XP) and on localized
|
||||
installs. It works by directly interrogating the registry and
|
||||
comparing the data there with the data returned by the
|
||||
GetTimeZoneInformation API, along with some other strategies. The
|
||||
registry contains time zone data under one of two keys (depending on
|
||||
the flavor of Windows):
|
||||
|
||||
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Time Zones\
|
||||
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\
|
||||
|
||||
Under this key are several subkeys, one for each time zone. These
|
||||
subkeys are named "Pacific" on Win9x/Me and "Pacific Standard Time"
|
||||
on WinNT/2k/XP. There are some other wrinkles; see the code for
|
||||
details. The subkey name is NOT LOCALIZED, allowing us to support
|
||||
localized installs.
|
||||
|
||||
Under the subkey are data values. We care about:
|
||||
|
||||
Std Standard time display name, localized
|
||||
TZI Binary block of data
|
||||
|
||||
The TZI data is of particular interest. It contains the offset, two
|
||||
more offsets for standard and daylight time, and the start and end
|
||||
rules. This is the same data returned by the GetTimeZoneInformation
|
||||
API. The API may modify the data on the way out, so we have to be
|
||||
careful, but essentially we do a binary comparison against the TZI
|
||||
blocks of various registry keys. When we find a match, we know what
|
||||
time zone Windows is set to. Since the registry key is not
|
||||
localized, we can then translate the key through a simple table
|
||||
lookup into the corresponding ICU time zone.
|
||||
|
||||
This strategy doesn't always work because there are zones which
|
||||
share an offset and rules, so more than one TZI block will match.
|
||||
For example, both Tokyo and Seoul are at GMT+9 with no DST rules;
|
||||
their TZI blocks are identical. For these cases, we fall back to a
|
||||
name lookup. We attempt to match the display name as stored in the
|
||||
registry for the current zone to the display name stored in the
|
||||
registry for various Windows zones. By comparing the registry data
|
||||
directly we avoid conversion complications.
|
||||
|
||||
Author: Alan Liu
|
||||
Since: ICU 2.6
|
||||
Based on original code by Carl Brown <cbrown@xnetinc.com>
|
||||
*/
|
||||
|
||||
static LONG openTZRegKey(HKEY* hkey, const char* tziname, int Wintype);
|
||||
|
||||
/**
|
||||
* Layout of the binary registry data under the "TZI" key.
|
||||
*/
|
||||
typedef struct {
|
||||
LONG Bias;
|
||||
LONG StandardBias;
|
||||
LONG DaylightBias;
|
||||
SYSTEMTIME StandardDate;
|
||||
SYSTEMTIME DaylightDate;
|
||||
} TZI;
|
||||
|
||||
typedef struct {
|
||||
const char* icuid;
|
||||
const char* winid;
|
||||
} WindowsICUMap;
|
||||
|
||||
/**
|
||||
* Mapping between Windows zone IDs and ICU zone IDs. This list has
|
||||
* been mechanically checked; all zone offsets match (most important)
|
||||
* and city names match the display city names (where possible). The
|
||||
* presence or absence of DST differs in some cases, but this is
|
||||
* acceptable as long as the zone is semantically the same (which has
|
||||
* been manually checked).
|
||||
*
|
||||
* Windows 9x/Me zone IDs are listed as "Pacific" rather than "Pacific
|
||||
* Standard Time", which is seen in NT/2k/XP. This is fixed-up at
|
||||
* runtime as needed. The one exception is "Mexico Standard Time 2",
|
||||
* which is not present on Windows 9x/Me.
|
||||
*
|
||||
* Zones that are not unique under Offset+Rules should be grouped
|
||||
* together for efficiency (see code below). In addition, rules must
|
||||
* be grouped so that all zones of a single offset are together. Any
|
||||
* other organization is not required.
|
||||
*
|
||||
* NOTE: Etc/GMT+12 is CORRECT for offset GMT-12:00. Consult
|
||||
* documentation elsewhere for an explanation.
|
||||
*/
|
||||
static const WindowsICUMap ZONE_MAP[] = {
|
||||
"Etc/GMT+12", "Dateline", /* S (GMT-12:00) International Date Line West */
|
||||
|
||||
"Pacific/Apia", "Samoa", /* S (GMT-11:00) Midway Island, Samoa */
|
||||
|
||||
"Pacific/Honolulu", "Hawaiian", /* S (GMT-10:00) Hawaii */
|
||||
|
||||
"America/Anchorage", "Alaskan", /* D (GMT-09:00) Alaska */
|
||||
|
||||
"America/Los_Angeles", "Pacific", /* D (GMT-08:00) Pacific Time (US & Canada); Tijuana */
|
||||
|
||||
"America/Phoenix", "US Mountain", /* S (GMT-07:00) Arizona */
|
||||
"America/Denver", "Mountain", /* D (GMT-07:00) Mountain Time (US & Canada) */
|
||||
"America/Chihuahua", "Mexico Standard Time 2", /* D (GMT-07:00) Chihuahua, La Paz, Mazatlan */
|
||||
|
||||
"America/Managua", "Central America", /* S (GMT-06:00) Central America */
|
||||
"America/Regina", "Canada Central", /* S (GMT-06:00) Saskatchewan */
|
||||
"America/Mexico_City", "Mexico", /* D (GMT-06:00) Guadalajara, Mexico City, Monterrey */
|
||||
"America/Chicago", "Central", /* D (GMT-06:00) Central Time (US & Canada) */
|
||||
|
||||
"America/Indianapolis", "US Eastern", /* S (GMT-05:00) Indiana (East) */
|
||||
"America/Bogota", "SA Pacific", /* S (GMT-05:00) Bogota, Lima, Quito */
|
||||
"America/New_York", "Eastern", /* D (GMT-05:00) Eastern Time (US & Canada) */
|
||||
|
||||
"America/Caracas", "SA Western", /* S (GMT-04:00) Caracas, La Paz */
|
||||
"America/Santiago", "Pacific SA", /* D (GMT-04:00) Santiago */
|
||||
"America/Halifax", "Atlantic", /* D (GMT-04:00) Atlantic Time (Canada) */
|
||||
|
||||
"America/St_Johns", "Newfoundland", /* D (GMT-03:30) Newfoundland */
|
||||
|
||||
"America/Buenos_Aires", "SA Eastern", /* S (GMT-03:00) Buenos Aires, Georgetown */
|
||||
"America/Godthab", "Greenland", /* D (GMT-03:00) Greenland */
|
||||
"America/Sao_Paulo", "E. South America", /* D (GMT-03:00) Brasilia */
|
||||
|
||||
"America/Noronha", "Mid-Atlantic", /* D (GMT-02:00) Mid-Atlantic */
|
||||
|
||||
"Atlantic/Cape_Verde", "Cape Verde", /* S (GMT-01:00) Cape Verde Is. */
|
||||
"Atlantic/Azores", "Azores", /* D (GMT-01:00) Azores */
|
||||
|
||||
"Africa/Casablanca", "Greenwich", /* S (GMT) Casablanca, Monrovia */
|
||||
"Europe/London", "GMT", /* D (GMT) Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London */
|
||||
|
||||
"Africa/Lagos", "W. Central Africa", /* S (GMT+01:00) West Central Africa */
|
||||
"Europe/Berlin", "W. Europe", /* D (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna */
|
||||
"Europe/Paris", "Romance", /* D (GMT+01:00) Brussels, Copenhagen, Madrid, Paris */
|
||||
"Europe/Sarajevo", "Central European", /* D (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb */
|
||||
"Europe/Belgrade", "Central Europe", /* D (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague */
|
||||
|
||||
"Africa/Johannesburg", "South Africa", /* S (GMT+02:00) Harare, Pretoria */
|
||||
"Asia/Jerusalem", "Israel", /* S (GMT+02:00) Jerusalem */
|
||||
"Europe/Istanbul", "GTB", /* D (GMT+02:00) Athens, Istanbul, Minsk */
|
||||
"Europe/Helsinki", "FLE", /* D (GMT+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius */
|
||||
"Africa/Cairo", "Egypt", /* D (GMT+02:00) Cairo */
|
||||
"Europe/Bucharest", "E. Europe", /* D (GMT+02:00) Bucharest */
|
||||
|
||||
"Africa/Nairobi", "E. Africa", /* S (GMT+03:00) Nairobi */
|
||||
"Asia/Riyadh", "Arab", /* S (GMT+03:00) Kuwait, Riyadh */
|
||||
"Europe/Moscow", "Russian", /* D (GMT+03:00) Moscow, St. Petersburg, Volgograd */
|
||||
"Asia/Baghdad", "Arabic", /* D (GMT+03:00) Baghdad */
|
||||
|
||||
"Asia/Tehran", "Iran", /* D (GMT+03:30) Tehran */
|
||||
|
||||
"Asia/Muscat", "Arabian", /* S (GMT+04:00) Abu Dhabi, Muscat */
|
||||
"Asia/Tbilisi", "Caucasus", /* D (GMT+04:00) Baku, Tbilisi, Yerevan */
|
||||
|
||||
"Asia/Kabul", "Afghanistan", /* S (GMT+04:30) Kabul */
|
||||
|
||||
"Asia/Karachi", "West Asia", /* S (GMT+05:00) Islamabad, Karachi, Tashkent */
|
||||
"Asia/Yekaterinburg", "Ekaterinburg", /* D (GMT+05:00) Ekaterinburg */
|
||||
|
||||
"Asia/Calcutta", "India", /* S (GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi */
|
||||
|
||||
"Asia/Katmandu", "Nepal", /* S (GMT+05:45) Kathmandu */
|
||||
|
||||
"Asia/Colombo", "Sri Lanka", /* S (GMT+06:00) Sri Jayawardenepura */
|
||||
"Asia/Dhaka", "Central Asia", /* S (GMT+06:00) Astana, Dhaka */
|
||||
"Asia/Novosibirsk", "N. Central Asia", /* D (GMT+06:00) Almaty, Novosibirsk */
|
||||
|
||||
"Asia/Rangoon", "Myanmar", /* S (GMT+06:30) Rangoon */
|
||||
|
||||
"Asia/Bangkok", "SE Asia", /* S (GMT+07:00) Bangkok, Hanoi, Jakarta */
|
||||
"Asia/Krasnoyarsk", "North Asia", /* D (GMT+07:00) Krasnoyarsk */
|
||||
|
||||
"Australia/Perth", "W. Australia", /* S (GMT+08:00) Perth */
|
||||
"Asia/Taipei", "Taipei", /* S (GMT+08:00) Taipei */
|
||||
"Asia/Singapore", "Singapore", /* S (GMT+08:00) Kuala Lumpur, Singapore */
|
||||
"Asia/Hong_Kong", "China", /* S (GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi */
|
||||
"Asia/Irkutsk", "North Asia East", /* D (GMT+08:00) Irkutsk, Ulaan Bataar */
|
||||
|
||||
"Asia/Tokyo", "Tokyo", /* S (GMT+09:00) Osaka, Sapporo, Tokyo */
|
||||
"Asia/Seoul", "Korea", /* S (GMT+09:00) Seoul */
|
||||
"Asia/Yakutsk", "Yakutsk", /* D (GMT+09:00) Yakutsk */
|
||||
|
||||
"Australia/Darwin", "AUS Central", /* S (GMT+09:30) Darwin */
|
||||
"Australia/Adelaide", "Cen. Australia", /* D (GMT+09:30) Adelaide */
|
||||
|
||||
"Pacific/Guam", "West Pacific", /* S (GMT+10:00) Guam, Port Moresby */
|
||||
"Australia/Brisbane", "E. Australia", /* S (GMT+10:00) Brisbane */
|
||||
"Asia/Vladivostok", "Vladivostok", /* D (GMT+10:00) Vladivostok */
|
||||
"Australia/Hobart", "Tasmania", /* D (GMT+10:00) Hobart */
|
||||
"Australia/Sydney", "AUS Eastern", /* D (GMT+10:00) Canberra, Melbourne, Sydney */
|
||||
|
||||
"Asia/Magadan", "Central Pacific", /* S (GMT+11:00) Magadan, Solomon Is., New Caledonia */
|
||||
|
||||
"Pacific/Fiji", "Fiji", /* S (GMT+12:00) Fiji, Kamchatka, Marshall Is. */
|
||||
"Pacific/Auckland", "New Zealand", /* D (GMT+12:00) Auckland, Wellington */
|
||||
|
||||
"Pacific/Tongatapu", "Tonga", /* S (GMT+13:00) Nuku'alofa */
|
||||
NULL, NULL
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const char* winid;
|
||||
const char* altwinid;
|
||||
} WindowsZoneRemap;
|
||||
|
||||
/**
|
||||
* If a lookup fails, we attempt to remap certain Windows ids to
|
||||
* alternate Windows ids. If the alternate listed here begins with
|
||||
* '-', we use it as is (without the '-'). If it begins with '+', we
|
||||
* append a " Standard Time" if appropriate.
|
||||
*/
|
||||
WindowsZoneRemap ZONE_REMAP[] = {
|
||||
"Central European", "-Warsaw",
|
||||
"Central Europe", "-Prague Bratislava",
|
||||
"China", "-Beijing",
|
||||
|
||||
"Greenwich", "+GMT",
|
||||
"GTB", "+GFT",
|
||||
"Arab", "+Saudi Arabia",
|
||||
"SE Asia", "+Bangkok",
|
||||
"AUS Eastern", "+Sydney",
|
||||
NULL, NULL,
|
||||
};
|
||||
|
||||
/**
|
||||
* Various registry keys and key fragments.
|
||||
*/
|
||||
static const char* CURRENT_ZONE_REGKEY = "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation\\";
|
||||
static const char* STANDARD_NAME_REGKEY = "StandardName";
|
||||
static const char* STANDARD_TIME_REGKEY = " Standard Time";
|
||||
static const char* TZI_REGKEY = "TZI";
|
||||
static const char* STD_REGKEY = "Std";
|
||||
|
||||
/**
|
||||
* HKLM subkeys used to probe for the flavor of Windows. Note that we
|
||||
* specifically check for the "GMT" zone sub key; this is present on
|
||||
* NT, but on XP has become "GMT Standard Time". We need to
|
||||
* discriminate between these cases.
|
||||
*/
|
||||
static const char* WIN_TYPE_PROBE_REGKEY[] = {
|
||||
/* WIN_9X_ME_TYPE */
|
||||
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Time Zones",
|
||||
|
||||
/* WIN_NT_TYPE */
|
||||
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\GMT"
|
||||
|
||||
/* otherwise: WIN_2K_XP_TYPE */
|
||||
};
|
||||
|
||||
/**
|
||||
* The time zone root subkeys (under HKLM) for different flavors of
|
||||
* Windows.
|
||||
*/
|
||||
static const char* TZ_REGKEY[] = {
|
||||
/* WIN_9X_ME_TYPE */
|
||||
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Time Zones\\",
|
||||
|
||||
/* WIN_NT_TYPE | WIN_2K_XP_TYPE */
|
||||
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\"
|
||||
};
|
||||
|
||||
/**
|
||||
* Flavor of Windows, from our perspective. Not a real OS version,
|
||||
* but rather the flavor of the layout of the time zone information in
|
||||
* the registry.
|
||||
*/
|
||||
enum {
|
||||
WIN_9X_ME_TYPE = 0,
|
||||
WIN_NT_TYPE = 1,
|
||||
WIN_2K_XP_TYPE = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* Main Windows time zone detection function. Returns the Windows
|
||||
* time zone, translated to an ICU time zone, or NULL upon failure.
|
||||
*/
|
||||
static const char* detectWindowsTimeZone() {
|
||||
int winType;
|
||||
LONG result;
|
||||
HKEY hkey;
|
||||
TZI tziKey;
|
||||
TZI tziReg;
|
||||
DWORD cbData = sizeof(TZI);
|
||||
TIME_ZONE_INFORMATION apiTZI;
|
||||
char stdName[32];
|
||||
DWORD stdNameSize;
|
||||
char stdRegName[64];
|
||||
DWORD stdRegNameSize;
|
||||
int firstMatch, lastMatch;
|
||||
int j;
|
||||
|
||||
/* Detect the version of windows by trying to open a sequence of
|
||||
probe keys. We don't use the OS version API because what we
|
||||
really want to know is how the registry is laid out.
|
||||
Specifically, is it 9x/Me or not, and is it "GMT" or "GMT
|
||||
Standard Time". */
|
||||
for (winType=0; winType<2; ++winType) {
|
||||
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||
WIN_TYPE_PROBE_REGKEY[winType],
|
||||
0,
|
||||
KEY_QUERY_VALUE,
|
||||
&hkey);
|
||||
RegCloseKey(hkey);
|
||||
if (result == ERROR_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Obtain TIME_ZONE_INFORMATION from the API, and then convert it
|
||||
to TZI. We could also interrogate the registry directly; we do
|
||||
this below if needed. */
|
||||
memset(&apiTZI, 0, sizeof(apiTZI));
|
||||
GetTimeZoneInformation(&apiTZI);
|
||||
tziKey.Bias = apiTZI.Bias;
|
||||
memcpy((char *)&tziKey.StandardDate, (char*)&apiTZI.StandardDate,
|
||||
sizeof(apiTZI.StandardDate));
|
||||
memcpy((char *)&tziKey.DaylightDate, (char*)&apiTZI.DaylightDate,
|
||||
sizeof(apiTZI.DaylightDate));
|
||||
|
||||
/* For each zone that can be identified by Offset+Rules, see if we
|
||||
have a match. Continue scanning after finding a match,
|
||||
recording the index of the first and the last match. We have
|
||||
to do this because some zones are not unique under
|
||||
Offset+Rules. */
|
||||
firstMatch = lastMatch = -1;
|
||||
for (j=0; ZONE_MAP[j].icuid; j++) {
|
||||
result = openTZRegKey(&hkey, ZONE_MAP[j].winid, winType);
|
||||
if (result == ERROR_SUCCESS) {
|
||||
result = RegQueryValueEx(hkey,
|
||||
TZI_REGKEY,
|
||||
NULL,
|
||||
NULL,
|
||||
(LPBYTE)&tziReg,
|
||||
&cbData);
|
||||
}
|
||||
RegCloseKey(hkey);
|
||||
if (result == ERROR_SUCCESS) {
|
||||
/* Windows alters the DaylightBias in some situations.
|
||||
Using the bias and the rules suffices, so overwrite
|
||||
these unreliable fields. */
|
||||
tziKey.StandardBias = tziReg.StandardBias;
|
||||
tziKey.DaylightBias = tziReg.DaylightBias;
|
||||
if (memcmp((char *)&tziKey, (char*)&tziReg,
|
||||
sizeof(tziKey)) == 0) {
|
||||
if (firstMatch < 0) {
|
||||
firstMatch = j;
|
||||
}
|
||||
lastMatch = j;
|
||||
}
|
||||
/* Assume that offsets are grouped together, and bail out
|
||||
when we've scanned everything with a matching
|
||||
offset. */
|
||||
if (firstMatch >= 0 && tziKey.Bias != tziReg.Bias) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This should never happen; if it does it means our table doesn't
|
||||
match Windows AT ALL, perhaps because this is post-XP? */
|
||||
if (firstMatch < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (firstMatch == lastMatch) { /* Offset+Rules matched exactly once */
|
||||
return ZONE_MAP[firstMatch].icuid;
|
||||
}
|
||||
|
||||
/* Offset+Rules lookup yielded >= 2 matches. Try to match the
|
||||
localized display name. Get the name from the registry (not
|
||||
the API). This avoids conversion issues. Use the standard
|
||||
name, since Windows modifies the daylight name to match the
|
||||
standard name if there is no DST. */
|
||||
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||
CURRENT_ZONE_REGKEY,
|
||||
0,
|
||||
KEY_QUERY_VALUE,
|
||||
&hkey);
|
||||
if (result != ERROR_SUCCESS) {
|
||||
RegCloseKey(hkey); /* should not happen */
|
||||
return NULL;
|
||||
}
|
||||
stdNameSize = sizeof(stdName);
|
||||
result = RegQueryValueEx(hkey,
|
||||
(LPTSTR)STANDARD_NAME_REGKEY,
|
||||
NULL,
|
||||
NULL,
|
||||
(LPBYTE)stdName,
|
||||
&stdNameSize);
|
||||
RegCloseKey(hkey);
|
||||
|
||||
/* Scan through our list again (just the range of zones that
|
||||
matched) and try for a name match. */
|
||||
for (j=firstMatch; j<=lastMatch; j++) {
|
||||
result = openTZRegKey(&hkey, ZONE_MAP[j].winid, winType);
|
||||
if (result == ERROR_SUCCESS) {
|
||||
stdRegNameSize = sizeof(stdRegName);
|
||||
result = RegQueryValueEx(hkey,
|
||||
(LPTSTR)STD_REGKEY,
|
||||
NULL,
|
||||
NULL,
|
||||
(LPBYTE)stdRegName,
|
||||
&stdRegNameSize);
|
||||
}
|
||||
RegCloseKey(hkey);
|
||||
if (result == ERROR_SUCCESS) {
|
||||
if (memcmp(stdName, stdRegName, stdNameSize) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* One of the display names should match; if not, take the first
|
||||
Offset+Rules match. */
|
||||
return ZONE_MAP[j <= lastMatch ? j : firstMatch].icuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Auxiliary Windows time zone function. Attempts to open the given
|
||||
* Windows time zone ID as a registry key. Returns ERROR_SUCCESS if
|
||||
* successful. Caller must close the registry key. Handles
|
||||
* variations in the resource layout in different flavors of Windows.
|
||||
*
|
||||
* @param hkey output parameter to receive opened registry key
|
||||
* @param winid Windows zone ID, e.g., "Pacific", without the
|
||||
* " Standard Time" suffix (if any). Special case "Mexico Standard Time 2"
|
||||
* allowed.
|
||||
* @param winType Windows flavor (WIN_9X_ME_TYPE, etc.)
|
||||
* @return ERROR_SUCCESS upon success
|
||||
*/
|
||||
static LONG openTZRegKey(HKEY *hkey, const char* winid, int winType) {
|
||||
LONG result;
|
||||
char subKeyName[96];
|
||||
char* name;
|
||||
int i;
|
||||
|
||||
strcpy(subKeyName, TZ_REGKEY[(winType == WIN_9X_ME_TYPE) ? 0 : 1]);
|
||||
name = &subKeyName[strlen(subKeyName)];
|
||||
strcat(subKeyName, winid);
|
||||
if (winType != WIN_9X_ME_TYPE) {
|
||||
/* Don't modify "Mexico Standard Time 2", which does not occur
|
||||
on WIN_9X_ME_TYPE. Also, if the type is WIN_NT_TYPE, then
|
||||
in practice this means the GMT key is not followed by
|
||||
" Standard Time", so don't append in that case. */
|
||||
int isMexico2 = (winid[strlen(winid)- 1] == '2');
|
||||
if (!isMexico2 &&
|
||||
!(winType == WIN_NT_TYPE && strcmp(winid, "GMT") == 0)) {
|
||||
strcat(subKeyName, STANDARD_TIME_REGKEY);
|
||||
}
|
||||
}
|
||||
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||
subKeyName,
|
||||
0,
|
||||
KEY_QUERY_VALUE,
|
||||
hkey);
|
||||
|
||||
if (result != ERROR_SUCCESS) {
|
||||
/* If the primary lookup fails, try to remap the Windows zone
|
||||
ID, according to the remapping table. */
|
||||
for (i=0; ZONE_REMAP[i].winid; ++i) {
|
||||
if (strcmp(winid, ZONE_REMAP[i].winid) == 0) {
|
||||
strcpy(name, ZONE_REMAP[i].altwinid + 1);
|
||||
if (*(ZONE_REMAP[i].altwinid) == '+' &&
|
||||
winType != WIN_9X_ME_TYPE) {
|
||||
strcat(subKeyName, STANDARD_TIME_REGKEY);
|
||||
}
|
||||
result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||
subKeyName,
|
||||
0,
|
||||
KEY_QUERY_VALUE,
|
||||
hkey);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /*WIN32*/
|
||||
|
||||
/* Generic time zone layer -------------------------------------------------- */
|
||||
|
||||
/* Time zone utilities */
|
||||
U_CAPI void U_EXPORT2
|
||||
uprv_tzset()
|
||||
|
@ -705,6 +1190,13 @@ extern U_IMPORT char *_tzname[2];
|
|||
U_CAPI char* U_EXPORT2
|
||||
uprv_tzname(int n)
|
||||
{
|
||||
#ifdef WIN32
|
||||
char* id = (char*) detectWindowsTimeZone();
|
||||
if (id != NULL) {
|
||||
return id;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef U_TZNAME
|
||||
return U_TZNAME[n];
|
||||
#else
|
||||
|
|
Loading…
Add table
Reference in a new issue