/src/FreeRDP/libfreerdp/core/timezone.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /**  | 
2  |  |  * FreeRDP: A Remote Desktop Protocol Implementation  | 
3  |  |  * Time Zone Redirection  | 
4  |  |  *  | 
5  |  |  * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>  | 
6  |  |  *  | 
7  |  |  * Licensed under the Apache License, Version 2.0 (the "License");  | 
8  |  |  * you may not use this file except in compliance with the License.  | 
9  |  |  * You may obtain a copy of the License at  | 
10  |  |  *  | 
11  |  |  *     http://www.apache.org/licenses/LICENSE-2.0  | 
12  |  |  *  | 
13  |  |  * Unless required by applicable law or agreed to in writing, software  | 
14  |  |  * distributed under the License is distributed on an "AS IS" BASIS,  | 
15  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  | 
16  |  |  * See the License for the specific language governing permissions and  | 
17  |  |  * limitations under the License.  | 
18  |  |  */  | 
19  |  |  | 
20  |  | #include <freerdp/config.h>  | 
21  |  |  | 
22  |  | #include <winpr/crt.h>  | 
23  |  | #include <winpr/assert.h>  | 
24  |  | #include <winpr/timezone.h>  | 
25  |  |  | 
26  |  | #include "settings.h"  | 
27  |  | #include "timezone.h"  | 
28  |  |  | 
29  |  | #include <freerdp/log.h>  | 
30  |  | #define TAG FREERDP_TAG("core.timezone") | 
31  |  |  | 
32  |  | #if !defined(WITH_DEBUG_TIMEZONE)  | 
33  |  | #define log_timezone(tzif, result)  | 
34  |  | #else  | 
35  |  | #define log_timezone(tzif, result) log_timezone_((tzif), (result), __FILE__, __func__, __LINE__)  | 
36  |  | static const char* weekday2str(WORD wDayOfWeek)  | 
37  |  | { | 
38  |  |   switch (wDayOfWeek)  | 
39  |  |   { | 
40  |  |     case 0:  | 
41  |  |       return "SUNDAY";  | 
42  |  |     case 1:  | 
43  |  |       return "MONDAY";  | 
44  |  |     case 2:  | 
45  |  |       return "TUESDAY";  | 
46  |  |     case 3:  | 
47  |  |       return "WEDNESDAY";  | 
48  |  |     case 4:  | 
49  |  |       return "THURSDAY";  | 
50  |  |     case 5:  | 
51  |  |       return "FRIDAY";  | 
52  |  |     case 6:  | 
53  |  |       return "SATURDAY";  | 
54  |  |     default:  | 
55  |  |       return "DAY-OF-MAGIC";  | 
56  |  |   }  | 
57  |  | }  | 
58  |  |  | 
59  |  | static char* systemtime2str(const SYSTEMTIME* t, char* buffer, size_t len)  | 
60  |  | { | 
61  |  |   const SYSTEMTIME empty = { 0 }; | 
62  |  |  | 
63  |  |   if (memcmp(t, &empty, sizeof(SYSTEMTIME)) == 0)  | 
64  |  |     _snprintf(buffer, len, "{ not set }"); | 
65  |  |   else  | 
66  |  |   { | 
67  |  |     _snprintf(buffer, len,  | 
68  |  |               "{ %" PRIu16 "-%" PRIu16 "-%" PRIu16 " [%s] %" PRIu16 ":%" PRIu16 ":%" PRIu16 | 
69  |  |               ".%" PRIu16 "}",  | 
70  |  |               t->wYear, t->wMonth, t->wDay, weekday2str(t->wDayOfWeek), t->wHour, t->wMinute,  | 
71  |  |               t->wSecond, t->wMilliseconds);  | 
72  |  |   }  | 
73  |  |   return buffer;  | 
74  |  | }  | 
75  |  |  | 
76  |  | static void log_print(wLog* log, DWORD level, const char* file, const char* fkt, size_t line, ...)  | 
77  |  | { | 
78  |  |   if (!WLog_IsLevelActive(log, level))  | 
79  |  |     return;  | 
80  |  |  | 
81  |  |   va_list ap;  | 
82  |  |   va_start(ap, line);  | 
83  |  |   WLog_PrintMessageVA(log, WLOG_MESSAGE_TEXT, level, line, file, fkt, ap);  | 
84  |  |   va_end(ap);  | 
85  |  | }  | 
86  |  |  | 
87  |  | static void log_timezone_(const TIME_ZONE_INFORMATION* tzif, DWORD result, const char* file,  | 
88  |  |                           const char* fkt, size_t line)  | 
89  |  | { | 
90  |  |   WINPR_ASSERT(tzif);  | 
91  |  |  | 
92  |  |   char buffer[64] = { 0 }; | 
93  |  |   DWORD level = WLOG_TRACE;  | 
94  |  |   wLog* log = WLog_Get(TIMEZONE_TAG);  | 
95  |  |   log_print(log, level, file, fkt, line, "TIME_ZONE_INFORMATION {"); | 
96  |  |   log_print(log, level, file, fkt, line, "  Bias=%" PRIu32, tzif->Bias);  | 
97  |  |   ConvertWCharNToUtf8(tzif->StandardName, ARRAYSIZE(tzif->StandardName), buffer,  | 
98  |  |                       ARRAYSIZE(buffer));  | 
99  |  |   log_print(log, level, file, fkt, line, "  StandardName=%s", buffer);  | 
100  |  |   log_print(log, level, file, fkt, line, "  StandardDate=%s",  | 
101  |  |             systemtime2str(&tzif->StandardDate, buffer, sizeof(buffer)));  | 
102  |  |   log_print(log, level, file, fkt, line, "  StandardBias=%" PRIu32, tzif->StandardBias);  | 
103  |  |  | 
104  |  |   ConvertWCharNToUtf8(tzif->DaylightName, ARRAYSIZE(tzif->DaylightName), buffer,  | 
105  |  |                       ARRAYSIZE(buffer));  | 
106  |  |   log_print(log, level, file, fkt, line, "  DaylightName=%s", buffer);  | 
107  |  |   log_print(log, level, file, fkt, line, "  DaylightDate=%s",  | 
108  |  |             systemtime2str(&tzif->DaylightDate, buffer, sizeof(buffer)));  | 
109  |  |   log_print(log, level, file, fkt, line, "  DaylightBias=%" PRIu32, tzif->DaylightBias);  | 
110  |  |  | 
111  |  |   switch (result)  | 
112  |  |   { | 
113  |  |     case TIME_ZONE_ID_DAYLIGHT:  | 
114  |  |       log_print(log, level, file, fkt, line, "  DaylightDate in use");  | 
115  |  |       break;  | 
116  |  |     case TIME_ZONE_ID_STANDARD:  | 
117  |  |       log_print(log, level, file, fkt, line, "  StandardDate in use");  | 
118  |  |       break;  | 
119  |  |     default:  | 
120  |  |       log_print(log, level, file, fkt, line, "  UnknownDate in use");  | 
121  |  |       break;  | 
122  |  |   }  | 
123  |  |   log_print(log, level, file, fkt, line, "}");  | 
124  |  | }  | 
125  |  | #endif  | 
126  |  |  | 
127  |  | static BOOL rdp_read_system_time(wStream* s, SYSTEMTIME* system_time);  | 
128  |  | static BOOL rdp_write_system_time(wStream* s, const SYSTEMTIME* system_time);  | 
129  |  |  | 
130  |  | /**  | 
131  |  |  * Read SYSTEM_TIME structure (TS_SYSTEMTIME).  | 
132  |  |  * msdn{cc240478} | 
133  |  |  * @param s stream  | 
134  |  |  * @param system_time system time structure  | 
135  |  |  */  | 
136  |  |  | 
137  |  | BOOL rdp_read_system_time(wStream* s, SYSTEMTIME* system_time)  | 
138  | 1.13k  | { | 
139  | 1.13k  |   WINPR_ASSERT(system_time);  | 
140  |  |  | 
141  | 1.13k  |   if (!Stream_CheckAndLogRequiredLength(TAG, s, 16ull))  | 
142  | 0  |     return FALSE;  | 
143  |  |  | 
144  | 1.13k  |   Stream_Read_UINT16(s, system_time->wYear);         /* wYear, must be set to 0 */  | 
145  | 1.13k  |   Stream_Read_UINT16(s, system_time->wMonth);        /* wMonth */  | 
146  | 1.13k  |   Stream_Read_UINT16(s, system_time->wDayOfWeek);    /* wDayOfWeek */  | 
147  | 1.13k  |   Stream_Read_UINT16(s, system_time->wDay);          /* wDay */  | 
148  | 1.13k  |   Stream_Read_UINT16(s, system_time->wHour);         /* wHour */  | 
149  | 1.13k  |   Stream_Read_UINT16(s, system_time->wMinute);       /* wMinute */  | 
150  | 1.13k  |   Stream_Read_UINT16(s, system_time->wSecond);       /* wSecond */  | 
151  | 1.13k  |   Stream_Read_UINT16(s, system_time->wMilliseconds); /* wMilliseconds */  | 
152  | 1.13k  |   return TRUE;  | 
153  | 1.13k  | }  | 
154  |  |  | 
155  |  | /**  | 
156  |  |  * Write SYSTEM_TIME structure (TS_SYSTEMTIME).  | 
157  |  |  * msdn{cc240478} | 
158  |  |  * @param s stream  | 
159  |  |  * @param system_time system time structure  | 
160  |  |  */  | 
161  |  |  | 
162  |  | BOOL rdp_write_system_time(wStream* s, const SYSTEMTIME* system_time)  | 
163  | 0  | { | 
164  | 0  |   WINPR_ASSERT(system_time);  | 
165  | 0  |   if (!Stream_EnsureRemainingCapacity(s, 16ull))  | 
166  | 0  |     return FALSE;  | 
167  |  |  | 
168  | 0  |   Stream_Write_UINT16(s, system_time->wYear);         /* wYear, must be set to 0 */  | 
169  | 0  |   Stream_Write_UINT16(s, system_time->wMonth);        /* wMonth */  | 
170  | 0  |   Stream_Write_UINT16(s, system_time->wDayOfWeek);    /* wDayOfWeek */  | 
171  | 0  |   Stream_Write_UINT16(s, system_time->wDay);          /* wDay */  | 
172  | 0  |   Stream_Write_UINT16(s, system_time->wHour);         /* wHour */  | 
173  | 0  |   Stream_Write_UINT16(s, system_time->wMinute);       /* wMinute */  | 
174  | 0  |   Stream_Write_UINT16(s, system_time->wSecond);       /* wSecond */  | 
175  | 0  |   Stream_Write_UINT16(s, system_time->wMilliseconds); /* wMilliseconds */  | 
176  | 0  |   return TRUE;  | 
177  | 0  | }  | 
178  |  |  | 
179  |  | /**  | 
180  |  |  * Read client time zone information (TS_TIME_ZONE_INFORMATION).  | 
181  |  |  * msdn{cc240477} | 
182  |  |  * @param s stream  | 
183  |  |  * @param settings settings  | 
184  |  |  *  | 
185  |  |  * @return \b TRUE for success, \b FALSE otherwise  | 
186  |  |  */  | 
187  |  |  | 
188  |  | BOOL rdp_read_client_time_zone(wStream* s, rdpSettings* settings)  | 
189  | 595  | { | 
190  | 595  |   LPTIME_ZONE_INFORMATION tz = { 0 }; | 
191  |  |  | 
192  | 595  |   if (!s || !settings)  | 
193  | 0  |     return FALSE;  | 
194  |  |  | 
195  | 595  |   if (!Stream_CheckAndLogRequiredLength(TAG, s, 172))  | 
196  | 27  |     return FALSE;  | 
197  |  |  | 
198  | 568  |   tz = settings->ClientTimeZone;  | 
199  |  |  | 
200  | 568  |   if (!tz)  | 
201  | 0  |     return FALSE;  | 
202  |  |  | 
203  | 568  |   Stream_Read_UINT32(s, tz->Bias); /* Bias */  | 
204  |  |   /* standardName (64 bytes) */  | 
205  | 568  |   Stream_Read(s, tz->StandardName, sizeof(tz->StandardName));  | 
206  | 568  |   if (!rdp_read_system_time(s, &tz->StandardDate)) /* StandardDate */  | 
207  | 0  |     return FALSE;  | 
208  | 568  |   Stream_Read_UINT32(s, tz->StandardBias);    /* StandardBias */  | 
209  |  |   /* daylightName (64 bytes) */  | 
210  | 568  |   Stream_Read(s, tz->DaylightName, sizeof(tz->DaylightName));  | 
211  | 568  |   if (!rdp_read_system_time(s, &tz->DaylightDate)) /* DaylightDate */  | 
212  | 0  |     return FALSE;  | 
213  | 568  |   Stream_Read_UINT32(s, tz->DaylightBias);    /* DaylightBias */  | 
214  | 568  |   log_timezone(tz, 0);  | 
215  | 568  |   return TRUE;  | 
216  | 568  | }  | 
217  |  |  | 
218  |  | /**  | 
219  |  |  * Write client time zone information (TS_TIME_ZONE_INFORMATION).  | 
220  |  |  * msdn{cc240477} | 
221  |  |  * @param s stream  | 
222  |  |  * @param settings settings  | 
223  |  |  *  | 
224  |  |  * @return \b TRUE for success, \b FALSE otherwise  | 
225  |  |  */  | 
226  |  |  | 
227  |  | BOOL rdp_write_client_time_zone(wStream* s, rdpSettings* settings)  | 
228  | 0  | { | 
229  | 0  |   LPTIME_ZONE_INFORMATION tz = { 0 }; | 
230  |  | 
  | 
231  | 0  |   WINPR_ASSERT(settings);  | 
232  | 0  |   tz = settings->ClientTimeZone;  | 
233  |  | 
  | 
234  | 0  |   if (!tz)  | 
235  | 0  |     return FALSE;  | 
236  |  |  | 
237  | 0  |   log_timezone(tz, 0);  | 
238  | 0  |   if (!Stream_EnsureRemainingCapacity(s, 4ull + sizeof(tz->StandardName)))  | 
239  | 0  |     return FALSE;  | 
240  |  |  | 
241  |  |   /* Bias */  | 
242  | 0  |   Stream_Write_UINT32(s, tz->Bias);  | 
243  |  |   /* standardName (64 bytes) */  | 
244  | 0  |   Stream_Write(s, tz->StandardName, sizeof(tz->StandardName));  | 
245  |  |   /* StandardDate */  | 
246  | 0  |   if (!rdp_write_system_time(s, &tz->StandardDate))  | 
247  | 0  |     return FALSE;  | 
248  |  |  | 
249  |  |   /* Note that StandardBias is ignored if no valid standardDate is provided. */  | 
250  |  |   /* StandardBias */  | 
251  | 0  |   if (!Stream_EnsureRemainingCapacity(s, 4ull + sizeof(tz->DaylightName)))  | 
252  | 0  |     return FALSE;  | 
253  | 0  |   Stream_Write_UINT32(s, tz->StandardBias);  | 
254  |  |  | 
255  |  |   /* daylightName (64 bytes) */  | 
256  | 0  |   Stream_Write(s, tz->DaylightName, sizeof(tz->DaylightName));  | 
257  |  |   /* DaylightDate */  | 
258  | 0  |   if (!rdp_write_system_time(s, &tz->DaylightDate))  | 
259  | 0  |     return FALSE;  | 
260  |  |   /* Note that DaylightBias is ignored if no valid daylightDate is provided. */  | 
261  |  |   /* DaylightBias */  | 
262  | 0  |   if (!Stream_EnsureRemainingCapacity(s, 4ull))  | 
263  | 0  |     return FALSE;  | 
264  | 0  |   Stream_Write_UINT32(s, tz->DaylightBias);  | 
265  |  | 
  | 
266  | 0  |   return TRUE;  | 
267  | 0  | }  |