mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 23:34:52 +02:00
8187443: Forest Consolidation: Move files to unified layout
Reviewed-by: darcy, ihse
This commit is contained in:
parent
270fe13182
commit
3789983e89
56923 changed files with 3 additions and 15727 deletions
587
src/java.base/windows/native/libjava/TimeZone_md.c
Normal file
587
src/java.base/windows/native/libjava/TimeZone_md.c
Normal file
|
@ -0,0 +1,587 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2015, 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.
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "jvm.h"
|
||||
#include "TimeZone_md.h"
|
||||
|
||||
#define VALUE_UNKNOWN 0
|
||||
#define VALUE_KEY 1
|
||||
#define VALUE_MAPID 2
|
||||
#define VALUE_GMTOFFSET 3
|
||||
|
||||
#define MAX_ZONE_CHAR 256
|
||||
#define MAX_MAPID_LENGTH 32
|
||||
|
||||
#define NT_TZ_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones"
|
||||
#define WIN_TZ_KEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Time Zones"
|
||||
#define WIN_CURRENT_TZ_KEY "System\\CurrentControlSet\\Control\\TimeZoneInformation"
|
||||
|
||||
typedef struct _TziValue {
|
||||
LONG bias;
|
||||
LONG stdBias;
|
||||
LONG dstBias;
|
||||
SYSTEMTIME stdDate;
|
||||
SYSTEMTIME dstDate;
|
||||
} TziValue;
|
||||
|
||||
/*
|
||||
* Registry key names
|
||||
*/
|
||||
static void *keyNames[] = {
|
||||
(void *) L"StandardName",
|
||||
(void *) "StandardName",
|
||||
(void *) L"Std",
|
||||
(void *) "Std"
|
||||
};
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
static LONG
|
||||
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;
|
||||
|
||||
*typePtr = 0;
|
||||
ret = RegQueryValueExW(hKey, (WCHAR *) keyNames[keyIndex], NULL,
|
||||
typePtr, buf, bufLengthPtr);
|
||||
if (ret == ERROR_SUCCESS && *typePtr == REG_SZ) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
valSize = sizeof(val);
|
||||
ret = RegQueryValueExA(hKey, (char *) keyNames[keyIndex + 1], NULL,
|
||||
typePtr, val, &valSize);
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
if (*typePtr != REG_SZ) {
|
||||
return ERROR_BADKEY;
|
||||
}
|
||||
|
||||
len = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS,
|
||||
(LPCSTR) val, -1,
|
||||
(LPWSTR) buf, bufLength/sizeof(WCHAR));
|
||||
if (len <= 0) {
|
||||
return ERROR_BADKEY;
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Produces custom name "GMT+hh:mm" from the given bias in buffer.
|
||||
*/
|
||||
static void customZoneName(LONG bias, char *buffer) {
|
||||
LONG gmtOffset;
|
||||
int sign;
|
||||
|
||||
if (bias > 0) {
|
||||
gmtOffset = bias;
|
||||
sign = -1;
|
||||
} else {
|
||||
gmtOffset = -bias;
|
||||
sign = 1;
|
||||
}
|
||||
if (gmtOffset != 0) {
|
||||
sprintf(buffer, "GMT%c%02d:%02d",
|
||||
((sign >= 0) ? '+' : '-'),
|
||||
gmtOffset / 60,
|
||||
gmtOffset % 60);
|
||||
} else {
|
||||
strcpy(buffer, "GMT");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the current time zone entry in the "Time Zones" registry.
|
||||
*/
|
||||
static int getWinTimeZone(char *winZoneName, char *winMapID)
|
||||
{
|
||||
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;
|
||||
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) {
|
||||
/*
|
||||
* 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,
|
||||
(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);
|
||||
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
/*
|
||||
* Vista doesn't have mapID. VALUE_UNKNOWN should be returned
|
||||
* only for Windows NT.
|
||||
*/
|
||||
if (onlyMapID == 1) {
|
||||
return VALUE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return VALUE_KEY;
|
||||
|
||||
err:
|
||||
if (hKey != NULL) {
|
||||
(void) RegCloseKey(hKey);
|
||||
}
|
||||
return VALUE_UNKNOWN;
|
||||
}
|
||||
|
||||
/*
|
||||
* The mapping table file name.
|
||||
*/
|
||||
#define MAPPINGS_FILE "\\lib\\tzmappings"
|
||||
|
||||
/*
|
||||
* Index values for the mapping table.
|
||||
*/
|
||||
#define TZ_WIN_NAME 0
|
||||
#define TZ_MAPID 1
|
||||
#define TZ_REGION 2
|
||||
#define TZ_JAVA_NAME 3
|
||||
|
||||
#define TZ_NITEMS 4 /* number of items (fields) */
|
||||
|
||||
/*
|
||||
* Looks up the mapping table (tzmappings) and returns a Java time
|
||||
* zone ID (e.g., "America/Los_Angeles") if found. Otherwise, NULL is
|
||||
* returned.
|
||||
*
|
||||
* value_type is one of the following values:
|
||||
* VALUE_KEY for exact key matching
|
||||
* VALUE_MAPID for MapID (this is
|
||||
* required for the old Windows, such as NT 4.0 SP3).
|
||||
*/
|
||||
static char *matchJavaTZ(const char *java_home_dir, int value_type, char *tzName,
|
||||
char *mapID)
|
||||
{
|
||||
int line;
|
||||
int IDmatched = 0;
|
||||
FILE *fp;
|
||||
char *javaTZName = NULL;
|
||||
char *items[TZ_NITEMS];
|
||||
char *mapFileName;
|
||||
char lineBuffer[MAX_ZONE_CHAR * 4];
|
||||
int noMapID = *mapID == '\0'; /* no mapID on Vista and later */
|
||||
|
||||
mapFileName = malloc(strlen(java_home_dir) + strlen(MAPPINGS_FILE) + 1);
|
||||
if (mapFileName == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
strcpy(mapFileName, java_home_dir);
|
||||
strcat(mapFileName, MAPPINGS_FILE);
|
||||
|
||||
if ((fp = fopen(mapFileName, "r")) == NULL) {
|
||||
jio_fprintf(stderr, "can't open %s.\n", mapFileName);
|
||||
free((void *) mapFileName);
|
||||
return NULL;
|
||||
}
|
||||
free((void *) mapFileName);
|
||||
|
||||
line = 0;
|
||||
while (fgets(lineBuffer, sizeof(lineBuffer), fp) != NULL) {
|
||||
char *start, *idx, *endp;
|
||||
int itemIndex = 0;
|
||||
|
||||
line++;
|
||||
start = idx = lineBuffer;
|
||||
endp = &lineBuffer[sizeof(lineBuffer)];
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
goto illegal_format;
|
||||
}
|
||||
}
|
||||
if (*idx == '\0') {
|
||||
goto illegal_format;
|
||||
}
|
||||
*idx++ = '\0';
|
||||
start = idx;
|
||||
}
|
||||
|
||||
if (*idx != '\n') {
|
||||
goto illegal_format;
|
||||
}
|
||||
|
||||
if (noMapID || strcmp(mapID, items[TZ_MAPID]) == 0) {
|
||||
/*
|
||||
* When there's no mapID, we need to scan items until the
|
||||
* exact match is found or the end of data is detected.
|
||||
*/
|
||||
if (!noMapID) {
|
||||
IDmatched = 1;
|
||||
}
|
||||
if (strcmp(items[TZ_WIN_NAME], tzName) == 0) {
|
||||
/*
|
||||
* Found the time zone in the mapping table.
|
||||
*/
|
||||
javaTZName = _strdup(items[TZ_JAVA_NAME]);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (IDmatched == 1) {
|
||||
/*
|
||||
* No need to look up the mapping table further.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
return javaTZName;
|
||||
|
||||
illegal_format:
|
||||
(void) fclose(fp);
|
||||
jio_fprintf(stderr, "tzmappings: Illegal format at line %d.\n", line);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Detects the platform time zone which maps to a Java time zone ID.
|
||||
*/
|
||||
char *findJavaTZ_md(const char *java_home_dir)
|
||||
{
|
||||
char winZoneName[MAX_ZONE_CHAR];
|
||||
char winMapID[MAX_MAPID_LENGTH];
|
||||
char *std_timezone = NULL;
|
||||
int result;
|
||||
|
||||
winMapID[0] = 0;
|
||||
result = getWinTimeZone(winZoneName, winMapID);
|
||||
|
||||
if (result != VALUE_UNKNOWN) {
|
||||
if (result == VALUE_GMTOFFSET) {
|
||||
std_timezone = _strdup(winZoneName);
|
||||
} else {
|
||||
std_timezone = matchJavaTZ(java_home_dir, result,
|
||||
winZoneName, winMapID);
|
||||
if (std_timezone == NULL) {
|
||||
std_timezone = getGMTOffsetID();
|
||||
}
|
||||
}
|
||||
}
|
||||
return std_timezone;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
customZoneName(bias, zonename);
|
||||
return _strdup(zonename);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue