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