Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Unified Diff: icu46/source/common/wintz.c

Issue 5516007: Check in the pristine copy of ICU 4.6... (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/third_party/
Patch Set: Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « icu46/source/common/wintz.h ('k') | icu46/source/config.guess » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: icu46/source/common/wintz.c
===================================================================
--- icu46/source/common/wintz.c (revision 0)
+++ icu46/source/common/wintz.c (revision 0)
@@ -0,0 +1,290 @@
+/*
+********************************************************************************
+* Copyright (C) 2005-2010, International Business Machines
+* Corporation and others. All Rights Reserved.
+********************************************************************************
+*
+* File WINTZ.CPP
+*
+********************************************************************************
+*/
+
+#include "unicode/utypes.h"
+
+#ifdef U_WINDOWS
+
+#include "wintz.h"
+
+#include "cmemory.h"
+#include "cstring.h"
+
+#include "unicode/ustring.h"
+#include "unicode/ures.h"
+
+# define WIN32_LEAN_AND_MEAN
+# define VC_EXTRALEAN
+# define NOUSER
+# define NOSERVICE
+# define NOIME
+# define NOMCX
+#include <windows.h>
+
+/* The layout of the Tzi value in the registry */
+typedef struct
+{
+ int32_t bias;
+ int32_t standardBias;
+ int32_t daylightBias;
+ SYSTEMTIME standardDate;
+ SYSTEMTIME daylightDate;
+} TZI;
+
+/**
+ * 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 subkey; this is present on
+ * NT, but on XP has become "GMT Standard Time". We need to
+ * discriminate between these cases.
+ */
+static const char* const 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* const 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 = 1,
+ WIN_NT_TYPE = 2,
+ WIN_2K_XP_TYPE = 3
+};
+
+static int32_t gWinType = 0;
+
+static int32_t detectWindowsType()
+{
+ int32_t winType;
+ LONG result;
+ HKEY hkey;
+
+ /* 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 = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
+ WIN_TYPE_PROBE_REGKEY[winType],
+ 0,
+ KEY_QUERY_VALUE,
+ &hkey);
+ RegCloseKey(hkey);
+
+ if (result == ERROR_SUCCESS) {
+ break;
+ }
+ }
+
+ return winType+1; // +1 to bring it inline with the enum
+}
+
+static LONG openTZRegKey(HKEY *hkey, const char *winid)
+{
+ char subKeyName[110]; /* TODO: why 96?? */
+ char *name;
+ LONG result;
+
+ /* This isn't thread safe, but it's good enough because the result should be constant per system. */
+ if (gWinType <= 0) {
+ gWinType = detectWindowsType();
+ }
+
+ uprv_strcpy(subKeyName, TZ_REGKEY[(gWinType != WIN_9X_ME_TYPE)]);
+ name = &subKeyName[strlen(subKeyName)];
+ uprv_strcat(subKeyName, winid);
+
+ if (gWinType == WIN_9X_ME_TYPE) {
+ /* Remove " Standard Time" */
+ char *pStd = uprv_strstr(subKeyName, STANDARD_TIME_REGKEY);
+ if (pStd) {
+ *pStd = 0;
+ }
+ }
+
+ result = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
+ subKeyName,
+ 0,
+ KEY_QUERY_VALUE,
+ hkey);
+ return result;
+}
+
+static LONG getTZI(const char *winid, TZI *tzi)
+{
+ DWORD cbData = sizeof(TZI);
+ LONG result;
+ HKEY hkey;
+
+ result = openTZRegKey(&hkey, winid);
+
+ if (result == ERROR_SUCCESS) {
+ result = RegQueryValueExA(hkey,
+ TZI_REGKEY,
+ NULL,
+ NULL,
+ (LPBYTE)tzi,
+ &cbData);
+
+ }
+
+ RegCloseKey(hkey);
+
+ return result;
+}
+
+/*
+ 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>
+*/
+
+/**
+ * Main Windows time zone detection function. Returns the Windows
+ * time zone, translated to an ICU time zone, or NULL upon failure.
+ */
+U_CFUNC const char* U_EXPORT2
+uprv_detectWindowsTimeZone() {
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle* bundle = NULL;
+ char* icuid = NULL;
+
+ LONG result;
+ TZI tziKey;
+ TZI tziReg;
+ TIME_ZONE_INFORMATION apiTZI;
+
+ /* 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. */
+ uprv_memset(&apiTZI, 0, sizeof(apiTZI));
+ uprv_memset(&tziKey, 0, sizeof(tziKey));
+ uprv_memset(&tziReg, 0, sizeof(tziReg));
+ GetTimeZoneInformation(&apiTZI);
+ tziKey.bias = apiTZI.Bias;
+ uprv_memcpy((char *)&tziKey.standardDate, (char*)&apiTZI.StandardDate,
+ sizeof(apiTZI.StandardDate));
+ uprv_memcpy((char *)&tziKey.daylightDate, (char*)&apiTZI.DaylightDate,
+ sizeof(apiTZI.DaylightDate));
+
+ bundle = ures_openDirect(NULL, "windowsZones", &status);
+ ures_getByKey(bundle, "mapTimezones", bundle, &status);
+
+ /* Note: We get the winid not from static tables but from resource bundle. */
+ while (U_SUCCESS(status) && ures_hasNext(bundle)) {
+ const char* winid;
+ int32_t len;
+ UResourceBundle* winTZ = ures_getNextResource(bundle, NULL, &status);
+ if (U_FAILURE(status)) {
+ break;
+ }
+ winid = ures_getKey(winTZ);
+ result = getTZI(winid, &tziReg);
+
+ 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 (uprv_memcmp((char *)&tziKey, (char*)&tziReg, sizeof(tziKey)) == 0) {
+ const UChar* icuTZ = ures_getStringByKey(winTZ, "001", &len, &status);
+ if (U_SUCCESS(status)) {
+ icuid = (char*)uprv_malloc(sizeof(char) * (len + 1));
+ uprv_memset(icuid, 0, len + 1);
+ u_austrncpy(icuid, icuTZ, len);
+ }
+ }
+ }
+ ures_close(winTZ);
+ if (icuid != NULL) {
+ break;
+ }
+ }
+
+ ures_close(bundle);
+
+ return icuid;
+}
+
+#endif /* #ifdef U_WINDOWS */
Property changes on: icu46/source/common/wintz.c
___________________________________________________________________
Added: svn:eol-style
+ LF
« no previous file with comments | « icu46/source/common/wintz.h ('k') | icu46/source/config.guess » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698