--- a/jdk/src/java.base/windows/native/libjava/TimeZone_md.c Thu Apr 16 11:33:59 2015 -0700
+++ b/jdk/src/java.base/windows/native/libjava/TimeZone_md.c Fri Apr 17 16:50:16 2015 +0900
@@ -147,219 +147,248 @@
*/
static int getWinTimeZone(char *winZoneName, char *winMapID)
{
- TIME_ZONE_INFORMATION tzi;
- OSVERSIONINFO ver;
- int onlyMapID;
- HANDLE hKey = NULL, hSubKey = NULL;
+ DYNAMIC_TIME_ZONE_INFORMATION dtzi;
+ DWORD timeType;
+ DWORD bufSize;
+ DWORD val;
+ HANDLE hKey = NULL;
LONG ret;
- DWORD nSubKeys, i;
ULONG valueType;
- TCHAR subKeyName[MAX_ZONE_CHAR];
- TCHAR szValue[MAX_ZONE_CHAR];
- WCHAR stdNameInReg[MAX_ZONE_CHAR];
- TziValue tempTzi;
- WCHAR *stdNamePtr = tzi.StandardName;
- DWORD valueSize;
- DWORD timeType;
- int isVista;
/*
- * Get the current time zone setting of the platform.
+ * Get the dynamic time zone information so that time zone redirection
+ * can be supported. (see JDK-7044727)
*/
- timeType = GetTimeZoneInformation(&tzi);
+ timeType = GetDynamicTimeZoneInformation(&dtzi);
if (timeType == TIME_ZONE_ID_INVALID) {
goto err;
}
/*
- * Determine if this is an NT system.
+ * Make sure TimeZoneKeyName is available from the API call. If
+ * DynamicDaylightTime is disabled, return a custom time zone name
+ * based on the GMT offset. Otherwise, return the TimeZoneKeyName
+ * value.
*/
- ver.dwOSVersionInfoSize = sizeof(ver);
- GetVersionEx(&ver);
- isVista = ver.dwMajorVersion >= 6;
+ if (dtzi.TimeZoneKeyName[0] != 0) {
+ if (dtzi.DynamicDaylightTimeDisabled) {
+ customZoneName(dtzi.Bias, winZoneName);
+ return VALUE_GMTOFFSET;
+ }
+ wcstombs(winZoneName, dtzi.TimeZoneKeyName, MAX_ZONE_CHAR);
+ return VALUE_KEY;
+ }
- ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_CURRENT_TZ_KEY, 0,
- KEY_READ, (PHKEY)&hKey);
- if (ret == ERROR_SUCCESS) {
- DWORD val;
- DWORD bufSize;
+ /*
+ * If TimeZoneKeyName is not available, check whether StandardName
+ * is available to fall back to the older API GetTimeZoneInformation.
+ * If not, directly read the value from registry keys.
+ */
+ if (dtzi.StandardName[0] == 0) {
+ ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_CURRENT_TZ_KEY, 0,
+ KEY_READ, (PHKEY)&hKey);
+ if (ret != ERROR_SUCCESS) {
+ goto err;
+ }
/*
* Determine if auto-daylight time adjustment is turned off.
*/
- valueType = 0;
bufSize = sizeof(val);
- ret = RegQueryValueExA(hKey, "DisableAutoDaylightTimeSet",
- NULL, &valueType, (LPBYTE) &val, &bufSize);
+ ret = RegQueryValueExA(hKey, "DynamicDaylightTimeDisabled", NULL,
+ &valueType, (LPBYTE) &val, &bufSize);
+ if (ret != ERROR_SUCCESS) {
+ goto err;
+ }
/*
- * Vista uses the different key name.
+ * Return a custom time zone name if auto-daylight time adjustment
+ * is disabled.
*/
+ if (val == 1) {
+ customZoneName(dtzi.Bias, winZoneName);
+ (void) RegCloseKey(hKey);
+ return VALUE_GMTOFFSET;
+ }
+
+ bufSize = MAX_ZONE_CHAR;
+ ret = RegQueryValueExA(hKey, "TimeZoneKeyName", NULL,
+ &valueType, (LPBYTE) winZoneName, &bufSize);
if (ret != ERROR_SUCCESS) {
- bufSize = sizeof(val);
- ret = RegQueryValueExA(hKey, "DynamicDaylightTimeDisabled",
- NULL, &valueType, (LPBYTE) &val, &bufSize);
+ goto err;
+ }
+ (void) RegCloseKey(hKey);
+ return VALUE_KEY;
+ } else {
+ /*
+ * Fall back to GetTimeZoneInformation
+ */
+ TIME_ZONE_INFORMATION tzi;
+ HANDLE hSubKey = NULL;
+ DWORD nSubKeys, i;
+ ULONG valueType;
+ TCHAR subKeyName[MAX_ZONE_CHAR];
+ TCHAR szValue[MAX_ZONE_CHAR];
+ WCHAR stdNameInReg[MAX_ZONE_CHAR];
+ TziValue tempTzi;
+ WCHAR *stdNamePtr = tzi.StandardName;
+ DWORD valueSize;
+ int onlyMapID;
+
+ timeType = GetTimeZoneInformation(&tzi);
+ if (timeType == TIME_ZONE_ID_INVALID) {
+ goto err;
}
+ ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_CURRENT_TZ_KEY, 0,
+ KEY_READ, (PHKEY)&hKey);
if (ret == ERROR_SUCCESS) {
- int daylightSavingsUpdateDisabledOther = val == 1 && tzi.DaylightDate.wMonth != 0;
- int daylightSavingsUpdateDisabledVista = val == 1;
- int daylightSavingsUpdateDisabled = isVista ? daylightSavingsUpdateDisabledVista : daylightSavingsUpdateDisabledOther;
+ /*
+ * Determine if auto-daylight time adjustment is turned off.
+ */
+ bufSize = sizeof(val);
+ ret = RegQueryValueExA(hKey, "DynamicDaylightTimeDisabled", NULL,
+ &valueType, (LPBYTE) &val, &bufSize);
+ if (ret == ERROR_SUCCESS) {
+ if (val == 1 && tzi.DaylightDate.wMonth != 0) {
+ (void) RegCloseKey(hKey);
+ customZoneName(tzi.Bias, winZoneName);
+ return VALUE_GMTOFFSET;
+ }
+ }
- if (daylightSavingsUpdateDisabled) {
- (void) RegCloseKey(hKey);
- customZoneName(tzi.Bias, winZoneName);
- return VALUE_GMTOFFSET;
+ /*
+ * Win32 problem: If the length of the standard time name is equal
+ * to (or probably longer than) 32 in the registry,
+ * GetTimeZoneInformation() on NT returns a null string as its
+ * standard time name. We need to work around this problem by
+ * getting the same information from the TimeZoneInformation
+ * registry.
+ */
+ if (tzi.StandardName[0] == 0) {
+ bufSize = sizeof(stdNameInReg);
+ ret = getValueInRegistry(hKey, STANDARD_NAME, &valueType,
+ (LPBYTE) stdNameInReg, &bufSize);
+ if (ret != ERROR_SUCCESS) {
+ goto err;
+ }
+ stdNamePtr = stdNameInReg;
+ }
+ (void) RegCloseKey(hKey);
+ }
+
+ /*
+ * Open the "Time Zones" registry.
+ */
+ ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NT_TZ_KEY, 0, KEY_READ, (PHKEY)&hKey);
+ if (ret != ERROR_SUCCESS) {
+ ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_TZ_KEY, 0, KEY_READ, (PHKEY)&hKey);
+ /*
+ * If both failed, then give up.
+ */
+ if (ret != ERROR_SUCCESS) {
+ return VALUE_UNKNOWN;
}
}
/*
- * Vista has the key for the current "Time Zones" entry.
- */
- if (isVista) {
- valueType = 0;
- bufSize = MAX_ZONE_CHAR;
- ret = RegQueryValueExA(hKey, "TimeZoneKeyName", NULL,
- &valueType, (LPBYTE) winZoneName, &bufSize);
- if (ret != ERROR_SUCCESS) {
- goto err;
- }
- (void) RegCloseKey(hKey);
- return VALUE_KEY;
- }
-
- /*
- * Win32 problem: If the length of the standard time name is equal
- * to (or probably longer than) 32 in the registry,
- * GetTimeZoneInformation() on NT returns a null string as its
- * standard time name. We need to work around this problem by
- * getting the same information from the TimeZoneInformation
- * registry. The function on Win98 seems to return its key name.
- * We can't do anything in that case.
+ * Get the number of subkeys of the "Time Zones" registry for
+ * enumeration.
*/
- if (tzi.StandardName[0] == 0) {
- bufSize = sizeof(stdNameInReg);
- ret = getValueInRegistry(hKey, STANDARD_NAME, &valueType,
- (LPBYTE) stdNameInReg, &bufSize);
- if (ret != ERROR_SUCCESS) {
- goto err;
- }
- stdNamePtr = stdNameInReg;
- }
- (void) RegCloseKey(hKey);
- }
-
- /*
- * Open the "Time Zones" registry.
- */
- ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NT_TZ_KEY, 0, KEY_READ, (PHKEY)&hKey);
- if (ret != ERROR_SUCCESS) {
- ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_TZ_KEY, 0, KEY_READ, (PHKEY)&hKey);
- /*
- * If both failed, then give up.
- */
- if (ret != ERROR_SUCCESS) {
- return VALUE_UNKNOWN;
- }
- }
-
- /*
- * Get the number of subkeys of the "Time Zones" registry for
- * enumeration.
- */
- ret = RegQueryInfoKey(hKey, NULL, NULL, NULL, &nSubKeys,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL);
- if (ret != ERROR_SUCCESS) {
- goto err;
- }
-
- /*
- * Compare to the "Std" value of each subkey and find the entry that
- * matches the current control panel setting.
- */
- onlyMapID = 0;
- for (i = 0; i < nSubKeys; ++i) {
- DWORD size = sizeof(subKeyName);
- ret = RegEnumKeyEx(hKey, i, subKeyName, &size, NULL, NULL, NULL, NULL);
- if (ret != ERROR_SUCCESS) {
- goto err;
- }
- ret = RegOpenKeyEx(hKey, subKeyName, 0, KEY_READ, (PHKEY)&hSubKey);
+ ret = RegQueryInfoKey(hKey, NULL, NULL, NULL, &nSubKeys,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (ret != ERROR_SUCCESS) {
goto err;
}
- size = sizeof(szValue);
- ret = getValueInRegistry(hSubKey, STD_NAME, &valueType,
- szValue, &size);
- if (ret != ERROR_SUCCESS) {
- /*
- * NT 4.0 SP3 fails here since it doesn't have the "Std"
- * entry in the Time Zones registry.
- */
- RegCloseKey(hSubKey);
- onlyMapID = 1;
- ret = RegOpenKeyExW(hKey, stdNamePtr, 0, KEY_READ, (PHKEY)&hSubKey);
+ /*
+ * Compare to the "Std" value of each subkey and find the entry that
+ * matches the current control panel setting.
+ */
+ onlyMapID = 0;
+ for (i = 0; i < nSubKeys; ++i) {
+ DWORD size = sizeof(subKeyName);
+ ret = RegEnumKeyEx(hKey, i, subKeyName, &size, NULL, NULL, NULL, NULL);
+ if (ret != ERROR_SUCCESS) {
+ goto err;
+ }
+ ret = RegOpenKeyEx(hKey, subKeyName, 0, KEY_READ, (PHKEY)&hSubKey);
if (ret != ERROR_SUCCESS) {
goto err;
}
- break;
- }
- if (wcscmp((WCHAR *)szValue, stdNamePtr) == 0) {
- /*
- * Some localized Win32 platforms use a same name to
- * different time zones. So, we can't rely only on the name
- * here. We need to check GMT offsets and transition dates
- * to make sure it's the registry of the current time
- * zone.
- */
- DWORD tziValueSize = sizeof(tempTzi);
- ret = RegQueryValueEx(hSubKey, "TZI", NULL, &valueType,
- (unsigned char *) &tempTzi, &tziValueSize);
- if (ret == ERROR_SUCCESS) {
- if ((tzi.Bias != tempTzi.bias) ||
- (memcmp((const void *) &tzi.StandardDate,
- (const void *) &tempTzi.stdDate,
- sizeof(SYSTEMTIME)) != 0)) {
- goto out;
+ size = sizeof(szValue);
+ ret = getValueInRegistry(hSubKey, STD_NAME, &valueType,
+ szValue, &size);
+ if (ret != ERROR_SUCCESS) {
+ /*
+ * NT 4.0 SP3 fails here since it doesn't have the "Std"
+ * entry in the Time Zones registry.
+ */
+ RegCloseKey(hSubKey);
+ onlyMapID = 1;
+ ret = RegOpenKeyExW(hKey, stdNamePtr, 0, KEY_READ, (PHKEY)&hSubKey);
+ if (ret != ERROR_SUCCESS) {
+ goto err;
}
+ break;
+ }
- if (tzi.DaylightBias != 0) {
- if ((tzi.DaylightBias != tempTzi.dstBias) ||
- (memcmp((const void *) &tzi.DaylightDate,
- (const void *) &tempTzi.dstDate,
+ if (wcscmp((WCHAR *)szValue, stdNamePtr) == 0) {
+ /*
+ * Some localized Win32 platforms use a same name to
+ * different time zones. So, we can't rely only on the name
+ * here. We need to check GMT offsets and transition dates
+ * to make sure it's the registry of the current time
+ * zone.
+ */
+ DWORD tziValueSize = sizeof(tempTzi);
+ ret = RegQueryValueEx(hSubKey, "TZI", NULL, &valueType,
+ (unsigned char *) &tempTzi, &tziValueSize);
+ if (ret == ERROR_SUCCESS) {
+ if ((tzi.Bias != tempTzi.bias) ||
+ (memcmp((const void *) &tzi.StandardDate,
+ (const void *) &tempTzi.stdDate,
sizeof(SYSTEMTIME)) != 0)) {
goto out;
}
+
+ if (tzi.DaylightBias != 0) {
+ if ((tzi.DaylightBias != tempTzi.dstBias) ||
+ (memcmp((const void *) &tzi.DaylightDate,
+ (const void *) &tempTzi.dstDate,
+ sizeof(SYSTEMTIME)) != 0)) {
+ goto out;
+ }
+ }
}
- }
-
- /*
- * found matched record, terminate search
- */
- strcpy(winZoneName, subKeyName);
- break;
- }
- out:
- (void) RegCloseKey(hSubKey);
- }
- /*
- * Get the "MapID" value of the registry to be able to eliminate
- * duplicated key names later.
- */
- valueSize = MAX_MAPID_LENGTH;
- ret = RegQueryValueExA(hSubKey, "MapID", NULL, &valueType, winMapID, &valueSize);
- (void) RegCloseKey(hSubKey);
- (void) RegCloseKey(hKey);
+ /*
+ * found matched record, terminate search
+ */
+ strcpy(winZoneName, subKeyName);
+ break;
+ }
+ out:
+ (void) RegCloseKey(hSubKey);
+ }
- if (ret != ERROR_SUCCESS) {
/*
- * Vista doesn't have mapID. VALUE_UNKNOWN should be returned
- * only for Windows NT.
+ * Get the "MapID" value of the registry to be able to eliminate
+ * duplicated key names later.
*/
- if (onlyMapID == 1) {
- return VALUE_UNKNOWN;
+ valueSize = MAX_MAPID_LENGTH;
+ ret = RegQueryValueExA(hSubKey, "MapID", NULL, &valueType, winMapID, &valueSize);
+ (void) RegCloseKey(hSubKey);
+ (void) RegCloseKey(hKey);
+
+ if (ret != ERROR_SUCCESS) {
+ /*
+ * Vista doesn't have mapID. VALUE_UNKNOWN should be returned
+ * only for Windows NT.
+ */
+ if (onlyMapID == 1) {
+ return VALUE_UNKNOWN;
+ }
}
}