Coverage Report

Created: 2026-01-09 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/libfreerdp/core/settings.c
Line
Count
Source
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * RDP Settings
4
 *
5
 * Copyright 2009-2011 Jay Sorg
6
 * Copyright 2023 Armin Novak <anovak@thincast.com>
7
 * Copyright 2023 Thincast Technologies GmbH
8
 *
9
 * Licensed under the Apache License, Version 2.0 (the "License");
10
 * you may not use this file except in compliance with the License.
11
 * You may obtain a copy of the License at
12
 *
13
 *     http://www.apache.org/licenses/LICENSE-2.0
14
 *
15
 * Unless required by applicable law or agreed to in writing, software
16
 * distributed under the License is distributed on an "AS IS" BASIS,
17
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
 * See the License for the specific language governing permissions and
19
 * limitations under the License.
20
 */
21
22
#include <freerdp/config.h>
23
24
#include "settings.h"
25
26
#include <freerdp/crypto/certificate.h>
27
28
#include <ctype.h>
29
30
#include <winpr/crt.h>
31
#include <winpr/file.h>
32
#include <winpr/path.h>
33
#include <winpr/sysinfo.h>
34
#include <winpr/registry.h>
35
#include <winpr/wtsapi.h>
36
37
#include <freerdp/version.h>
38
#include <freerdp/settings.h>
39
#include <freerdp/utils/helpers.h>
40
#include <freerdp/build-config.h>
41
42
#include "../crypto/certificate.h"
43
#include "../crypto/privatekey.h"
44
#include "capabilities.h"
45
46
0
#define TAG FREERDP_TAG("settings")
47
48
#ifdef _MSC_VER
49
#pragma warning(push)
50
#pragma warning(disable : 4244)
51
#endif
52
53
static const char client_dll[] = "C:\\Windows\\System32\\mstscax.dll";
54
55
17.2k
#define SERVER_KEY "Software\\" FREERDP_VENDOR_STRING "\\" FREERDP_PRODUCT_STRING "\\Server"
56
207k
#define CLIENT_KEY "Software\\" FREERDP_VENDOR_STRING "\\" FREERDP_PRODUCT_STRING "\\Client"
57
51.8k
#define BITMAP_CACHE_KEY CLIENT_KEY "\\BitmapCacheV2"
58
51.8k
#define GLYPH_CACHE_KEY CLIENT_KEY "\\GlyphCache"
59
51.8k
#define POINTER_CACHE_KEY CLIENT_KEY "\\PointerCache"
60
61
struct bounds_t
62
{
63
  INT32 x;
64
  INT32 y;
65
  INT32 width;
66
  INT32 height;
67
};
68
69
static const char* bounds2str(const struct bounds_t* bounds, char* buffer, size_t len)
70
0
{
71
0
  WINPR_ASSERT(bounds);
72
0
  (void)_snprintf(buffer, len, "{%dx%d-%dx%d}", bounds->x, bounds->y, bounds->x + bounds->width,
73
0
                  bounds->y + bounds->height);
74
0
  return buffer;
75
0
}
76
77
static struct bounds_t union_rect(const struct bounds_t* a, const struct bounds_t* b)
78
0
{
79
0
  WINPR_ASSERT(a);
80
0
  WINPR_ASSERT(b);
81
82
0
  struct bounds_t u = *a;
83
0
  if (b->x < u.x)
84
0
    u.x = b->x;
85
0
  if (b->y < u.y)
86
0
    u.y = b->y;
87
88
0
  const INT32 rightA = a->x + a->width;
89
0
  const INT32 rightB = b->x + b->width;
90
0
  const INT32 right = MAX(rightA, rightB);
91
0
  u.width = right - u.x;
92
93
0
  const INT32 bottomA = a->y + a->height;
94
0
  const INT32 bottomB = b->y + b->height;
95
0
  const INT32 bottom = MAX(bottomA, bottomB);
96
0
  u.height = bottom - u.y;
97
98
0
  return u;
99
0
}
100
101
static BOOL intersect_rects(const struct bounds_t* r1, const struct bounds_t* r2)
102
0
{
103
0
  WINPR_ASSERT(r1);
104
0
  WINPR_ASSERT(r2);
105
106
0
  const INT32 left = MAX(r1->x, r2->x);
107
0
  const INT32 top = MAX(r1->y, r2->y);
108
0
  const INT32 right = MIN(r1->x + r1->width, r2->x + r2->width);
109
0
  const INT32 bottom = MIN(r1->y + r1->height, r2->y + r2->height);
110
111
0
  return (left < right) && (top < bottom);
112
0
}
113
114
static BOOL align_rects(const struct bounds_t* r1, const struct bounds_t* r2)
115
0
{
116
0
  WINPR_ASSERT(r1);
117
0
  WINPR_ASSERT(r2);
118
119
0
  const INT32 left = MAX(r1->x, r2->x);
120
0
  const INT32 top = MAX(r1->y, r2->y);
121
0
  const INT32 right = MIN(r1->x + r1->width, r2->x + r2->width);
122
0
  const INT32 bottom = MIN(r1->y + r1->height, r2->y + r2->height);
123
124
0
  return (left == right) || (top == bottom);
125
0
}
126
127
static BOOL settings_reg_query_dword_val(HKEY hKey, const TCHAR* sub, DWORD* value)
128
0
{
129
0
  DWORD dwType = 0;
130
0
  DWORD dwSize = 0;
131
132
0
  dwSize = sizeof(DWORD);
133
0
  if (RegQueryValueEx(hKey, sub, NULL, &dwType, (BYTE*)value, &dwSize) != ERROR_SUCCESS)
134
0
    return FALSE;
135
0
  if (dwType != REG_DWORD)
136
0
    return FALSE;
137
138
0
  return TRUE;
139
0
}
140
141
static BOOL settings_reg_query_word_val(HKEY hKey, const TCHAR* sub, UINT16* value)
142
0
{
143
0
  DWORD dwValue = 0;
144
145
0
  if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
146
0
    return FALSE;
147
148
0
  if (dwValue > UINT16_MAX)
149
0
    return FALSE;
150
151
0
  *value = (UINT16)dwValue;
152
0
  return TRUE;
153
0
}
154
155
static BOOL settings_reg_query_bool_val(HKEY hKey, const TCHAR* sub, BOOL* value)
156
0
{
157
0
  DWORD dwValue = 0;
158
159
0
  if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
160
0
    return FALSE;
161
0
  *value = dwValue != 0;
162
0
  return TRUE;
163
0
}
164
165
static BOOL settings_reg_query_dword(rdpSettings* settings, FreeRDP_Settings_Keys_UInt32 id,
166
                                     HKEY hKey, const TCHAR* sub)
167
0
{
168
0
  DWORD dwValue = 0;
169
170
0
  if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
171
0
    return FALSE;
172
173
0
  return freerdp_settings_set_uint32(settings, id, dwValue);
174
0
}
175
176
static BOOL settings_reg_query_bool(rdpSettings* settings, FreeRDP_Settings_Keys_Bool id, HKEY hKey,
177
                                    const TCHAR* sub)
178
0
{
179
0
  DWORD dwValue = 0;
180
181
0
  if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
182
0
    return FALSE;
183
184
0
  return freerdp_settings_set_bool(settings, id, dwValue != 0 ? TRUE : FALSE);
185
0
}
186
187
static void settings_client_load_hkey_local_machine(rdpSettings* settings)
188
51.8k
{
189
51.8k
  HKEY hKey = NULL;
190
51.8k
  LONG status = 0;
191
51.8k
  status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, CLIENT_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
192
193
51.8k
  if (status == ERROR_SUCCESS)
194
0
  {
195
0
    settings_reg_query_dword(settings, FreeRDP_DesktopWidth, hKey, _T("DesktopWidth"));
196
0
    settings_reg_query_dword(settings, FreeRDP_DesktopHeight, hKey, _T("DesktopHeight"));
197
0
    settings_reg_query_bool(settings, FreeRDP_Fullscreen, hKey, _T("Fullscreen"));
198
0
    settings_reg_query_dword(settings, FreeRDP_ColorDepth, hKey, _T("ColorDepth"));
199
0
    settings_reg_query_dword(settings, FreeRDP_KeyboardType, hKey, _T("KeyboardType"));
200
0
    settings_reg_query_dword(settings, FreeRDP_KeyboardSubType, hKey, _T("KeyboardSubType"));
201
0
    settings_reg_query_dword(settings, FreeRDP_KeyboardFunctionKey, hKey,
202
0
                             _T("KeyboardFunctionKeys"));
203
0
    settings_reg_query_dword(settings, FreeRDP_KeyboardLayout, hKey, _T("KeyboardLayout"));
204
0
    settings_reg_query_bool(settings, FreeRDP_ExtSecurity, hKey, _T("ExtSecurity"));
205
0
    settings_reg_query_bool(settings, FreeRDP_NlaSecurity, hKey, _T("NlaSecurity"));
206
0
    settings_reg_query_bool(settings, FreeRDP_TlsSecurity, hKey, _T("TlsSecurity"));
207
0
    settings_reg_query_bool(settings, FreeRDP_RdpSecurity, hKey, _T("RdpSecurity"));
208
0
    settings_reg_query_bool(settings, FreeRDP_MstscCookieMode, hKey, _T("MstscCookieMode"));
209
0
    settings_reg_query_dword(settings, FreeRDP_CookieMaxLength, hKey, _T("CookieMaxLength"));
210
0
    settings_reg_query_bool(settings, FreeRDP_BitmapCacheEnabled, hKey, _T("BitmapCache"));
211
0
    settings_reg_query_dword(settings, FreeRDP_OffscreenSupportLevel, hKey,
212
0
                             _T("OffscreenBitmapCache"));
213
0
    settings_reg_query_dword(settings, FreeRDP_OffscreenCacheSize, hKey,
214
0
                             _T("OffscreenBitmapCacheSize"));
215
0
    settings_reg_query_dword(settings, FreeRDP_OffscreenCacheEntries, hKey,
216
0
                             _T("OffscreenBitmapCacheEntries"));
217
0
    RegCloseKey(hKey);
218
0
  }
219
220
51.8k
  status =
221
51.8k
      RegOpenKeyExA(HKEY_LOCAL_MACHINE, BITMAP_CACHE_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
222
223
51.8k
  if (status == ERROR_SUCCESS)
224
0
  {
225
0
    settings_reg_query_dword(settings, FreeRDP_BitmapCacheV2NumCells, hKey, _T("NumCells"));
226
0
    for (unsigned x = 0; x < 5; x++)
227
0
    {
228
0
      DWORD val = 0;
229
0
      TCHAR numentries[64] = { 0 };
230
0
      TCHAR persist[64] = { 0 };
231
0
      BITMAP_CACHE_V2_CELL_INFO cache = { 0 };
232
0
      (void)_sntprintf(numentries, ARRAYSIZE(numentries), _T("Cell%uNumEntries"), x);
233
0
      (void)_sntprintf(persist, ARRAYSIZE(persist), _T("Cell%uPersistent"), x);
234
0
      if (!settings_reg_query_dword_val(hKey, numentries, &val) ||
235
0
          !settings_reg_query_bool_val(hKey, persist, &cache.persistent) ||
236
0
          !freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, x,
237
0
                                              &cache))
238
0
        WLog_WARN(TAG, "Failed to load registry keys to settings!");
239
0
      cache.numEntries = val;
240
0
    }
241
242
0
    settings_reg_query_bool(settings, FreeRDP_AllowCacheWaitingList, hKey,
243
0
                            _T("AllowCacheWaitingList"));
244
0
    RegCloseKey(hKey);
245
0
  }
246
247
51.8k
  status =
248
51.8k
      RegOpenKeyExA(HKEY_LOCAL_MACHINE, GLYPH_CACHE_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
249
250
51.8k
  if (status == ERROR_SUCCESS)
251
0
  {
252
0
    unsigned x = 0;
253
0
    UINT32 GlyphSupportLevel = 0;
254
0
    settings_reg_query_dword(settings, FreeRDP_GlyphSupportLevel, hKey, _T("SupportLevel"));
255
0
    for (; x < 10; x++)
256
0
    {
257
0
      GLYPH_CACHE_DEFINITION cache = { 0 };
258
0
      TCHAR numentries[64] = { 0 };
259
0
      TCHAR maxsize[64] = { 0 };
260
0
      (void)_sntprintf(numentries, ARRAYSIZE(numentries), _T("Cache%uNumEntries"), x);
261
0
      (void)_sntprintf(maxsize, ARRAYSIZE(maxsize), _T("Cache%uMaxCellSize"), x);
262
263
0
      settings_reg_query_word_val(hKey, numentries, &cache.cacheEntries);
264
0
      settings_reg_query_word_val(hKey, maxsize, &cache.cacheMaximumCellSize);
265
0
      if (!freerdp_settings_set_pointer_array(settings, FreeRDP_GlyphCache, x, &cache))
266
0
        WLog_WARN(TAG, "Failed to store GlyphCache %" PRIuz, x);
267
0
    }
268
0
    {
269
0
      GLYPH_CACHE_DEFINITION cache = { 0 };
270
0
      settings_reg_query_word_val(hKey, _T("FragCacheNumEntries"), &cache.cacheEntries);
271
0
      settings_reg_query_word_val(hKey, _T("FragCacheMaxCellSize"),
272
0
                                  &cache.cacheMaximumCellSize);
273
0
      if (!freerdp_settings_set_pointer_array(settings, FreeRDP_FragCache, x, &cache))
274
0
        WLog_WARN(TAG, "Failed to store FragCache");
275
0
    }
276
277
0
    RegCloseKey(hKey);
278
279
0
    if (!freerdp_settings_set_uint32(settings, FreeRDP_GlyphSupportLevel, GlyphSupportLevel))
280
0
      WLog_WARN(TAG, "Failed to load registry keys to settings!");
281
0
  }
282
283
51.8k
  status =
284
51.8k
      RegOpenKeyExA(HKEY_LOCAL_MACHINE, POINTER_CACHE_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
285
286
51.8k
  if (status == ERROR_SUCCESS)
287
0
  {
288
0
    settings_reg_query_dword(settings, FreeRDP_LargePointerFlag, hKey, _T("LargePointer"));
289
0
    settings_reg_query_dword(settings, FreeRDP_PointerCacheSize, hKey, _T("PointerCacheSize"));
290
0
    settings_reg_query_dword(settings, FreeRDP_ColorPointerCacheSize, hKey,
291
0
                             _T("ColorPointerCacheSize"));
292
0
    RegCloseKey(hKey);
293
0
  }
294
51.8k
}
295
296
static void settings_server_load_hkey_local_machine(rdpSettings* settings)
297
17.2k
{
298
17.2k
  HKEY hKey = NULL;
299
17.2k
  LONG status = 0;
300
301
17.2k
  status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, SERVER_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
302
303
17.2k
  if (status != ERROR_SUCCESS)
304
17.2k
    return;
305
306
0
  settings_reg_query_bool(settings, FreeRDP_ExtSecurity, hKey, _T("ExtSecurity"));
307
0
  settings_reg_query_bool(settings, FreeRDP_NlaSecurity, hKey, _T("NlaSecurity"));
308
0
  settings_reg_query_bool(settings, FreeRDP_TlsSecurity, hKey, _T("TlsSecurity"));
309
0
  settings_reg_query_dword(settings, FreeRDP_TlsSecLevel, hKey, _T("TlsSecLevel"));
310
0
  settings_reg_query_bool(settings, FreeRDP_RdpSecurity, hKey, _T("RdpSecurity"));
311
312
0
  RegCloseKey(hKey);
313
0
}
314
315
static void settings_load_hkey_local_machine(rdpSettings* settings)
316
69.1k
{
317
69.1k
  if (freerdp_settings_get_bool(settings, FreeRDP_ServerMode))
318
17.2k
    settings_server_load_hkey_local_machine(settings);
319
51.8k
  else
320
51.8k
    settings_client_load_hkey_local_machine(settings);
321
69.1k
}
322
323
static BOOL settings_init_computer_name(rdpSettings* settings)
324
69.1k
{
325
69.1k
  CHAR computerName[MAX_COMPUTERNAME_LENGTH + 1] = { 0 };
326
69.1k
  DWORD nSize = ARRAYSIZE(computerName);
327
328
69.1k
  if (!GetComputerNameExA(ComputerNameNetBIOS, computerName, &nSize))
329
0
    return FALSE;
330
331
69.1k
  if (!freerdp_settings_set_string(settings, FreeRDP_ComputerName, computerName))
332
0
    return FALSE;
333
69.1k
  return freerdp_settings_set_string(settings, FreeRDP_ClientHostname, computerName);
334
69.1k
}
335
336
void freerdp_settings_print_warnings(const rdpSettings* settings)
337
0
{
338
0
  const UINT32 level = freerdp_settings_get_uint32(settings, FreeRDP_GlyphSupportLevel);
339
0
  if (level != GLYPH_SUPPORT_NONE)
340
0
  {
341
0
    char buffer[32] = { 0 };
342
0
    WLog_WARN(TAG, "[experimental] enabled GlyphSupportLevel %s, expect visual artefacts!",
343
0
              freerdp_settings_glyph_level_string(level, buffer, sizeof(buffer)));
344
0
  }
345
0
}
346
347
static BOOL monitor_operlaps(const rdpSettings* settings, UINT32 orig, UINT32 start, UINT32 count,
348
                             const rdpMonitor* compare)
349
0
{
350
0
  const struct bounds_t rect1 = {
351
0
    .x = compare->x, .y = compare->y, .width = compare->width, .height = compare->height
352
0
  };
353
0
  for (UINT32 x = start; x < count; x++)
354
0
  {
355
0
    const rdpMonitor* monitor =
356
0
        freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
357
0
    const struct bounds_t rect2 = {
358
0
      .x = monitor->x, .y = monitor->y, .width = monitor->width, .height = monitor->height
359
0
    };
360
361
0
    if (intersect_rects(&rect1, &rect2))
362
0
    {
363
0
      char buffer1[32] = { 0 };
364
0
      char buffer2[32] = { 0 };
365
366
0
      WLog_ERR(TAG, "Monitor %" PRIu32 " and %" PRIu32 " are overlapping:", orig, x);
367
0
      WLog_ERR(TAG, "%s overlapps with %s", bounds2str(&rect1, buffer1, sizeof(buffer1)),
368
0
               bounds2str(&rect2, buffer2, sizeof(buffer2)));
369
0
      WLog_ERR(
370
0
          TAG,
371
0
          "Mulitimonitor mode requested, but local layout has gaps or overlapping areas!");
372
0
      WLog_ERR(TAG,
373
0
               "Please reconfigure your local monitor setup so that there are no gaps or "
374
0
               "overlapping areas!");
375
0
      return TRUE;
376
0
    }
377
0
  }
378
0
  return FALSE;
379
0
}
380
381
static BOOL monitor_has_gaps(const rdpSettings* settings, UINT32 start, UINT32 count,
382
                             const rdpMonitor* compare, UINT32** graph)
383
0
{
384
0
  const struct bounds_t rect1 = {
385
0
    .x = compare->x, .y = compare->y, .width = compare->width, .height = compare->height
386
0
  };
387
388
0
  BOOL hasNeighbor = FALSE;
389
0
  for (UINT32 i = 0; i < count; i++)
390
0
  {
391
0
    if (i == start)
392
0
      continue;
393
394
0
    const rdpMonitor* monitor =
395
0
        freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, i);
396
397
0
    const struct bounds_t rect2 = {
398
0
      .x = monitor->x, .y = monitor->y, .width = monitor->width, .height = monitor->height
399
0
    };
400
0
    if (align_rects(&rect1, &rect2))
401
0
    {
402
0
      hasNeighbor = TRUE;
403
0
      graph[start][i] = 1;
404
0
      graph[i][start] = 1;
405
0
    }
406
0
  }
407
408
0
  if (!hasNeighbor)
409
0
  {
410
0
    WLog_ERR(TAG,
411
0
             "Monitor configuration has gaps! Monitor %" PRIu32 " does not have any neighbor",
412
0
             start);
413
0
  }
414
415
0
  return !hasNeighbor;
416
0
}
417
418
static void alloc_free(UINT32** ptr)
419
0
{
420
0
  free((void*)ptr);
421
0
}
422
423
WINPR_ATTR_MALLOC(alloc_free, 1)
424
static UINT32** alloc_array(size_t count)
425
0
{
426
  // NOLINTNEXTLINE(clang-analyzer-unix.MallocSizeof)
427
0
  BYTE* array = calloc(count * sizeof(uintptr_t), count * sizeof(UINT32));
428
0
  UINT32** dst = (UINT32**)array;
429
0
  UINT32* val = (UINT32*)(array + count * sizeof(uintptr_t));
430
0
  for (size_t x = 0; x < count; x++)
431
0
    dst[x] = &val[x];
432
433
0
  return dst;
434
0
}
435
436
/* Monitors in the array need to:
437
 *
438
 * 1. be connected to another monitor (edges touch but don't overlap or have gaps)
439
 * 2. all monitors need to be connected so there are no separate groups.
440
 *
441
 * So, what we do here is we use dijkstra algorithm to find a path from any start node
442
 * (lazy as we are we always use the first in the array) to each other node.
443
 */
444
static BOOL find_path_exists_with_dijkstra(UINT32** graph, size_t count, UINT32 start)
445
0
{
446
0
  if (count < 1)
447
0
    return FALSE;
448
449
0
  WINPR_ASSERT(start < count);
450
451
0
  UINT32** cost = alloc_array(count);
452
0
  WINPR_ASSERT(cost);
453
454
0
  UINT32* distance = calloc(count, sizeof(UINT32));
455
0
  WINPR_ASSERT(distance);
456
457
0
  UINT32* visited = calloc(count, sizeof(UINT32));
458
0
  WINPR_ASSERT(visited);
459
460
0
  UINT32* parent = calloc(count, sizeof(UINT32));
461
0
  WINPR_ASSERT(parent);
462
463
0
  for (size_t x = 0; x < count; x++)
464
0
  {
465
0
    for (size_t y = 0; y < count; y++)
466
0
    {
467
0
      if (graph[x][y] == 0)
468
0
        cost[x][y] = UINT32_MAX;
469
0
      else
470
0
        cost[x][y] = graph[x][y];
471
0
    }
472
0
  }
473
474
0
  for (UINT32 x = 0; x < count; x++)
475
0
  {
476
0
    distance[x] = cost[start][x];
477
0
    parent[x] = start;
478
0
    visited[x] = 0;
479
0
  }
480
481
0
  distance[start] = 0;
482
0
  visited[start] = 1;
483
484
0
  size_t pos = 1;
485
0
  UINT32 nextnode = UINT32_MAX;
486
0
  while (pos < count - 1)
487
0
  {
488
0
    UINT32 mindistance = UINT32_MAX;
489
490
0
    for (UINT32 x = 0; x < count; x++)
491
0
    {
492
0
      if ((distance[x] < mindistance) && !visited[x])
493
0
      {
494
0
        mindistance = distance[x];
495
0
        nextnode = x;
496
0
      }
497
0
    }
498
499
0
    visited[nextnode] = 1;
500
501
0
    for (size_t y = 0; y < count; y++)
502
0
    {
503
0
      if (!visited[y])
504
0
      {
505
0
        UINT32 dist = mindistance + cost[nextnode][y];
506
0
        if (dist < distance[y])
507
0
        {
508
0
          distance[y] = dist;
509
0
          parent[y] = nextnode;
510
0
        }
511
0
      }
512
0
    }
513
0
    pos++;
514
0
  }
515
516
0
  BOOL rc = TRUE;
517
0
  for (size_t x = 0; x < count; x++)
518
0
  {
519
0
    if (x != start)
520
0
    {
521
0
      if (distance[x] == UINT32_MAX)
522
0
      {
523
0
        WLog_ERR(TAG, "monitor %" PRIu32 " not connected with monitor %" PRIuz, start, x);
524
0
        rc = FALSE;
525
0
        break;
526
0
      }
527
0
    }
528
0
  }
529
0
  alloc_free(cost);
530
0
  free(distance);
531
0
  free(visited);
532
0
  free(parent);
533
534
0
  return rc;
535
0
}
536
537
static BOOL freerdp_settings_client_monitors_have_gaps(const rdpSettings* settings)
538
0
{
539
0
  BOOL rc = TRUE;
540
0
  const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount);
541
0
  if (count <= 1)
542
0
    return FALSE;
543
544
0
  UINT32** graph = alloc_array(count);
545
0
  WINPR_ASSERT(graph);
546
547
0
  for (UINT32 x = 0; x < count; x++)
548
0
  {
549
0
    const rdpMonitor* monitor =
550
0
        freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
551
0
    if (monitor_has_gaps(settings, x, count, monitor, graph))
552
0
      goto fail;
553
0
  }
554
555
0
  rc = !find_path_exists_with_dijkstra(graph, count, 0);
556
557
0
fail:
558
0
  alloc_free(graph);
559
560
0
  return rc;
561
0
}
562
563
static void log_monitor(UINT32 idx, const rdpMonitor* monitor, wLog* log, DWORD level)
564
0
{
565
0
  WINPR_ASSERT(monitor);
566
567
0
  WLog_Print(log, level,
568
0
             "[%" PRIu32 "] [%s] {%dx%d-%dx%d} [%" PRIu32 "] {%" PRIu32 "x%" PRIu32
569
0
             ", orientation: %" PRIu32 ", desktopScale: %" PRIu32 ", deviceScale: %" PRIu32 "}",
570
0
             idx, monitor->is_primary ? "primary" : "       ", monitor->x, monitor->y,
571
0
             monitor->width, monitor->height, monitor->orig_screen,
572
0
             monitor->attributes.physicalWidth, monitor->attributes.physicalHeight,
573
0
             monitor->attributes.orientation, monitor->attributes.desktopScaleFactor,
574
0
             monitor->attributes.deviceScaleFactor);
575
0
}
576
577
static void log_monitor_configuration(const rdpSettings* settings, wLog* log, DWORD level)
578
0
{
579
0
  const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount);
580
0
  WLog_Print(log, level, "[BEGIN] MonitorDefArray[%" PRIu32 "]", count);
581
0
  for (UINT32 x = 0; x < count; x++)
582
0
  {
583
0
    const rdpMonitor* monitor =
584
0
        freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
585
0
    log_monitor(x, monitor, log, level);
586
0
  }
587
0
  WLog_Print(log, level, "[END] MonitorDefArray[%" PRIu32 "]", count);
588
0
}
589
590
static BOOL freerdp_settings_client_monitors_overlap(const rdpSettings* settings)
591
0
{
592
0
  const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount);
593
0
  for (UINT32 x = 0; x < count; x++)
594
0
  {
595
0
    const rdpMonitor* monitor =
596
0
        freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
597
0
    if (monitor_operlaps(settings, x, x + 1, count, monitor))
598
0
      return TRUE;
599
0
  }
600
0
  return FALSE;
601
0
}
602
603
/* See [MS-RDPBCGR] 2.2.1.3.6.1 for details on limits
604
 * https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/c3964b39-3d54-4ae1-a84a-ceaed311e0f6
605
 */
606
static BOOL freerdp_settings_client_monitors_check_primary_and_origin(const rdpSettings* settings)
607
0
{
608
0
  const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount);
609
0
  BOOL havePrimary = FALSE;
610
0
  BOOL foundOrigin = FALSE;
611
0
  BOOL primaryIsOrigin = FALSE;
612
0
  BOOL rc = TRUE;
613
614
0
  struct bounds_t bounds = { 0 };
615
616
0
  if (count == 0)
617
0
  {
618
0
    WLog_WARN(TAG, "Monitor configuration empty.");
619
0
    return TRUE;
620
0
  }
621
622
0
  for (UINT32 x = 0; x < count; x++)
623
0
  {
624
0
    const rdpMonitor* monitor =
625
0
        freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
626
0
    struct bounds_t cur = {
627
0
      .x = monitor->x, .y = monitor->y, .width = monitor->width, .height = monitor->height
628
0
    };
629
630
0
    bounds = union_rect(&bounds, &cur);
631
632
0
    if (monitor->is_primary)
633
0
    {
634
0
      if (havePrimary)
635
0
      {
636
0
        WLog_ERR(TAG, "Monitor configuration contains multiple primary monitors!");
637
0
        rc = FALSE;
638
0
      }
639
0
      havePrimary = TRUE;
640
0
    }
641
642
0
    if ((monitor->x == 0) && (monitor->y == 0))
643
0
    {
644
0
      if (foundOrigin)
645
0
      {
646
0
        WLog_ERR(TAG, "Monitor configuration does have multiple origin 0/0");
647
0
        rc = FALSE;
648
0
      }
649
0
      foundOrigin = TRUE;
650
0
      primaryIsOrigin = monitor->is_primary != 0;
651
0
    }
652
0
  }
653
654
0
  if ((bounds.width > 32766) || (bounds.width < 200))
655
0
  {
656
0
    WLog_ERR(TAG,
657
0
             "Monitor configuration virtual desktop width must be 200 <= %" PRId32 " <= 32766",
658
0
             bounds.width);
659
0
    rc = FALSE;
660
0
  }
661
0
  if ((bounds.height > 32766) || (bounds.height < 200))
662
0
  {
663
0
    WLog_ERR(TAG,
664
0
             "Monitor configuration virtual desktop height must be 200 <= %" PRId32 " <= 32766",
665
0
             bounds.height);
666
0
    rc = FALSE;
667
0
  }
668
669
0
  if (!havePrimary)
670
0
  {
671
0
    WLog_ERR(TAG, "Monitor configuration does not contain a primary monitor!");
672
0
    rc = FALSE;
673
0
  }
674
0
  if (!foundOrigin)
675
0
  {
676
0
    WLog_ERR(TAG, "Monitor configuration must start at 0/0 for first monitor!");
677
0
    rc = FALSE;
678
0
  }
679
0
  if (!primaryIsOrigin)
680
0
  {
681
0
    WLog_ERR(TAG, "Monitor configuration must start at 0/0 for primary monitor!");
682
0
    rc = FALSE;
683
0
  }
684
685
0
  return rc;
686
0
}
687
688
BOOL freerdp_settings_check_client_after_preconnect(const rdpSettings* settings)
689
0
{
690
0
  wLog* log = WLog_Get(TAG);
691
0
  BOOL rc = TRUE;
692
0
  log_monitor_configuration(settings, log, WLOG_DEBUG);
693
0
  if (freerdp_settings_client_monitors_overlap(settings))
694
0
    rc = FALSE;
695
0
  if (freerdp_settings_client_monitors_have_gaps(settings))
696
0
    rc = FALSE;
697
0
  if (!freerdp_settings_client_monitors_check_primary_and_origin(settings))
698
0
    rc = FALSE;
699
0
  if (!rc)
700
0
  {
701
0
    DWORD level = WLOG_ERROR;
702
0
    WLog_Print(log, level, "Invalid or unsupported monitor configuration detected");
703
0
    WLog_Print(log, level, "Check if the configuration is valid.");
704
0
    WLog_Print(log, level,
705
0
               "If you suspect a bug create a new issue at "
706
0
               "https://github.com/FreeRDP/FreeRDP/issues/new");
707
0
    WLog_Print(
708
0
        log, level,
709
0
        "Provide at least the following log lines detailing your monitor configuration:");
710
0
    log_monitor_configuration(settings, log, level);
711
0
  }
712
713
0
  return rc;
714
0
}
715
716
BOOL freerdp_settings_set_default_order_support(rdpSettings* settings)
717
69.1k
{
718
69.1k
  BYTE* OrderSupport = freerdp_settings_get_pointer_writable(settings, FreeRDP_OrderSupport);
719
69.1k
  if (!OrderSupport)
720
0
    return FALSE;
721
722
69.1k
  ZeroMemory(OrderSupport, 32);
723
69.1k
  OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
724
69.1k
  OrderSupport[NEG_PATBLT_INDEX] = TRUE;
725
69.1k
  OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
726
69.1k
  OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
727
69.1k
  OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE;
728
69.1k
  OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
729
69.1k
  OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
730
69.1k
  OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
731
69.1k
  OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
732
69.1k
  OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
733
69.1k
  OrderSupport[NEG_LINETO_INDEX] = TRUE;
734
69.1k
  OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
735
69.1k
  OrderSupport[NEG_MEMBLT_INDEX] =
736
69.1k
      freerdp_settings_get_bool(settings, FreeRDP_BitmapCacheEnabled) ? 1 : 0;
737
69.1k
  OrderSupport[NEG_MEM3BLT_INDEX] =
738
69.1k
      freerdp_settings_get_bool(settings, FreeRDP_BitmapCacheEnabled) ? 1 : 0;
739
69.1k
  OrderSupport[NEG_MEMBLT_V2_INDEX] =
740
69.1k
      freerdp_settings_get_bool(settings, FreeRDP_BitmapCacheEnabled) ? 1 : 0;
741
69.1k
  OrderSupport[NEG_MEM3BLT_V2_INDEX] =
742
69.1k
      freerdp_settings_get_bool(settings, FreeRDP_BitmapCacheEnabled) ? 1 : 0;
743
69.1k
  OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
744
69.1k
  OrderSupport[NEG_GLYPH_INDEX_INDEX] =
745
69.1k
      freerdp_settings_get_uint32(settings, FreeRDP_GlyphSupportLevel) != GLYPH_SUPPORT_NONE;
746
69.1k
  OrderSupport[NEG_FAST_INDEX_INDEX] =
747
69.1k
      freerdp_settings_get_uint32(settings, FreeRDP_GlyphSupportLevel) != GLYPH_SUPPORT_NONE;
748
69.1k
  OrderSupport[NEG_FAST_GLYPH_INDEX] =
749
69.1k
      freerdp_settings_get_uint32(settings, FreeRDP_GlyphSupportLevel) != GLYPH_SUPPORT_NONE;
750
69.1k
  OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE;
751
69.1k
  OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE;
752
69.1k
  OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
753
69.1k
  OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
754
69.1k
  return TRUE;
755
69.1k
}
756
757
char* freerdp_settings_get_config_path(void)
758
51.8k
{
759
51.8k
  return freerdp_GetConfigFilePath(FALSE, "");
760
51.8k
}
761
762
rdpSettings* freerdp_settings_new(DWORD flags)
763
69.1k
{
764
69.1k
  char* issuers[] = { "FreeRDP", "FreeRDP-licenser" };
765
69.1k
  const BOOL server = (flags & FREERDP_SETTINGS_SERVER_MODE) != 0 ? TRUE : FALSE;
766
69.1k
  const BOOL remote = (flags & FREERDP_SETTINGS_REMOTE_MODE) != 0 ? TRUE : FALSE;
767
69.1k
  rdpSettings* settings = (rdpSettings*)calloc(1, sizeof(rdpSettings));
768
769
69.1k
  if (!settings)
770
0
    return NULL;
771
772
69.1k
  if (!server && !remote)
773
43.6k
  {
774
43.6k
    if (!freerdp_settings_set_string(settings, FreeRDP_GatewayHttpUserAgent,
775
43.6k
                                     FREERDP_USER_AGENT))
776
0
      goto out_fail;
777
43.6k
    if (!freerdp_settings_set_string(settings, FreeRDP_GatewayHttpMsUserAgent,
778
43.6k
                                     FREERDP_USER_AGENT))
779
0
      goto out_fail;
780
781
43.6k
    if (!freerdp_settings_set_string(settings, FreeRDP_GatewayHttpReferer, ""))
782
0
      goto out_fail;
783
43.6k
    if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdAccessTokenFormat,
784
43.6k
                                     "ms-appx-web%%3a%%2f%%2fMicrosoft.AAD.BrokerPlugin%%2f%s"))
785
0
      goto out_fail;
786
43.6k
    if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdAccessAadFormat,
787
43.6k
                                     "https%%3A%%2F%%2F%s%%2F%s%%2Foauth2%%2Fnativeclient"))
788
0
      goto out_fail;
789
43.6k
    if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdScope,
790
43.6k
                                     "https%3A%2F%2Fwww.wvd.microsoft.com%2F.default%20openid%"
791
43.6k
                                     "20profile%20offline_access"))
792
793
0
      goto out_fail;
794
43.6k
    if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdClientID,
795
43.6k
                                     "a85cf173-4192-42f8-81fa-777a763e6e2c"))
796
0
      goto out_fail;
797
43.6k
    if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAzureActiveDirectory,
798
43.6k
                                     "login.microsoftonline.com"))
799
0
      goto out_fail;
800
43.6k
    if (!freerdp_settings_set_string(settings, FreeRDP_GatewayAvdAadtenantid, "common"))
801
0
      goto out_fail;
802
43.6k
    if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayAvdUseTenantid, FALSE))
803
0
      goto out_fail;
804
43.6k
    if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopPhysicalWidth, 1000))
805
0
      goto out_fail;
806
43.6k
    if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopPhysicalHeight, 1000))
807
0
      goto out_fail;
808
43.6k
    if (!freerdp_settings_set_uint16(settings, FreeRDP_DesktopOrientation,
809
43.6k
                                     ORIENTATION_LANDSCAPE))
810
0
      goto out_fail;
811
43.6k
    if (!freerdp_settings_set_uint32(settings, FreeRDP_DeviceScaleFactor, 100))
812
0
      goto out_fail;
813
43.6k
    if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopScaleFactor, 100))
814
0
      goto out_fail;
815
43.6k
  }
816
69.1k
  if (!freerdp_settings_set_uint32(settings, FreeRDP_SurfaceCommandsSupported,
817
69.1k
                                   SURFCMDS_SET_SURFACE_BITS | SURFCMDS_STREAM_SURFACE_BITS |
818
69.1k
                                       SURFCMDS_FRAME_MARKER))
819
0
    goto out_fail;
820
821
69.1k
  if (!freerdp_settings_set_uint32(settings, FreeRDP_RemoteFxRlgrMode, RLGR3))
822
0
    goto out_fail;
823
824
69.1k
  if (!freerdp_settings_set_uint16(settings, FreeRDP_CapsProtocolVersion,
825
69.1k
                                   TS_CAPS_PROTOCOLVERSION))
826
0
    goto out_fail;
827
828
69.1k
  if (!freerdp_settings_set_uint32(settings, FreeRDP_ClipboardFeatureMask,
829
69.1k
                                   CLIPRDR_FLAG_DEFAULT_MASK))
830
0
    goto out_fail;
831
69.1k
  if (!freerdp_settings_set_string(settings, FreeRDP_ServerLicenseCompanyName, "FreeRDP"))
832
0
    goto out_fail;
833
69.1k
  if (!freerdp_settings_set_string(settings, FreeRDP_ServerLicenseProductName,
834
69.1k
                                   "FreeRDP-licensing-server"))
835
0
    goto out_fail;
836
69.1k
  if (!freerdp_settings_set_uint32(settings, FreeRDP_ServerLicenseProductVersion, 1))
837
0
    goto out_fail;
838
69.1k
  if (!freerdp_server_license_issuers_copy(settings, issuers, ARRAYSIZE(issuers)))
839
0
    goto out_fail;
840
841
69.1k
  if (!freerdp_settings_set_uint16(settings, FreeRDP_SupportedColorDepths,
842
69.1k
                                   RNS_UD_32BPP_SUPPORT | RNS_UD_24BPP_SUPPORT |
843
69.1k
                                       RNS_UD_16BPP_SUPPORT | RNS_UD_15BPP_SUPPORT))
844
0
    goto out_fail;
845
846
69.1k
  if (!freerdp_settings_set_bool(settings, FreeRDP_UnicodeInput, TRUE) ||
847
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_HasHorizontalWheel, TRUE) ||
848
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_HasExtendedMouseEvent, TRUE) ||
849
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_HasQoeEvent, TRUE) ||
850
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_HasRelativeMouseEvent, TRUE) ||
851
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_HiDefRemoteApp, TRUE) ||
852
69.1k
      !freerdp_settings_set_uint32(
853
69.1k
          settings, FreeRDP_RemoteApplicationSupportMask,
854
69.1k
          RAIL_LEVEL_SUPPORTED | RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED |
855
69.1k
              RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED | RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED |
856
69.1k
              RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED |
857
69.1k
              RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED | RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED |
858
69.1k
              RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED) ||
859
69.1k
      !freerdp_settings_set_uint16(settings, FreeRDP_TextANSICodePage, CP_UTF8) ||
860
69.1k
      !freerdp_settings_set_uint16(settings, FreeRDP_OrderSupportFlags,
861
69.1k
                                   NEGOTIATE_ORDER_SUPPORT | ZERO_BOUNDS_DELTA_SUPPORT |
862
69.1k
                                       COLOR_INDEX_SUPPORT) ||
863
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_SupportHeartbeatPdu, TRUE) ||
864
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_ServerMode, server) ||
865
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_WaitForOutputBufferFlush, TRUE) ||
866
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_ClusterInfoFlags, REDIRECTION_SUPPORTED) ||
867
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, 1024) ||
868
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, 768) ||
869
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_Workarea, FALSE) ||
870
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_Fullscreen, FALSE) ||
871
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_GrabKeyboard, TRUE) ||
872
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_Decorations, TRUE) ||
873
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_RdpVersion, RDP_VERSION_10_12) ||
874
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth, 32) ||
875
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_AadSecurity, FALSE) ||
876
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_ExtSecurity, FALSE) ||
877
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, TRUE) ||
878
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, TRUE) ||
879
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, TRUE) ||
880
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_RdstlsSecurity, FALSE) ||
881
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_NegotiateSecurityLayer, TRUE) ||
882
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_RestrictedAdminModeRequired, FALSE) ||
883
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_RestrictedAdminModeSupported, TRUE) ||
884
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_MstscCookieMode, FALSE) ||
885
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_CookieMaxLength,
886
69.1k
                                   DEFAULT_COOKIE_MAX_LENGTH) ||
887
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_ClientBuild,
888
69.1k
                                   18363) || /* Windows 10, Version 1909 */
889
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_KeyboardType, 4) ||
890
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_KeyboardSubType, 0) ||
891
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_KeyboardFunctionKey, 12) ||
892
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_KeyboardLayout, 0) ||
893
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_KeyboardHook,
894
69.1k
                                   KEYBOARD_HOOK_FULLSCREEN_ONLY) ||
895
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, FALSE) ||
896
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_SaltedChecksum, TRUE) ||
897
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_ServerPort, 3389) ||
898
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_GatewayPort, 443) ||
899
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_DesktopResize, TRUE) ||
900
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_ToggleFullscreen, TRUE) ||
901
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_DesktopPosX, UINT32_MAX) ||
902
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_DesktopPosY, UINT32_MAX) ||
903
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_SoftwareGdi, TRUE) ||
904
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_UnmapButtons, FALSE) ||
905
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_PerformanceFlags, PERF_FLAG_NONE) ||
906
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_AllowFontSmoothing, TRUE) ||
907
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_AllowDesktopComposition, FALSE) ||
908
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_DisableWallpaper, FALSE) ||
909
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_DisableFullWindowDrag, TRUE) ||
910
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_DisableMenuAnims, TRUE) ||
911
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_DisableThemes, FALSE) ||
912
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_ConnectionType,
913
69.1k
                                   CONNECTION_TYPE_AUTODETECT) ||
914
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_NetworkAutoDetect, TRUE) ||
915
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_EncryptionMethods, ENCRYPTION_METHOD_NONE) ||
916
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel, ENCRYPTION_LEVEL_NONE) ||
917
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_FIPSMode, FALSE) ||
918
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_CompressionEnabled, TRUE) ||
919
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_LogonNotify, TRUE) ||
920
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_BrushSupportLevel, BRUSH_COLOR_FULL) ||
921
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_CompressionLevel, PACKET_COMPR_TYPE_RDP61) ||
922
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_Authentication, TRUE) ||
923
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_AuthenticationOnly, FALSE) ||
924
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_CredentialsFromStdin, FALSE) ||
925
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_DisableCredentialsDelegation, FALSE) ||
926
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_AuthenticationLevel, 2) ||
927
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_ChannelCount, 0) ||
928
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_CertificateCallbackPreferPEM, FALSE) ||
929
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_KeySpec, AT_KEYEXCHANGE))
930
0
    goto out_fail;
931
932
69.1k
  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ChannelDefArray, NULL,
933
69.1k
                                        CHANNEL_MAX_COUNT))
934
0
    goto out_fail;
935
936
69.1k
  if (!freerdp_settings_set_bool(settings, FreeRDP_SupportMonitorLayoutPdu, FALSE))
937
0
    goto out_fail;
938
939
69.1k
  if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, 0))
940
0
    goto out_fail;
941
942
69.1k
  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorDefArray, NULL, 32))
943
0
    goto out_fail;
944
945
69.1k
  if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftX, 0))
946
0
    goto out_fail;
947
948
69.1k
  if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftY, 0))
949
0
    goto out_fail;
950
951
69.1k
  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorIds, NULL, 0))
952
0
    goto out_fail;
953
954
69.1k
  if (!freerdp_settings_set_uint32(settings, FreeRDP_MultitransportFlags,
955
69.1k
                                   TRANSPORT_TYPE_UDP_FECR))
956
0
    goto out_fail;
957
69.1k
  if (!freerdp_settings_set_bool(settings, FreeRDP_SupportMultitransport, TRUE))
958
0
    goto out_fail;
959
960
69.1k
  if (!settings_init_computer_name(settings))
961
0
    goto out_fail;
962
963
69.1k
  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_RdpServerCertificate, NULL, 1))
964
0
    goto out_fail;
965
966
69.1k
  if (!freerdp_capability_buffer_resize(settings, 32, FALSE))
967
0
    goto out_fail;
968
969
69.1k
  {
970
69.1k
    char tmp[32] = { 0 };
971
69.1k
    if (!freerdp_settings_set_string_len(settings, FreeRDP_ClientProductId, tmp, sizeof(tmp)))
972
0
      goto out_fail;
973
69.1k
  }
974
975
  /* [MS-RDPBCGR] 2.2.7.1.5 Pointer Capability Set (TS_POINTER_CAPABILITYSET)
976
   *
977
   * if we are in server mode send a reasonable large cache size,
978
   * if we are in client mode just set the value to the maximum we want to
979
   * support and during capability exchange that size will be limited to the
980
   * sizes the server supports
981
   *
982
   * We have chosen 128 cursors in cache which is at worst 128 * 576kB (384x384 pixel cursor with
983
   * 32bit color depth)
984
   * */
985
69.1k
  if (freerdp_settings_get_bool(settings, FreeRDP_ServerMode))
986
17.2k
  {
987
17.2k
    if (!freerdp_settings_set_uint32(settings, FreeRDP_PointerCacheSize, 25) ||
988
17.2k
        !freerdp_settings_set_uint32(settings, FreeRDP_ColorPointerCacheSize, 25))
989
0
      goto out_fail;
990
17.2k
  }
991
51.8k
  else
992
51.8k
  {
993
51.8k
    if (!freerdp_settings_set_uint32(settings, FreeRDP_PointerCacheSize, 128) ||
994
51.8k
        !freerdp_settings_set_uint32(settings, FreeRDP_ColorPointerCacheSize, 128))
995
0
      goto out_fail;
996
51.8k
  }
997
998
69.1k
  if (!freerdp_settings_set_uint32(settings, FreeRDP_LargePointerFlag,
999
69.1k
                                   (LARGE_POINTER_FLAG_96x96 | LARGE_POINTER_FLAG_384x384)) ||
1000
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_SoundBeepsEnabled, TRUE) ||
1001
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_DrawGdiPlusEnabled, FALSE) ||
1002
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_DrawAllowSkipAlpha, TRUE) ||
1003
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_DrawAllowColorSubsampling, FALSE) ||
1004
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_DrawAllowDynamicColorFidelity, TRUE) ||
1005
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_FrameMarkerCommandEnabled, TRUE) ||
1006
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_SurfaceFrameMarkerEnabled, TRUE) ||
1007
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_AllowCacheWaitingList, TRUE) ||
1008
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_BitmapCacheV2NumCells, 5))
1009
0
    goto out_fail;
1010
69.1k
  settings->BitmapCacheV2CellInfo =
1011
69.1k
      (BITMAP_CACHE_V2_CELL_INFO*)calloc(6, sizeof(BITMAP_CACHE_V2_CELL_INFO));
1012
1013
69.1k
  if (!settings->BitmapCacheV2CellInfo)
1014
0
    goto out_fail;
1015
1016
69.1k
  {
1017
69.1k
    BITMAP_CACHE_V2_CELL_INFO cache = { 0 };
1018
69.1k
    cache.numEntries = 600;
1019
69.1k
    if (!freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 0,
1020
69.1k
                                            &cache) ||
1021
69.1k
        !freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 1, &cache))
1022
0
      goto out_fail;
1023
69.1k
    cache.numEntries = 2048;
1024
69.1k
    if (!freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 2,
1025
69.1k
                                            &cache) ||
1026
69.1k
        !freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 4, &cache))
1027
0
      goto out_fail;
1028
69.1k
    cache.numEntries = 4096;
1029
69.1k
    if (!freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 3, &cache))
1030
0
      goto out_fail;
1031
69.1k
  }
1032
69.1k
  if (!freerdp_settings_set_bool(settings, FreeRDP_NoBitmapCompressionHeader, TRUE) ||
1033
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_RefreshRect, TRUE) ||
1034
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_SuppressOutput, TRUE) ||
1035
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_GlyphSupportLevel, GLYPH_SUPPORT_NONE))
1036
0
    goto out_fail;
1037
69.1k
  settings->GlyphCache = calloc(10, sizeof(GLYPH_CACHE_DEFINITION));
1038
1039
69.1k
  if (!settings->GlyphCache)
1040
0
    goto out_fail;
1041
1042
69.1k
  settings->FragCache = calloc(1, sizeof(GLYPH_CACHE_DEFINITION));
1043
1044
69.1k
  if (!settings->FragCache)
1045
0
    goto out_fail;
1046
1047
760k
  for (size_t x = 0; x < 10; x++)
1048
691k
  {
1049
691k
    GLYPH_CACHE_DEFINITION cache = { 0 };
1050
691k
    cache.cacheEntries = 254;
1051
691k
    switch (x)
1052
691k
    {
1053
69.1k
      case 0:
1054
138k
      case 1:
1055
138k
        cache.cacheMaximumCellSize = 4;
1056
138k
        break;
1057
69.1k
      case 2:
1058
138k
      case 3:
1059
138k
        cache.cacheMaximumCellSize = 8;
1060
138k
        break;
1061
69.1k
      case 4:
1062
69.1k
        cache.cacheMaximumCellSize = 16;
1063
69.1k
        break;
1064
69.1k
      case 5:
1065
69.1k
        cache.cacheMaximumCellSize = 32;
1066
69.1k
        break;
1067
69.1k
      case 6:
1068
69.1k
        cache.cacheMaximumCellSize = 64;
1069
69.1k
        break;
1070
69.1k
      case 7:
1071
69.1k
        cache.cacheMaximumCellSize = 128;
1072
69.1k
        break;
1073
69.1k
      case 8:
1074
69.1k
        cache.cacheMaximumCellSize = 256;
1075
69.1k
        break;
1076
69.1k
      case 9:
1077
69.1k
        cache.cacheMaximumCellSize = 256;
1078
69.1k
        break;
1079
0
      default:
1080
0
        goto out_fail;
1081
691k
    }
1082
1083
691k
    if (!freerdp_settings_set_pointer_array(settings, FreeRDP_GlyphCache, x, &cache))
1084
0
      goto out_fail;
1085
691k
  }
1086
69.1k
  {
1087
69.1k
    GLYPH_CACHE_DEFINITION cache = { 0 };
1088
69.1k
    cache.cacheEntries = 256;
1089
69.1k
    cache.cacheMaximumCellSize = 256;
1090
69.1k
    if (!freerdp_settings_set_pointer_array(settings, FreeRDP_FragCache, 0, &cache))
1091
0
      goto out_fail;
1092
69.1k
  }
1093
69.1k
  if (!freerdp_settings_set_uint32(settings, FreeRDP_OffscreenSupportLevel, 0) ||
1094
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_OffscreenCacheSize, 7680) ||
1095
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_OffscreenCacheEntries, 2000) ||
1096
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_DrawNineGridCacheSize, 2560) ||
1097
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_DrawNineGridCacheEntries, 256) ||
1098
69.1k
      !freerdp_settings_set_string(settings, FreeRDP_ClientDir, client_dll) ||
1099
69.1k
      !freerdp_settings_get_string(settings, FreeRDP_ClientDir) ||
1100
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_RemoteWndSupportLevel,
1101
69.1k
                                   WINDOW_LEVEL_SUPPORTED | WINDOW_LEVEL_SUPPORTED_EX) ||
1102
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_RemoteAppNumIconCaches, 3) ||
1103
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_RemoteAppNumIconCacheEntries, 12) ||
1104
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_VCChunkSize,
1105
69.1k
                                   (server && !remote) ? CHANNEL_CHUNK_MAX_LENGTH
1106
69.1k
                                                       : CHANNEL_CHUNK_LENGTH) ||
1107
      /* [MS-RDPBCGR] 2.2.7.2.7 Large Pointer Capability Set (TS_LARGE_POINTER_CAPABILITYSET)
1108
         requires at least this size */
1109
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_MultifragMaxRequestSize,
1110
69.1k
                                   server ? 0 : 608299) ||
1111
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_GatewayUseSameCredentials, FALSE) ||
1112
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE) ||
1113
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_GatewayRpcTransport, TRUE) ||
1114
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpTransport, TRUE) ||
1115
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_GatewayUdpTransport, TRUE) ||
1116
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpUseWebsockets, TRUE) ||
1117
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpExtAuthSspiNtlm, FALSE) ||
1118
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_GatewayArmTransport, FALSE) ||
1119
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_FastPathInput, TRUE) ||
1120
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_FastPathOutput, TRUE) ||
1121
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_LongCredentialsSupported, TRUE) ||
1122
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_FrameAcknowledge, 2) ||
1123
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_MouseMotion, TRUE) ||
1124
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_NSCodecColorLossLevel, 3) ||
1125
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_NSCodecAllowSubsampling, TRUE) ||
1126
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_NSCodecAllowDynamicColorFidelity, TRUE) ||
1127
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_AutoReconnectionEnabled, FALSE) ||
1128
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_AutoReconnectMaxRetries, 20) ||
1129
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_GfxThinClient, FALSE) ||
1130
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_GfxSmallCache, TRUE) ||
1131
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_GfxProgressive, FALSE) ||
1132
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_GfxProgressiveV2, FALSE) ||
1133
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_GfxPlanar, TRUE) ||
1134
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_GfxH264, FALSE) ||
1135
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_GfxAVC444, FALSE) ||
1136
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_GfxSendQoeAck, FALSE) ||
1137
69.1k
      !freerdp_settings_set_bool(settings, FreeRDP_SupportDisplayControl, TRUE))
1138
0
    goto out_fail;
1139
69.1k
  {
1140
69.1k
    ARC_CS_PRIVATE_PACKET cookie = { 0 };
1141
69.1k
    if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ClientAutoReconnectCookie, &cookie,
1142
69.1k
                                          1))
1143
0
      goto out_fail;
1144
69.1k
  }
1145
69.1k
  {
1146
69.1k
    ARC_SC_PRIVATE_PACKET cookie = { 0 };
1147
69.1k
    if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ServerAutoReconnectCookie, &cookie,
1148
69.1k
                                          1))
1149
0
      goto out_fail;
1150
69.1k
  }
1151
1152
69.1k
  settings->ClientTimeZone = (LPTIME_ZONE_INFORMATION)calloc(1, sizeof(TIME_ZONE_INFORMATION));
1153
1154
69.1k
  if (!settings->ClientTimeZone)
1155
0
    goto out_fail;
1156
1157
69.1k
  if (!settings->ServerMode)
1158
51.8k
  {
1159
51.8k
    DYNAMIC_TIME_ZONE_INFORMATION dynamic = { 0 };
1160
51.8k
    TIME_ZONE_INFORMATION* tz =
1161
51.8k
        freerdp_settings_get_pointer_writable(settings, FreeRDP_ClientTimeZone);
1162
51.8k
    WINPR_ASSERT(tz);
1163
1164
51.8k
    GetTimeZoneInformation(tz);
1165
51.8k
    GetDynamicTimeZoneInformation(&dynamic);
1166
1167
51.8k
    if (!freerdp_settings_set_string_from_utf16N(settings, FreeRDP_DynamicDSTTimeZoneKeyName,
1168
51.8k
                                                 dynamic.TimeZoneKeyName,
1169
51.8k
                                                 ARRAYSIZE(dynamic.TimeZoneKeyName)))
1170
0
      goto out_fail;
1171
1172
51.8k
    if (!freerdp_settings_set_bool(settings, FreeRDP_DynamicDaylightTimeDisabled,
1173
51.8k
                                   dynamic.DynamicDaylightTimeDisabled))
1174
0
      goto out_fail;
1175
51.8k
  }
1176
1177
69.1k
  if (!freerdp_settings_set_bool(settings, FreeRDP_TcpKeepAlive, TRUE) ||
1178
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_TcpKeepAliveRetries, 3) ||
1179
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_TcpKeepAliveDelay, 5) ||
1180
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_TcpKeepAliveInterval, 2) ||
1181
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_TcpAckTimeout, 9000) ||
1182
69.1k
      !freerdp_settings_set_uint32(settings, FreeRDP_TcpConnectTimeout, 15000))
1183
0
    goto out_fail;
1184
1185
69.1k
  if (!freerdp_settings_get_bool(settings, FreeRDP_ServerMode))
1186
51.8k
  {
1187
51.8k
    BOOL rc = FALSE;
1188
51.8k
    char* path = NULL;
1189
51.8k
    if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectClipboard, TRUE))
1190
0
      goto out_fail;
1191
    /* these values are used only by the client part */
1192
51.8k
    path = GetKnownPath(KNOWN_PATH_HOME);
1193
51.8k
    rc = freerdp_settings_set_string(settings, FreeRDP_HomePath, path);
1194
51.8k
    free(path);
1195
1196
51.8k
    if (!rc || !freerdp_settings_get_string(settings, FreeRDP_HomePath))
1197
0
      goto out_fail;
1198
1199
51.8k
    char* config = freerdp_settings_get_config_path();
1200
51.8k
    rc = freerdp_settings_set_string(settings, FreeRDP_ConfigPath, config);
1201
51.8k
    if (rc)
1202
51.8k
    {
1203
51.8k
      char* action = GetCombinedPath(config, "action.sh");
1204
51.8k
      rc = freerdp_settings_set_string(settings, FreeRDP_ActionScript, action);
1205
51.8k
      free(action);
1206
51.8k
    }
1207
1208
51.8k
    free(config);
1209
51.8k
    if (!rc)
1210
0
      goto out_fail;
1211
51.8k
  }
1212
1213
69.1k
  settings_load_hkey_local_machine(settings);
1214
1215
69.1k
  if (!freerdp_settings_set_bool(settings, FreeRDP_SmartcardLogon, FALSE))
1216
0
    goto out_fail;
1217
69.1k
  if (!freerdp_settings_set_uint32(settings, FreeRDP_TlsSecLevel, 1))
1218
0
    goto out_fail;
1219
69.1k
  settings->OrderSupport = calloc(1, 32);
1220
1221
69.1k
  if (!freerdp_settings_set_uint16(settings, FreeRDP_TLSMinVersion, TLS1_VERSION))
1222
0
    goto out_fail;
1223
69.1k
  if (!freerdp_settings_set_uint16(settings, FreeRDP_TLSMaxVersion, 0))
1224
0
    goto out_fail;
1225
1226
69.1k
  if (!settings->OrderSupport)
1227
0
    goto out_fail;
1228
1229
69.1k
  if (!freerdp_settings_set_default_order_support(settings))
1230
0
    goto out_fail;
1231
1232
69.1k
  {
1233
69.1k
    const BOOL enable = freerdp_settings_get_bool(settings, FreeRDP_ServerMode);
1234
69.1k
    {
1235
69.1k
      const FreeRDP_Settings_Keys_Bool keys[] = { FreeRDP_SupportGraphicsPipeline,
1236
69.1k
                                                FreeRDP_SupportStatusInfoPdu,
1237
69.1k
                                                FreeRDP_SupportErrorInfoPdu,
1238
69.1k
                                                FreeRDP_SupportAsymetricKeys };
1239
1240
345k
      for (size_t x = 0; x < ARRAYSIZE(keys); x++)
1241
276k
      {
1242
276k
        if (!freerdp_settings_set_bool(settings, keys[x], enable))
1243
0
          goto out_fail;
1244
276k
      }
1245
69.1k
    }
1246
69.1k
  }
1247
1248
69.1k
  if (!freerdp_settings_set_bool(settings, FreeRDP_SupportDynamicTimeZone, TRUE))
1249
0
    goto out_fail;
1250
69.1k
  if (!freerdp_settings_set_bool(settings, FreeRDP_SupportSkipChannelJoin, TRUE))
1251
0
    goto out_fail;
1252
1253
69.1k
  return settings;
1254
0
out_fail:
1255
0
  WINPR_PRAGMA_DIAG_PUSH
1256
0
  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1257
0
  freerdp_settings_free(settings);
1258
0
  WINPR_PRAGMA_DIAG_POP
1259
0
  return NULL;
1260
69.1k
}
1261
1262
static void freerdp_settings_free_internal(rdpSettings* settings)
1263
103k
{
1264
103k
  freerdp_server_license_issuers_free(settings);
1265
103k
  freerdp_target_net_addresses_free(settings);
1266
103k
  freerdp_device_collection_free(settings);
1267
103k
  freerdp_static_channel_collection_free(settings);
1268
103k
  freerdp_dynamic_channel_collection_free(settings);
1269
1270
103k
  freerdp_capability_buffer_free(settings);
1271
1272
  /* Free all strings, set other pointers NULL */
1273
103k
  freerdp_settings_free_keys(settings, TRUE);
1274
103k
}
1275
1276
static void freerdp_settings_free_internal_ensure_reset(rdpSettings* settings)
1277
17.2k
{
1278
17.2k
  settings->ServerLicenseProductIssuersCount = 0;
1279
17.2k
  settings->ServerLicenseProductIssuers = NULL;
1280
1281
17.2k
  settings->ReceivedCapabilitiesSize = 0;
1282
17.2k
}
1283
1284
void freerdp_settings_free(rdpSettings* settings)
1285
120k
{
1286
120k
  if (!settings)
1287
34.5k
    return;
1288
1289
86.4k
  freerdp_settings_free_internal(settings);
1290
86.4k
  free(settings);
1291
86.4k
}
1292
1293
static BOOL freerdp_settings_int_buffer_copy(rdpSettings* _settings, const rdpSettings* settings)
1294
17.2k
{
1295
17.2k
  BOOL rc = FALSE;
1296
1297
17.2k
  if (!_settings || !settings)
1298
0
    return FALSE;
1299
1300
17.2k
  typedef struct
1301
17.2k
  {
1302
17.2k
    FreeRDP_Settings_Keys_UInt32 lenKey;
1303
17.2k
    FreeRDP_Settings_Keys_Pointer pointerKey;
1304
17.2k
  } PointerDefs;
1305
1306
17.2k
  PointerDefs pointerDefs[] = {
1307
    /* */
1308
17.2k
    { FreeRDP_LoadBalanceInfoLength, FreeRDP_LoadBalanceInfo },
1309
17.2k
    { FreeRDP_ServerRandomLength, FreeRDP_ServerRandom },
1310
17.2k
    { FreeRDP_ClientRandomLength, FreeRDP_ClientRandom },
1311
17.2k
    { FreeRDP_ServerCertificateLength, FreeRDP_ServerCertificate },
1312
17.2k
    { FreeRDP_ChannelDefArraySize, FreeRDP_ChannelDefArray },
1313
17.2k
    { FreeRDP_NumMonitorIds, FreeRDP_MonitorIds },
1314
17.2k
    { FreeRDP_BitmapCacheV2NumCells, FreeRDP_BitmapCacheV2CellInfo },
1315
17.2k
    { FreeRDP_RedirectionPasswordLength, FreeRDP_RedirectionPassword },
1316
17.2k
    { FreeRDP_RedirectionTsvUrlLength, FreeRDP_RedirectionTsvUrl },
1317
17.2k
    { FreeRDP_RedirectionGuidLength, FreeRDP_RedirectionGuid },
1318
17.2k
    { FreeRDP_MonitorDefArraySize, FreeRDP_MonitorDefArray }
1319
17.2k
  };
1320
1321
207k
  for (size_t i = 0; i < ARRAYSIZE(pointerDefs); i++)
1322
190k
  {
1323
190k
    const PointerDefs* keys = &pointerDefs[i];
1324
190k
    UINT32 n = freerdp_settings_get_uint32(settings, keys->lenKey);
1325
1326
190k
    const void* ptr = freerdp_settings_get_pointer(settings, keys->pointerKey);
1327
190k
    if (!freerdp_settings_set_pointer_len(_settings, keys->pointerKey, ptr, n))
1328
0
      goto out_fail;
1329
190k
  }
1330
1331
17.2k
  if (!freerdp_server_license_issuers_copy(_settings, settings->ServerLicenseProductIssuers,
1332
17.2k
                                           settings->ServerLicenseProductIssuersCount))
1333
0
    goto out_fail;
1334
1335
17.2k
  if (settings->RdpServerCertificate)
1336
17.2k
  {
1337
17.2k
    rdpCertificate* cert = freerdp_certificate_clone(settings->RdpServerCertificate);
1338
17.2k
    if (!cert)
1339
0
      goto out_fail;
1340
17.2k
    if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_RdpServerCertificate, cert, 1))
1341
0
      goto out_fail;
1342
17.2k
  }
1343
0
  else
1344
0
  {
1345
0
    if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_RdpServerCertificate, NULL, 0))
1346
0
      goto out_fail;
1347
0
  }
1348
1349
17.2k
  if (settings->RdpServerRsaKey)
1350
0
  {
1351
0
    rdpPrivateKey* key = freerdp_key_clone(settings->RdpServerRsaKey);
1352
0
    if (!key)
1353
0
      goto out_fail;
1354
0
    if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_RdpServerRsaKey, key, 1))
1355
0
      goto out_fail;
1356
0
  }
1357
17.2k
  else
1358
17.2k
  {
1359
17.2k
    if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_RdpServerRsaKey, NULL, 0))
1360
0
      goto out_fail;
1361
17.2k
  }
1362
1363
17.2k
  if (!freerdp_settings_set_uint32(_settings, FreeRDP_ChannelCount,
1364
17.2k
                                   freerdp_settings_get_uint32(settings, FreeRDP_ChannelCount)))
1365
0
    goto out_fail;
1366
1367
17.2k
  if (settings->OrderSupport)
1368
17.2k
  {
1369
17.2k
    _settings->OrderSupport = calloc(32, sizeof(BYTE));
1370
17.2k
    if (!_settings->OrderSupport)
1371
0
      goto out_fail;
1372
1373
17.2k
    CopyMemory(_settings->OrderSupport, settings->OrderSupport, 32);
1374
17.2k
  }
1375
1376
17.2k
  if (!freerdp_capability_buffer_copy(_settings, settings))
1377
0
    goto out_fail;
1378
1379
17.2k
  {
1380
17.2k
    const UINT32 glyphCacheCount = 10;
1381
17.2k
    const GLYPH_CACHE_DEFINITION* glyphCache =
1382
17.2k
        freerdp_settings_get_pointer(settings, FreeRDP_GlyphCache);
1383
17.2k
    if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_GlyphCache, glyphCache,
1384
17.2k
                                          glyphCacheCount))
1385
0
      goto out_fail;
1386
17.2k
  }
1387
1388
17.2k
  {
1389
17.2k
    const UINT32 fragCacheCount = 1;
1390
17.2k
    const GLYPH_CACHE_DEFINITION* fragCache =
1391
17.2k
        freerdp_settings_get_pointer(settings, FreeRDP_FragCache);
1392
17.2k
    if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_FragCache, fragCache,
1393
17.2k
                                          fragCacheCount))
1394
0
      goto out_fail;
1395
17.2k
  }
1396
1397
17.2k
  if (!freerdp_settings_set_pointer_len(
1398
17.2k
          _settings, FreeRDP_ClientAutoReconnectCookie,
1399
17.2k
          freerdp_settings_get_pointer(settings, FreeRDP_ClientAutoReconnectCookie), 1))
1400
0
    goto out_fail;
1401
17.2k
  if (!freerdp_settings_set_pointer_len(
1402
17.2k
          _settings, FreeRDP_ServerAutoReconnectCookie,
1403
17.2k
          freerdp_settings_get_pointer(settings, FreeRDP_ServerAutoReconnectCookie), 1))
1404
0
    goto out_fail;
1405
1406
17.2k
  {
1407
17.2k
    const TIME_ZONE_INFORMATION* tz =
1408
17.2k
        freerdp_settings_get_pointer(settings, FreeRDP_ClientTimeZone);
1409
17.2k
    if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_ClientTimeZone, tz, 1))
1410
0
      goto out_fail;
1411
17.2k
  }
1412
1413
17.2k
  {
1414
17.2k
    const UINT32 nrports = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
1415
17.2k
    if (!freerdp_target_net_adresses_reset(_settings, nrports))
1416
0
      goto out_fail;
1417
1418
17.2k
    for (UINT32 i = 0; i < nrports; i++)
1419
0
    {
1420
0
      const char* address =
1421
0
          freerdp_settings_get_pointer_array(settings, FreeRDP_TargetNetAddresses, i);
1422
0
      const UINT32* port =
1423
0
          freerdp_settings_get_pointer_array(settings, FreeRDP_TargetNetPorts, i);
1424
1425
0
      if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_TargetNetAddresses, i,
1426
0
                                              address))
1427
0
        goto out_fail;
1428
0
      if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_TargetNetPorts, i, port))
1429
0
        goto out_fail;
1430
0
    }
1431
17.2k
  }
1432
1433
17.2k
  {
1434
17.2k
    const UINT32 len = freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize);
1435
17.2k
    const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_DeviceCount);
1436
1437
17.2k
    if (len < count)
1438
0
      goto out_fail;
1439
17.2k
    if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_DeviceArray, NULL, len))
1440
0
      goto out_fail;
1441
17.2k
    if (!freerdp_settings_set_uint32(_settings, FreeRDP_DeviceCount, count))
1442
0
      goto out_fail;
1443
1444
17.2k
    for (size_t index = 0; index < count; index++)
1445
0
    {
1446
0
      const RDPDR_DEVICE* argv =
1447
0
          freerdp_settings_get_pointer_array(settings, FreeRDP_DeviceArray, index);
1448
0
      WINPR_ASSERT(argv);
1449
0
      if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_DeviceArray, index, argv))
1450
0
        goto out_fail;
1451
0
    }
1452
17.2k
    WINPR_ASSERT(_settings->DeviceArray || (len == 0));
1453
17.2k
    WINPR_ASSERT(len >= count);
1454
17.2k
  }
1455
17.2k
  {
1456
17.2k
    const UINT32 len = freerdp_settings_get_uint32(_settings, FreeRDP_StaticChannelArraySize);
1457
17.2k
    const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
1458
1459
17.2k
    if (len < count)
1460
0
      goto out_fail;
1461
17.2k
    if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_StaticChannelArray, NULL, len))
1462
0
      goto out_fail;
1463
17.2k
    if (!freerdp_settings_set_uint32(_settings, FreeRDP_StaticChannelCount, count))
1464
0
      goto out_fail;
1465
1466
17.2k
    for (size_t index = 0; index < count; index++)
1467
0
    {
1468
0
      const ADDIN_ARGV* argv =
1469
0
          freerdp_settings_get_pointer_array(settings, FreeRDP_StaticChannelArray, index);
1470
0
      WINPR_ASSERT(argv);
1471
0
      if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_StaticChannelArray, index,
1472
0
                                              argv))
1473
0
        goto out_fail;
1474
0
    }
1475
17.2k
  }
1476
17.2k
  {
1477
17.2k
    const UINT32 len = freerdp_settings_get_uint32(_settings, FreeRDP_DynamicChannelArraySize);
1478
17.2k
    const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
1479
1480
17.2k
    if (len < count)
1481
0
      goto out_fail;
1482
17.2k
    if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_DynamicChannelArray, NULL, len))
1483
0
      goto out_fail;
1484
17.2k
    if (!freerdp_settings_set_uint32(_settings, FreeRDP_DynamicChannelCount, count))
1485
0
      goto out_fail;
1486
1487
17.2k
    for (size_t index = 0; index < count; index++)
1488
0
    {
1489
0
      const ADDIN_ARGV* argv =
1490
0
          freerdp_settings_get_pointer_array(settings, FreeRDP_DynamicChannelArray, index);
1491
0
      WINPR_ASSERT(argv);
1492
0
      if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_DynamicChannelArray, index,
1493
0
                                              argv))
1494
0
        goto out_fail;
1495
0
    }
1496
17.2k
  }
1497
1498
17.2k
  rc = freerdp_settings_set_string(_settings, FreeRDP_ActionScript,
1499
17.2k
                                   freerdp_settings_get_string(settings, FreeRDP_ActionScript));
1500
1501
17.2k
out_fail:
1502
17.2k
  return rc;
1503
17.2k
}
1504
1505
BOOL freerdp_settings_copy(rdpSettings* _settings, const rdpSettings* settings)
1506
17.2k
{
1507
17.2k
  BOOL rc = 0;
1508
1509
17.2k
  if (!settings || !_settings)
1510
0
    return FALSE;
1511
1512
  /* This is required to free all non string buffers */
1513
17.2k
  freerdp_settings_free_internal(_settings);
1514
1515
  /* This copies everything except allocated non string buffers. reset all allocated buffers to
1516
   * NULL to fix issues during cleanup */
1517
17.2k
  rc = freerdp_settings_clone_keys(_settings, settings);
1518
17.2k
  if (!rc)
1519
0
    goto out_fail;
1520
17.2k
  freerdp_settings_free_internal_ensure_reset(_settings);
1521
1522
  /* Begin copying */
1523
17.2k
  if (!freerdp_settings_int_buffer_copy(_settings, settings))
1524
0
    goto out_fail;
1525
17.2k
  return TRUE;
1526
0
out_fail:
1527
0
  freerdp_settings_free_internal(_settings);
1528
0
  return FALSE;
1529
17.2k
}
1530
1531
rdpSettings* freerdp_settings_clone(const rdpSettings* settings)
1532
17.2k
{
1533
17.2k
  rdpSettings* _settings = (rdpSettings*)calloc(1, sizeof(rdpSettings));
1534
1535
17.2k
  if (!freerdp_settings_copy(_settings, settings))
1536
0
    goto out_fail;
1537
1538
17.2k
  return _settings;
1539
0
out_fail:
1540
0
  WINPR_PRAGMA_DIAG_PUSH
1541
0
  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1542
0
  freerdp_settings_free(_settings);
1543
0
  WINPR_PRAGMA_DIAG_POP
1544
0
  return NULL;
1545
17.2k
}
1546
#ifdef _MSC_VER
1547
#pragma warning(pop)
1548
#endif
1549
1550
static void zfree(WCHAR* str, size_t len)
1551
0
{
1552
0
  if (str)
1553
0
    memset(str, 0, len * sizeof(WCHAR));
1554
0
  free(str);
1555
0
}
1556
1557
BOOL identity_set_from_settings_with_pwd(SEC_WINNT_AUTH_IDENTITY* identity,
1558
                                         const rdpSettings* settings,
1559
                                         FreeRDP_Settings_Keys_String UserId,
1560
                                         FreeRDP_Settings_Keys_String DomainId,
1561
                                         const WCHAR* Password, size_t pwdLen)
1562
0
{
1563
0
  WINPR_ASSERT(identity);
1564
0
  WINPR_ASSERT(settings);
1565
1566
0
  size_t UserLen = 0;
1567
0
  size_t DomainLen = 0;
1568
1569
0
  WCHAR* Username = freerdp_settings_get_string_as_utf16(settings, UserId, &UserLen);
1570
0
  WCHAR* Domain = freerdp_settings_get_string_as_utf16(settings, DomainId, &DomainLen);
1571
1572
0
  const int rc = sspi_SetAuthIdentityWithLengthW(identity, Username, UserLen, Domain, DomainLen,
1573
0
                                                 Password, pwdLen);
1574
0
  zfree(Username, UserLen);
1575
0
  zfree(Domain, DomainLen);
1576
0
  if (rc < 0)
1577
0
    return FALSE;
1578
0
  return TRUE;
1579
0
}
1580
1581
BOOL identity_set_from_settings(SEC_WINNT_AUTH_IDENTITY_W* identity, const rdpSettings* settings,
1582
                                FreeRDP_Settings_Keys_String UserId,
1583
                                FreeRDP_Settings_Keys_String DomainId,
1584
                                FreeRDP_Settings_Keys_String PwdId)
1585
0
{
1586
0
  WINPR_ASSERT(identity);
1587
0
  WINPR_ASSERT(settings);
1588
1589
0
  size_t PwdLen = 0;
1590
1591
0
  WCHAR* Password = freerdp_settings_get_string_as_utf16(settings, PwdId, &PwdLen);
1592
1593
0
  const BOOL rc =
1594
0
      identity_set_from_settings_with_pwd(identity, settings, UserId, DomainId, Password, PwdLen);
1595
0
  zfree(Password, PwdLen);
1596
0
  return rc;
1597
0
}
1598
1599
BOOL identity_set_from_smartcard_hash(SEC_WINNT_AUTH_IDENTITY_W* identity,
1600
                                      const rdpSettings* settings,
1601
                                      FreeRDP_Settings_Keys_String userId,
1602
                                      FreeRDP_Settings_Keys_String domainId,
1603
                                      FreeRDP_Settings_Keys_String pwdId,
1604
                                      WINPR_ATTR_UNUSED const BYTE* certSha1,
1605
                                      WINPR_ATTR_UNUSED size_t sha1len)
1606
0
{
1607
#ifdef _WIN32
1608
  CERT_CREDENTIAL_INFO certInfo = { sizeof(CERT_CREDENTIAL_INFO), { 0 } };
1609
  LPWSTR marshalledCredentials = NULL;
1610
1611
  memcpy(certInfo.rgbHashOfCert, certSha1, MIN(sha1len, sizeof(certInfo.rgbHashOfCert)));
1612
1613
  if (!CredMarshalCredentialW(CertCredential, &certInfo, &marshalledCredentials))
1614
  {
1615
    WLog_ERR(TAG, "error marshalling cert credentials");
1616
    return FALSE;
1617
  }
1618
1619
  size_t pwdLen = 0;
1620
  WCHAR* Password = freerdp_settings_get_string_as_utf16(settings, pwdId, &pwdLen);
1621
  const int rc = sspi_SetAuthIdentityWithLengthW(
1622
      identity, marshalledCredentials, _wcslen(marshalledCredentials), NULL, 0, Password, pwdLen);
1623
  zfree(Password, pwdLen);
1624
  CredFree(marshalledCredentials);
1625
  if (rc < 0)
1626
    return FALSE;
1627
1628
#else
1629
0
  if (!identity_set_from_settings(identity, settings, userId, domainId, pwdId))
1630
0
    return FALSE;
1631
0
#endif /* _WIN32 */
1632
0
  return TRUE;
1633
0
}
1634
1635
const char* freerdp_settings_glyph_level_string(UINT32 level, char* buffer, size_t size)
1636
0
{
1637
0
  const char* str = "GLYPH_SUPPORT_UNKNOWN";
1638
0
  switch (level)
1639
0
  {
1640
0
    case GLYPH_SUPPORT_NONE:
1641
0
      str = "GLYPH_SUPPORT_NONE";
1642
0
      break;
1643
0
    case GLYPH_SUPPORT_PARTIAL:
1644
0
      str = "GLYPH_SUPPORT_PARTIAL";
1645
0
      break;
1646
0
    case GLYPH_SUPPORT_FULL:
1647
0
      str = "GLYPH_SUPPORT_FULL";
1648
0
      break;
1649
0
    case GLYPH_SUPPORT_ENCODE:
1650
0
      str = "GLYPH_SUPPORT_ENCODE";
1651
0
      break;
1652
0
    default:
1653
0
      break;
1654
0
  }
1655
1656
0
  (void)_snprintf(buffer, size, "%s[0x%08" PRIx32 "]", str, level);
1657
0
  return buffer;
1658
0
}
1659
1660
BOOL freerdp_target_net_adresses_reset(rdpSettings* settings, size_t size)
1661
17.2k
{
1662
17.2k
  freerdp_target_net_addresses_free(settings);
1663
1664
17.2k
  return freerdp_target_net_addresses_resize(settings, size);
1665
17.2k
}
1666
1667
BOOL freerdp_settings_enforce_monitor_exists(rdpSettings* settings)
1668
0
{
1669
0
  const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount);
1670
0
  const BOOL fullscreen = freerdp_settings_get_bool(settings, FreeRDP_Fullscreen);
1671
0
  const BOOL multimon = freerdp_settings_get_bool(settings, FreeRDP_UseMultimon);
1672
0
  const BOOL useMonitors = fullscreen || multimon;
1673
1674
0
  const UINT32 size = freerdp_settings_get_uint32(settings, FreeRDP_MonitorDefArraySize);
1675
0
  if (size == 0)
1676
0
  {
1677
0
    if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorDefArray, NULL, 16))
1678
0
      return FALSE;
1679
0
  }
1680
1681
0
  if (!useMonitors || (count == 0))
1682
0
  {
1683
0
    const UINT32 width = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
1684
0
    const UINT32 height = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
1685
0
    const UINT32 pwidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopPhysicalWidth);
1686
0
    const UINT32 pheight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopPhysicalHeight);
1687
0
    const UINT16 orientation =
1688
0
        freerdp_settings_get_uint16(settings, FreeRDP_DesktopOrientation);
1689
0
    const UINT32 desktopScaleFactor =
1690
0
        freerdp_settings_get_uint32(settings, FreeRDP_DeviceScaleFactor);
1691
0
    const UINT32 deviceScaleFactor =
1692
0
        freerdp_settings_get_uint32(settings, FreeRDP_DesktopScaleFactor);
1693
1694
0
    if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, 1))
1695
0
      return FALSE;
1696
1697
0
    rdpMonitor monitor = { 0 };
1698
0
    monitor.x = 0;
1699
0
    monitor.y = 0;
1700
0
    monitor.width = WINPR_ASSERTING_INT_CAST(int32_t, width);
1701
0
    monitor.height = WINPR_ASSERTING_INT_CAST(int32_t, height);
1702
0
    monitor.is_primary = TRUE;
1703
0
    monitor.orig_screen = 0;
1704
0
    monitor.attributes.physicalWidth = pwidth;
1705
0
    monitor.attributes.physicalHeight = pheight;
1706
0
    monitor.attributes.orientation = orientation;
1707
0
    monitor.attributes.desktopScaleFactor = desktopScaleFactor;
1708
0
    monitor.attributes.deviceScaleFactor = deviceScaleFactor;
1709
0
    if (!freerdp_settings_set_monitor_def_array_sorted(settings, &monitor, 1))
1710
0
      return FALSE;
1711
0
  }
1712
1713
0
  return TRUE;
1714
0
}
1715
1716
BOOL freerdp_settings_enforce_consistency(rdpSettings* settings)
1717
0
{
1718
0
  if (freerdp_settings_get_bool(settings, FreeRDP_BitmapCacheV3Enabled))
1719
0
  {
1720
0
    settings->OrderSupportFlagsEx |= CACHE_BITMAP_V3_SUPPORT;
1721
0
    settings->OrderSupportFlags |= ORDER_FLAGS_EXTRA_SUPPORT;
1722
0
  }
1723
1724
0
  if (settings->FrameMarkerCommandEnabled)
1725
0
  {
1726
0
    settings->OrderSupportFlagsEx |= ALTSEC_FRAME_MARKER_SUPPORT;
1727
0
    settings->OrderSupportFlags |= ORDER_FLAGS_EXTRA_SUPPORT;
1728
0
  }
1729
  return TRUE;
1730
0
}