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#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
35#include <winpr/registry.h>
37#include <winpr/wtsapi.h>
38#include <winpr/input.h>
40#include <freerdp/version.h>
41#include <freerdp/settings.h>
42#include <freerdp/utils/string.h>
43#include <freerdp/utils/helpers.h>
44#include <freerdp/build-config.h>
46#include "../core/utils.h"
47#include "../crypto/certificate.h"
48#include "../crypto/privatekey.h"
49#include "capabilities.h"
51#define TAG FREERDP_TAG("settings")
55#pragma warning(disable : 4244)
58static const char client_dll[] =
"C:\\Windows\\System32\\mstscax.dll";
60#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
61#define SERVER_KEY "Software\\%s\\Server"
62#define CLIENT_KEY "Software\\%s\\Client"
63#define BITMAP_CACHE_KEY CLIENT_KEY "\\BitmapCacheV2"
64#define GLYPH_CACHE_KEY CLIENT_KEY "\\GlyphCache"
65#define POINTER_CACHE_KEY CLIENT_KEY "\\PointerCache"
76static const char* bounds2str(
const struct bounds_t* bounds,
char* buffer,
size_t len)
79 (void)_snprintf(buffer, len,
"{%dx%d-%dx%d}", bounds->x, bounds->y, bounds->x + bounds->width,
80 bounds->y + bounds->height);
84static struct bounds_t union_rect(const struct bounds_t* a,
const struct bounds_t* b)
89 struct bounds_t u = *a;
95 const INT32 rightA = a->x + a->width;
96 const INT32 rightB = b->x + b->width;
97 const INT32 right = MAX(rightA, rightB);
98 u.width = right - u.x;
100 const INT32 bottomA = a->y + a->height;
101 const INT32 bottomB = b->y + b->height;
102 const INT32 bottom = MAX(bottomA, bottomB);
103 u.height = bottom - u.y;
108static BOOL intersect_rects(
const struct bounds_t* r1,
const struct bounds_t* r2)
113 const INT32 left = MAX(r1->x, r2->x);
114 const INT32 top = MAX(r1->y, r2->y);
115 const INT32 right = MIN(r1->x + r1->width, r2->x + r2->width);
116 const INT32 bottom = MIN(r1->y + r1->height, r2->y + r2->height);
118 return (left < right) && (top < bottom);
121static BOOL align_rects(
const struct bounds_t* r1,
const struct bounds_t* r2)
126 const INT32 left = MAX(r1->x, r2->x);
127 const INT32 top = MAX(r1->y, r2->y);
128 const INT32 right = MIN(r1->x + r1->width, r2->x + r2->width);
129 const INT32 bottom = MIN(r1->y + r1->height, r2->y + r2->height);
131 return (left == right) || (top == bottom);
134#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
135static BOOL settings_reg_query_dword_val(HKEY hKey,
const TCHAR* sub, DWORD* value)
140 dwSize =
sizeof(DWORD);
141 if (RegQueryValueEx(hKey, sub,
nullptr, &dwType, (BYTE*)value, &dwSize) != ERROR_SUCCESS)
143 if (dwType != REG_DWORD)
149static BOOL settings_reg_query_word_val(HKEY hKey,
const TCHAR* sub, UINT16* value)
153 if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
156 if (dwValue > UINT16_MAX)
159 *value = (UINT16)dwValue;
163static BOOL settings_reg_query_bool_val(HKEY hKey,
const TCHAR* sub, BOOL* value)
167 if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
169 *value = dwValue != 0;
173static BOOL settings_reg_query_dword(rdpSettings* settings, FreeRDP_Settings_Keys_UInt32
id,
174 HKEY hKey,
const TCHAR* sub)
178 if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
184static BOOL settings_reg_query_bool(rdpSettings* settings, FreeRDP_Settings_Keys_Bool
id, HKEY hKey,
189 if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
196static void settings_load_config(rdpSettings* settings,
const char* config)
198 WINPR_JSON* json = freerdp_GetJSONConfigFile(TRUE, config);
202 if (!freerdp_settings_apply_from_json(settings, json))
204 WLog_DBG(TAG,
"%s could not be applied. File does not exist or is not valid", config);
209static void settings_client_load_hkey_local_machine(rdpSettings* settings)
211 const char config[] =
"settings-defaults-client.json";
212#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
214 char* key = freerdp_getApplicatonDetailsRegKey(CLIENT_KEY);
219 RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
222 if (status == ERROR_SUCCESS)
224 WLog_WARN(TAG,
"HKLM.reg is deprecated since 3.33.0. ATTENTION Use %s instead",
227 settings_reg_query_dword(settings, FreeRDP_DesktopWidth, hKey, _T(
"DesktopWidth"));
228 settings_reg_query_dword(settings, FreeRDP_DesktopHeight, hKey,
229 _T(
"DesktopHeight"));
230 settings_reg_query_bool(settings, FreeRDP_Fullscreen, hKey, _T(
"Fullscreen"));
231 settings_reg_query_dword(settings, FreeRDP_ColorDepth, hKey, _T(
"ColorDepth"));
232 settings_reg_query_dword(settings, FreeRDP_KeyboardType, hKey, _T(
"KeyboardType"));
233 settings_reg_query_dword(settings, FreeRDP_KeyboardSubType, hKey,
234 _T(
"KeyboardSubType"));
235 settings_reg_query_dword(settings, FreeRDP_KeyboardFunctionKey, hKey,
236 _T(
"KeyboardFunctionKeys"));
237 settings_reg_query_dword(settings, FreeRDP_KeyboardLayout, hKey,
238 _T(
"KeyboardLayout"));
239 settings_reg_query_bool(settings, FreeRDP_ExtSecurity, hKey, _T(
"ExtSecurity"));
240 settings_reg_query_bool(settings, FreeRDP_NlaSecurity, hKey, _T(
"NlaSecurity"));
241 settings_reg_query_bool(settings, FreeRDP_TlsSecurity, hKey, _T(
"TlsSecurity"));
242 settings_reg_query_bool(settings, FreeRDP_RdpSecurity, hKey, _T(
"RdpSecurity"));
243 settings_reg_query_bool(settings, FreeRDP_MstscCookieMode, hKey,
244 _T(
"MstscCookieMode"));
245 settings_reg_query_dword(settings, FreeRDP_CookieMaxLength, hKey,
246 _T(
"CookieMaxLength"));
247 settings_reg_query_bool(settings, FreeRDP_BitmapCacheEnabled, hKey,
249 settings_reg_query_dword(settings, FreeRDP_OffscreenSupportLevel, hKey,
250 _T(
"OffscreenBitmapCache"));
251 settings_reg_query_dword(settings, FreeRDP_OffscreenCacheSize, hKey,
252 _T(
"OffscreenBitmapCacheSize"));
253 settings_reg_query_dword(settings, FreeRDP_OffscreenCacheEntries, hKey,
254 _T(
"OffscreenBitmapCacheEntries"));
260 char* key = freerdp_getApplicatonDetailsRegKey(BITMAP_CACHE_KEY);
265 RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
268 if (status == ERROR_SUCCESS)
270 settings_reg_query_dword(settings, FreeRDP_BitmapCacheV2NumCells, hKey,
272 for (
unsigned x = 0; x < 5; x++)
275 TCHAR numentries[64] = WINPR_C_ARRAY_INIT;
276 TCHAR persist[64] = WINPR_C_ARRAY_INIT;
278 (void)_sntprintf(numentries, ARRAYSIZE(numentries), _T(
"Cell%uNumEntries"), x);
279 (void)_sntprintf(persist, ARRAYSIZE(persist), _T(
"Cell%uPersistent"), x);
280 if (!settings_reg_query_dword_val(hKey, numentries, &val) ||
281 !settings_reg_query_bool_val(hKey, persist, &cache.persistent))
284 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo,
286 WLog_WARN(TAG,
"Failed to load registry keys to settings!");
287 cache.numEntries = val;
290 settings_reg_query_bool(settings, FreeRDP_AllowCacheWaitingList, hKey,
291 _T(
"AllowCacheWaitingList"));
297 char* key = freerdp_getApplicatonDetailsRegKey(GLYPH_CACHE_KEY);
302 RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
305 if (status == ERROR_SUCCESS)
308 UINT32 GlyphSupportLevel = 0;
309 settings_reg_query_dword(settings, FreeRDP_GlyphSupportLevel, hKey,
314 TCHAR numentries[64] = WINPR_C_ARRAY_INIT;
315 TCHAR maxsize[64] = WINPR_C_ARRAY_INIT;
316 (void)_sntprintf(numentries, ARRAYSIZE(numentries), _T(
"Cache%uNumEntries"), x);
317 (void)_sntprintf(maxsize, ARRAYSIZE(maxsize), _T(
"Cache%uMaxCellSize"), x);
319 settings_reg_query_word_val(hKey, numentries, &cache.cacheEntries);
320 settings_reg_query_word_val(hKey, maxsize, &cache.cacheMaximumCellSize);
321 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_GlyphCache, x,
323 WLog_WARN(TAG,
"Failed to store GlyphCache %u", x);
327 settings_reg_query_word_val(hKey, _T(
"FragCacheNumEntries"),
328 &cache.cacheEntries);
329 settings_reg_query_word_val(hKey, _T(
"FragCacheMaxCellSize"),
330 &cache.cacheMaximumCellSize);
331 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_FragCache, x, &cache))
332 WLog_WARN(TAG,
"Failed to store FragCache");
339 WLog_WARN(TAG,
"Failed to load registry keys to settings!");
344 char* key = freerdp_getApplicatonDetailsRegKey(POINTER_CACHE_KEY);
349 RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
352 if (status == ERROR_SUCCESS)
354 settings_reg_query_dword(settings, FreeRDP_LargePointerFlag, hKey,
356 settings_reg_query_dword(settings, FreeRDP_PointerCacheSize, hKey,
357 _T(
"PointerCacheSize"));
358 settings_reg_query_dword(settings, FreeRDP_ColorPointerCacheSize, hKey,
359 _T(
"ColorPointerCacheSize"));
365 settings_load_config(settings, config);
368static void settings_server_load_hkey_local_machine(rdpSettings* settings)
370 const char config[] =
"settings-defaults-server.json";
372#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
376 char* key = freerdp_getApplicatonDetailsRegKey(SERVER_KEY);
381 RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
384 if (status != ERROR_SUCCESS)
387 WLog_WARN(TAG,
"HKLM.reg is deprecated since 3.33.0. ATTENTION Use %s instead", config);
389 settings_reg_query_bool(settings, FreeRDP_ExtSecurity, hKey, _T(
"ExtSecurity"));
390 settings_reg_query_bool(settings, FreeRDP_NlaSecurity, hKey, _T(
"NlaSecurity"));
391 settings_reg_query_bool(settings, FreeRDP_TlsSecurity, hKey, _T(
"TlsSecurity"));
392 settings_reg_query_dword(settings, FreeRDP_TlsSecLevel, hKey, _T(
"TlsSecLevel"));
393 settings_reg_query_bool(settings, FreeRDP_RdpSecurity, hKey, _T(
"RdpSecurity"));
399 settings_load_config(settings, config);
403static BOOL settings_load_hkey_local_machine(rdpSettings* settings)
407 settings_server_load_hkey_local_machine(settings);
409 settings_client_load_hkey_local_machine(settings);
415 "default configuration changed FreeRDP_ServerMode! This is not allowed, aborting");
420static BOOL settings_init_computer_name(rdpSettings* settings)
422 CHAR computerName[MAX_COMPUTERNAME_LENGTH + 1] = WINPR_C_ARRAY_INIT;
423 DWORD nSize = ARRAYSIZE(computerName);
425 if (!GetComputerNameExA(ComputerNameNetBIOS, computerName, &nSize))
433void freerdp_settings_print_warnings(
const rdpSettings* settings)
436 if (level != GLYPH_SUPPORT_NONE)
438 char buffer[32] = WINPR_C_ARRAY_INIT;
439 WLog_WARN(TAG,
"[experimental] enabled GlyphSupportLevel %s, expect visual artefacts!",
440 freerdp_settings_glyph_level_string(level, buffer,
sizeof(buffer)));
444static BOOL monitor_operlaps(
const rdpSettings* settings, UINT32 orig, UINT32 start, UINT32 count,
447 const struct bounds_t rect1 = {
448 .x = compare->x, .y = compare->y, .width = compare->width, .height = compare->height
450 for (UINT32 x = start; x < count; x++)
453 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
454 const struct bounds_t rect2 = {
455 .x = monitor->x, .y = monitor->y, .width = monitor->width, .height = monitor->height
458 if (intersect_rects(&rect1, &rect2))
460 char buffer1[32] = WINPR_C_ARRAY_INIT;
461 char buffer2[32] = WINPR_C_ARRAY_INIT;
463 WLog_ERR(TAG,
"Monitor %" PRIu32
" and %" PRIu32
" are overlapping:", orig, x);
464 WLog_ERR(TAG,
"%s overlapps with %s", bounds2str(&rect1, buffer1,
sizeof(buffer1)),
465 bounds2str(&rect2, buffer2,
sizeof(buffer2)));
468 "Mulitimonitor mode requested, but local layout has gaps or overlapping areas!");
470 "Please reconfigure your local monitor setup so that there are no gaps or "
471 "overlapping areas!");
478static BOOL monitor_has_gaps(
const rdpSettings* settings, UINT32 start, UINT32 count,
481 const struct bounds_t rect1 = {
482 .x = compare->x, .y = compare->y, .width = compare->width, .height = compare->height
485 BOOL hasNeighbor = FALSE;
486 for (UINT32 i = 0; i < count; i++)
492 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, i);
494 const struct bounds_t rect2 = {
495 .x = monitor->x, .y = monitor->y, .width = monitor->width, .height = monitor->height
497 if (align_rects(&rect1, &rect2))
508 "Monitor configuration has gaps! Monitor %" PRIu32
" does not have any neighbor",
515static void alloc_free(UINT32** ptr)
520WINPR_ATTR_MALLOC(alloc_free, 1)
522static UINT32** alloc_array(
size_t count)
525 BYTE* array = calloc(count *
sizeof(uintptr_t), count *
sizeof(UINT32));
526 UINT32** dst = WINPR_PACKED_ALIGN_CAST(UINT32**, array);
527 UINT32* val = WINPR_PACKED_ALIGN_CAST(UINT32*, (array + count *
sizeof(uintptr_t)));
528 for (
size_t x = 0; x < count; x++)
542static BOOL find_path_exists_with_dijkstra(UINT32** graph,
size_t count, UINT32 start)
547 WINPR_ASSERT(start < count);
549 UINT32** cost = alloc_array(count);
552 UINT32* distance = calloc(count,
sizeof(UINT32));
553 WINPR_ASSERT(distance);
555 UINT32* visited = calloc(count,
sizeof(UINT32));
556 WINPR_ASSERT(visited);
558 UINT32* parent = calloc(count,
sizeof(UINT32));
559 WINPR_ASSERT(parent);
561 for (
size_t x = 0; x < count; x++)
563 for (
size_t y = 0; y < count; y++)
565 if (graph[x][y] == 0)
566 cost[x][y] = UINT32_MAX;
568 cost[x][y] = graph[x][y];
572 for (UINT32 x = 0; x < count; x++)
574 distance[x] = cost[start][x];
583 UINT32 nextnode = UINT32_MAX;
584 while (pos < count - 1)
586 UINT32 mindistance = UINT32_MAX;
588 for (UINT32 x = 0; x < count; x++)
590 if ((distance[x] < mindistance) && !visited[x])
592 mindistance = distance[x];
597 visited[nextnode] = 1;
599 for (
size_t y = 0; y < count; y++)
603 UINT32 dist = mindistance + cost[nextnode][y];
604 if (dist < distance[y])
607 parent[y] = nextnode;
615 for (
size_t x = 0; x < count; x++)
619 if (distance[x] == UINT32_MAX)
621 WLog_ERR(TAG,
"monitor %" PRIu32
" not connected with monitor %" PRIuz, start, x);
635static BOOL freerdp_settings_client_monitors_have_gaps(
const rdpSettings* settings)
642 UINT32** graph = alloc_array(count);
645 for (UINT32 x = 0; x < count; x++)
648 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
649 if (monitor_has_gaps(settings, x, count, monitor, graph))
653 rc = !find_path_exists_with_dijkstra(graph, count, 0);
661static void log_monitor(UINT32 idx,
const rdpMonitor* monitor, wLog* log, DWORD level)
663 WINPR_ASSERT(monitor);
665 WLog_Print(log, level,
666 "[%" PRIu32
"] [%s] {%dx%d-%dx%d} [%" PRIu32
"] {%" PRIu32
"x%" PRIu32
667 ", orientation: %s [%" PRIu32
"], desktopScale: %" PRIu32
", deviceScale: %" PRIu32
669 idx, monitor->is_primary ?
"primary" :
" ", monitor->x, monitor->y,
670 monitor->width, monitor->height, monitor->orig_screen,
671 monitor->attributes.physicalWidth, monitor->attributes.physicalHeight,
672 freerdp_desktop_rotation_flags_to_string(monitor->attributes.orientation),
673 monitor->attributes.orientation, monitor->attributes.desktopScaleFactor,
674 monitor->attributes.deviceScaleFactor);
677static void log_monitor_configuration(
const rdpSettings* settings, wLog* log, DWORD level)
680 WLog_Print(log, level,
"[BEGIN] MonitorDefArray[%" PRIu32
"]", count);
681 for (UINT32 x = 0; x < count; x++)
684 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
685 log_monitor(x, monitor, log, level);
687 WLog_Print(log, level,
"[END] MonitorDefArray[%" PRIu32
"]", count);
690static BOOL freerdp_settings_client_monitors_overlap(
const rdpSettings* settings)
693 for (UINT32 x = 0; x < count; x++)
696 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
697 if (monitor_operlaps(settings, x, x + 1, count, monitor))
706static BOOL freerdp_settings_client_monitors_check_primary_and_origin(
const rdpSettings* settings)
709 BOOL havePrimary = FALSE;
710 BOOL foundOrigin = FALSE;
711 BOOL primaryIsOrigin = FALSE;
714 struct bounds_t bounds = WINPR_C_ARRAY_INIT;
718 WLog_WARN(TAG,
"Monitor configuration empty.");
722 for (UINT32 x = 0; x < count; x++)
725 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
726 struct bounds_t cur = {
727 .x = monitor->x, .y = monitor->y, .width = monitor->width, .height = monitor->height
730 bounds = union_rect(&bounds, &cur);
732 if (monitor->is_primary)
736 WLog_ERR(TAG,
"Monitor configuration contains multiple primary monitors!");
742 if ((monitor->x == 0) && (monitor->y == 0))
746 WLog_ERR(TAG,
"Monitor configuration does have multiple origin 0/0");
750 primaryIsOrigin = monitor->is_primary != 0;
754 if ((bounds.width > 32766) || (bounds.width < 200))
757 "Monitor configuration virtual desktop width must be 200 <= %" PRId32
" <= 32766",
761 if ((bounds.height > 32766) || (bounds.height < 200))
764 "Monitor configuration virtual desktop height must be 200 <= %" PRId32
" <= 32766",
771 WLog_ERR(TAG,
"Monitor configuration does not contain a primary monitor!");
776 WLog_ERR(TAG,
"Monitor configuration must start at 0/0 for first monitor!");
779 if (!primaryIsOrigin)
781 WLog_ERR(TAG,
"Monitor configuration must start at 0/0 for primary monitor!");
788BOOL freerdp_settings_check_client_after_preconnect(
const rdpSettings* settings)
790 wLog* log = WLog_Get(TAG);
792 log_monitor_configuration(settings, log, WLOG_DEBUG);
793 if (freerdp_settings_client_monitors_overlap(settings))
795 if (freerdp_settings_client_monitors_have_gaps(settings))
797 if (!freerdp_settings_client_monitors_check_primary_and_origin(settings))
801 DWORD level = WLOG_ERROR;
802 WLog_Print(log, level,
"Invalid or unsupported monitor configuration detected");
803 WLog_Print(log, level,
"Check if the configuration is valid.");
804 WLog_Print(log, level,
805 "If you suspect a bug create a new issue at "
806 "https://github.com/FreeRDP/FreeRDP/issues/new");
809 "Provide at least the following log lines detailing your monitor configuration:");
810 log_monitor_configuration(settings, log, level);
816BOOL freerdp_settings_set_default_order_support(rdpSettings* settings)
822 ZeroMemory(OrderSupport, 32);
823 OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
824 OrderSupport[NEG_PATBLT_INDEX] = TRUE;
825 OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
826 OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
827 OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE;
828 OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
829 OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
830 OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
831 OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
832 OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
833 OrderSupport[NEG_LINETO_INDEX] = TRUE;
834 OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
835 OrderSupport[NEG_MEMBLT_INDEX] =
837 OrderSupport[NEG_MEM3BLT_INDEX] =
839 OrderSupport[NEG_MEMBLT_V2_INDEX] =
841 OrderSupport[NEG_MEM3BLT_V2_INDEX] =
843 OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
844 OrderSupport[NEG_GLYPH_INDEX_INDEX] =
846 OrderSupport[NEG_FAST_INDEX_INDEX] =
848 OrderSupport[NEG_FAST_GLYPH_INDEX] =
850 OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE;
851 OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE;
852 OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
853 OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
859 return freerdp_GetConfigFilePath(FALSE,
"");
865 const BOOL remote = ((flags & FREERDP_SETTINGS_REMOTE_MODE) != 0);
866 rdpSettings* settings = (rdpSettings*)calloc(1,
sizeof(rdpSettings));
872 const char* vendor = freerdp_getApplicationDetailsVendor();
873 const char* product = freerdp_getApplicationDetailsProduct();
874 const char* details = freerdp_getApplicationDetailsString();
875 char* issuer1 =
nullptr;
876 char* issuer2 =
nullptr;
877 char* issuer3 =
nullptr;
879 (void)winpr_asprintf(&issuer1, &len,
"%s-licenser", freerdp_getApplicationDetailsString());
880 (void)winpr_asprintf(&issuer2, &len,
"%s-licenser", freerdp_getApplicationDetailsVendor());
881 (void)winpr_asprintf(&issuer3, &len,
"%s-licenser", freerdp_getApplicationDetailsProduct());
883 char* issuers[] = { WINPR_CAST_CONST_PTR_AWAY(vendor,
char*),
884 WINPR_CAST_CONST_PTR_AWAY(product,
char*),
885 WINPR_CAST_CONST_PTR_AWAY(details,
char*),
890 const BOOL res = freerdp_server_license_issuers_copy(settings, issuers, ARRAYSIZE(issuers));
897 if (!server && !remote)
909 "ms-appx-web%%3a%%2f%%2fMicrosoft.AAD.BrokerPlugin%%2f%s"))
912 "https%%3A%%2F%%2F%s%%2F%s%%2Foauth2%%2Fnativeclient"))
915 "https%3A%2F%2Fwww.wvd.microsoft.com%2F.default%20openid%"
916 "20profile%20offline_access"))
920 "a85cf173-4192-42f8-81fa-777a763e6e2c"))
923 "login.microsoftonline.com"))
934 ORIENTATION_LANDSCAPE))
942 SURFCMDS_SET_SURFACE_BITS | SURFCMDS_STREAM_SURFACE_BITS |
943 SURFCMDS_FRAME_MARKER))
950 TS_CAPS_PROTOCOLVERSION))
954 CLIPRDR_FLAG_DEFAULT_MASK))
957 freerdp_getApplicationDetailsVendor()))
963 (void)winpr_asprintf(&val, &len,
"%s-licensing-server",
964 freerdp_getApplicationDetailsProduct());
979 RNS_UD_32BPP_SUPPORT | RNS_UD_24BPP_SUPPORT |
980 RNS_UD_16BPP_SUPPORT | RNS_UD_15BPP_SUPPORT))
983 const UINT32 railflags = TS_RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE |
984 TS_RAIL_CLIENTSTATUS_ZORDER_SYNC |
985 TS_RAIL_CLIENTSTATUS_WINDOW_RESIZE_MARGIN_SUPPORTED |
986 TS_RAIL_CLIENTSTATUS_APPBAR_REMOTING_SUPPORTED |
987 TS_RAIL_CLIENTSTATUS_POWER_DISPLAY_REQUEST_SUPPORTED |
988 TS_RAIL_CLIENTSTATUS_BIDIRECTIONAL_CLOAK_SUPPORTED;
999 settings, FreeRDP_RemoteApplicationSupportMask,
1000 RAIL_LEVEL_SUPPORTED | RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED |
1001 RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED | RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED |
1002 RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED |
1003 RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED | RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED |
1004 RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED) ||
1007 NEGOTIATE_ORDER_SUPPORT | ZERO_BOUNDS_DELTA_SUPPORT |
1008 COLOR_INDEX_SUPPORT) ||
1032 DEFAULT_COOKIE_MAX_LENGTH) ||
1040 KEYBOARD_HOOK_FULLSCREEN_ONLY) ||
1059 CONNECTION_TYPE_AUTODETECT) ||
1101 UINT32 multitransportFlags = TRANSPORT_TYPE_UDP_FECR;
1102#if defined(WITH_RDPEUDP)
1105 multitransportFlags |= SOFTSYNC_TCP_TO_UDP;
1110 multitransportFlags = 0;
1113 multitransportFlags))
1119 if (!settings_init_computer_name(settings))
1125 if (!freerdp_capability_buffer_resize(settings, 32, FALSE))
1129 char tmp[32] = WINPR_C_ARRAY_INIT;
1158 (LARGE_POINTER_FLAG_96x96 | LARGE_POINTER_FLAG_384x384)) ||
1170 { 600, FALSE }, { 600, FALSE }, { 65536, FALSE }, { 4096, FALSE }, { 2048, FALSE }
1173 ARRAYSIZE(CellInfo)))
1183 if (!settings->GlyphCache)
1188 if (!settings->FragCache)
1191 for (
size_t x = 0; x < 10; x++)
1194 cache.cacheEntries = 254;
1199 cache.cacheMaximumCellSize = 4;
1203 cache.cacheMaximumCellSize = 8;
1206 cache.cacheMaximumCellSize = 16;
1209 cache.cacheMaximumCellSize = 32;
1212 cache.cacheMaximumCellSize = 64;
1215 cache.cacheMaximumCellSize = 128;
1218 cache.cacheMaximumCellSize = 256;
1221 cache.cacheMaximumCellSize = 256;
1227 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_GlyphCache, x, &cache))
1232 cache.cacheEntries = 256;
1233 cache.cacheMaximumCellSize = 256;
1234 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_FragCache, 0, &cache))
1245 WINDOW_LEVEL_SUPPORTED | WINDOW_LEVEL_SUPPORTED_EX) ||
1249 (server && !remote) ? CHANNEL_CHUNK_MAX_LENGTH
1250 : CHANNEL_CHUNK_LENGTH) ||
1254 server ? 0 : 608299) ||
1300 if (!settings->ClientTimeZone)
1303 if (!settings->ServerMode)
1310 GetTimeZoneInformation(tz);
1311 GetDynamicTimeZoneInformation(&dynamic);
1314 dynamic.TimeZoneKeyName,
1315 ARRAYSIZE(dynamic.TimeZoneKeyName)))
1319 dynamic.DynamicDaylightTimeDisabled))
1339 char* path =
nullptr;
1343 path = GetKnownPath(KNOWN_PATH_HOME);
1354 char* action = GetCombinedPath(config,
"action.sh");
1368 settings->OrderSupport = calloc(1, 32);
1375 if (!settings->OrderSupport)
1378 if (!freerdp_settings_set_default_order_support(settings))
1384 const FreeRDP_Settings_Keys_Bool keys[] = { FreeRDP_SupportGraphicsPipeline,
1385 FreeRDP_SupportStatusInfoPdu,
1386 FreeRDP_SupportErrorInfoPdu,
1387 FreeRDP_SupportAsymetricKeys };
1389 for (
size_t x = 0; x < ARRAYSIZE(keys); x++)
1402 UUID corrId = WINPR_C_ARRAY_INIT;
1403 if (UuidCreate(&corrId) != RPC_S_OK)
1406 char buffer[64] = WINPR_C_ARRAY_INIT;
1408 guid2str(&corrId, buffer,
sizeof(buffer))))
1411 if (!settings_load_hkey_local_machine(settings))
1416 WINPR_PRAGMA_DIAG_PUSH
1417 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1419 WINPR_PRAGMA_DIAG_POP
1423static void freerdp_settings_free_internal(rdpSettings* settings)
1425 freerdp_server_license_issuers_free(settings);
1426 freerdp_target_net_addresses_free(settings);
1427 freerdp_device_collection_free(settings);
1428 freerdp_static_channel_collection_free(settings);
1429 freerdp_dynamic_channel_collection_free(settings);
1431 freerdp_capability_buffer_free(settings);
1434 freerdp_settings_free_keys(settings, TRUE);
1437static void freerdp_settings_free_internal_ensure_reset(rdpSettings* settings)
1439 settings->ServerLicenseProductIssuersCount = 0;
1440 settings->ServerLicenseProductIssuers =
nullptr;
1442 settings->ReceivedCapabilitiesSize = 0;
1450 freerdp_settings_free_internal(settings);
1454static BOOL freerdp_settings_int_buffer_copy(rdpSettings* dst,
const rdpSettings* settings)
1458 if (!dst || !settings)
1463 FreeRDP_Settings_Keys_UInt32 lenKey;
1464 FreeRDP_Settings_Keys_Pointer pointerKey;
1467 PointerDefs pointerDefs[] = {
1469 { FreeRDP_LoadBalanceInfoLength, FreeRDP_LoadBalanceInfo },
1470 { FreeRDP_ServerRandomLength, FreeRDP_ServerRandom },
1471 { FreeRDP_ClientRandomLength, FreeRDP_ClientRandom },
1472 { FreeRDP_ServerCertificateLength, FreeRDP_ServerCertificate },
1473 { FreeRDP_ChannelDefArraySize, FreeRDP_ChannelDefArray },
1474 { FreeRDP_NumMonitorIds, FreeRDP_MonitorIds },
1475 { FreeRDP_BitmapCacheV2NumCells, FreeRDP_BitmapCacheV2CellInfo },
1476 { FreeRDP_RedirectionPasswordLength, FreeRDP_RedirectionPassword },
1477 { FreeRDP_RedirectionTsvUrlLength, FreeRDP_RedirectionTsvUrl },
1478 { FreeRDP_RedirectionGuidLength, FreeRDP_RedirectionGuid },
1479 { FreeRDP_MonitorDefArraySize, FreeRDP_MonitorDefArray }
1482 for (
size_t i = 0; i < ARRAYSIZE(pointerDefs); i++)
1484 const PointerDefs* keys = &pointerDefs[i];
1492 if (!freerdp_server_license_issuers_copy(dst, settings->ServerLicenseProductIssuers,
1493 settings->ServerLicenseProductIssuersCount))
1496 if (settings->RdpServerCertificate)
1498 rdpCertificate* cert = freerdp_certificate_clone(settings->RdpServerCertificate);
1503 freerdp_certificate_free(cert);
1513 if (settings->RdpServerRsaKey)
1515 rdpPrivateKey* key = freerdp_key_clone(settings->RdpServerRsaKey);
1520 freerdp_key_free(key);
1534 if (settings->OrderSupport)
1536 dst->OrderSupport = calloc(32,
sizeof(BYTE));
1537 if (!dst->OrderSupport)
1540 CopyMemory(dst->OrderSupport, settings->OrderSupport, 32);
1543 if (!freerdp_capability_buffer_copy(dst, settings))
1547 const UINT32 glyphCacheCount = 10;
1555 const UINT32 fragCacheCount = 1;
1563 dst, FreeRDP_ClientAutoReconnectCookie,
1567 dst, FreeRDP_ServerAutoReconnectCookie,
1580 if (!freerdp_target_net_adresses_reset(dst, nrports))
1583 for (UINT32 i = 0; i < nrports; i++)
1585 const char* address =
1586 freerdp_settings_get_pointer_array(settings, FreeRDP_TargetNetAddresses, i);
1587 const UINT32* port =
1588 freerdp_settings_get_pointer_array(settings, FreeRDP_TargetNetPorts, i);
1590 if (!freerdp_settings_set_pointer_array(dst, FreeRDP_TargetNetAddresses, i, address))
1592 if (!freerdp_settings_set_pointer_array(dst, FreeRDP_TargetNetPorts, i, port))
1608 for (
size_t index = 0; index < count; index++)
1611 freerdp_settings_get_pointer_array(settings, FreeRDP_DeviceArray, index);
1613 if (!freerdp_settings_set_pointer_array(dst, FreeRDP_DeviceArray, index, argv))
1616 WINPR_ASSERT(dst->DeviceArray || (len == 0));
1617 WINPR_ASSERT(len >= count);
1630 for (
size_t index = 0; index < count; index++)
1633 freerdp_settings_get_pointer_array(settings, FreeRDP_StaticChannelArray, index);
1635 if (!freerdp_settings_set_pointer_array(dst, FreeRDP_StaticChannelArray, index, argv))
1650 for (
size_t index = 0; index < count; index++)
1653 freerdp_settings_get_pointer_array(settings, FreeRDP_DynamicChannelArray, index);
1655 if (!freerdp_settings_set_pointer_array(dst, FreeRDP_DynamicChannelArray, index, argv))
1675 freerdp_settings_free_internal(dst);
1679 rc = freerdp_settings_clone_keys(dst, src);
1682 freerdp_settings_free_internal_ensure_reset(dst);
1685 if (!freerdp_settings_int_buffer_copy(dst, src))
1689 freerdp_settings_free_internal(dst);
1695 rdpSettings* dst = (rdpSettings*)calloc(1,
sizeof(rdpSettings));
1702 WINPR_PRAGMA_DIAG_PUSH
1703 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1705 WINPR_PRAGMA_DIAG_POP
1712BOOL identity_set_from_settings_with_pwd(SEC_WINNT_AUTH_IDENTITY* identity,
1713 const rdpSettings* settings,
1714 FreeRDP_Settings_Keys_String UserId,
1715 FreeRDP_Settings_Keys_String DomainId,
1716 const WCHAR* Password,
size_t pwdLen)
1718 WINPR_ASSERT(identity);
1719 WINPR_ASSERT(settings);
1722 size_t DomainLen = 0;
1727 const int rc = sspi_SetAuthIdentityWithLengthW(identity, Username, UserLen, Domain, DomainLen,
1729 winpr_znfree(Username, UserLen *
sizeof(WCHAR));
1730 winpr_znfree(Domain, DomainLen *
sizeof(WCHAR));
1735 FreeRDP_Settings_Keys_String UserId,
1736 FreeRDP_Settings_Keys_String DomainId,
1737 FreeRDP_Settings_Keys_String PwdId)
1739 WINPR_ASSERT(identity);
1740 WINPR_ASSERT(settings);
1747 identity_set_from_settings_with_pwd(identity, settings, UserId, DomainId, Password, PwdLen);
1748 winpr_znfree(Password, PwdLen *
sizeof(WCHAR));
1753 const rdpSettings* settings,
1754 FreeRDP_Settings_Keys_String userId,
1755 FreeRDP_Settings_Keys_String domainId,
1756 FreeRDP_Settings_Keys_String pwdId,
1757 WINPR_ATTR_UNUSED
const BYTE* certSha1,
1758 WINPR_ATTR_UNUSED
size_t sha1len)
1762 LPWSTR marshalledCredentials =
nullptr;
1764 memcpy(certInfo.rgbHashOfCert, certSha1, MIN(sha1len,
sizeof(certInfo.rgbHashOfCert)));
1766 if (!CredMarshalCredentialW(CertCredential, &certInfo, &marshalledCredentials))
1768 WLog_ERR(TAG,
"error marshalling cert credentials");
1774 const int rc = sspi_SetAuthIdentityWithLengthW(identity, marshalledCredentials,
1775 _wcslen(marshalledCredentials),
nullptr, 0,
1777 winpr_znfree(Password, pwdLen *
sizeof(WCHAR));
1778 CredFree(marshalledCredentials);
1781 return identity_set_from_settings(identity, settings, userId, domainId, pwdId);
1785const char* freerdp_settings_glyph_level_string(UINT32 level,
char* buffer,
size_t size)
1787 const char* str =
"GLYPH_SUPPORT_UNKNOWN";
1790 case GLYPH_SUPPORT_NONE:
1791 str =
"GLYPH_SUPPORT_NONE";
1793 case GLYPH_SUPPORT_PARTIAL:
1794 str =
"GLYPH_SUPPORT_PARTIAL";
1796 case GLYPH_SUPPORT_FULL:
1797 str =
"GLYPH_SUPPORT_FULL";
1799 case GLYPH_SUPPORT_ENCODE:
1800 str =
"GLYPH_SUPPORT_ENCODE";
1806 (void)_snprintf(buffer, size,
"%s[0x%08" PRIx32
"]", str, level);
1810BOOL freerdp_target_net_adresses_reset(rdpSettings* settings,
size_t size)
1812 freerdp_target_net_addresses_free(settings);
1814 return freerdp_target_net_addresses_resize(settings, size);
1817BOOL freerdp_settings_enforce_monitor_exists(rdpSettings* settings)
1822 const BOOL useMonitors = fullscreen || multimon;
1831 if (!useMonitors || (count == 0))
1837 const UINT16 orientation =
1839 const UINT32 desktopScaleFactor =
1841 const UINT32 deviceScaleFactor =
1850 monitor.width = WINPR_ASSERTING_INT_CAST(int32_t, width);
1851 monitor.height = WINPR_ASSERTING_INT_CAST(int32_t, height);
1852 monitor.is_primary = TRUE;
1853 monitor.orig_screen = 0;
1854 monitor.attributes.physicalWidth = pwidth;
1855 monitor.attributes.physicalHeight = pheight;
1856 monitor.attributes.orientation = orientation;
1857 monitor.attributes.desktopScaleFactor = desktopScaleFactor;
1858 monitor.attributes.deviceScaleFactor = deviceScaleFactor;
1866void freerdp_settings_sanitize_keyboard_type(wLog* log, rdpSettings* settings,
const char* source)
1868 WINPR_ASSERT(settings);
1870 switch (settings->KeyboardType)
1872 case WINPR_KBD_TYPE_IBM_PC_XT:
1873 case WINPR_KBD_TYPE_OLIVETTI_ICO:
1874 case WINPR_KBD_TYPE_IBM_PC_AT:
1875 case WINPR_KBD_TYPE_IBM_ENHANCED:
1876 case WINPR_KBD_TYPE_NOKIA_1050:
1877 case WINPR_KBD_TYPE_NOKIA_9140:
1878 case WINPR_KBD_TYPE_JAPANESE:
1879 case WINPR_KBD_TYPE_KOREAN:
1886 log = WLog_Get(TAG);
1887 WLog_Print(log, WLOG_WARN,
1888 "%s: KeyboardType=0x%08" PRIx32
1889 " is not a known WINPR_KBD_TYPE, using WINPR_KBD_TYPE_IBM_ENHANCED instead",
1890 source ? source :
"settings", settings->KeyboardType);
1891 settings->KeyboardType = WINPR_KBD_TYPE_IBM_ENHANCED;
1894BOOL freerdp_settings_enforce_consistency(rdpSettings* settings)
1898 settings->OrderSupportFlagsEx |= CACHE_BITMAP_V3_SUPPORT;
1899 settings->OrderSupportFlags |= ORDER_FLAGS_EXTRA_SUPPORT;
1902 if (settings->FrameMarkerCommandEnabled)
1904 settings->OrderSupportFlagsEx |= ALTSEC_FRAME_MARKER_SUPPORT;
1905 settings->OrderSupportFlags |= ORDER_FLAGS_EXTRA_SUPPORT;
WINPR_API void WINPR_JSON_Delete(WINPR_JSON *item)
Delete a WinPR JSON wrapper object.
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.
WINPR_ATTR_NODISCARD 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.
rdpSettings * freerdp_settings_new(DWORD flags)
creates a new setting struct
rdpSettings * freerdp_settings_clone(const rdpSettings *settings)
Creates a deep copy of settings.
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.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL val)
Sets a BOOL settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_string_len(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *val, size_t len)
Sets a string settings value. The val is copied.
char * freerdp_settings_get_config_path(void)
return the configuration directory for the library
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.
BOOL freerdp_settings_copy(rdpSettings *dst, const rdpSettings *src)
Deep copies settings from src to dst.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
WINPR_ATTR_NODISCARD 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 BOOL freerdp_settings_set_int32(rdpSettings *settings, FreeRDP_Settings_Keys_Int32 id, INT32 val)
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
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
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_uint16(rdpSettings *settings, FreeRDP_Settings_Keys_UInt16 id, UINT16 val)
Sets a UINT16 settings value.
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:
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *val)
Sets a string settings value. The param is copied.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.