Coverage Report

Created: 2026-07-30 07:11

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