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