Coverage Report

Created: 2025-07-11 06:46

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