/* * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
/* * Indices to keyNames[]
*/ #define STANDARD_NAME 0 #define STD_NAME 2
/* * Calls RegQueryValueEx() to get the value for the specified key. If * the platform is NT, 2000 or XP, it calls the Unicode * version. Otherwise, it calls the ANSI version and converts the * value to Unicode. In this case, it assumes that the current ANSI * Code Page is the same as the native platform code page (e.g., Code * Page 932 for the Japanese Windows systems. * * `keyIndex' is an index value to the keyNames in Unicode * (WCHAR). `keyIndex' + 1 points to its ANSI value. * * Returns the status value. ERROR_SUCCESS if succeeded, a * non-ERROR_SUCCESS value otherwise.
*/ staticLONG
getValueInRegistry(HKEY hKey, int keyIndex,
LPDWORD typePtr,
LPBYTE buf,
LPDWORD bufLengthPtr)
{ LONG ret;
DWORD bufLength = *bufLengthPtr; char val[MAX_ZONE_CHAR];
DWORD valSize; int len;
/* * Gets the current time zone entry in the "Time Zones" registry.
*/ staticint getWinTimeZone(char *winZoneName)
{
DYNAMIC_TIME_ZONE_INFORMATION dtzi;
DWORD timeType;
DWORD bufSize;
DWORD val;
HANDLE hKey = NULL; LONG ret;
ULONG valueType;
/* * Get the dynamic time zone information so that time zone redirection * can be supported. (see JDK-7044727)
*/
timeType = GetDynamicTimeZoneInformation(&dtzi); if (timeType == TIME_ZONE_ID_INVALID) { goto err;
}
/* * 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;
} 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; int onlyMapID;
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_CURRENT_TZ_KEY, 0,
KEY_READ, (PHKEY)&hKey); if (ret == ERROR_SUCCESS) { /* * 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;
}
}
/* * 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;
}
}
/* * 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); 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); 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,
(unsignedchar *) &tempTzi, &tziValueSize); if (ret == ERROR_SUCCESS) { if ((tzi.Bias != tempTzi.bias) ||
(memcmp((constvoid *) &tzi.StandardDate,
(constvoid *) &tempTzi.stdDate, sizeof(SYSTEMTIME)) != 0)) { goto out;
}
/* * Ignore comment and blank lines.
*/ if (*idx == '#' || *idx == '\n') { continue;
}
for (itemIndex = 0; itemIndex < TZ_NITEMS; itemIndex++) {
items[itemIndex] = start; while (*idx && *idx != ':') { if (++idx >= endp) {
errorMessage = "premature end of line";
offset = (int)(idx - lineBuffer); goto illegal_format;
}
} if (*idx == '\0') {
errorMessage = "illegal null character found";
offset = (int)(idx - lineBuffer); goto illegal_format;
}
*idx++ = '\0';
start = idx;
}
if (*idx != '\n') {
errorMessage = "illegal non-newline character found";
offset = (int)(idx - lineBuffer); goto illegal_format;
}
/* * We need to scan items until the * exact match is found or the end of data is detected.
*/ if (strcmp(items[TZ_WIN_NAME], tzName) == 0) { /* * Found the time zone in the mapping table. * Check the region code and select the appropriate entry
*/ if (strcmp(items[TZ_REGION], region) == 0 ||
strcmp(items[TZ_REGION], "001") == 0) {
javaTZName = _strdup(items[TZ_JAVA_NAME]); break;
}
}
}
fclose(fp);
return javaTZName;
illegal_format:
(void) fclose(fp);
jio_fprintf(stderr, "Illegal format in tzmappings file: %s at line %d, offset %d.\n",
errorMessage, line, offset); return NULL;
}
/* * Detects the platform time zone which maps to a Java time zone ID.
*/ char *findJavaTZ_md(constchar *java_home_dir)
{ char winZoneName[MAX_ZONE_CHAR]; char *std_timezone = NULL; int result;
/** * Returns a GMT-offset-based time zone ID.
*/ char *
getGMTOffsetID()
{ LONG bias = 0; LONG ret;
HANDLE hKey = NULL; char zonename[32];
// Obtain the current GMT offset value of ActiveTimeBias.
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_CURRENT_TZ_KEY, 0,
KEY_READ, (PHKEY)&hKey); if (ret == ERROR_SUCCESS) {
DWORD val;
DWORD bufSize = sizeof(val);
ULONG valueType = 0;
ret = RegQueryValueExA(hKey, "ActiveTimeBias",
NULL, &valueType, (LPBYTE) &val, &bufSize); if (ret == ERROR_SUCCESS) {
bias = (LONG) val;
}
(void) RegCloseKey(hKey);
}
// If we can't get the ActiveTimeBias value, use Bias of TimeZoneInformation. // Note: Bias doesn't reflect current daylight saving. if (ret != ERROR_SUCCESS) {
TIME_ZONE_INFORMATION tzi; if (GetTimeZoneInformation(&tzi) != TIME_ZONE_ID_INVALID) {
bias = tzi.Bias;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.