| OLD | NEW |
| 1 /* | 1 /* |
| 2 ******************************************************************************** | 2 ******************************************************************************** |
| 3 * Copyright (C) 2005-2013, International Business Machines | 3 * Copyright (C) 2005-2014, International Business Machines |
| 4 * Corporation and others. All Rights Reserved. | 4 * Corporation and others. All Rights Reserved. |
| 5 ******************************************************************************** | 5 ******************************************************************************** |
| 6 * | 6 * |
| 7 * File WINTZ.CPP | 7 * File WINTZ.CPP |
| 8 * | 8 * |
| 9 ******************************************************************************** | 9 ******************************************************************************** |
| 10 */ | 10 */ |
| 11 | 11 |
| 12 #include "unicode/utypes.h" | 12 #include "unicode/utypes.h" |
| 13 | 13 |
| 14 #if U_PLATFORM_HAS_WIN32_API | 14 #if U_PLATFORM_HAS_WIN32_API |
| 15 | 15 |
| 16 #include "wintz.h" | 16 #include "wintz.h" |
| 17 #include "cmemory.h" | 17 #include "cmemory.h" |
| 18 #include "cstring.h" | 18 #include "cstring.h" |
| 19 | 19 |
| 20 #include "unicode/ures.h" |
| 20 #include "unicode/ustring.h" | 21 #include "unicode/ustring.h" |
| 21 #include "unicode/ures.h" | |
| 22 | 22 |
| 23 # define WIN32_LEAN_AND_MEAN | 23 # define WIN32_LEAN_AND_MEAN |
| 24 # define VC_EXTRALEAN | 24 # define VC_EXTRALEAN |
| 25 # define NOUSER | 25 # define NOUSER |
| 26 # define NOSERVICE | 26 # define NOSERVICE |
| 27 # define NOIME | 27 # define NOIME |
| 28 # define NOMCX | 28 # define NOMCX |
| 29 #include <windows.h> | 29 #include <windows.h> |
| 30 | 30 |
| 31 #define MAX_LENGTH_ID 40 | 31 #define MAX_LENGTH_ID 40 |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 (LPBYTE)regStdName, | 186 (LPBYTE)regStdName, |
| 187 &cbData); | 187 &cbData); |
| 188 | 188 |
| 189 } | 189 } |
| 190 | 190 |
| 191 RegCloseKey(hkey); | 191 RegCloseKey(hkey); |
| 192 | 192 |
| 193 return result; | 193 return result; |
| 194 } | 194 } |
| 195 | 195 |
| 196 static LONG getTZKeyName(char* tzKeyName, int32_t length) { |
| 197 HKEY hkey; |
| 198 LONG result = FALSE; |
| 199 DWORD cbData = length; |
| 200 |
| 201 if(ERROR_SUCCESS == RegOpenKeyExA( |
| 202 HKEY_LOCAL_MACHINE, |
| 203 CURRENT_ZONE_REGKEY, |
| 204 0, |
| 205 KEY_QUERY_VALUE, |
| 206 &hkey)) |
| 207 { |
| 208 result = RegQueryValueExA( |
| 209 hkey, |
| 210 "TimeZoneKeyName", |
| 211 NULL, |
| 212 NULL, |
| 213 (LPBYTE)tzKeyName, |
| 214 &cbData); |
| 215 } |
| 216 |
| 217 return result; |
| 218 } |
| 219 |
| 196 /* | 220 /* |
| 197 This code attempts to detect the Windows time zone, as set in the | 221 This code attempts to detect the Windows time zone, as set in the |
| 198 Windows Date and Time control panel. It attempts to work on | 222 Windows Date and Time control panel. It attempts to work on |
| 199 multiple flavors of Windows (9x, Me, NT, 2000, XP) and on localized | 223 multiple flavors of Windows (9x, Me, NT, 2000, XP) and on localized |
| 200 installs. It works by directly interrogating the registry and | 224 installs. It works by directly interrogating the registry and |
| 201 comparing the data there with the data returned by the | 225 comparing the data there with the data returned by the |
| 202 GetTimeZoneInformation API, along with some other strategies. The | 226 GetTimeZoneInformation API, along with some other strategies. The |
| 203 registry contains time zone data under one of two keys (depending on | 227 registry contains time zone data under one of two keys (depending on |
| 204 the flavor of Windows): | 228 the flavor of Windows): |
| 205 | 229 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 | 267 |
| 244 /** | 268 /** |
| 245 * Main Windows time zone detection function. Returns the Windows | 269 * Main Windows time zone detection function. Returns the Windows |
| 246 * time zone, translated to an ICU time zone, or NULL upon failure. | 270 * time zone, translated to an ICU time zone, or NULL upon failure. |
| 247 */ | 271 */ |
| 248 U_CFUNC const char* U_EXPORT2 | 272 U_CFUNC const char* U_EXPORT2 |
| 249 uprv_detectWindowsTimeZone() { | 273 uprv_detectWindowsTimeZone() { |
| 250 UErrorCode status = U_ZERO_ERROR; | 274 UErrorCode status = U_ZERO_ERROR; |
| 251 UResourceBundle* bundle = NULL; | 275 UResourceBundle* bundle = NULL; |
| 252 char* icuid = NULL; | 276 char* icuid = NULL; |
| 253 UChar apiStd[MAX_LENGTH_ID]; | |
| 254 char apiStdName[MAX_LENGTH_ID]; | 277 char apiStdName[MAX_LENGTH_ID]; |
| 255 char regStdName[MAX_LENGTH_ID]; | 278 char regStdName[MAX_LENGTH_ID]; |
| 256 char tmpid[MAX_LENGTH_ID]; | 279 char tmpid[MAX_LENGTH_ID]; |
| 257 int32_t len; | 280 int32_t len; |
| 258 int id; | 281 int id; |
| 259 int errorCode; | 282 int errorCode; |
| 260 char ISOcode[3]; /* 2 letter iso code */ | 283 UChar ISOcodeW[3]; /* 2 letter iso code in UTF-16*/ |
| 284 char ISOcodeA[3]; /* 2 letter iso code in ansi */ |
| 261 | 285 |
| 262 LONG result; | 286 LONG result; |
| 263 TZI tziKey; | 287 TZI tziKey; |
| 264 TZI tziReg; | 288 TZI tziReg; |
| 265 TIME_ZONE_INFORMATION apiTZI; | 289 TIME_ZONE_INFORMATION apiTZI; |
| 266 | 290 |
| 291 BOOL isVistaOrHigher; |
| 292 BOOL tryPreVistaFallback; |
| 293 OSVERSIONINFO osVerInfo; |
| 294 |
| 267 /* Obtain TIME_ZONE_INFORMATION from the API, and then convert it | 295 /* Obtain TIME_ZONE_INFORMATION from the API, and then convert it |
| 268 to TZI. We could also interrogate the registry directly; we do | 296 to TZI. We could also interrogate the registry directly; we do |
| 269 this below if needed. */ | 297 this below if needed. */ |
| 270 uprv_memset(&apiTZI, 0, sizeof(apiTZI)); | 298 uprv_memset(&apiTZI, 0, sizeof(apiTZI)); |
| 271 uprv_memset(&tziKey, 0, sizeof(tziKey)); | 299 uprv_memset(&tziKey, 0, sizeof(tziKey)); |
| 272 uprv_memset(&tziReg, 0, sizeof(tziReg)); | 300 uprv_memset(&tziReg, 0, sizeof(tziReg)); |
| 273 GetTimeZoneInformation(&apiTZI); | 301 GetTimeZoneInformation(&apiTZI); |
| 274 tziKey.bias = apiTZI.Bias; | 302 tziKey.bias = apiTZI.Bias; |
| 275 uprv_memcpy((char *)&tziKey.standardDate, (char*)&apiTZI.StandardDate, | 303 uprv_memcpy((char *)&tziKey.standardDate, (char*)&apiTZI.StandardDate, |
| 276 sizeof(apiTZI.StandardDate)); | 304 sizeof(apiTZI.StandardDate)); |
| 277 uprv_memcpy((char *)&tziKey.daylightDate, (char*)&apiTZI.DaylightDate, | 305 uprv_memcpy((char *)&tziKey.daylightDate, (char*)&apiTZI.DaylightDate, |
| 278 sizeof(apiTZI.DaylightDate)); | 306 sizeof(apiTZI.DaylightDate)); |
| 279 | 307 |
| 280 /* Convert the wchar_t* standard name to char* */ | 308 /* Convert the wchar_t* standard name to char* */ |
| 281 uprv_memset(apiStdName, 0, sizeof(apiStdName)); | 309 uprv_memset(apiStdName, 0, sizeof(apiStdName)); |
| 282 u_strFromWCS(apiStd, MAX_LENGTH_ID, NULL, apiTZI.StandardName, -1, &status); | 310 wcstombs(apiStdName, apiTZI.StandardName, MAX_LENGTH_ID); |
| 283 u_austrncpy(apiStdName, apiStd, sizeof(apiStdName) - 1); | |
| 284 | 311 |
| 285 tmpid[0] = 0; | 312 tmpid[0] = 0; |
| 286 | 313 |
| 287 id = GetUserGeoID(GEOCLASS_NATION); | 314 id = GetUserGeoID(GEOCLASS_NATION); |
| 288 errorCode = GetGeoInfoA(id,GEO_ISO2,ISOcode,3,0); | 315 errorCode = GetGeoInfoW(id,GEO_ISO2,ISOcodeW,3,0); |
| 316 u_strToUTF8(ISOcodeA, 3, NULL, ISOcodeW, 3, &status); |
| 289 | 317 |
| 290 bundle = ures_openDirect(NULL, "windowsZones", &status); | 318 bundle = ures_openDirect(NULL, "windowsZones", &status); |
| 291 ures_getByKey(bundle, "mapTimezones", bundle, &status); | 319 ures_getByKey(bundle, "mapTimezones", bundle, &status); |
| 292 | 320 |
| 293 /* Note: We get the winid not from static tables but from resource bundle. *
/ | 321 /* |
| 294 while (U_SUCCESS(status) && ures_hasNext(bundle)) { | 322 Windows Vista+ provides us with a "TimeZoneKeyName" that is not localize
d |
| 295 UBool idFound = FALSE; | 323 and can be used to directly map a name in our bundle. Try to use that fi
rst |
| 296 const char* winid; | 324 if we're on Vista or higher |
| 297 UResourceBundle* winTZ = ures_getNextResource(bundle, NULL, &status); | 325 */ |
| 298 if (U_FAILURE(status)) { | 326 uprv_memset(&osVerInfo, 0, sizeof(osVerInfo)); |
| 299 break; | 327 osVerInfo.dwOSVersionInfoSize = sizeof(osVerInfo); |
| 300 } | 328 GetVersionEx(&osVerInfo); |
| 301 winid = ures_getKey(winTZ); | 329 isVistaOrHigher = osVerInfo.dwMajorVersion >= 6;» /* actually includes Win
dows Server 2008 as well, but don't worry about it */ |
| 302 result = getTZI(winid, &tziReg); | 330 tryPreVistaFallback = TRUE; |
| 303 | 331 if(isVistaOrHigher) { |
| 304 if (result == ERROR_SUCCESS) { | 332 result = getTZKeyName(regStdName, sizeof(regStdName)); |
| 305 /* Windows alters the DaylightBias in some situations. | 333 if(ERROR_SUCCESS == result) { |
| 306 Using the bias and the rules suffices, so overwrite | 334 UResourceBundle* winTZ = ures_getByKey(bundle, regStdName, NULL, &st
atus); |
| 307 these unreliable fields. */ | 335 if(U_SUCCESS(status)) { |
| 308 tziKey.standardBias = tziReg.standardBias; | |
| 309 tziKey.daylightBias = tziReg.daylightBias; | |
| 310 | |
| 311 if (uprv_memcmp((char *)&tziKey, (char*)&tziReg, sizeof(tziKey)) ==
0) { | |
| 312 const UChar* icuTZ = NULL; | 336 const UChar* icuTZ = NULL; |
| 313 if (errorCode != 0) { | 337 if (errorCode != 0) { |
| 314 icuTZ = ures_getStringByKey(winTZ, ISOcode, &len, &status); | 338 icuTZ = ures_getStringByKey(winTZ, ISOcodeA, &len, &status); |
| 315 } | 339 } |
| 316 if (errorCode==0 || icuTZ==NULL) { | 340 if (errorCode==0 || icuTZ==NULL) { |
| 317 /* fallback to default "001" and reset status */ | 341 /* fallback to default "001" and reset status */ |
| 318 status = U_ZERO_ERROR; | 342 status = U_ZERO_ERROR; |
| 319 icuTZ = ures_getStringByKey(winTZ, "001", &len, &status); | 343 icuTZ = ures_getStringByKey(winTZ, "001", &len, &status); |
| 320 } | 344 } |
| 321 | 345 |
| 322 if (U_SUCCESS(status)) { | 346 if(U_SUCCESS(status)) { |
| 323 /* Get the standard name from the registry key to compare wi
th | 347 int index=0; |
| 324 the one from Windows API call. */ | 348 while (! (*icuTZ == '\0' || *icuTZ ==' ')) { |
| 325 uprv_memset(regStdName, 0, sizeof(regStdName)); | 349 tmpid[index++]=(char)(*icuTZ++); /* safe to assume 'cha
r' is ASCII compatible on windows */ |
| 326 result = getSTDName(winid, regStdName, sizeof(regStdName)); | 350 } |
| 327 if (result == ERROR_SUCCESS) { | 351 tmpid[index]='\0'; |
| 328 if (uprv_strcmp(apiStdName, regStdName) == 0) { | 352 tryPreVistaFallback = FALSE; |
| 329 idFound = TRUE; | 353 } |
| 330 } | 354 } |
| 355 } |
| 356 } |
| 357 |
| 358 if(tryPreVistaFallback) { |
| 359 |
| 360 /* Note: We get the winid not from static tables but from resource bundl
e. */ |
| 361 while (U_SUCCESS(status) && ures_hasNext(bundle)) { |
| 362 UBool idFound = FALSE; |
| 363 const char* winid; |
| 364 UResourceBundle* winTZ = ures_getNextResource(bundle, NULL, &status)
; |
| 365 if (U_FAILURE(status)) { |
| 366 break; |
| 367 } |
| 368 winid = ures_getKey(winTZ); |
| 369 result = getTZI(winid, &tziReg); |
| 370 |
| 371 if (result == ERROR_SUCCESS) { |
| 372 /* Windows alters the DaylightBias in some situations. |
| 373 Using the bias and the rules suffices, so overwrite |
| 374 these unreliable fields. */ |
| 375 tziKey.standardBias = tziReg.standardBias; |
| 376 tziKey.daylightBias = tziReg.daylightBias; |
| 377 |
| 378 if (uprv_memcmp((char *)&tziKey, (char*)&tziReg, sizeof(tziKey))
== 0) { |
| 379 const UChar* icuTZ = NULL; |
| 380 if (errorCode != 0) { |
| 381 icuTZ = ures_getStringByKey(winTZ, ISOcodeA, &len, &stat
us); |
| 382 } |
| 383 if (errorCode==0 || icuTZ==NULL) { |
| 384 /* fallback to default "001" and reset status */ |
| 385 status = U_ZERO_ERROR; |
| 386 icuTZ = ures_getStringByKey(winTZ, "001", &len, &status)
; |
| 331 } | 387 } |
| 332 | 388 |
| 333 /* tmpid buffer holds the ICU timezone ID corresponding to t
he timezone ID from Windows. | 389 if (U_SUCCESS(status)) { |
| 334 * If none is found, tmpid buffer will contain a fallback ID
(i.e. the time zone ID matching | 390 /* Get the standard name from the registry key to compar
e with |
| 335 * the current time zone information) | 391 the one from Windows API call. */ |
| 336 */ | 392 uprv_memset(regStdName, 0, sizeof(regStdName)); |
| 337 if (idFound || tmpid[0] == 0) { | 393 result = getSTDName(winid, regStdName, sizeof(regStdName
)); |
| 338 /* if icuTZ has more than one city, take only the first
(i.e. terminate icuTZ at first space) */ | 394 if (result == ERROR_SUCCESS) { |
| 339 int index=0; | 395 if (uprv_strcmp(apiStdName, regStdName) == 0) { |
| 340 while (! (*icuTZ == '\0' || *icuTZ ==' ')) { | 396 idFound = TRUE; |
| 341 tmpid[index++]=(char)(*icuTZ++); /* safe to assume
'char' is ASCII compatible on windows */ | 397 } |
| 342 } | 398 } |
| 343 tmpid[index]='\0'; | 399 |
| 400 /* tmpid buffer holds the ICU timezone ID corresponding
to the timezone ID from Windows. |
| 401 * If none is found, tmpid buffer will contain a fallbac
k ID (i.e. the time zone ID matching |
| 402 * the current time zone information) |
| 403 */ |
| 404 if (idFound || tmpid[0] == 0) { |
| 405 /* if icuTZ has more than one city, take only the fi
rst (i.e. terminate icuTZ at first space) */ |
| 406 int index=0; |
| 407 while (! (*icuTZ == '\0' || *icuTZ ==' ')) { |
| 408 tmpid[index++]=(char)(*icuTZ++); /* safe to ass
ume 'char' is ASCII compatible on windows */ |
| 409 } |
| 410 tmpid[index]='\0'; |
| 411 } |
| 344 } | 412 } |
| 345 } | 413 } |
| 346 } | 414 } |
| 347 } | 415 ures_close(winTZ); |
| 348 ures_close(winTZ); | 416 if (idFound) { |
| 349 if (idFound) { | 417 break; |
| 350 break; | 418 } |
| 351 } | 419 } |
| 352 } | 420 } |
| 353 | 421 |
| 354 /* | 422 /* |
| 355 * Copy the timezone ID to icuid to be returned. | 423 * Copy the timezone ID to icuid to be returned. |
| 356 */ | 424 */ |
| 357 if (tmpid[0] != 0) { | 425 if (tmpid[0] != 0) { |
| 358 len = uprv_strlen(tmpid); | 426 len = uprv_strlen(tmpid); |
| 359 icuid = (char*)uprv_calloc(len + 1, sizeof(char)); | 427 icuid = (char*)uprv_calloc(len + 1, sizeof(char)); |
| 360 if (icuid != NULL) { | 428 if (icuid != NULL) { |
| 361 uprv_strcpy(icuid, tmpid); | 429 uprv_strcpy(icuid, tmpid); |
| 362 } | 430 } |
| 363 } | 431 } |
| 364 | 432 |
| 365 ures_close(bundle); | 433 ures_close(bundle); |
| 366 | 434 |
| 367 return icuid; | 435 return icuid; |
| 368 } | 436 } |
| 369 | 437 |
| 370 #endif /* U_PLATFORM_HAS_WIN32_API */ | 438 #endif /* U_PLATFORM_HAS_WIN32_API */ |
| OLD | NEW |