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