Coverage Report

Created: 2026-10-15 06:31

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