提交 6482890a 编写于 作者: O okutsu

7044727: (tz) TimeZone.getDefault() call returns incorrect value in Windows terminal session

Reviewed-by: naoto
上级 1c4975a0
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "jvm.h" #include "jvm.h"
#include "TimeZone_md.h" #include "TimeZone_md.h"
#include "jdk_util.h"
#define VALUE_UNKNOWN 0 #define VALUE_UNKNOWN 0
#define VALUE_KEY 1 #define VALUE_KEY 1
...@@ -49,6 +50,20 @@ typedef struct _TziValue { ...@@ -49,6 +50,20 @@ typedef struct _TziValue {
SYSTEMTIME dstDate; SYSTEMTIME dstDate;
} TziValue; } TziValue;
#if _WIN32_WINNT < 0x0600 /* < _WIN32_WINNT_VISTA */
typedef struct _TIME_DYNAMIC_ZONE_INFORMATION {
LONG Bias;
WCHAR StandardName[32];
SYSTEMTIME StandardDate;
LONG StandardBias;
WCHAR DaylightName[32];
SYSTEMTIME DaylightDate;
LONG DaylightBias;
WCHAR TimeZoneKeyName[128];
BOOLEAN DynamicDaylightTimeDisabled;
} DYNAMIC_TIME_ZONE_INFORMATION, *PDYNAMIC_TIME_ZONE_INFORMATION;
#endif
/* /*
* Registry key names * Registry key names
*/ */
...@@ -142,6 +157,33 @@ static void customZoneName(LONG bias, char *buffer) { ...@@ -142,6 +157,33 @@ static void customZoneName(LONG bias, char *buffer) {
} }
} }
/*
* Use NO_DYNAMIC_TIME_ZONE_INFO as the return value indicating that no
* dynamic time zone information is available.
*/
#define NO_DYNAMIC_TIME_ZONE_INFO (-128)
static int getDynamicTimeZoneInfo(PDYNAMIC_TIME_ZONE_INFORMATION pdtzi) {
DWORD timeType = NO_DYNAMIC_TIME_ZONE_INFO;
HMODULE dllHandle;
/*
* Dynamically load the dll to call GetDynamicTimeZoneInformation.
*/
dllHandle = JDK_LoadSystemLibrary("Kernel32.dll");
if (dllHandle != NULL) {
typedef DWORD (WINAPI *GetDynamicTimezoneInfoType)(PDYNAMIC_TIME_ZONE_INFORMATION);
GetDynamicTimezoneInfoType getDynamicTimeZoneInfoFunc =
(GetDynamicTimezoneInfoType) GetProcAddress(dllHandle,
"GetDynamicTimeZoneInformation");
if (getDynamicTimeZoneInfo != NULL) {
timeType = getDynamicTimeZoneInfoFunc(pdtzi);
}
}
return timeType;
}
/* /*
* Gets the current time zone entry in the "Time Zones" registry. * Gets the current time zone entry in the "Time Zones" registry.
*/ */
...@@ -161,22 +203,95 @@ static int getWinTimeZone(char *winZoneName, char *winMapID) ...@@ -161,22 +203,95 @@ static int getWinTimeZone(char *winZoneName, char *winMapID)
WCHAR *stdNamePtr = tzi.StandardName; WCHAR *stdNamePtr = tzi.StandardName;
DWORD valueSize; DWORD valueSize;
DWORD timeType; DWORD timeType;
int isVista; int isVistaOrLater;
/* /*
* Get the current time zone setting of the platform. * Determine if this is a Vista or later.
*/ */
timeType = GetTimeZoneInformation(&tzi); ver.dwOSVersionInfoSize = sizeof(ver);
if (timeType == TIME_ZONE_ID_INVALID) { GetVersionEx(&ver);
goto err; isVistaOrLater = (ver.dwMajorVersion >= 6);
if (isVistaOrLater) {
DYNAMIC_TIME_ZONE_INFORMATION dtzi;
DWORD bufSize;
DWORD val;
/*
* Get the dynamic time zone information, if available, so that time
* zone redirection can be supported. (see JDK-7044727)
*/
timeType = getDynamicTimeZoneInfo(&dtzi);
if (timeType == TIME_ZONE_ID_INVALID) {
goto err;
}
if (timeType != NO_DYNAMIC_TIME_ZONE_INFO) {
/*
* 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.
*/
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;
}
/*
* 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.
*/
bufSize = sizeof(val);
ret = RegQueryValueExA(hKey, "DynamicDaylightTimeDisabled", NULL,
&valueType, (LPBYTE) &val, &bufSize);
if (ret != ERROR_SUCCESS) {
goto err;
}
/*
* 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) {
goto err;
}
(void) RegCloseKey(hKey);
return VALUE_KEY;
}
}
} }
/* /*
* Determine if this is an NT system. * Fall back to GetTimeZoneInformation
*/ */
ver.dwOSVersionInfoSize = sizeof(ver); timeType = GetTimeZoneInformation(&tzi);
GetVersionEx(&ver); if (timeType == TIME_ZONE_ID_INVALID) {
isVista = ver.dwMajorVersion >= 6; goto err;
}
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_CURRENT_TZ_KEY, 0, ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_CURRENT_TZ_KEY, 0,
KEY_READ, (PHKEY)&hKey); KEY_READ, (PHKEY)&hKey);
...@@ -187,23 +302,23 @@ static int getWinTimeZone(char *winZoneName, char *winMapID) ...@@ -187,23 +302,23 @@ static int getWinTimeZone(char *winZoneName, char *winMapID)
/* /*
* Determine if auto-daylight time adjustment is turned off. * Determine if auto-daylight time adjustment is turned off.
*/ */
valueType = 0;
bufSize = sizeof(val); bufSize = sizeof(val);
ret = RegQueryValueExA(hKey, "DisableAutoDaylightTimeSet", ret = RegQueryValueExA(hKey, "DynamicDaylightTimeDisabled", NULL,
NULL, &valueType, (LPBYTE) &val, &bufSize); &valueType, (LPBYTE) &val, &bufSize);
/*
* Vista uses the different key name.
*/
if (ret != ERROR_SUCCESS) { if (ret != ERROR_SUCCESS) {
/*
* Try the old key name.
*/
bufSize = sizeof(val); bufSize = sizeof(val);
ret = RegQueryValueExA(hKey, "DynamicDaylightTimeDisabled", ret = RegQueryValueExA(hKey, "DisableAutoDaylightTimeSet", NULL,
NULL, &valueType, (LPBYTE) &val, &bufSize); &valueType, (LPBYTE) &val, &bufSize);
} }
if (ret == ERROR_SUCCESS) { if (ret == ERROR_SUCCESS) {
int daylightSavingsUpdateDisabledOther = val == 1 && tzi.DaylightDate.wMonth != 0; int daylightSavingsUpdateDisabledOther = (val == 1 && tzi.DaylightDate.wMonth != 0);
int daylightSavingsUpdateDisabledVista = val == 1; int daylightSavingsUpdateDisabledVista = (val == 1);
int daylightSavingsUpdateDisabled = isVista ? daylightSavingsUpdateDisabledVista : daylightSavingsUpdateDisabledOther; int daylightSavingsUpdateDisabled
= (isVistaOrLater ? daylightSavingsUpdateDisabledVista : daylightSavingsUpdateDisabledOther);
if (daylightSavingsUpdateDisabled) { if (daylightSavingsUpdateDisabled) {
(void) RegCloseKey(hKey); (void) RegCloseKey(hKey);
...@@ -212,29 +327,13 @@ static int getWinTimeZone(char *winZoneName, char *winMapID) ...@@ -212,29 +327,13 @@ static int getWinTimeZone(char *winZoneName, char *winMapID)
} }
} }
/*
* 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 * Win32 problem: If the length of the standard time name is equal
* to (or probably longer than) 32 in the registry, * to (or probably longer than) 32 in the registry,
* GetTimeZoneInformation() on NT returns a null string as its * GetTimeZoneInformation() on NT returns a null string as its
* standard time name. We need to work around this problem by * standard time name. We need to work around this problem by
* getting the same information from the TimeZoneInformation * getting the same information from the TimeZoneInformation
* registry. The function on Win98 seems to return its key name. * registry.
* We can't do anything in that case.
*/ */
if (tzi.StandardName[0] == 0) { if (tzi.StandardName[0] == 0) {
bufSize = sizeof(stdNameInReg); bufSize = sizeof(stdNameInReg);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册