1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott******************************************************************************** 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott* Copyright (C) 2005-2008, International Business Machines 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott* Corporation and others. All Rights Reserved. 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott******************************************************************************** 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott* 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott* File WINTZ.CPP 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott* 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott******************************************************************************** 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/ 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "unicode/utypes.h" 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef U_WINDOWS 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "wintz.h" 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "cmemory.h" 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "cstring.h" 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "unicode/ustring.h" 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "unicode/ures.h" 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# define WIN32_LEAN_AND_MEAN 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# define VC_EXTRALEAN 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# define NOUSER 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# define NOSERVICE 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# define NOIME 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott# define NOMCX 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <windows.h> 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* The layout of the Tzi value in the registry */ 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef struct 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int32_t bias; 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int32_t standardBias; 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int32_t daylightBias; 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SYSTEMTIME standardDate; 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SYSTEMTIME daylightDate; 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} TZI; 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/** 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Various registry keys and key fragments. 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const char CURRENT_ZONE_REGKEY[] = "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation\\"; 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const char STANDARD_NAME_REGKEY[] = "StandardName"; 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const char STANDARD_TIME_REGKEY[] = " Standard Time"; 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const char TZI_REGKEY[] = "TZI"; 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const char STD_REGKEY[] = "Std"; 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/** 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * HKLM subkeys used to probe for the flavor of Windows. Note that we 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * specifically check for the "GMT" zone subkey; this is present on 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * NT, but on XP has become "GMT Standard Time". We need to 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * discriminate between these cases. 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const char* const WIN_TYPE_PROBE_REGKEY[] = { 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* WIN_9X_ME_TYPE */ 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Time Zones", 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* WIN_NT_TYPE */ 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\GMT" 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* otherwise: WIN_2K_XP_TYPE */ 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/** 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * The time zone root subkeys (under HKLM) for different flavors of 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Windows. 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const char* const TZ_REGKEY[] = { 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* WIN_9X_ME_TYPE */ 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Time Zones\\", 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* WIN_NT_TYPE | WIN_2K_XP_TYPE */ 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\" 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/** 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Flavor of Windows, from our perspective. Not a real OS version, 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * but rather the flavor of the layout of the time zone information in 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * the registry. 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottenum { 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WIN_9X_ME_TYPE = 1, 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WIN_NT_TYPE = 2, 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WIN_2K_XP_TYPE = 3 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int32_t gWinType = 0; 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int32_t detectWindowsType() 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int32_t winType; 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LONG result; 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HKEY hkey; 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Detect the version of windows by trying to open a sequence of 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott probe keys. We don't use the OS version API because what we 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott really want to know is how the registry is laid out. 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Specifically, is it 9x/Me or not, and is it "GMT" or "GMT 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Standard Time". */ 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (winType = 0; winType < 2; winType++) { 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = RegOpenKeyExA(HKEY_LOCAL_MACHINE, 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WIN_TYPE_PROBE_REGKEY[winType], 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0, 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott KEY_QUERY_VALUE, 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &hkey); 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == ERROR_SUCCESS) { 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RegCloseKey(hkey); 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return winType+1; // +1 to bring it inline with the enum 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic LONG openTZRegKey(HKEY *hkey, const char *winid) 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char subKeyName[110]; /* TODO: why 96?? */ 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char *name; 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LONG result; 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* This isn't thread safe, but it's good enough because the result should be constant per system. */ 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (gWinType <= 0) { 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott gWinType = detectWindowsType(); 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uprv_strcpy(subKeyName, TZ_REGKEY[(gWinType != WIN_9X_ME_TYPE)]); 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott name = &subKeyName[strlen(subKeyName)]; 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uprv_strcat(subKeyName, winid); 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (gWinType == WIN_9X_ME_TYPE) { 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Remove " Standard Time" */ 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char *pStd = uprv_strstr(subKeyName, STANDARD_TIME_REGKEY); 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (pStd) { 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *pStd = 0; 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = RegOpenKeyExA(HKEY_LOCAL_MACHINE, 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott subKeyName, 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 0, 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott KEY_QUERY_VALUE, 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott hkey); 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic LONG getTZI(const char *winid, TZI *tzi) 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD cbData = sizeof(TZI); 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LONG result; 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HKEY hkey; 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = openTZRegKey(&hkey, winid); 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == ERROR_SUCCESS) { 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = RegQueryValueExA(hkey, 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TZI_REGKEY, 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NULL, 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (LPBYTE)tzi, 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &cbData); 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RegCloseKey(hkey); 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/* 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott This code attempts to detect the Windows time zone, as set in the 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Windows Date and Time control panel. It attempts to work on 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott multiple flavors of Windows (9x, Me, NT, 2000, XP) and on localized 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott installs. It works by directly interrogating the registry and 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott comparing the data there with the data returned by the 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GetTimeZoneInformation API, along with some other strategies. The 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott registry contains time zone data under one of two keys (depending on 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott the flavor of Windows): 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Time Zones\ 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\ 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Under this key are several subkeys, one for each time zone. These 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott subkeys are named "Pacific" on Win9x/Me and "Pacific Standard Time" 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott on WinNT/2k/XP. There are some other wrinkles; see the code for 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott details. The subkey name is NOT LOCALIZED, allowing us to support 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott localized installs. 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Under the subkey are data values. We care about: 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Std Standard time display name, localized 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TZI Binary block of data 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott The TZI data is of particular interest. It contains the offset, two 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott more offsets for standard and daylight time, and the start and end 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rules. This is the same data returned by the GetTimeZoneInformation 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott API. The API may modify the data on the way out, so we have to be 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott careful, but essentially we do a binary comparison against the TZI 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott blocks of various registry keys. When we find a match, we know what 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott time zone Windows is set to. Since the registry key is not 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott localized, we can then translate the key through a simple table 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott lookup into the corresponding ICU time zone. 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott This strategy doesn't always work because there are zones which 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott share an offset and rules, so more than one TZI block will match. 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott For example, both Tokyo and Seoul are at GMT+9 with no DST rules; 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott their TZI blocks are identical. For these cases, we fall back to a 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott name lookup. We attempt to match the display name as stored in the 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott registry for the current zone to the display name stored in the 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott registry for various Windows zones. By comparing the registry data 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott directly we avoid conversion complications. 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Author: Alan Liu 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Since: ICU 2.6 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Based on original code by Carl Brown <cbrown@xnetinc.com> 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott*/ 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott/** 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * Main Windows time zone detection function. Returns the Windows 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott * time zone, translated to an ICU time zone, or NULL upon failure. 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott */ 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottU_CFUNC const char* U_EXPORT2 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottuprv_detectWindowsTimeZone() { 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UErrorCode status = U_ZERO_ERROR; 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UResourceBundle* bundle = NULL; 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* icuid = NULL; 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LONG result; 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TZI tziKey; 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TZI tziReg; 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TIME_ZONE_INFORMATION apiTZI; 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Obtain TIME_ZONE_INFORMATION from the API, and then convert it 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott to TZI. We could also interrogate the registry directly; we do 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott this below if needed. */ 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uprv_memset(&apiTZI, 0, sizeof(apiTZI)); 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uprv_memset(&tziKey, 0, sizeof(tziKey)); 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uprv_memset(&tziReg, 0, sizeof(tziReg)); 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GetTimeZoneInformation(&apiTZI); 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tziKey.bias = apiTZI.Bias; 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uprv_memcpy((char *)&tziKey.standardDate, (char*)&apiTZI.StandardDate, 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sizeof(apiTZI.StandardDate)); 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uprv_memcpy((char *)&tziKey.daylightDate, (char*)&apiTZI.DaylightDate, 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sizeof(apiTZI.DaylightDate)); 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bundle = ures_openDirect(NULL, "supplementalData", &status); 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bundle = ures_getByKey(bundle, "mapTimezones", bundle, &status); 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bundle = ures_getByKey(bundle, "windows", bundle, &status); 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Note: We get the winid not from static tables but from resource bundle. */ 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (U_SUCCESS(status) && ures_hasNext(bundle)) { 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* winid; 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int32_t len; 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UResourceBundle* winTZ = ures_getNextResource(bundle, NULL, &status); 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (U_FAILURE(status)) { 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott winid = ures_getKey(winTZ); 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = getTZI(winid, &tziReg); 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == ERROR_SUCCESS) { 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott /* Windows alters the DaylightBias in some situations. 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Using the bias and the rules suffices, so overwrite 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott these unreliable fields. */ 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tziKey.standardBias = tziReg.standardBias; 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tziKey.daylightBias = tziReg.daylightBias; 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (uprv_memcmp((char *)&tziKey, (char*)&tziReg, sizeof(tziKey)) == 0) { 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const UChar* icuTZ = ures_getString(winTZ, &len, &status); 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (U_SUCCESS(status)) { 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott icuid = (char*)uprv_malloc(sizeof(char) * (len + 1)); 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uprv_memset(icuid, 0, len + 1); 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott u_austrncpy(icuid, icuTZ, len); 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ures_close(winTZ); 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (icuid != NULL) { 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ures_close(bundle); 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return icuid; 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif /* #ifdef U_WINDOWS */ 290