@@ -70,9 +70,11 @@ struct tzhead {
70
70
71
71
#include <time.h>
72
72
73
+ #if !TARGET_OS_WIN32
73
74
static CFStringRef __tzZoneInfo = NULL ;
74
75
static char * __tzDir = NULL ;
75
76
static void __InitTZStrings (void );
77
+ #endif
76
78
77
79
CONST_STRING_DECL (kCFTimeZoneSystemTimeZoneDidChangeNotification , "kCFTimeZoneSystemTimeZoneDidChangeNotification" )
78
80
@@ -116,6 +118,9 @@ CF_INLINE void __CFTimeZoneUnlockCompatibilityMapping(void) {
116
118
}
117
119
118
120
#if TARGET_OS_WIN32
121
+ #define CF_TIME_ZONES_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones"
122
+ #define COUNT_OF (array ) (sizeof((array)) / sizeof((array)[0]))
123
+
119
124
/* This function should be used for WIN32 instead of
120
125
* __CFCopyRecursiveDirectoryList function.
121
126
* It takes TimeZone names from the registry
@@ -124,33 +129,60 @@ CF_INLINE void __CFTimeZoneUnlockCompatibilityMapping(void) {
124
129
static CFMutableArrayRef __CFCopyWindowsTimeZoneList () {
125
130
CFMutableArrayRef result = NULL ;
126
131
HKEY hkResult ;
127
- TCHAR lpName [MAX_PATH + 1 ];
132
+ WCHAR szName [MAX_PATH + 1 ];
128
133
DWORD dwIndex , retCode ;
129
134
130
- if (RegOpenKey (HKEY_LOCAL_MACHINE , _T ("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones" ), & hkResult ) !=
131
- ERROR_SUCCESS )
135
+ if (RegOpenKeyW (HKEY_LOCAL_MACHINE , CF_TIME_ZONES_KEY , & hkResult ) != ERROR_SUCCESS )
132
136
return NULL ;
133
137
134
138
result = CFArrayCreateMutable (kCFAllocatorSystemDefault , 0 , & kCFTypeArrayCallBacks );
135
- for (dwIndex = 0 ; (retCode = RegEnumKey (hkResult ,dwIndex ,lpName , MAX_PATH )) != ERROR_NO_MORE_ITEMS ; dwIndex ++ ) {
139
+ for (dwIndex = 0 ; (retCode = RegEnumKeyW (hkResult , dwIndex , szName , COUNT_OF ( szName ) - 1 )) != ERROR_NO_MORE_ITEMS ; dwIndex ++ ) {
136
140
if (retCode != ERROR_SUCCESS ) {
137
141
RegCloseKey (hkResult );
138
142
CFRelease (result );
139
143
return NULL ;
140
144
} else {
141
- #if defined(UNICODE )
142
- CFStringRef string = CFStringCreateWithBytes (kCFAllocatorSystemDefault , (const UInt8 * )lpName , (_tcslen (lpName ) * sizeof (UniChar )), kCFStringEncodingUnicode , false);
143
- #else
144
- CFStringRef string = CFStringCreateWithBytes (kCFAllocatorSystemDefault , (const unsigned char * )lpName , _tcslen (lpName ), CFStringGetSystemEncoding (), false);
145
- #endif
146
- CFArrayAppendValue (result , string );
147
- CFRelease (string );
145
+ CFStringRef string = CFStringCreateWithBytes (kCFAllocatorSystemDefault , (const UInt8 * )szName , (wcslen (szName ) * sizeof (WCHAR )), kCFStringEncodingUTF16 , false);
146
+ CFArrayAppendValue (result , string );
147
+ CFRelease (string );
148
148
}
149
149
}
150
150
151
151
RegCloseKey (hkResult );
152
152
return result ;
153
153
}
154
+
155
+ static void __CFTimeZoneGetOffset (CFStringRef timezone , int32_t * offset ) {
156
+ typedef struct _REG_TZI_FORMAT {
157
+ LONG Bias ;
158
+ LONG StandardBias ;
159
+ LONG DaylightBias ;
160
+ SYSTEMTIME StandardDate ;
161
+ SYSTEMTIME DaylightDate ;
162
+ } REG_TZI_FORMAT ;
163
+
164
+ WCHAR szRegKey [COUNT_OF (CF_TIME_ZONES_KEY ) + 1 + COUNT_OF (((TIME_ZONE_INFORMATION * )0 )-> StandardName ) + 1 ];
165
+ REG_TZI_FORMAT tziInfo ;
166
+ Boolean bResult ;
167
+ DWORD cbData ;
168
+ HKEY hKey ;
169
+
170
+ * offset = 0 ;
171
+
172
+ memset (szRegKey , 0 , sizeof (szRegKey ));
173
+ wcscpy (szRegKey , CF_TIME_ZONES_KEY );
174
+ szRegKey [COUNT_OF (CF_TIME_ZONES_KEY ) - 1 ] = L'\\' ;
175
+ CFStringGetBytes (timezone , CFRangeMake (0 , CFStringGetLength (timezone )), kCFStringEncodingUnicode , FALSE, FALSE, (uint8_t * )& szRegKey [wcslen (CF_TIME_ZONES_KEY ) + 1 ], sizeof (((TIME_ZONE_INFORMATION * )0 )-> StandardName ) + sizeof (WCHAR ), NULL );
176
+
177
+ if (RegOpenKeyW (HKEY_LOCAL_MACHINE , szRegKey , & hKey ) != ERROR_SUCCESS )
178
+ return ;
179
+
180
+ cbData = sizeof (tziInfo );
181
+ if (RegQueryValueExW (hKey , L"TZI" , NULL , NULL , (LPBYTE )& tziInfo , & cbData ) == ERROR_SUCCESS )
182
+ * offset = tziInfo .Bias ;
183
+
184
+ RegCloseKey (hKey );
185
+ }
154
186
#elif TARGET_OS_MAC || TARGET_OS_LINUX || TARGET_OS_BSD
155
187
static CFMutableArrayRef __CFCopyRecursiveDirectoryList () {
156
188
CFMutableArrayRef result = CFArrayCreateMutable (kCFAllocatorSystemDefault , 0 , & kCFTypeArrayCallBacks );
@@ -476,21 +508,27 @@ CF_INLINE void __CFTimeZoneUnlockWinToOlson(void) {
476
508
__CFUnlock (& __CFTimeZoneWinToOlsonLock );
477
509
}
478
510
479
- static Boolean CFTimeZoneLoadWindowsOlsonPlist ( LPVOID * ppResource , LPDWORD pdwSize ) {
511
+ static Boolean CFTimeZoneLoadPlistResource ( LPCSTR lpName , LPVOID * ppResource , LPDWORD pdwSize ) {
480
512
HRSRC hResource ;
481
513
HGLOBAL hMemory ;
514
+ HMODULE hModule ;
515
+
516
+ if (!GetModuleHandleExW (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT ,
517
+ (LPCWSTR )& CFTimeZoneLoadPlistResource , & hModule )) {
518
+ return FALSE;
519
+ }
482
520
483
- hResource = FindResourceA (NULL , MAKEINTRESOURCEA ( IDR_WINDOWS_OLSON_MAPPING ) , "PLIST" );
521
+ hResource = FindResourceA (hModule , lpName , "PLIST" );
484
522
if (hResource == NULL ) {
485
523
return FALSE;
486
524
}
487
525
488
- hMemory = LoadResource (NULL , hResource );
526
+ hMemory = LoadResource (hModule , hResource );
489
527
if (hMemory == NULL ) {
490
528
return FALSE;
491
529
}
492
530
493
- * pdwSize = SizeofResource (NULL , hResource );
531
+ * pdwSize = SizeofResource (hModule , hResource );
494
532
* ppResource = LockResource (hMemory );
495
533
496
534
return * pdwSize && * ppResource ;
@@ -504,7 +542,7 @@ CFDictionaryRef CFTimeZoneCopyWinToOlsonDictionary(void) {
504
542
const uint8_t * plist ;
505
543
DWORD dwSize ;
506
544
507
- if (CFTimeZoneLoadWindowsOlsonPlist ( & plist , & dwSize )) {
545
+ if (CFTimeZoneLoadPlistResource ( MAKEINTRESOURCEA ( IDR_WINDOWS_OLSON_MAPPING ), ( LPVOID * ) & plist , & dwSize )) {
508
546
CFDataRef data = CFDataCreate (kCFAllocatorSystemDefault , plist , dwSize );
509
547
__CFTimeZoneWinToOlsonDict = (CFDictionaryRef )CFPropertyListCreateFromXMLData (kCFAllocatorSystemDefault , data , kCFPropertyListImmutable , NULL );
510
548
CFRelease (data );
@@ -519,6 +557,26 @@ CFDictionaryRef CFTimeZoneCopyWinToOlsonDictionary(void) {
519
557
return dict ;
520
558
}
521
559
560
+ static CFDictionaryRef CFTimeZoneCopyOlsonToWindowsDictionary (void ) {
561
+ static CFDictionaryRef dict ;
562
+ static CFLock_t lock ;
563
+
564
+ __CFLock (& lock );
565
+ if (dict == NULL ) {
566
+ const uint8_t * plist ;
567
+ DWORD dwSize ;
568
+
569
+ if (CFTimeZoneLoadPlistResource (MAKEINTRESOURCEA (IDR_OLSON_WINDOWS_MAPPING ), (LPVOID * )& plist , & dwSize )) {
570
+ CFDataRef data = CFDataCreate (kCFAllocatorSystemDefault , plist , dwSize );
571
+ dict = CFPropertyListCreateFromXMLData (kCFAllocatorSystemDefault , data , kCFPropertyListImmutable , NULL );
572
+ CFRelease (data );
573
+ }
574
+ }
575
+ __CFUnlock (& lock );
576
+
577
+ return dict ? CFRetain (dict ) : NULL ;
578
+ }
579
+
522
580
void CFTimeZoneSetWinToOlsonDictionary (CFDictionaryRef dict ) {
523
581
__CFGenericValidateType (dict , CFDictionaryGetTypeID ());
524
582
__CFTimeZoneLockWinToOlson ();
@@ -544,23 +602,6 @@ CFTimeZoneRef CFTimeZoneCreateWithWindowsName(CFAllocatorRef allocator, CFString
544
602
CFRelease (winToOlson );
545
603
return retval ;
546
604
}
547
-
548
- static void __InitTZStrings (void ) {
549
- static CFLock_t __CFTZDirLock = CFLockInit ;
550
- __CFLock (& __CFTZDirLock );
551
- // TODO(compnerd) figure out how to initialize __tzZoneInfo
552
- if (!__tzDir && __tzZoneInfo ) {
553
- int length = CFStringGetLength (__tzZoneInfo ) + sizeof ("\\zone.tab" ) + 1 ;
554
- __tzDir = malloc (length ); // If we don't use ascii, we'll need to malloc more space
555
- if (!__tzDir || !CFStringGetCString (__tzZoneInfo , __tzDir , length , kCFStringEncodingASCII )) {
556
- free (__tzDir );
557
- } else {
558
- strcat (__tzDir , "\\zone.tab" );
559
- }
560
- }
561
- __CFUnlock (& __CFTZDirLock );
562
- }
563
-
564
605
#elif TARGET_OS_MAC
565
606
static void __InitTZStrings (void ) {
566
607
static dispatch_once_t initOnce = 0 ;
@@ -1056,14 +1097,33 @@ Boolean _CFTimeZoneInit(CFTimeZoneRef timeZone, CFStringRef name, CFDataRef data
1056
1097
void * bytes ;
1057
1098
CFIndex length ;
1058
1099
Boolean result = false;
1059
-
1060
- if (!__tzZoneInfo ) __InitTZStrings ();
1061
- if (!__tzZoneInfo ) return NULL ;
1100
+
1062
1101
#if TARGET_OS_WIN32
1063
- baseURL = CFURLCreateWithFileSystemPath (kCFAllocatorSystemDefault , __tzZoneInfo , kCFURLWindowsPathStyle , true);
1102
+ CFDictionaryRef abbrevs = CFTimeZoneCopyAbbreviationDictionary ();
1103
+
1104
+ tzName = CFDictionaryGetValue (abbrevs , name );
1105
+ if (tzName == NULL ) {
1106
+ CFDictionaryRef olson = CFTimeZoneCopyOlsonToWindowsDictionary ();
1107
+ tzName = CFDictionaryGetValue (olson , name );
1108
+ CFRelease (olson );
1109
+ }
1110
+
1111
+ CFRelease (abbrevs );
1112
+
1113
+ if (tzName ) {
1114
+ int32_t offset ;
1115
+ __CFTimeZoneGetOffset (tzName , & offset );
1116
+ CFRelease (tzName );
1117
+ // TODO(compnerd) handle DST
1118
+ __CFTimeZoneInitFixed (timeZone , offset , name , 0 );
1119
+ return TRUE;
1120
+ }
1121
+
1122
+ return FALSE;
1064
1123
#else
1124
+ if (!__tzZoneInfo ) __InitTZStrings ();
1125
+ if (!__tzZoneInfo ) return NULL ;
1065
1126
baseURL = CFURLCreateWithFileSystemPath (kCFAllocatorSystemDefault , __tzZoneInfo , kCFURLPOSIXPathStyle , true);
1066
- #endif
1067
1127
1068
1128
CFDictionaryRef abbrevs = CFTimeZoneCopyAbbreviationDictionary ();
1069
1129
tzName = CFDictionaryGetValue (abbrevs , name );
@@ -1113,6 +1173,7 @@ Boolean _CFTimeZoneInit(CFTimeZoneRef timeZone, CFStringRef name, CFDataRef data
1113
1173
CFRelease (data );
1114
1174
}
1115
1175
return result ;
1176
+ #endif
1116
1177
}
1117
1178
1118
1179
CFTimeZoneRef CFTimeZoneCreate (CFAllocatorRef allocator , CFStringRef name , CFDataRef data ) {
@@ -1254,13 +1315,31 @@ CFTimeZoneRef CFTimeZoneCreateWithName(CFAllocatorRef allocator, CFStringRef nam
1254
1315
void * bytes ;
1255
1316
CFIndex length ;
1256
1317
1257
- if (!__tzZoneInfo ) __InitTZStrings ();
1258
- if (!__tzZoneInfo ) return NULL ;
1259
1318
#if TARGET_OS_WIN32
1260
- baseURL = CFURLCreateWithFileSystemPath (kCFAllocatorSystemDefault , __tzZoneInfo , kCFURLWindowsPathStyle , true);
1319
+ CFDictionaryRef abbrevs = CFTimeZoneCopyAbbreviationDictionary ();
1320
+
1321
+ tzName = CFDictionaryGetValue (abbrevs , name );
1322
+ if (tzName == NULL ) {
1323
+ CFDictionaryRef olson = CFTimeZoneCopyOlsonToWindowsDictionary ();
1324
+ tzName = CFDictionaryGetValue (olson , name );
1325
+ CFRelease (olson );
1326
+ }
1327
+
1328
+ CFRelease (abbrevs );
1329
+
1330
+ if (tzName ) {
1331
+ int32_t offset ;
1332
+ __CFTimeZoneGetOffset (tzName , & offset );
1333
+ CFRelease (tzName );
1334
+ // TODO(compnerd) handle DST
1335
+ result = __CFTimeZoneCreateFixed (allocator , offset , name , 0 );
1336
+ }
1337
+
1338
+ return result ;
1261
1339
#else
1340
+ if (!__tzZoneInfo ) __InitTZStrings ();
1341
+ if (!__tzZoneInfo ) return NULL ;
1262
1342
baseURL = CFURLCreateWithFileSystemPath (kCFAllocatorSystemDefault , __tzZoneInfo , kCFURLPOSIXPathStyle , true);
1263
- #endif
1264
1343
if (tryAbbrev ) {
1265
1344
CFDictionaryRef abbrevs = CFTimeZoneCopyAbbreviationDictionary ();
1266
1345
tzName = CFDictionaryGetValue (abbrevs , name );
@@ -1317,6 +1396,7 @@ CFTimeZoneRef CFTimeZoneCreateWithName(CFAllocatorRef allocator, CFStringRef nam
1317
1396
CFRelease (data );
1318
1397
}
1319
1398
return result ;
1399
+ #endif
1320
1400
}
1321
1401
1322
1402
CFStringRef CFTimeZoneGetName (CFTimeZoneRef tz ) {
0 commit comments