1 // 2 // timeset.cpp 3 // 4 // Copyright (c) Microsoft Corporation. All rights reserved. 5 // 6 // The time zone values for the default time zone, and other global time data. 7 // 8 #include <corecrt_internal_time.h> 9 10 #undef _daylight 11 #undef _dstbias 12 #undef _timezone 13 #undef _tzname 14 15 16 17 __crt_state_management::dual_state_global<long> _timezone; // Pacific Time Zone 18 __crt_state_management::dual_state_global<int> _daylight; // Daylight Saving Time (DST) in timezone 19 __crt_state_management::dual_state_global<long> _dstbias; // DST offset in seconds 20 21 // Note that NT POSIX's TZNAME_MAX is only 10. 22 23 #define _PST_STRING "PST" 24 #define _PDT_STRING "PDT" 25 26 #define L_PST_STRING L"PST" 27 #define L_PDT_STRING L"PDT" 28 29 static char tzstd_program[_TZ_STRINGS_SIZE] = { _PST_STRING }; 30 static char tzdst_program[_TZ_STRINGS_SIZE] = { _PDT_STRING }; 31 32 static wchar_t w_tzstd_program[_TZ_STRINGS_SIZE] = { L_PST_STRING }; 33 static wchar_t w_tzdst_program[_TZ_STRINGS_SIZE] = { L_PDT_STRING }; 34 35 #ifdef _CRT_GLOBAL_STATE_ISOLATION 36 static char tzstd_os[_TZ_STRINGS_SIZE] = { _PST_STRING }; 37 static char tzdst_os[_TZ_STRINGS_SIZE] = { _PDT_STRING }; 38 39 static wchar_t w_tzstd_os[_TZ_STRINGS_SIZE] = { L_PST_STRING }; 40 static wchar_t w_tzdst_os[_TZ_STRINGS_SIZE] = { L_PDT_STRING }; 41 #endif 42 43 static char* tzname_states[__crt_state_management::state_index_count][2] = 44 { 45 { tzstd_program, tzdst_program }, 46 #ifdef _CRT_GLOBAL_STATE_ISOLATION 47 { tzstd_os, tzdst_os } 48 #endif 49 }; 50 51 static wchar_t* w_tzname_states[__crt_state_management::state_index_count][2] = 52 { 53 { w_tzstd_program, w_tzdst_program }, 54 #ifdef _CRT_GLOBAL_STATE_ISOLATION 55 { w_tzstd_os, w_tzdst_os } 56 #endif 57 }; 58 59 static __crt_state_management::dual_state_global<char **> _tzname; 60 static __crt_state_management::dual_state_global<wchar_t **> w_tzname; 61 62 // Initializer for the timeset globals: 63 _CRT_LINKER_FORCE_INCLUDE(__acrt_timeset_initializer); 64 65 extern "C" int __cdecl __acrt_initialize_timeset() 66 { 67 _timezone.initialize(8 * 3600L); 68 _daylight.initialize(1); 69 _dstbias.initialize (-3600); 70 71 char*** const first_state = _tzname.dangerous_get_state_array(); 72 for (unsigned i = 0; i != __crt_state_management::state_index_count; ++i) 73 { 74 first_state[i] = tzname_states[i]; 75 } 76 77 wchar_t*** const w_first_state = w_tzname.dangerous_get_state_array(); 78 for (unsigned i = 0; i != __crt_state_management::state_index_count; ++i) 79 { 80 w_first_state[i] = w_tzname_states[i]; 81 } 82 83 return 0; 84 } 85 86 extern "C" errno_t __cdecl _get_daylight(int* const result) 87 { 88 _VALIDATE_RETURN_ERRCODE(result != nullptr, EINVAL); 89 90 // This variable is correctly inited at startup, so no need to check if 91 // CRT init finished. 92 *result = _daylight.value(); 93 return 0; 94 } 95 96 extern "C" errno_t __cdecl _get_dstbias(long* result) 97 { 98 _VALIDATE_RETURN_ERRCODE(result != nullptr, EINVAL); 99 100 // This variable is correctly inited at startup, so no need to check if 101 // CRT init finished. 102 *result = _dstbias.value(); 103 return 0; 104 } 105 106 extern "C" errno_t __cdecl _get_timezone(long* result) 107 { 108 _VALIDATE_RETURN_ERRCODE(result != nullptr, EINVAL); 109 110 // This variable is correctly inited at startup, so no need to check if 111 // CRT init finished. 112 *result = _timezone.value(); 113 return 0; 114 } 115 116 extern "C" errno_t __cdecl _get_tzname( 117 size_t* const length, 118 char* const buffer, 119 size_t const size_in_bytes, 120 int const index) 121 { 122 _VALIDATE_RETURN_ERRCODE( 123 (buffer != nullptr && size_in_bytes > 0) || 124 (buffer == nullptr && size_in_bytes == 0), 125 EINVAL); 126 127 if (buffer != nullptr) 128 buffer[0] = '\0'; 129 130 _VALIDATE_RETURN_ERRCODE(length != nullptr, EINVAL); 131 _VALIDATE_RETURN_ERRCODE(index == 0 || index == 1, EINVAL); 132 133 // _tzname is correctly inited at startup, so no need to check if 134 // CRT init finished. 135 *length = strlen(_tzname.value()[index]) + 1; 136 137 // If the buffer pointer is null, the caller is interested only in the size 138 // of the string, not in the actual value of the string: 139 if (buffer == nullptr) 140 return 0; 141 142 if (*length > size_in_bytes) 143 return ERANGE; 144 145 return strcpy_s(buffer, size_in_bytes, _tzname.value()[index]); 146 } 147 148 149 150 // Day names must be three character abbreviations strung together 151 extern "C" const char __dnames[] = 152 { 153 "SunMonTueWedThuFriSat" 154 }; 155 156 // Month names must be three character abbreviations strung together 157 extern "C" const char __mnames[] = 158 { 159 "JanFebMarAprMayJunJulAugSepOctNovDec" 160 }; 161 162 163 164 // Accessors for the global time data 165 extern "C" int* __cdecl __daylight() 166 { 167 return &_daylight.value(); 168 } 169 170 extern "C" long* __cdecl __dstbias() 171 { 172 return &_dstbias.value(); 173 } 174 175 extern "C" long* __cdecl __timezone() 176 { 177 return &_timezone.value(); 178 } 179 180 extern "C" char** __cdecl __tzname() 181 { 182 return _tzname.value(); 183 } 184 185 extern "C" wchar_t** __cdecl __wide_tzname() 186 { 187 return w_tzname.value(); 188 } 189