Coverage Report

Created: 2025-10-10 06:50

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