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/settings.h>
38#include <freerdp/build-config.h>
40#include "../crypto/certificate.h"
41#include "../crypto/privatekey.h"
42#include "capabilities.h"
44#define TAG FREERDP_TAG("settings")
48#pragma warning(disable : 4244)
51static const char client_dll[] =
"C:\\Windows\\System32\\mstscax.dll";
53#define SERVER_KEY "Software\\" FREERDP_VENDOR_STRING "\\" FREERDP_PRODUCT_STRING "\\Server"
54#define CLIENT_KEY "Software\\" FREERDP_VENDOR_STRING "\\" FREERDP_PRODUCT_STRING "\\Client"
55#define BITMAP_CACHE_KEY CLIENT_KEY "\\BitmapCacheV2"
56#define GLYPH_CACHE_KEY CLIENT_KEY "\\GlyphCache"
57#define POINTER_CACHE_KEY CLIENT_KEY "\\PointerCache"
67static const char* bounds2str(
const struct bounds_t* bounds,
char* buffer,
size_t len)
70 (void)_snprintf(buffer, len,
"{%dx%d-%dx%d}", bounds->x, bounds->y, bounds->x + bounds->width,
71 bounds->y + bounds->height);
75static struct bounds_t union_rect(const struct bounds_t* a,
const struct bounds_t* b)
80 struct bounds_t u = *a;
86 const INT32 rightA = a->x + a->width;
87 const INT32 rightB = b->x + b->width;
88 const INT32 right = MAX(rightA, rightB);
89 u.width = right - u.x;
91 const INT32 bottomA = a->y + a->height;
92 const INT32 bottomB = b->y + b->height;
93 const INT32 bottom = MAX(bottomA, bottomB);
94 u.height = bottom - u.y;
99static BOOL intersect_rects(
const struct bounds_t* r1,
const struct bounds_t* r2)
104 const INT32 left = MAX(r1->x, r2->x);
105 const INT32 top = MAX(r1->y, r2->y);
106 const INT32 right = MIN(r1->x + r1->width, r2->x + r2->width);
107 const INT32 bottom = MIN(r1->y + r1->height, r2->y + r2->height);
109 return (left < right) && (top < bottom);
112static BOOL align_rects(
const struct bounds_t* r1,
const struct bounds_t* r2)
117 const INT32 left = MAX(r1->x, r2->x);
118 const INT32 top = MAX(r1->y, r2->y);
119 const INT32 right = MIN(r1->x + r1->width, r2->x + r2->width);
120 const INT32 bottom = MIN(r1->y + r1->height, r2->y + r2->height);
122 return (left == right) || (top == bottom);
125static BOOL settings_reg_query_dword_val(HKEY hKey,
const TCHAR* sub, DWORD* value)
130 dwSize =
sizeof(DWORD);
131 if (RegQueryValueEx(hKey, sub, NULL, &dwType, (BYTE*)value, &dwSize) != ERROR_SUCCESS)
133 if (dwType != REG_DWORD)
139static BOOL settings_reg_query_word_val(HKEY hKey,
const TCHAR* sub, UINT16* value)
143 if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
146 if (dwValue > UINT16_MAX)
149 *value = (UINT16)dwValue;
153static BOOL settings_reg_query_bool_val(HKEY hKey,
const TCHAR* sub, BOOL* value)
157 if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
159 *value = dwValue != 0;
163static BOOL settings_reg_query_dword(rdpSettings* settings, FreeRDP_Settings_Keys_UInt32
id,
164 HKEY hKey,
const TCHAR* sub)
168 if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
174static BOOL settings_reg_query_bool(rdpSettings* settings, FreeRDP_Settings_Keys_Bool
id, HKEY hKey,
179 if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
185static void settings_client_load_hkey_local_machine(rdpSettings* settings)
189 status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, CLIENT_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
191 if (status == ERROR_SUCCESS)
193 settings_reg_query_dword(settings, FreeRDP_DesktopWidth, hKey, _T(
"DesktopWidth"));
194 settings_reg_query_dword(settings, FreeRDP_DesktopHeight, hKey, _T(
"DesktopHeight"));
195 settings_reg_query_bool(settings, FreeRDP_Fullscreen, hKey, _T(
"Fullscreen"));
196 settings_reg_query_dword(settings, FreeRDP_ColorDepth, hKey, _T(
"ColorDepth"));
197 settings_reg_query_dword(settings, FreeRDP_KeyboardType, hKey, _T(
"KeyboardType"));
198 settings_reg_query_dword(settings, FreeRDP_KeyboardSubType, hKey, _T(
"KeyboardSubType"));
199 settings_reg_query_dword(settings, FreeRDP_KeyboardFunctionKey, hKey,
200 _T(
"KeyboardFunctionKeys"));
201 settings_reg_query_dword(settings, FreeRDP_KeyboardLayout, hKey, _T(
"KeyboardLayout"));
202 settings_reg_query_bool(settings, FreeRDP_ExtSecurity, hKey, _T(
"ExtSecurity"));
203 settings_reg_query_bool(settings, FreeRDP_NlaSecurity, hKey, _T(
"NlaSecurity"));
204 settings_reg_query_bool(settings, FreeRDP_TlsSecurity, hKey, _T(
"TlsSecurity"));
205 settings_reg_query_bool(settings, FreeRDP_RdpSecurity, hKey, _T(
"RdpSecurity"));
206 settings_reg_query_bool(settings, FreeRDP_MstscCookieMode, hKey, _T(
"MstscCookieMode"));
207 settings_reg_query_dword(settings, FreeRDP_CookieMaxLength, hKey, _T(
"CookieMaxLength"));
208 settings_reg_query_bool(settings, FreeRDP_BitmapCacheEnabled, hKey, _T(
"BitmapCache"));
209 settings_reg_query_dword(settings, FreeRDP_OffscreenSupportLevel, hKey,
210 _T(
"OffscreenBitmapCache"));
211 settings_reg_query_dword(settings, FreeRDP_OffscreenCacheSize, hKey,
212 _T(
"OffscreenBitmapCacheSize"));
213 settings_reg_query_dword(settings, FreeRDP_OffscreenCacheEntries, hKey,
214 _T(
"OffscreenBitmapCacheEntries"));
219 RegOpenKeyExA(HKEY_LOCAL_MACHINE, BITMAP_CACHE_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
221 if (status == ERROR_SUCCESS)
223 settings_reg_query_dword(settings, FreeRDP_BitmapCacheV2NumCells, hKey, _T(
"NumCells"));
224 for (
unsigned x = 0; x < 5; x++)
227 TCHAR numentries[64] = { 0 };
228 TCHAR persist[64] = { 0 };
230 (void)_sntprintf(numentries, ARRAYSIZE(numentries), _T(
"Cell%uNumEntries"), x);
231 (void)_sntprintf(persist, ARRAYSIZE(persist), _T(
"Cell%uPersistent"), x);
232 if (!settings_reg_query_dword_val(hKey, numentries, &val) ||
233 !settings_reg_query_bool_val(hKey, persist, &cache.persistent) ||
234 !freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, x,
236 WLog_WARN(TAG,
"Failed to load registry keys to settings!");
237 cache.numEntries = val;
240 settings_reg_query_bool(settings, FreeRDP_AllowCacheWaitingList, hKey,
241 _T(
"AllowCacheWaitingList"));
246 RegOpenKeyExA(HKEY_LOCAL_MACHINE, GLYPH_CACHE_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
248 if (status == ERROR_SUCCESS)
251 UINT32 GlyphSupportLevel = 0;
252 settings_reg_query_dword(settings, FreeRDP_GlyphSupportLevel, hKey, _T(
"SupportLevel"));
256 TCHAR numentries[64] = { 0 };
257 TCHAR maxsize[64] = { 0 };
258 (void)_sntprintf(numentries, ARRAYSIZE(numentries), _T(
"Cache%uNumEntries"), x);
259 (void)_sntprintf(maxsize, ARRAYSIZE(maxsize), _T(
"Cache%uMaxCellSize"), x);
261 settings_reg_query_word_val(hKey, numentries, &cache.cacheEntries);
262 settings_reg_query_word_val(hKey, maxsize, &cache.cacheMaximumCellSize);
263 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_GlyphCache, x, &cache))
264 WLog_WARN(TAG,
"Failed to store GlyphCache %" PRIuz, x);
268 settings_reg_query_word_val(hKey, _T(
"FragCacheNumEntries"), &cache.cacheEntries);
269 settings_reg_query_word_val(hKey, _T(
"FragCacheMaxCellSize"),
270 &cache.cacheMaximumCellSize);
271 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_FragCache, x, &cache))
272 WLog_WARN(TAG,
"Failed to store FragCache");
278 WLog_WARN(TAG,
"Failed to load registry keys to settings!");
282 RegOpenKeyExA(HKEY_LOCAL_MACHINE, POINTER_CACHE_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
284 if (status == ERROR_SUCCESS)
286 settings_reg_query_dword(settings, FreeRDP_LargePointerFlag, hKey, _T(
"LargePointer"));
287 settings_reg_query_dword(settings, FreeRDP_PointerCacheSize, hKey, _T(
"PointerCacheSize"));
288 settings_reg_query_dword(settings, FreeRDP_ColorPointerCacheSize, hKey,
289 _T(
"ColorPointerCacheSize"));
294static void settings_server_load_hkey_local_machine(rdpSettings* settings)
299 status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, SERVER_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
301 if (status != ERROR_SUCCESS)
304 settings_reg_query_bool(settings, FreeRDP_ExtSecurity, hKey, _T(
"ExtSecurity"));
305 settings_reg_query_bool(settings, FreeRDP_NlaSecurity, hKey, _T(
"NlaSecurity"));
306 settings_reg_query_bool(settings, FreeRDP_TlsSecurity, hKey, _T(
"TlsSecurity"));
307 settings_reg_query_dword(settings, FreeRDP_TlsSecLevel, hKey, _T(
"TlsSecLevel"));
308 settings_reg_query_bool(settings, FreeRDP_RdpSecurity, hKey, _T(
"RdpSecurity"));
313static void settings_load_hkey_local_machine(rdpSettings* settings)
316 settings_server_load_hkey_local_machine(settings);
318 settings_client_load_hkey_local_machine(settings);
321static BOOL settings_init_computer_name(rdpSettings* settings)
323 CHAR computerName[MAX_COMPUTERNAME_LENGTH + 1] = { 0 };
324 DWORD nSize = ARRAYSIZE(computerName);
326 if (!GetComputerNameExA(ComputerNameNetBIOS, computerName, &nSize))
334void freerdp_settings_print_warnings(
const rdpSettings* settings)
337 if (level != GLYPH_SUPPORT_NONE)
339 char buffer[32] = { 0 };
340 WLog_WARN(TAG,
"[experimental] enabled GlyphSupportLevel %s, expect visual artefacts!",
341 freerdp_settings_glyph_level_string(level, buffer,
sizeof(buffer)));
345static BOOL monitor_operlaps(
const rdpSettings* settings, UINT32 orig, UINT32 start, UINT32 count,
348 const struct bounds_t rect1 = {
349 .x = compare->x, .y = compare->y, .width = compare->width, .height = compare->height
351 for (UINT32 x = start; x < count; x++)
354 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
355 const struct bounds_t rect2 = {
356 .x = monitor->x, .y = monitor->y, .width = monitor->width, .height = monitor->height
359 if (intersect_rects(&rect1, &rect2))
361 char buffer1[32] = { 0 };
362 char buffer2[32] = { 0 };
364 WLog_ERR(TAG,
"Monitor %" PRIu32
" and %" PRIu32
" are overlapping:", orig, x);
365 WLog_ERR(TAG,
"%s overlapps with %s", bounds2str(&rect1, buffer1,
sizeof(buffer1)),
366 bounds2str(&rect2, buffer2,
sizeof(buffer2)));
369 "Mulitimonitor mode requested, but local layout has gaps or overlapping areas!");
371 "Please reconfigure your local monitor setup so that there are no gaps or "
372 "overlapping areas!");
379static BOOL monitor_has_gaps(
const rdpSettings* settings, UINT32 start, UINT32 count,
382 const struct bounds_t rect1 = {
383 .x = compare->x, .y = compare->y, .width = compare->width, .height = compare->height
386 BOOL hasNeighbor = FALSE;
387 for (UINT32 i = 0; i < count; i++)
393 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, i);
395 const struct bounds_t rect2 = {
396 .x = monitor->x, .y = monitor->y, .width = monitor->width, .height = monitor->height
398 if (align_rects(&rect1, &rect2))
409 "Monitor configuration has gaps! Monitor %" PRIu32
" does not have any neighbor",
416static void alloc_free(UINT32** ptr)
421WINPR_ATTR_MALLOC(alloc_free, 1)
422static UINT32** alloc_array(
size_t count)
425 BYTE* array = calloc(count *
sizeof(uintptr_t), count *
sizeof(UINT32));
426 UINT32** dst = (UINT32**)array;
427 UINT32* val = (UINT32*)(array + count *
sizeof(uintptr_t));
428 for (
size_t x = 0; x < count; x++)
442static BOOL find_path_exists_with_dijkstra(UINT32** graph,
size_t count, UINT32 start)
447 WINPR_ASSERT(start < count);
449 UINT32** cost = alloc_array(count);
452 UINT32* distance = calloc(count,
sizeof(UINT32));
453 WINPR_ASSERT(distance);
455 UINT32* visited = calloc(count,
sizeof(UINT32));
456 WINPR_ASSERT(visited);
458 UINT32* parent = calloc(count,
sizeof(UINT32));
459 WINPR_ASSERT(parent);
461 for (
size_t x = 0; x < count; x++)
463 for (
size_t y = 0; y < count; y++)
465 if (graph[x][y] == 0)
466 cost[x][y] = UINT32_MAX;
468 cost[x][y] = graph[x][y];
472 for (UINT32 x = 0; x < count; x++)
474 distance[x] = cost[start][x];
483 UINT32 nextnode = UINT32_MAX;
484 while (pos < count - 1)
486 UINT32 mindistance = UINT32_MAX;
488 for (UINT32 x = 0; x < count; x++)
490 if ((distance[x] < mindistance) && !visited[x])
492 mindistance = distance[x];
497 visited[nextnode] = 1;
499 for (
size_t y = 0; y < count; y++)
503 UINT32 dist = mindistance + cost[nextnode][y];
504 if (dist < distance[y])
507 parent[y] = nextnode;
515 for (
size_t x = 0; x < count; x++)
519 if (distance[x] == UINT32_MAX)
521 WLog_ERR(TAG,
"monitor %" PRIu32
" not connected with monitor %" PRIuz, start, x);
535static BOOL freerdp_settings_client_monitors_have_gaps(
const rdpSettings* settings)
542 UINT32** graph = alloc_array(count);
545 for (UINT32 x = 0; x < count; x++)
548 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
549 if (monitor_has_gaps(settings, x, count, monitor, graph))
553 rc = !find_path_exists_with_dijkstra(graph, count, 0);
561static void log_monitor(UINT32 idx,
const rdpMonitor* monitor, wLog* log, DWORD level)
563 WINPR_ASSERT(monitor);
565 WLog_Print(log, level,
566 "[%" PRIu32
"] [%s] {%dx%d-%dx%d} [%" PRIu32
"] {%" PRIu32
"x%" PRIu32
567 ", orientation: %" PRIu32
", desktopScale: %" PRIu32
", deviceScale: %" PRIu32
"}",
568 idx, monitor->is_primary ?
"primary" :
" ", monitor->x, monitor->y,
569 monitor->width, monitor->height, monitor->orig_screen,
570 monitor->attributes.physicalWidth, monitor->attributes.physicalHeight,
571 monitor->attributes.orientation, monitor->attributes.desktopScaleFactor,
572 monitor->attributes.deviceScaleFactor);
575static void log_monitor_configuration(
const rdpSettings* settings, wLog* log, DWORD level)
578 WLog_Print(log, level,
"[BEGIN] MonitorDefArray[%" PRIu32
"]", count);
579 for (UINT32 x = 0; x < count; x++)
582 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
583 log_monitor(x, monitor, log, level);
585 WLog_Print(log, level,
"[END] MonitorDefArray[%" PRIu32
"]", count);
588static BOOL freerdp_settings_client_monitors_overlap(
const rdpSettings* settings)
591 for (UINT32 x = 0; x < count; x++)
594 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
595 if (monitor_operlaps(settings, x, x + 1, count, monitor))
604static BOOL freerdp_settings_client_monitors_check_primary_and_origin(
const rdpSettings* settings)
607 BOOL havePrimary = FALSE;
608 BOOL foundOrigin = FALSE;
609 BOOL primaryIsOrigin = FALSE;
612 struct bounds_t bounds = { 0 };
616 WLog_WARN(TAG,
"Monitor configuration empty.");
620 for (UINT32 x = 0; x < count; x++)
623 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
624 struct bounds_t cur = {
625 .x = monitor->x, .y = monitor->y, .width = monitor->width, .height = monitor->height
628 bounds = union_rect(&bounds, &cur);
630 if (monitor->is_primary)
634 WLog_ERR(TAG,
"Monitor configuration contains multiple primary monitors!");
640 if ((monitor->x == 0) && (monitor->y == 0))
644 WLog_ERR(TAG,
"Monitor configuration does have multiple origin 0/0");
648 primaryIsOrigin = monitor->is_primary != 0;
652 if ((bounds.width > 32766) || (bounds.width < 200))
655 "Monitor configuration virtual desktop width must be 200 <= %" PRId32
" <= 32766",
659 if ((bounds.height > 32766) || (bounds.height < 200))
662 "Monitor configuration virtual desktop height must be 200 <= %" PRId32
" <= 32766",
669 WLog_ERR(TAG,
"Monitor configuration does not contain a primary monitor!");
674 WLog_ERR(TAG,
"Monitor configuration must start at 0/0 for first monitor!");
677 if (!primaryIsOrigin)
679 WLog_ERR(TAG,
"Monitor configuration must start at 0/0 for primary monitor!");
686BOOL freerdp_settings_check_client_after_preconnect(
const rdpSettings* settings)
688 wLog* log = WLog_Get(TAG);
690 log_monitor_configuration(settings, log, WLOG_DEBUG);
691 if (freerdp_settings_client_monitors_overlap(settings))
693 if (freerdp_settings_client_monitors_have_gaps(settings))
695 if (!freerdp_settings_client_monitors_check_primary_and_origin(settings))
699 DWORD level = WLOG_ERROR;
700 WLog_Print(log, level,
"Invalid or unsupported monitor configuration detected");
701 WLog_Print(log, level,
"Check if the configuration is valid.");
702 WLog_Print(log, level,
703 "If you suspect a bug create a new issue at "
704 "https://github.com/FreeRDP/FreeRDP/issues/new");
707 "Provide at least the following log lines detailing your monitor configuration:");
708 log_monitor_configuration(settings, log, level);
714BOOL freerdp_settings_set_default_order_support(rdpSettings* settings)
720 ZeroMemory(OrderSupport, 32);
721 OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
722 OrderSupport[NEG_PATBLT_INDEX] = TRUE;
723 OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
724 OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
725 OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE;
726 OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
727 OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
728 OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
729 OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
730 OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
731 OrderSupport[NEG_LINETO_INDEX] = TRUE;
732 OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
733 OrderSupport[NEG_MEMBLT_INDEX] =
735 OrderSupport[NEG_MEM3BLT_INDEX] =
737 OrderSupport[NEG_MEMBLT_V2_INDEX] =
739 OrderSupport[NEG_MEM3BLT_V2_INDEX] =
741 OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
742 OrderSupport[NEG_GLYPH_INDEX_INDEX] =
744 OrderSupport[NEG_FAST_INDEX_INDEX] =
746 OrderSupport[NEG_FAST_GLYPH_INDEX] =
748 OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE;
749 OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE;
750 OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
751 OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
755BOOL freerdp_capability_buffer_allocate(rdpSettings* settings, UINT32 count)
757 WINPR_ASSERT(settings);
758 WINPR_ASSERT(count > 0);
759 WINPR_ASSERT(count == 32);
761 freerdp_capability_buffer_free(settings);
762 WINPR_ASSERT(settings->ReceivedCapabilitiesSize == 0);
764 settings->ReceivedCapabilitiesSize = count;
765 void* tmp = realloc(settings->ReceivedCapabilities, count *
sizeof(BYTE));
768 memset(tmp, 0, count *
sizeof(BYTE));
769 settings->ReceivedCapabilities = tmp;
771 tmp = realloc((
void*)settings->ReceivedCapabilityData, count *
sizeof(BYTE*));
774 memset(tmp, 0, count *
sizeof(BYTE*));
775 settings->ReceivedCapabilityData = (BYTE**)tmp;
777 tmp = realloc(settings->ReceivedCapabilityDataSizes, count *
sizeof(UINT32));
780 memset(tmp, 0, count *
sizeof(UINT32));
781 settings->ReceivedCapabilityDataSizes = tmp;
783 return (settings->ReceivedCapabilities && settings->ReceivedCapabilityData &&
784 settings->ReceivedCapabilityDataSizes);
787#if !defined(WITH_FULL_CONFIG_PATH)
788static char* freerdp_settings_get_legacy_config_path(
void)
790 char product[
sizeof(FREERDP_PRODUCT_STRING)] = { 0 };
792 for (
size_t i = 0; i <
sizeof(product); i++)
793 product[i] = (
char)tolower(FREERDP_PRODUCT_STRING[i]);
795 return GetKnownSubPath(KNOWN_PATH_XDG_CONFIG_HOME, product);
805#if !defined(WITH_FULL_CONFIG_PATH)
806 if (_stricmp(FREERDP_VENDOR_STRING, FREERDP_PRODUCT_STRING) == 0)
807 return freerdp_settings_get_legacy_config_path();
810 char* base = GetKnownSubPath(KNOWN_PATH_XDG_CONFIG_HOME, FREERDP_VENDOR_STRING);
812 path = GetCombinedPath(base, FREERDP_PRODUCT_STRING);
820 char* issuers[] = {
"FreeRDP",
"FreeRDP-licenser" };
822 const BOOL remote = (flags & FREERDP_SETTINGS_REMOTE_MODE) != 0 ? TRUE : FALSE;
823 rdpSettings* settings = (rdpSettings*)calloc(1,
sizeof(rdpSettings));
828 if (!server && !remote)
831 "a85cf173-4192-42f8-81fa-777a763e6e2c"))
834 "login.microsoftonline.com"))
845 ORIENTATION_LANDSCAPE))
853 SURFCMDS_SET_SURFACE_BITS | SURFCMDS_STREAM_SURFACE_BITS |
854 SURFCMDS_FRAME_MARKER))
861 TS_CAPS_PROTOCOLVERSION))
865 CLIPRDR_FLAG_DEFAULT_MASK))
870 "FreeRDP-licensing-server"))
874 if (!freerdp_server_license_issuers_copy(settings, issuers, ARRAYSIZE(issuers)))
878 RNS_UD_32BPP_SUPPORT | RNS_UD_24BPP_SUPPORT |
879 RNS_UD_16BPP_SUPPORT | RNS_UD_15BPP_SUPPORT))
889 settings, FreeRDP_RemoteApplicationSupportMask,
890 RAIL_LEVEL_SUPPORTED | RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED |
891 RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED | RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED |
892 RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED |
893 RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED | RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED |
894 RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED) ||
897 NEGOTIATE_ORDER_SUPPORT | ZERO_BOUNDS_DELTA_SUPPORT |
898 COLOR_INDEX_SUPPORT) ||
921 DEFAULT_COOKIE_MAX_LENGTH) ||
929 KEYBOARD_HOOK_FULLSCREEN_ONLY) ||
948 CONNECTION_TYPE_AUTODETECT) ||
990 TRANSPORT_TYPE_UDP_FECR))
995 if (!settings_init_computer_name(settings))
1001 if (!freerdp_capability_buffer_allocate(settings, 32))
1005 char tmp[32] = { 0 };
1034 (LARGE_POINTER_FLAG_96x96 | LARGE_POINTER_FLAG_384x384)) ||
1045 settings->BitmapCacheV2CellInfo =
1048 if (!settings->BitmapCacheV2CellInfo)
1053 cache.numEntries = 600;
1054 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 0,
1056 !freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 1, &cache))
1058 cache.numEntries = 2048;
1059 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 2,
1061 !freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 4, &cache))
1063 cache.numEntries = 4096;
1064 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 3, &cache))
1074 if (!settings->GlyphCache)
1079 if (!settings->FragCache)
1082 for (
size_t x = 0; x < 10; x++)
1085 cache.cacheEntries = 254;
1090 cache.cacheMaximumCellSize = 4;
1094 cache.cacheMaximumCellSize = 8;
1097 cache.cacheMaximumCellSize = 16;
1100 cache.cacheMaximumCellSize = 32;
1103 cache.cacheMaximumCellSize = 64;
1106 cache.cacheMaximumCellSize = 128;
1109 cache.cacheMaximumCellSize = 256;
1112 cache.cacheMaximumCellSize = 256;
1118 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_GlyphCache, x, &cache))
1123 cache.cacheEntries = 256;
1124 cache.cacheMaximumCellSize = 256;
1125 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_FragCache, 0, &cache))
1136 WINDOW_LEVEL_SUPPORTED | WINDOW_LEVEL_SUPPORTED_EX) ||
1140 (server && !remote) ? CHANNEL_CHUNK_MAX_LENGTH
1141 : CHANNEL_CHUNK_LENGTH) ||
1145 server ? 0 : 608299) ||
1189 if (!settings->ClientTimeZone)
1192 if (!settings->ServerMode)
1199 GetTimeZoneInformation(tz);
1200 GetDynamicTimeZoneInformation(&dynamic);
1203 dynamic.TimeZoneKeyName,
1204 ARRAYSIZE(dynamic.TimeZoneKeyName)))
1208 dynamic.DynamicDaylightTimeDisabled))
1227 path = GetKnownPath(KNOWN_PATH_HOME);
1238 char* action = GetCombinedPath(config,
"action.sh");
1248 settings_load_hkey_local_machine(settings);
1254 settings->OrderSupport = calloc(1, 32);
1261 if (!settings->OrderSupport)
1264 if (!freerdp_settings_set_default_order_support(settings))
1270 const FreeRDP_Settings_Keys_Bool keys[] = { FreeRDP_SupportGraphicsPipeline,
1271 FreeRDP_SupportStatusInfoPdu,
1272 FreeRDP_SupportErrorInfoPdu,
1273 FreeRDP_SupportAsymetricKeys };
1275 for (
size_t x = 0; x < ARRAYSIZE(keys); x++)
1289 WINPR_PRAGMA_DIAG_PUSH
1290 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1292 WINPR_PRAGMA_DIAG_POP
1296static void freerdp_settings_free_internal(rdpSettings* settings)
1298 freerdp_server_license_issuers_free(settings);
1299 freerdp_target_net_addresses_free(settings);
1300 freerdp_device_collection_free(settings);
1301 freerdp_static_channel_collection_free(settings);
1302 freerdp_dynamic_channel_collection_free(settings);
1304 freerdp_capability_buffer_free(settings);
1307 freerdp_settings_free_keys(settings, TRUE);
1315 freerdp_settings_free_internal(settings);
1319static BOOL freerdp_settings_int_buffer_copy(rdpSettings* _settings,
const rdpSettings* settings)
1323 if (!_settings || !settings)
1328 FreeRDP_Settings_Keys_UInt32 lenKey;
1329 FreeRDP_Settings_Keys_Pointer pointerKey;
1332 PointerDefs pointerDefs[] = {
1334 { FreeRDP_LoadBalanceInfoLength, FreeRDP_LoadBalanceInfo },
1335 { FreeRDP_ServerRandomLength, FreeRDP_ServerRandom },
1336 { FreeRDP_ClientRandomLength, FreeRDP_ClientRandom },
1337 { FreeRDP_ServerCertificateLength, FreeRDP_ServerCertificate },
1338 { FreeRDP_ChannelDefArraySize, FreeRDP_ChannelDefArray },
1339 { FreeRDP_NumMonitorIds, FreeRDP_MonitorIds },
1340 { FreeRDP_BitmapCacheV2NumCells, FreeRDP_BitmapCacheV2CellInfo },
1341 { FreeRDP_RedirectionPasswordLength, FreeRDP_RedirectionPassword },
1342 { FreeRDP_RedirectionTsvUrlLength, FreeRDP_RedirectionTsvUrl },
1343 { FreeRDP_RedirectionGuidLength, FreeRDP_RedirectionGuid },
1344 { FreeRDP_MonitorDefArraySize, FreeRDP_MonitorDefArray }
1347 for (
size_t i = 0; i < ARRAYSIZE(pointerDefs); i++)
1349 const PointerDefs* keys = &pointerDefs[i];
1357 if (!freerdp_server_license_issuers_copy(_settings, settings->ServerLicenseProductIssuers,
1358 settings->ServerLicenseProductIssuersCount))
1361 if (settings->RdpServerCertificate)
1363 rdpCertificate* cert = freerdp_certificate_clone(settings->RdpServerCertificate);
1375 if (settings->RdpServerRsaKey)
1377 rdpPrivateKey* key = freerdp_key_clone(settings->RdpServerRsaKey);
1393 _settings->OrderSupport = malloc(32);
1394 if (!_settings->OrderSupport)
1397 if (!freerdp_capability_buffer_copy(_settings, settings))
1399 CopyMemory(_settings->OrderSupport, settings->OrderSupport, 32);
1401 const UINT32 glyphCacheCount = 10;
1408 const UINT32 fragCacheCount = 1;
1415 _settings, FreeRDP_ClientAutoReconnectCookie,
1419 _settings, FreeRDP_ServerAutoReconnectCookie,
1429 if (!freerdp_target_net_adresses_reset(_settings, nrports))
1432 for (UINT32 i = 0; i < nrports; i++)
1434 const char* address =
1435 freerdp_settings_get_pointer_array(settings, FreeRDP_TargetNetAddresses, i);
1436 const UINT32* port =
1437 freerdp_settings_get_pointer_array(settings, FreeRDP_TargetNetPorts, i);
1438 if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_TargetNetAddresses, i, address))
1440 if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_TargetNetPorts, i, port))
1455 for (
size_t index = 0; index < count; index++)
1458 freerdp_settings_get_pointer_array(settings, FreeRDP_DeviceArray, index);
1459 if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_DeviceArray, index, argv))
1474 for (
size_t index = 0; index < count; index++)
1477 freerdp_settings_get_pointer_array(settings, FreeRDP_StaticChannelArray, index);
1478 if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_StaticChannelArray, index,
1494 for (
size_t index = 0; index < count; index++)
1497 freerdp_settings_get_pointer_array(settings, FreeRDP_DynamicChannelArray, index);
1498 if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_DynamicChannelArray, index,
1515 if (!settings || !_settings)
1519 freerdp_settings_free_internal(_settings);
1522 rc = freerdp_settings_clone_keys(_settings, settings);
1524 _settings->LoadBalanceInfo = NULL;
1525 _settings->ServerRandom = NULL;
1526 _settings->ClientRandom = NULL;
1527 _settings->ServerCertificate = NULL;
1528 _settings->RdpServerCertificate = NULL;
1529 _settings->RdpServerRsaKey = NULL;
1530 _settings->ChannelDefArray = NULL;
1531 _settings->MonitorDefArray = NULL;
1532 _settings->MonitorIds = NULL;
1533 _settings->OrderSupport = NULL;
1534 _settings->BitmapCacheV2CellInfo = NULL;
1535 _settings->GlyphCache = NULL;
1536 _settings->FragCache = NULL;
1537 _settings->ClientAutoReconnectCookie = NULL;
1538 _settings->ServerAutoReconnectCookie = NULL;
1539 _settings->ClientTimeZone = NULL;
1540 _settings->RedirectionPassword = NULL;
1541 _settings->RedirectionTsvUrl = NULL;
1542 _settings->TargetNetAddresses = NULL;
1543 _settings->TargetNetPorts = NULL;
1544 _settings->RedirectionGuid = NULL;
1545 _settings->DeviceArray = NULL;
1546 _settings->StaticChannelArray = NULL;
1547 _settings->DynamicChannelArray = NULL;
1548 _settings->ReceivedCapabilities = NULL;
1549 _settings->ReceivedCapabilityData = NULL;
1550 _settings->ReceivedCapabilityDataSizes = NULL;
1552 _settings->ServerLicenseProductIssuersCount = 0;
1553 _settings->ServerLicenseProductIssuers = NULL;
1559 if (!freerdp_settings_int_buffer_copy(_settings, settings))
1563 freerdp_settings_free_internal(_settings);
1569 rdpSettings* _settings = (rdpSettings*)calloc(1,
sizeof(rdpSettings));
1576 WINPR_PRAGMA_DIAG_PUSH
1577 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1579 WINPR_PRAGMA_DIAG_POP
1586static void zfree(WCHAR* str,
size_t len)
1589 memset(str, 0, len *
sizeof(WCHAR));
1593BOOL identity_set_from_settings_with_pwd(SEC_WINNT_AUTH_IDENTITY* identity,
1594 const rdpSettings* settings,
1595 FreeRDP_Settings_Keys_String UserId,
1596 FreeRDP_Settings_Keys_String DomainId,
1597 const WCHAR* Password,
size_t pwdLen)
1599 WINPR_ASSERT(identity);
1600 WINPR_ASSERT(settings);
1603 size_t DomainLen = 0;
1608 const int rc = sspi_SetAuthIdentityWithLengthW(identity, Username, UserLen, Domain, DomainLen,
1610 zfree(Username, UserLen);
1611 zfree(Domain, DomainLen);
1618 FreeRDP_Settings_Keys_String UserId,
1619 FreeRDP_Settings_Keys_String DomainId,
1620 FreeRDP_Settings_Keys_String PwdId)
1622 WINPR_ASSERT(identity);
1623 WINPR_ASSERT(settings);
1630 identity_set_from_settings_with_pwd(identity, settings, UserId, DomainId, Password, PwdLen);
1631 zfree(Password, PwdLen);
1636 const rdpSettings* settings,
1637 FreeRDP_Settings_Keys_String userId,
1638 FreeRDP_Settings_Keys_String domainId,
1639 FreeRDP_Settings_Keys_String pwdId,
1640 WINPR_ATTR_UNUSED
const BYTE* certSha1,
1641 WINPR_ATTR_UNUSED
size_t sha1len)
1645 LPWSTR marshalledCredentials = NULL;
1647 memcpy(certInfo.rgbHashOfCert, certSha1, MIN(sha1len,
sizeof(certInfo.rgbHashOfCert)));
1649 if (!CredMarshalCredentialW(CertCredential, &certInfo, &marshalledCredentials))
1651 WLog_ERR(TAG,
"error marshalling cert credentials");
1657 const int rc = sspi_SetAuthIdentityWithLengthW(
1658 identity, marshalledCredentials, _wcslen(marshalledCredentials), NULL, 0, Password, pwdLen);
1659 zfree(Password, pwdLen);
1660 CredFree(marshalledCredentials);
1665 if (!identity_set_from_settings(identity, settings, userId, domainId, pwdId))
1671const char* freerdp_settings_glyph_level_string(UINT32 level,
char* buffer,
size_t size)
1673 const char* str =
"GLYPH_SUPPORT_UNKNOWN";
1676 case GLYPH_SUPPORT_NONE:
1677 str =
"GLYPH_SUPPORT_NONE";
1679 case GLYPH_SUPPORT_PARTIAL:
1680 str =
"GLYPH_SUPPORT_PARTIAL";
1682 case GLYPH_SUPPORT_FULL:
1683 str =
"GLYPH_SUPPORT_FULL";
1685 case GLYPH_SUPPORT_ENCODE:
1686 str =
"GLYPH_SUPPORT_ENCODE";
1692 (void)_snprintf(buffer, size,
"%s[0x%08" PRIx32
"]", str, level);
1696BOOL freerdp_target_net_adresses_reset(rdpSettings* settings,
size_t size)
1698 freerdp_target_net_addresses_free(settings);
1702 if (!freerdp_settings_set_pointer_len_(settings, FreeRDP_TargetNetPorts,
1703 FreeRDP_UINT32_UNUSED, NULL, size,
sizeof(UINT32)))
1705 if (!freerdp_settings_set_pointer_len_(settings, FreeRDP_TargetNetAddresses,
1706 FreeRDP_TargetNetAddressCount, NULL, size,
1713BOOL freerdp_settings_enforce_monitor_exists(rdpSettings* settings)
1719 const BOOL useMonitors = fullscreen || multimon;
1733 if (!useMonitors || (count == 0))
1739 const UINT16 orientation =
1741 const UINT32 desktopScaleFactor =
1743 const UINT32 deviceScaleFactor =
1752 monitor.width = WINPR_ASSERTING_INT_CAST(int32_t, width);
1753 monitor.height = WINPR_ASSERTING_INT_CAST(int32_t, height);
1754 monitor.is_primary = TRUE;
1755 monitor.orig_screen = 0;
1756 monitor.attributes.physicalWidth = pwidth;
1757 monitor.attributes.physicalHeight = pheight;
1758 monitor.attributes.orientation = orientation;
1759 monitor.attributes.desktopScaleFactor = desktopScaleFactor;
1760 monitor.attributes.deviceScaleFactor = deviceScaleFactor;
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.