Coverage Report

Created: 2024-09-08 06:20

/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
}