1 // 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ******************************************************************************** 5 * Copyright (C) 2005-2015, International Business Machines 6 * Corporation and others. All Rights Reserved. 7 ******************************************************************************** 8 * 9 * File WINTZ.CPP 10 * 11 ******************************************************************************** 12 */ 13 14 #include "unicode/utypes.h" 15 16 #if U_PLATFORM_USES_ONLY_WIN32_API 17 18 #include "wintz.h" 19 #include "cmemory.h" 20 #include "cstring.h" 21 22 #include "unicode/ures.h" 23 #include "unicode/ustring.h" 24 #include "uresimp.h" 25 26 #ifndef WIN32_LEAN_AND_MEAN 27 # define WIN32_LEAN_AND_MEAN 28 #endif 29 # define VC_EXTRALEAN 30 # define NOUSER 31 # define NOSERVICE 32 # define NOIME 33 # define NOMCX 34 #include <windows.h> 35 36 U_NAMESPACE_BEGIN 37 38 // The value of MAX_TIMEZONE_ID_LENGTH is 128, which is defined in DYNAMIC_TIME_ZONE_INFORMATION 39 #define MAX_TIMEZONE_ID_LENGTH 128 40 41 /** 42 * Main Windows time zone detection function. 43 * Returns the Windows time zone converted to an ICU time zone as a heap-allocated buffer, or nullptr upon failure. 44 * Note: We use the Win32 API GetDynamicTimeZoneInformation to get the current time zone info. 45 * This API returns a non-localized time zone name, which we can then map to an ICU time zone name. 46 */ 47 U_CFUNC const char* U_EXPORT2 48 uprv_detectWindowsTimeZone() 49 { 50 UErrorCode status = U_ZERO_ERROR; 51 char* icuid = nullptr; 52 char dynamicTZKeyName[MAX_TIMEZONE_ID_LENGTH]; 53 char tmpid[MAX_TIMEZONE_ID_LENGTH]; 54 int32_t len; 55 int id = GEOID_NOT_AVAILABLE; 56 int errorCode; 57 wchar_t ISOcodeW[3] = {}; /* 2 letter ISO code in UTF-16 */ 58 char ISOcode[3] = {}; /* 2 letter ISO code in UTF-8 */ 59 60 DYNAMIC_TIME_ZONE_INFORMATION dynamicTZI; 61 uprv_memset(&dynamicTZI, 0, sizeof(dynamicTZI)); 62 uprv_memset(dynamicTZKeyName, 0, sizeof(dynamicTZKeyName)); 63 uprv_memset(tmpid, 0, sizeof(tmpid)); 64 65 /* Obtain TIME_ZONE_INFORMATION from the API and get the non-localized time zone name. */ 66 if (TIME_ZONE_ID_INVALID == GetDynamicTimeZoneInformation(&dynamicTZI)) { 67 return nullptr; 68 } 69 70 id = GetUserGeoID(GEOCLASS_NATION); 71 errorCode = GetGeoInfoW(id, GEO_ISO2, ISOcodeW, 3, 0); 72 73 // convert from wchar_t* (UTF-16 on Windows) to char* (UTF-8). 74 u_strToUTF8(ISOcode, UPRV_LENGTHOF(ISOcode), nullptr, 75 reinterpret_cast<const UChar*>(ISOcodeW), UPRV_LENGTHOF(ISOcodeW), &status); 76 77 LocalUResourceBundlePointer bundle(ures_openDirect(nullptr, "windowsZones", &status)); 78 ures_getByKey(bundle.getAlias(), "mapTimezones", bundle.getAlias(), &status); 79 80 // convert from wchar_t* (UTF-16 on Windows) to char* (UTF-8). 81 u_strToUTF8(dynamicTZKeyName, UPRV_LENGTHOF(dynamicTZKeyName), nullptr, 82 reinterpret_cast<const UChar*>(dynamicTZI.TimeZoneKeyName), UPRV_LENGTHOF(dynamicTZI.TimeZoneKeyName), &status); 83 84 if (U_FAILURE(status)) { 85 return nullptr; 86 } 87 88 if (dynamicTZI.TimeZoneKeyName[0] != 0) { 89 UResourceBundle winTZ; 90 ures_initStackObject(&winTZ); 91 ures_getByKey(bundle.getAlias(), dynamicTZKeyName, &winTZ, &status); 92 93 if (U_SUCCESS(status)) { 94 const UChar* icuTZ = nullptr; 95 if (errorCode != 0) { 96 icuTZ = ures_getStringByKey(&winTZ, ISOcode, &len, &status); 97 } 98 if (errorCode == 0 || icuTZ == nullptr) { 99 /* fallback to default "001" and reset status */ 100 status = U_ZERO_ERROR; 101 icuTZ = ures_getStringByKey(&winTZ, "001", &len, &status); 102 } 103 104 if (U_SUCCESS(status)) { 105 int index = 0; 106 107 while (!(*icuTZ == '\0' || *icuTZ == ' ')) { 108 // time zone IDs only contain ASCII invariant characters. 109 tmpid[index++] = (char)(*icuTZ++); 110 } 111 tmpid[index] = '\0'; 112 } 113 } 114 ures_close(&winTZ); 115 } 116 117 // Copy the timezone ID to icuid to be returned. 118 if (tmpid[0] != 0) { 119 icuid = uprv_strdup(tmpid); 120 } 121 122 return icuid; 123 } 124 125 U_NAMESPACE_END 126 #endif /* U_PLATFORM_USES_ONLY_WIN32_API */ 127