xref: /reactos/sdk/lib/ucrt/time/timeset.cpp (revision 04e0dc4a)
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 
__acrt_initialize_timeset()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 
_get_daylight(int * const result)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 
_get_dstbias(long * result)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 
_get_timezone(long * result)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 
_get_tzname(size_t * const length,char * const buffer,size_t const size_in_bytes,int const index)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
__daylight()165 extern "C" int* __cdecl __daylight()
166 {
167     return &_daylight.value();
168 }
169 
__dstbias()170 extern "C" long* __cdecl __dstbias()
171 {
172     return &_dstbias.value();
173 }
174 
__timezone()175 extern "C" long* __cdecl __timezone()
176 {
177     return &_timezone.value();
178 }
179 
__tzname()180 extern "C" char** __cdecl __tzname()
181 {
182     return _tzname.value();
183 }
184 
__wide_tzname()185 extern "C" wchar_t** __cdecl __wide_tzname()
186 {
187     return w_tzname.value();
188 }
189