22#include <freerdp/config.h>
26#include <freerdp/crypto/certificate.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>
37#include <freerdp/version.h>
38#include <freerdp/settings.h>
39#include <freerdp/utils/string.h>
40#include <freerdp/utils/helpers.h>
41#include <freerdp/build-config.h>
43#include "../core/utils.h"
44#include "../crypto/certificate.h"
45#include "../crypto/privatekey.h"
46#include "capabilities.h"
48#define TAG FREERDP_TAG("settings")
52#pragma warning(disable : 4244)
55static const char client_dll[] =
"C:\\Windows\\System32\\mstscax.dll";
57#define SERVER_KEY "Software\\%s\\Server"
58#define CLIENT_KEY "Software\\%s\\Client"
59#define BITMAP_CACHE_KEY CLIENT_KEY "\\BitmapCacheV2"
60#define GLYPH_CACHE_KEY CLIENT_KEY "\\GlyphCache"
61#define POINTER_CACHE_KEY CLIENT_KEY "\\PointerCache"
71static const char* bounds2str(
const struct bounds_t* bounds,
char* buffer,
size_t len)
74 (void)_snprintf(buffer, len,
"{%dx%d-%dx%d}", bounds->x, bounds->y, bounds->x + bounds->width,
75 bounds->y + bounds->height);
79static struct bounds_t union_rect(const struct bounds_t* a,
const struct bounds_t* b)
84 struct bounds_t u = *a;
90 const INT32 rightA = a->x + a->width;
91 const INT32 rightB = b->x + b->width;
92 const INT32 right = MAX(rightA, rightB);
93 u.width = right - u.x;
95 const INT32 bottomA = a->y + a->height;
96 const INT32 bottomB = b->y + b->height;
97 const INT32 bottom = MAX(bottomA, bottomB);
98 u.height = bottom - u.y;
103static BOOL intersect_rects(
const struct bounds_t* r1,
const struct bounds_t* r2)
108 const INT32 left = MAX(r1->x, r2->x);
109 const INT32 top = MAX(r1->y, r2->y);
110 const INT32 right = MIN(r1->x + r1->width, r2->x + r2->width);
111 const INT32 bottom = MIN(r1->y + r1->height, r2->y + r2->height);
113 return (left < right) && (top < bottom);
116static BOOL align_rects(
const struct bounds_t* r1,
const struct bounds_t* r2)
121 const INT32 left = MAX(r1->x, r2->x);
122 const INT32 top = MAX(r1->y, r2->y);
123 const INT32 right = MIN(r1->x + r1->width, r2->x + r2->width);
124 const INT32 bottom = MIN(r1->y + r1->height, r2->y + r2->height);
126 return (left == right) || (top == bottom);
129static BOOL settings_reg_query_dword_val(HKEY hKey,
const TCHAR* sub, DWORD* value)
134 dwSize =
sizeof(DWORD);
135 if (RegQueryValueEx(hKey, sub, NULL, &dwType, (BYTE*)value, &dwSize) != ERROR_SUCCESS)
137 if (dwType != REG_DWORD)
143static BOOL settings_reg_query_word_val(HKEY hKey,
const TCHAR* sub, UINT16* value)
147 if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
150 if (dwValue > UINT16_MAX)
153 *value = (UINT16)dwValue;
157static BOOL settings_reg_query_bool_val(HKEY hKey,
const TCHAR* sub, BOOL* value)
161 if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
163 *value = dwValue != 0;
167static BOOL settings_reg_query_dword(rdpSettings* settings, FreeRDP_Settings_Keys_UInt32
id,
168 HKEY hKey,
const TCHAR* sub)
172 if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
178static BOOL settings_reg_query_bool(rdpSettings* settings, FreeRDP_Settings_Keys_Bool
id, HKEY hKey,
183 if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
189static void settings_client_load_hkey_local_machine(rdpSettings* settings)
192 char* key = freerdp_getApplicatonDetailsRegKey(CLIENT_KEY);
197 RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
200 if (status == ERROR_SUCCESS)
202 settings_reg_query_dword(settings, FreeRDP_DesktopWidth, hKey, _T(
"DesktopWidth"));
203 settings_reg_query_dword(settings, FreeRDP_DesktopHeight, hKey,
204 _T(
"DesktopHeight"));
205 settings_reg_query_bool(settings, FreeRDP_Fullscreen, hKey, _T(
"Fullscreen"));
206 settings_reg_query_dword(settings, FreeRDP_ColorDepth, hKey, _T(
"ColorDepth"));
207 settings_reg_query_dword(settings, FreeRDP_KeyboardType, hKey, _T(
"KeyboardType"));
208 settings_reg_query_dword(settings, FreeRDP_KeyboardSubType, hKey,
209 _T(
"KeyboardSubType"));
210 settings_reg_query_dword(settings, FreeRDP_KeyboardFunctionKey, hKey,
211 _T(
"KeyboardFunctionKeys"));
212 settings_reg_query_dword(settings, FreeRDP_KeyboardLayout, hKey,
213 _T(
"KeyboardLayout"));
214 settings_reg_query_bool(settings, FreeRDP_ExtSecurity, hKey, _T(
"ExtSecurity"));
215 settings_reg_query_bool(settings, FreeRDP_NlaSecurity, hKey, _T(
"NlaSecurity"));
216 settings_reg_query_bool(settings, FreeRDP_TlsSecurity, hKey, _T(
"TlsSecurity"));
217 settings_reg_query_bool(settings, FreeRDP_RdpSecurity, hKey, _T(
"RdpSecurity"));
218 settings_reg_query_bool(settings, FreeRDP_MstscCookieMode, hKey,
219 _T(
"MstscCookieMode"));
220 settings_reg_query_dword(settings, FreeRDP_CookieMaxLength, hKey,
221 _T(
"CookieMaxLength"));
222 settings_reg_query_bool(settings, FreeRDP_BitmapCacheEnabled, hKey,
224 settings_reg_query_dword(settings, FreeRDP_OffscreenSupportLevel, hKey,
225 _T(
"OffscreenBitmapCache"));
226 settings_reg_query_dword(settings, FreeRDP_OffscreenCacheSize, hKey,
227 _T(
"OffscreenBitmapCacheSize"));
228 settings_reg_query_dword(settings, FreeRDP_OffscreenCacheEntries, hKey,
229 _T(
"OffscreenBitmapCacheEntries"));
235 char* key = freerdp_getApplicatonDetailsRegKey(BITMAP_CACHE_KEY);
240 RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
243 if (status == ERROR_SUCCESS)
245 settings_reg_query_dword(settings, FreeRDP_BitmapCacheV2NumCells, hKey,
247 for (
unsigned x = 0; x < 5; x++)
250 TCHAR numentries[64] = { 0 };
251 TCHAR persist[64] = { 0 };
253 (void)_sntprintf(numentries, ARRAYSIZE(numentries), _T(
"Cell%uNumEntries"), x);
254 (void)_sntprintf(persist, ARRAYSIZE(persist), _T(
"Cell%uPersistent"), x);
255 if (!settings_reg_query_dword_val(hKey, numentries, &val) ||
256 !settings_reg_query_bool_val(hKey, persist, &cache.persistent) ||
257 !freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo,
259 WLog_WARN(TAG,
"Failed to load registry keys to settings!");
260 cache.numEntries = val;
263 settings_reg_query_bool(settings, FreeRDP_AllowCacheWaitingList, hKey,
264 _T(
"AllowCacheWaitingList"));
270 char* key = freerdp_getApplicatonDetailsRegKey(GLYPH_CACHE_KEY);
275 RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
278 if (status == ERROR_SUCCESS)
281 UINT32 GlyphSupportLevel = 0;
282 settings_reg_query_dword(settings, FreeRDP_GlyphSupportLevel, hKey,
287 TCHAR numentries[64] = { 0 };
288 TCHAR maxsize[64] = { 0 };
289 (void)_sntprintf(numentries, ARRAYSIZE(numentries), _T(
"Cache%uNumEntries"), x);
290 (void)_sntprintf(maxsize, ARRAYSIZE(maxsize), _T(
"Cache%uMaxCellSize"), x);
292 settings_reg_query_word_val(hKey, numentries, &cache.cacheEntries);
293 settings_reg_query_word_val(hKey, maxsize, &cache.cacheMaximumCellSize);
294 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_GlyphCache, x,
296 WLog_WARN(TAG,
"Failed to store GlyphCache %u", x);
300 settings_reg_query_word_val(hKey, _T(
"FragCacheNumEntries"),
301 &cache.cacheEntries);
302 settings_reg_query_word_val(hKey, _T(
"FragCacheMaxCellSize"),
303 &cache.cacheMaximumCellSize);
304 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_FragCache, x, &cache))
305 WLog_WARN(TAG,
"Failed to store FragCache");
312 WLog_WARN(TAG,
"Failed to load registry keys to settings!");
317 char* key = freerdp_getApplicatonDetailsRegKey(POINTER_CACHE_KEY);
322 RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
325 if (status == ERROR_SUCCESS)
327 settings_reg_query_dword(settings, FreeRDP_LargePointerFlag, hKey,
329 settings_reg_query_dword(settings, FreeRDP_PointerCacheSize, hKey,
330 _T(
"PointerCacheSize"));
331 settings_reg_query_dword(settings, FreeRDP_ColorPointerCacheSize, hKey,
332 _T(
"ColorPointerCacheSize"));
339static void settings_server_load_hkey_local_machine(rdpSettings* settings)
343 char* key = freerdp_getApplicatonDetailsRegKey(SERVER_KEY);
348 RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
351 if (status != ERROR_SUCCESS)
354 settings_reg_query_bool(settings, FreeRDP_ExtSecurity, hKey, _T(
"ExtSecurity"));
355 settings_reg_query_bool(settings, FreeRDP_NlaSecurity, hKey, _T(
"NlaSecurity"));
356 settings_reg_query_bool(settings, FreeRDP_TlsSecurity, hKey, _T(
"TlsSecurity"));
357 settings_reg_query_dword(settings, FreeRDP_TlsSecLevel, hKey, _T(
"TlsSecLevel"));
358 settings_reg_query_bool(settings, FreeRDP_RdpSecurity, hKey, _T(
"RdpSecurity"));
363static void settings_load_hkey_local_machine(rdpSettings* settings)
366 settings_server_load_hkey_local_machine(settings);
368 settings_client_load_hkey_local_machine(settings);
371static BOOL settings_init_computer_name(rdpSettings* settings)
373 CHAR computerName[MAX_COMPUTERNAME_LENGTH + 1] = { 0 };
374 DWORD nSize = ARRAYSIZE(computerName);
376 if (!GetComputerNameExA(ComputerNameNetBIOS, computerName, &nSize))
384void freerdp_settings_print_warnings(
const rdpSettings* settings)
387 if (level != GLYPH_SUPPORT_NONE)
389 char buffer[32] = { 0 };
390 WLog_WARN(TAG,
"[experimental] enabled GlyphSupportLevel %s, expect visual artefacts!",
391 freerdp_settings_glyph_level_string(level, buffer,
sizeof(buffer)));
395static BOOL monitor_operlaps(
const rdpSettings* settings, UINT32 orig, UINT32 start, UINT32 count,
398 const struct bounds_t rect1 = {
399 .x = compare->x, .y = compare->y, .width = compare->width, .height = compare->height
401 for (UINT32 x = start; x < count; x++)
404 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
405 const struct bounds_t rect2 = {
406 .x = monitor->x, .y = monitor->y, .width = monitor->width, .height = monitor->height
409 if (intersect_rects(&rect1, &rect2))
411 char buffer1[32] = { 0 };
412 char buffer2[32] = { 0 };
414 WLog_ERR(TAG,
"Monitor %" PRIu32
" and %" PRIu32
" are overlapping:", orig, x);
415 WLog_ERR(TAG,
"%s overlapps with %s", bounds2str(&rect1, buffer1,
sizeof(buffer1)),
416 bounds2str(&rect2, buffer2,
sizeof(buffer2)));
419 "Mulitimonitor mode requested, but local layout has gaps or overlapping areas!");
421 "Please reconfigure your local monitor setup so that there are no gaps or "
422 "overlapping areas!");
429static BOOL monitor_has_gaps(
const rdpSettings* settings, UINT32 start, UINT32 count,
432 const struct bounds_t rect1 = {
433 .x = compare->x, .y = compare->y, .width = compare->width, .height = compare->height
436 BOOL hasNeighbor = FALSE;
437 for (UINT32 i = 0; i < count; i++)
443 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, i);
445 const struct bounds_t rect2 = {
446 .x = monitor->x, .y = monitor->y, .width = monitor->width, .height = monitor->height
448 if (align_rects(&rect1, &rect2))
459 "Monitor configuration has gaps! Monitor %" PRIu32
" does not have any neighbor",
466static void alloc_free(UINT32** ptr)
471WINPR_ATTR_MALLOC(alloc_free, 1)
473static UINT32** alloc_array(
size_t count)
476 BYTE* array = calloc(count *
sizeof(uintptr_t), count *
sizeof(UINT32));
477 UINT32** dst = (UINT32**)array;
478 UINT32* val = (UINT32*)(array + count *
sizeof(uintptr_t));
479 for (
size_t x = 0; x < count; x++)
493static BOOL find_path_exists_with_dijkstra(UINT32** graph,
size_t count, UINT32 start)
498 WINPR_ASSERT(start < count);
500 UINT32** cost = alloc_array(count);
503 UINT32* distance = calloc(count,
sizeof(UINT32));
504 WINPR_ASSERT(distance);
506 UINT32* visited = calloc(count,
sizeof(UINT32));
507 WINPR_ASSERT(visited);
509 UINT32* parent = calloc(count,
sizeof(UINT32));
510 WINPR_ASSERT(parent);
512 for (
size_t x = 0; x < count; x++)
514 for (
size_t y = 0; y < count; y++)
516 if (graph[x][y] == 0)
517 cost[x][y] = UINT32_MAX;
519 cost[x][y] = graph[x][y];
523 for (UINT32 x = 0; x < count; x++)
525 distance[x] = cost[start][x];
534 UINT32 nextnode = UINT32_MAX;
535 while (pos < count - 1)
537 UINT32 mindistance = UINT32_MAX;
539 for (UINT32 x = 0; x < count; x++)
541 if ((distance[x] < mindistance) && !visited[x])
543 mindistance = distance[x];
548 visited[nextnode] = 1;
550 for (
size_t y = 0; y < count; y++)
554 UINT32 dist = mindistance + cost[nextnode][y];
555 if (dist < distance[y])
558 parent[y] = nextnode;
566 for (
size_t x = 0; x < count; x++)
570 if (distance[x] == UINT32_MAX)
572 WLog_ERR(TAG,
"monitor %" PRIu32
" not connected with monitor %" PRIuz, start, x);
586static BOOL freerdp_settings_client_monitors_have_gaps(
const rdpSettings* settings)
593 UINT32** graph = alloc_array(count);
596 for (UINT32 x = 0; x < count; x++)
599 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
600 if (monitor_has_gaps(settings, x, count, monitor, graph))
604 rc = !find_path_exists_with_dijkstra(graph, count, 0);
612static void log_monitor(UINT32 idx,
const rdpMonitor* monitor, wLog* log, DWORD level)
614 WINPR_ASSERT(monitor);
616 WLog_Print(log, level,
617 "[%" PRIu32
"] [%s] {%dx%d-%dx%d} [%" PRIu32
"] {%" PRIu32
"x%" PRIu32
618 ", orientation: %s [%" PRIu32
"], desktopScale: %" PRIu32
", deviceScale: %" PRIu32
620 idx, monitor->is_primary ?
"primary" :
" ", monitor->x, monitor->y,
621 monitor->width, monitor->height, monitor->orig_screen,
622 monitor->attributes.physicalWidth, monitor->attributes.physicalHeight,
623 freerdp_desktop_rotation_flags_to_string(monitor->attributes.orientation),
624 monitor->attributes.orientation, monitor->attributes.desktopScaleFactor,
625 monitor->attributes.deviceScaleFactor);
628static void log_monitor_configuration(
const rdpSettings* settings, wLog* log, DWORD level)
631 WLog_Print(log, level,
"[BEGIN] MonitorDefArray[%" PRIu32
"]", count);
632 for (UINT32 x = 0; x < count; x++)
635 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
636 log_monitor(x, monitor, log, level);
638 WLog_Print(log, level,
"[END] MonitorDefArray[%" PRIu32
"]", count);
641static BOOL freerdp_settings_client_monitors_overlap(
const rdpSettings* settings)
644 for (UINT32 x = 0; x < count; x++)
647 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
648 if (monitor_operlaps(settings, x, x + 1, count, monitor))
657static BOOL freerdp_settings_client_monitors_check_primary_and_origin(
const rdpSettings* settings)
660 BOOL havePrimary = FALSE;
661 BOOL foundOrigin = FALSE;
662 BOOL primaryIsOrigin = FALSE;
665 struct bounds_t bounds = { 0 };
669 WLog_WARN(TAG,
"Monitor configuration empty.");
673 for (UINT32 x = 0; x < count; x++)
676 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
677 struct bounds_t cur = {
678 .x = monitor->x, .y = monitor->y, .width = monitor->width, .height = monitor->height
681 bounds = union_rect(&bounds, &cur);
683 if (monitor->is_primary)
687 WLog_ERR(TAG,
"Monitor configuration contains multiple primary monitors!");
693 if ((monitor->x == 0) && (monitor->y == 0))
697 WLog_ERR(TAG,
"Monitor configuration does have multiple origin 0/0");
701 primaryIsOrigin = monitor->is_primary != 0;
705 if ((bounds.width > 32766) || (bounds.width < 200))
708 "Monitor configuration virtual desktop width must be 200 <= %" PRId32
" <= 32766",
712 if ((bounds.height > 32766) || (bounds.height < 200))
715 "Monitor configuration virtual desktop height must be 200 <= %" PRId32
" <= 32766",
722 WLog_ERR(TAG,
"Monitor configuration does not contain a primary monitor!");
727 WLog_ERR(TAG,
"Monitor configuration must start at 0/0 for first monitor!");
730 if (!primaryIsOrigin)
732 WLog_ERR(TAG,
"Monitor configuration must start at 0/0 for primary monitor!");
739BOOL freerdp_settings_check_client_after_preconnect(
const rdpSettings* settings)
741 wLog* log = WLog_Get(TAG);
743 log_monitor_configuration(settings, log, WLOG_DEBUG);
744 if (freerdp_settings_client_monitors_overlap(settings))
746 if (freerdp_settings_client_monitors_have_gaps(settings))
748 if (!freerdp_settings_client_monitors_check_primary_and_origin(settings))
752 DWORD level = WLOG_ERROR;
753 WLog_Print(log, level,
"Invalid or unsupported monitor configuration detected");
754 WLog_Print(log, level,
"Check if the configuration is valid.");
755 WLog_Print(log, level,
756 "If you suspect a bug create a new issue at "
757 "https://github.com/FreeRDP/FreeRDP/issues/new");
760 "Provide at least the following log lines detailing your monitor configuration:");
761 log_monitor_configuration(settings, log, level);
767BOOL freerdp_settings_set_default_order_support(rdpSettings* settings)
773 ZeroMemory(OrderSupport, 32);
774 OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
775 OrderSupport[NEG_PATBLT_INDEX] = TRUE;
776 OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
777 OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
778 OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE;
779 OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
780 OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
781 OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
782 OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
783 OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
784 OrderSupport[NEG_LINETO_INDEX] = TRUE;
785 OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
786 OrderSupport[NEG_MEMBLT_INDEX] =
788 OrderSupport[NEG_MEM3BLT_INDEX] =
790 OrderSupport[NEG_MEMBLT_V2_INDEX] =
792 OrderSupport[NEG_MEM3BLT_V2_INDEX] =
794 OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
795 OrderSupport[NEG_GLYPH_INDEX_INDEX] =
797 OrderSupport[NEG_FAST_INDEX_INDEX] =
799 OrderSupport[NEG_FAST_GLYPH_INDEX] =
801 OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE;
802 OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE;
803 OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
804 OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
810 return freerdp_GetConfigFilePath(FALSE,
"");
816 const BOOL remote = (flags & FREERDP_SETTINGS_REMOTE_MODE) != 0 ? TRUE : FALSE;
817 rdpSettings* settings = (rdpSettings*)calloc(1,
sizeof(rdpSettings));
823 const char* vendor = freerdp_getApplicationDetailsVendor();
824 const char* product = freerdp_getApplicationDetailsProduct();
825 const char* details = freerdp_getApplicationDetailsString();
826 char* issuer1 = NULL;
827 char* issuer2 = NULL;
828 char* issuer3 = NULL;
830 (void)winpr_asprintf(&issuer1, &len,
"%s-licenser", freerdp_getApplicationDetailsString());
831 (void)winpr_asprintf(&issuer2, &len,
"%s-licenser", freerdp_getApplicationDetailsVendor());
832 (void)winpr_asprintf(&issuer3, &len,
"%s-licenser", freerdp_getApplicationDetailsProduct());
834 char* issuers[] = { WINPR_CAST_CONST_PTR_AWAY(vendor,
char*),
835 WINPR_CAST_CONST_PTR_AWAY(product,
char*),
836 WINPR_CAST_CONST_PTR_AWAY(details,
char*),
841 const BOOL res = freerdp_server_license_issuers_copy(settings, issuers, ARRAYSIZE(issuers));
848 if (!server && !remote)
860 "ms-appx-web%%3a%%2f%%2fMicrosoft.AAD.BrokerPlugin%%2f%s"))
863 "https%%3A%%2F%%2F%s%%2F%s%%2Foauth2%%2Fnativeclient"))
866 "https%3A%2F%2Fwww.wvd.microsoft.com%2F.default%20openid%"
867 "20profile%20offline_access"))
871 "a85cf173-4192-42f8-81fa-777a763e6e2c"))
874 "login.microsoftonline.com"))
885 ORIENTATION_LANDSCAPE))
893 SURFCMDS_SET_SURFACE_BITS | SURFCMDS_STREAM_SURFACE_BITS |
894 SURFCMDS_FRAME_MARKER))
901 TS_CAPS_PROTOCOLVERSION))
905 CLIPRDR_FLAG_DEFAULT_MASK))
908 freerdp_getApplicationDetailsVendor()))
914 (void)winpr_asprintf(&val, &len,
"%s-licensing-server",
915 freerdp_getApplicationDetailsProduct());
930 RNS_UD_32BPP_SUPPORT | RNS_UD_24BPP_SUPPORT |
931 RNS_UD_16BPP_SUPPORT | RNS_UD_15BPP_SUPPORT))
941 settings, FreeRDP_RemoteApplicationSupportMask,
942 RAIL_LEVEL_SUPPORTED | RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED |
943 RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED | RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED |
944 RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED |
945 RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED | RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED |
946 RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED) ||
949 NEGOTIATE_ORDER_SUPPORT | ZERO_BOUNDS_DELTA_SUPPORT |
950 COLOR_INDEX_SUPPORT) ||
974 DEFAULT_COOKIE_MAX_LENGTH) ||
982 KEYBOARD_HOOK_FULLSCREEN_ONLY) ||
1001 CONNECTION_TYPE_AUTODETECT) ||
1043 TRANSPORT_TYPE_UDP_FECR))
1048 if (!settings_init_computer_name(settings))
1054 if (!freerdp_capability_buffer_resize(settings, 32, FALSE))
1058 char tmp[32] = { 0 };
1087 (LARGE_POINTER_FLAG_96x96 | LARGE_POINTER_FLAG_384x384)) ||
1098 settings->BitmapCacheV2CellInfo =
1101 if (!settings->BitmapCacheV2CellInfo)
1106 cache.numEntries = 600;
1107 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 0,
1109 !freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 1, &cache))
1111 cache.numEntries = 2048;
1112 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 2,
1114 !freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 4, &cache))
1116 cache.numEntries = 4096;
1117 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 3, &cache))
1127 if (!settings->GlyphCache)
1132 if (!settings->FragCache)
1135 for (
size_t x = 0; x < 10; x++)
1138 cache.cacheEntries = 254;
1143 cache.cacheMaximumCellSize = 4;
1147 cache.cacheMaximumCellSize = 8;
1150 cache.cacheMaximumCellSize = 16;
1153 cache.cacheMaximumCellSize = 32;
1156 cache.cacheMaximumCellSize = 64;
1159 cache.cacheMaximumCellSize = 128;
1162 cache.cacheMaximumCellSize = 256;
1165 cache.cacheMaximumCellSize = 256;
1171 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_GlyphCache, x, &cache))
1176 cache.cacheEntries = 256;
1177 cache.cacheMaximumCellSize = 256;
1178 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_FragCache, 0, &cache))
1189 WINDOW_LEVEL_SUPPORTED | WINDOW_LEVEL_SUPPORTED_EX) ||
1193 (server && !remote) ? CHANNEL_CHUNK_MAX_LENGTH
1194 : CHANNEL_CHUNK_LENGTH) ||
1198 server ? 0 : 608299) ||
1242 if (!settings->ClientTimeZone)
1245 if (!settings->ServerMode)
1252 GetTimeZoneInformation(tz);
1253 GetDynamicTimeZoneInformation(&dynamic);
1256 dynamic.TimeZoneKeyName,
1257 ARRAYSIZE(dynamic.TimeZoneKeyName)))
1261 dynamic.DynamicDaylightTimeDisabled))
1280 path = GetKnownPath(KNOWN_PATH_HOME);
1291 char* action = GetCombinedPath(config,
"action.sh");
1301 settings_load_hkey_local_machine(settings);
1307 settings->OrderSupport = calloc(1, 32);
1314 if (!settings->OrderSupport)
1317 if (!freerdp_settings_set_default_order_support(settings))
1323 const FreeRDP_Settings_Keys_Bool keys[] = { FreeRDP_SupportGraphicsPipeline,
1324 FreeRDP_SupportStatusInfoPdu,
1325 FreeRDP_SupportErrorInfoPdu,
1326 FreeRDP_SupportAsymetricKeys };
1328 for (
size_t x = 0; x < ARRAYSIZE(keys); x++)
1343 WINPR_PRAGMA_DIAG_PUSH
1344 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1346 WINPR_PRAGMA_DIAG_POP
1350static void freerdp_settings_free_internal(rdpSettings* settings)
1352 freerdp_server_license_issuers_free(settings);
1353 freerdp_target_net_addresses_free(settings);
1354 freerdp_device_collection_free(settings);
1355 freerdp_static_channel_collection_free(settings);
1356 freerdp_dynamic_channel_collection_free(settings);
1358 freerdp_capability_buffer_free(settings);
1361 freerdp_settings_free_keys(settings, TRUE);
1364static void freerdp_settings_free_internal_ensure_reset(rdpSettings* settings)
1366 settings->ServerLicenseProductIssuersCount = 0;
1367 settings->ServerLicenseProductIssuers = NULL;
1369 settings->ReceivedCapabilitiesSize = 0;
1377 freerdp_settings_free_internal(settings);
1381static BOOL freerdp_settings_int_buffer_copy(rdpSettings* _settings,
const rdpSettings* settings)
1385 if (!_settings || !settings)
1390 FreeRDP_Settings_Keys_UInt32 lenKey;
1391 FreeRDP_Settings_Keys_Pointer pointerKey;
1394 PointerDefs pointerDefs[] = {
1396 { FreeRDP_LoadBalanceInfoLength, FreeRDP_LoadBalanceInfo },
1397 { FreeRDP_ServerRandomLength, FreeRDP_ServerRandom },
1398 { FreeRDP_ClientRandomLength, FreeRDP_ClientRandom },
1399 { FreeRDP_ServerCertificateLength, FreeRDP_ServerCertificate },
1400 { FreeRDP_ChannelDefArraySize, FreeRDP_ChannelDefArray },
1401 { FreeRDP_NumMonitorIds, FreeRDP_MonitorIds },
1402 { FreeRDP_BitmapCacheV2NumCells, FreeRDP_BitmapCacheV2CellInfo },
1403 { FreeRDP_RedirectionPasswordLength, FreeRDP_RedirectionPassword },
1404 { FreeRDP_RedirectionTsvUrlLength, FreeRDP_RedirectionTsvUrl },
1405 { FreeRDP_RedirectionGuidLength, FreeRDP_RedirectionGuid },
1406 { FreeRDP_MonitorDefArraySize, FreeRDP_MonitorDefArray }
1409 for (
size_t i = 0; i < ARRAYSIZE(pointerDefs); i++)
1411 const PointerDefs* keys = &pointerDefs[i];
1419 if (!freerdp_server_license_issuers_copy(_settings, settings->ServerLicenseProductIssuers,
1420 settings->ServerLicenseProductIssuersCount))
1423 if (settings->RdpServerCertificate)
1425 rdpCertificate* cert = freerdp_certificate_clone(settings->RdpServerCertificate);
1437 if (settings->RdpServerRsaKey)
1439 rdpPrivateKey* key = freerdp_key_clone(settings->RdpServerRsaKey);
1455 if (settings->OrderSupport)
1457 _settings->OrderSupport = calloc(32,
sizeof(BYTE));
1458 if (!_settings->OrderSupport)
1461 CopyMemory(_settings->OrderSupport, settings->OrderSupport, 32);
1464 if (!freerdp_capability_buffer_copy(_settings, settings))
1468 const UINT32 glyphCacheCount = 10;
1477 const UINT32 fragCacheCount = 1;
1486 _settings, FreeRDP_ClientAutoReconnectCookie,
1490 _settings, FreeRDP_ServerAutoReconnectCookie,
1503 if (!freerdp_target_net_adresses_reset(_settings, nrports))
1506 for (UINT32 i = 0; i < nrports; i++)
1508 const char* address =
1509 freerdp_settings_get_pointer_array(settings, FreeRDP_TargetNetAddresses, i);
1510 const UINT32* port =
1511 freerdp_settings_get_pointer_array(settings, FreeRDP_TargetNetPorts, i);
1513 if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_TargetNetAddresses, i,
1516 if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_TargetNetPorts, i, port))
1532 for (
size_t index = 0; index < count; index++)
1535 freerdp_settings_get_pointer_array(settings, FreeRDP_DeviceArray, index);
1537 if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_DeviceArray, index, argv))
1540 WINPR_ASSERT(_settings->DeviceArray || (len == 0));
1541 WINPR_ASSERT(len >= count);
1554 for (
size_t index = 0; index < count; index++)
1557 freerdp_settings_get_pointer_array(settings, FreeRDP_StaticChannelArray, index);
1559 if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_StaticChannelArray, index,
1575 for (
size_t index = 0; index < count; index++)
1578 freerdp_settings_get_pointer_array(settings, FreeRDP_DynamicChannelArray, index);
1580 if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_DynamicChannelArray, index,
1597 if (!settings || !_settings)
1601 freerdp_settings_free_internal(_settings);
1605 rc = freerdp_settings_clone_keys(_settings, settings);
1608 freerdp_settings_free_internal_ensure_reset(_settings);
1611 if (!freerdp_settings_int_buffer_copy(_settings, settings))
1615 freerdp_settings_free_internal(_settings);
1621 rdpSettings* _settings = (rdpSettings*)calloc(1,
sizeof(rdpSettings));
1628 WINPR_PRAGMA_DIAG_PUSH
1629 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1631 WINPR_PRAGMA_DIAG_POP
1638static void zfree(WCHAR* str,
size_t len)
1641 memset(str, 0, len *
sizeof(WCHAR));
1645BOOL identity_set_from_settings_with_pwd(SEC_WINNT_AUTH_IDENTITY* identity,
1646 const rdpSettings* settings,
1647 FreeRDP_Settings_Keys_String UserId,
1648 FreeRDP_Settings_Keys_String DomainId,
1649 const WCHAR* Password,
size_t pwdLen)
1651 WINPR_ASSERT(identity);
1652 WINPR_ASSERT(settings);
1655 size_t DomainLen = 0;
1660 const int rc = sspi_SetAuthIdentityWithLengthW(identity, Username, UserLen, Domain, DomainLen,
1662 zfree(Username, UserLen);
1663 zfree(Domain, DomainLen);
1670 FreeRDP_Settings_Keys_String UserId,
1671 FreeRDP_Settings_Keys_String DomainId,
1672 FreeRDP_Settings_Keys_String PwdId)
1674 WINPR_ASSERT(identity);
1675 WINPR_ASSERT(settings);
1682 identity_set_from_settings_with_pwd(identity, settings, UserId, DomainId, Password, PwdLen);
1683 zfree(Password, PwdLen);
1688 const rdpSettings* settings,
1689 FreeRDP_Settings_Keys_String userId,
1690 FreeRDP_Settings_Keys_String domainId,
1691 FreeRDP_Settings_Keys_String pwdId,
1692 WINPR_ATTR_UNUSED
const BYTE* certSha1,
1693 WINPR_ATTR_UNUSED
size_t sha1len)
1697 LPWSTR marshalledCredentials = NULL;
1699 memcpy(certInfo.rgbHashOfCert, certSha1, MIN(sha1len,
sizeof(certInfo.rgbHashOfCert)));
1701 if (!CredMarshalCredentialW(CertCredential, &certInfo, &marshalledCredentials))
1703 WLog_ERR(TAG,
"error marshalling cert credentials");
1709 const int rc = sspi_SetAuthIdentityWithLengthW(
1710 identity, marshalledCredentials, _wcslen(marshalledCredentials), NULL, 0, Password, pwdLen);
1711 zfree(Password, pwdLen);
1712 CredFree(marshalledCredentials);
1717 if (!identity_set_from_settings(identity, settings, userId, domainId, pwdId))
1723const char* freerdp_settings_glyph_level_string(UINT32 level,
char* buffer,
size_t size)
1725 const char* str =
"GLYPH_SUPPORT_UNKNOWN";
1728 case GLYPH_SUPPORT_NONE:
1729 str =
"GLYPH_SUPPORT_NONE";
1731 case GLYPH_SUPPORT_PARTIAL:
1732 str =
"GLYPH_SUPPORT_PARTIAL";
1734 case GLYPH_SUPPORT_FULL:
1735 str =
"GLYPH_SUPPORT_FULL";
1737 case GLYPH_SUPPORT_ENCODE:
1738 str =
"GLYPH_SUPPORT_ENCODE";
1744 (void)_snprintf(buffer, size,
"%s[0x%08" PRIx32
"]", str, level);
1748BOOL freerdp_target_net_adresses_reset(rdpSettings* settings,
size_t size)
1750 freerdp_target_net_addresses_free(settings);
1752 return freerdp_target_net_addresses_resize(settings, size);
1755BOOL freerdp_settings_enforce_monitor_exists(rdpSettings* settings)
1760 const BOOL useMonitors = fullscreen || multimon;
1769 if (!useMonitors || (count == 0))
1775 const UINT16 orientation =
1777 const UINT32 desktopScaleFactor =
1779 const UINT32 deviceScaleFactor =
1788 monitor.width = WINPR_ASSERTING_INT_CAST(int32_t, width);
1789 monitor.height = WINPR_ASSERTING_INT_CAST(int32_t, height);
1790 monitor.is_primary = TRUE;
1791 monitor.orig_screen = 0;
1792 monitor.attributes.physicalWidth = pwidth;
1793 monitor.attributes.physicalHeight = pheight;
1794 monitor.attributes.orientation = orientation;
1795 monitor.attributes.desktopScaleFactor = desktopScaleFactor;
1796 monitor.attributes.deviceScaleFactor = deviceScaleFactor;
1804BOOL freerdp_settings_enforce_consistency(rdpSettings* settings)
1808 settings->OrderSupportFlagsEx |= CACHE_BITMAP_V3_SUPPORT;
1809 settings->OrderSupportFlags |= ORDER_FLAGS_EXTRA_SUPPORT;
1812 if (settings->FrameMarkerCommandEnabled)
1814 settings->OrderSupportFlagsEx |= ALTSEC_FRAME_MARKER_SUPPORT;
1815 settings->OrderSupportFlags |= ORDER_FLAGS_EXTRA_SUPPORT;
WINPR_ATTR_NODISCARD FREERDP_API const void * freerdp_settings_get_pointer(const rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a immutable pointer settings value.
FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *param)
Sets a string settings value. The param is copied.
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
rdpSettings * freerdp_settings_clone(const rdpSettings *settings)
Creates a deep copy of settings.
FREERDP_API BOOL freerdp_settings_set_string_from_utf16N(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const WCHAR *param, size_t length)
Sets a string settings value. The param is converted to UTF-8 and the copy stored.
char * freerdp_settings_get_config_path(void)
return the configuration directory for the library
FREERDP_API BOOL freerdp_settings_set_pointer_len(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id, const void *data, size_t len)
Set a pointer to value data.
WINPR_ATTR_NODISCARD FREERDP_API void * freerdp_settings_get_pointer_writable(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a mutable pointer settings value.
WINPR_ATTR_NODISCARD FREERDP_API UINT16 freerdp_settings_get_uint16(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt16 id)
Returns a UINT16 settings value.
FREERDP_API BOOL freerdp_settings_set_int32(rdpSettings *settings, FreeRDP_Settings_Keys_Int32 id, INT32 param)
Sets a INT32 settings value.
BOOL freerdp_settings_copy(rdpSettings *_settings, const rdpSettings *settings)
Deep copies settings from src to dst.
void freerdp_settings_free(rdpSettings *settings)
Free a settings struct with all data in it.
#define FREERDP_SETTINGS_SERVER_MODE
rdpSettings * freerdp_settings_new(DWORD flags)
creates a new setting struct
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API WCHAR * freerdp_settings_get_string_as_utf16(const rdpSettings *settings, FreeRDP_Settings_Keys_String id, size_t *pCharLen)
Return an allocated UTF16 string.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_monitor_def_array_sorted(rdpSettings *settings, const rdpMonitor *monitors, size_t count)
Sort monitor array according to:
FREERDP_API BOOL freerdp_settings_set_string_len(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *param, size_t len)
Sets a string settings value. The param is copied.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_uint16(rdpSettings *settings, FreeRDP_Settings_Keys_UInt16 id, UINT16 param)
Sets a UINT16 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL param)
Sets a BOOL settings value.