FreeRDP
core/settings.c
1 
22 #include <freerdp/config.h>
23 
24 #include "settings.h"
25 
26 #include <freerdp/crypto/certificate.h>
27 
28 #include <ctype.h>
29 
30 #include <winpr/crt.h>
31 #include <winpr/file.h>
32 #include <winpr/path.h>
33 #include <winpr/sysinfo.h>
34 #include <winpr/registry.h>
35 #include <winpr/wtsapi.h>
36 
37 #include <freerdp/settings.h>
38 #include <freerdp/build-config.h>
39 
40 #include "../crypto/certificate.h"
41 #include "../crypto/privatekey.h"
42 #include "capabilities.h"
43 
44 #define TAG FREERDP_TAG("settings")
45 
46 #ifdef _MSC_VER
47 #pragma warning(push)
48 #pragma warning(disable : 4244)
49 #endif
50 
51 static const char client_dll[] = "C:\\Windows\\System32\\mstscax.dll";
52 
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"
58 
59 static BOOL settings_reg_query_dword_val(HKEY hKey, const TCHAR* sub, DWORD* value)
60 {
61  DWORD dwType = 0;
62  DWORD dwSize = 0;
63 
64  dwSize = sizeof(DWORD);
65  if (RegQueryValueEx(hKey, sub, NULL, &dwType, (BYTE*)value, &dwSize) != ERROR_SUCCESS)
66  return FALSE;
67  if (dwType != REG_DWORD)
68  return FALSE;
69 
70  return TRUE;
71 }
72 
73 static BOOL settings_reg_query_word_val(HKEY hKey, const TCHAR* sub, UINT16* value)
74 {
75  DWORD dwValue = 0;
76 
77  if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
78  return FALSE;
79 
80  if (dwValue > UINT16_MAX)
81  return FALSE;
82 
83  *value = (UINT16)dwValue;
84  return TRUE;
85 }
86 
87 static BOOL settings_reg_query_bool_val(HKEY hKey, const TCHAR* sub, BOOL* value)
88 {
89  DWORD dwValue = 0;
90 
91  if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
92  return FALSE;
93  *value = dwValue != 0;
94  return TRUE;
95 }
96 
97 static BOOL settings_reg_query_dword(rdpSettings* settings, FreeRDP_Settings_Keys_UInt32 id,
98  HKEY hKey, const TCHAR* sub)
99 {
100  DWORD dwValue = 0;
101 
102  if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
103  return FALSE;
104 
105  return freerdp_settings_set_uint32(settings, id, dwValue);
106 }
107 
108 static BOOL settings_reg_query_bool(rdpSettings* settings, FreeRDP_Settings_Keys_Bool id, HKEY hKey,
109  const TCHAR* sub)
110 {
111  DWORD dwValue = 0;
112 
113  if (!settings_reg_query_dword_val(hKey, sub, &dwValue))
114  return FALSE;
115 
116  return freerdp_settings_set_bool(settings, id, dwValue != 0 ? TRUE : FALSE);
117 }
118 
119 static void settings_client_load_hkey_local_machine(rdpSettings* settings)
120 {
121  HKEY hKey = NULL;
122  LONG status = 0;
123  status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, CLIENT_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
124 
125  if (status == ERROR_SUCCESS)
126  {
127  settings_reg_query_dword(settings, FreeRDP_DesktopWidth, hKey, _T("DesktopWidth"));
128  settings_reg_query_dword(settings, FreeRDP_DesktopHeight, hKey, _T("DesktopHeight"));
129  settings_reg_query_bool(settings, FreeRDP_Fullscreen, hKey, _T("Fullscreen"));
130  settings_reg_query_dword(settings, FreeRDP_ColorDepth, hKey, _T("ColorDepth"));
131  settings_reg_query_dword(settings, FreeRDP_KeyboardType, hKey, _T("KeyboardType"));
132  settings_reg_query_dword(settings, FreeRDP_KeyboardSubType, hKey, _T("KeyboardSubType"));
133  settings_reg_query_dword(settings, FreeRDP_KeyboardFunctionKey, hKey,
134  _T("KeyboardFunctionKeys"));
135  settings_reg_query_dword(settings, FreeRDP_KeyboardLayout, hKey, _T("KeyboardLayout"));
136  settings_reg_query_bool(settings, FreeRDP_ExtSecurity, hKey, _T("ExtSecurity"));
137  settings_reg_query_bool(settings, FreeRDP_NlaSecurity, hKey, _T("NlaSecurity"));
138  settings_reg_query_bool(settings, FreeRDP_TlsSecurity, hKey, _T("TlsSecurity"));
139  settings_reg_query_bool(settings, FreeRDP_RdpSecurity, hKey, _T("RdpSecurity"));
140  settings_reg_query_bool(settings, FreeRDP_MstscCookieMode, hKey, _T("MstscCookieMode"));
141  settings_reg_query_dword(settings, FreeRDP_CookieMaxLength, hKey, _T("CookieMaxLength"));
142  settings_reg_query_bool(settings, FreeRDP_BitmapCacheEnabled, hKey, _T("BitmapCache"));
143  settings_reg_query_dword(settings, FreeRDP_OffscreenSupportLevel, hKey,
144  _T("OffscreenBitmapCache"));
145  settings_reg_query_dword(settings, FreeRDP_OffscreenCacheSize, hKey,
146  _T("OffscreenBitmapCacheSize"));
147  settings_reg_query_dword(settings, FreeRDP_OffscreenCacheEntries, hKey,
148  _T("OffscreenBitmapCacheEntries"));
149  RegCloseKey(hKey);
150  }
151 
152  status =
153  RegOpenKeyExA(HKEY_LOCAL_MACHINE, BITMAP_CACHE_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
154 
155  if (status == ERROR_SUCCESS)
156  {
157  settings_reg_query_dword(settings, FreeRDP_BitmapCacheV2NumCells, hKey, _T("NumCells"));
158  for (unsigned x = 0; x < 5; x++)
159  {
160  DWORD val = 0;
161  TCHAR numentries[64] = { 0 };
162  TCHAR persist[64] = { 0 };
163  BITMAP_CACHE_V2_CELL_INFO cache = { 0 };
164  (void)_sntprintf(numentries, ARRAYSIZE(numentries), _T("Cell%uNumEntries"), x);
165  (void)_sntprintf(persist, ARRAYSIZE(persist), _T("Cell%uPersistent"), x);
166  if (!settings_reg_query_dword_val(hKey, numentries, &val) ||
167  !settings_reg_query_bool_val(hKey, persist, &cache.persistent) ||
168  !freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, x,
169  &cache))
170  WLog_WARN(TAG, "Failed to load registry keys to settings!");
171  cache.numEntries = val;
172  }
173 
174  settings_reg_query_bool(settings, FreeRDP_AllowCacheWaitingList, hKey,
175  _T("AllowCacheWaitingList"));
176  RegCloseKey(hKey);
177  }
178 
179  status =
180  RegOpenKeyExA(HKEY_LOCAL_MACHINE, GLYPH_CACHE_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
181 
182  if (status == ERROR_SUCCESS)
183  {
184  unsigned x = 0;
185  UINT32 GlyphSupportLevel = 0;
186  settings_reg_query_dword(settings, FreeRDP_GlyphSupportLevel, hKey, _T("SupportLevel"));
187  for (; x < 10; x++)
188  {
189  GLYPH_CACHE_DEFINITION cache = { 0 };
190  TCHAR numentries[64] = { 0 };
191  TCHAR maxsize[64] = { 0 };
192  (void)_sntprintf(numentries, ARRAYSIZE(numentries), _T("Cache%uNumEntries"), x);
193  (void)_sntprintf(maxsize, ARRAYSIZE(maxsize), _T("Cache%uMaxCellSize"), x);
194 
195  settings_reg_query_word_val(hKey, numentries, &cache.cacheEntries);
196  settings_reg_query_word_val(hKey, maxsize, &cache.cacheMaximumCellSize);
197  if (!freerdp_settings_set_pointer_array(settings, FreeRDP_GlyphCache, x, &cache))
198  WLog_WARN(TAG, "Failed to store GlyphCache %" PRIuz, x);
199  }
200  {
201  GLYPH_CACHE_DEFINITION cache = { 0 };
202  settings_reg_query_word_val(hKey, _T("FragCacheNumEntries"), &cache.cacheEntries);
203  settings_reg_query_word_val(hKey, _T("FragCacheMaxCellSize"),
204  &cache.cacheMaximumCellSize);
205  if (!freerdp_settings_set_pointer_array(settings, FreeRDP_FragCache, x, &cache))
206  WLog_WARN(TAG, "Failed to store FragCache");
207  }
208 
209  RegCloseKey(hKey);
210 
211  if (!freerdp_settings_set_uint32(settings, FreeRDP_GlyphSupportLevel, GlyphSupportLevel))
212  WLog_WARN(TAG, "Failed to load registry keys to settings!");
213  }
214 
215  status =
216  RegOpenKeyExA(HKEY_LOCAL_MACHINE, POINTER_CACHE_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
217 
218  if (status == ERROR_SUCCESS)
219  {
220  settings_reg_query_dword(settings, FreeRDP_LargePointerFlag, hKey, _T("LargePointer"));
221  settings_reg_query_dword(settings, FreeRDP_PointerCacheSize, hKey, _T("PointerCacheSize"));
222  settings_reg_query_dword(settings, FreeRDP_ColorPointerCacheSize, hKey,
223  _T("ColorPointerCacheSize"));
224  RegCloseKey(hKey);
225  }
226 }
227 
228 static void settings_server_load_hkey_local_machine(rdpSettings* settings)
229 {
230  HKEY hKey = NULL;
231  LONG status = 0;
232 
233  status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, SERVER_KEY, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
234 
235  if (status != ERROR_SUCCESS)
236  return;
237 
238  settings_reg_query_bool(settings, FreeRDP_ExtSecurity, hKey, _T("ExtSecurity"));
239  settings_reg_query_bool(settings, FreeRDP_NlaSecurity, hKey, _T("NlaSecurity"));
240  settings_reg_query_bool(settings, FreeRDP_TlsSecurity, hKey, _T("TlsSecurity"));
241  settings_reg_query_dword(settings, FreeRDP_TlsSecLevel, hKey, _T("TlsSecLevel"));
242  settings_reg_query_bool(settings, FreeRDP_RdpSecurity, hKey, _T("RdpSecurity"));
243 
244  RegCloseKey(hKey);
245 }
246 
247 static void settings_load_hkey_local_machine(rdpSettings* settings)
248 {
249  if (freerdp_settings_get_bool(settings, FreeRDP_ServerMode))
250  settings_server_load_hkey_local_machine(settings);
251  else
252  settings_client_load_hkey_local_machine(settings);
253 }
254 
255 static BOOL settings_get_computer_name(rdpSettings* settings)
256 {
257  CHAR computerName[256] = { 0 };
258  DWORD nSize = sizeof(computerName);
259 
260  if (!GetComputerNameExA(ComputerNameNetBIOS, computerName, &nSize))
261  return FALSE;
262 
263  if (nSize > MAX_COMPUTERNAME_LENGTH)
264  computerName[MAX_COMPUTERNAME_LENGTH] = '\0';
265 
266  return freerdp_settings_set_string(settings, FreeRDP_ComputerName, computerName);
267 }
268 
269 void freerdp_settings_print_warnings(const rdpSettings* settings)
270 {
271  const UINT32 level = freerdp_settings_get_uint32(settings, FreeRDP_GlyphSupportLevel);
272  if (level != GLYPH_SUPPORT_NONE)
273  {
274  char buffer[32] = { 0 };
275  WLog_WARN(TAG, "[experimental] enabled GlyphSupportLevel %s, expect visual artefacts!",
276  freerdp_settings_glyph_level_string(level, buffer, sizeof(buffer)));
277  }
278 }
279 
280 BOOL freerdp_settings_set_default_order_support(rdpSettings* settings)
281 {
282  BYTE* OrderSupport = freerdp_settings_get_pointer_writable(settings, FreeRDP_OrderSupport);
283  if (!OrderSupport)
284  return FALSE;
285 
286  ZeroMemory(OrderSupport, 32);
287  OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
288  OrderSupport[NEG_PATBLT_INDEX] = TRUE;
289  OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
290  OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
291  OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE;
292  OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
293  OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
294  OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
295  OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
296  OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
297  OrderSupport[NEG_LINETO_INDEX] = TRUE;
298  OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
299  OrderSupport[NEG_MEMBLT_INDEX] =
300  freerdp_settings_get_bool(settings, FreeRDP_BitmapCacheEnabled) ? 1 : 0;
301  OrderSupport[NEG_MEM3BLT_INDEX] =
302  freerdp_settings_get_bool(settings, FreeRDP_BitmapCacheEnabled) ? 1 : 0;
303  OrderSupport[NEG_MEMBLT_V2_INDEX] =
304  freerdp_settings_get_bool(settings, FreeRDP_BitmapCacheEnabled) ? 1 : 0;
305  OrderSupport[NEG_MEM3BLT_V2_INDEX] =
306  freerdp_settings_get_bool(settings, FreeRDP_BitmapCacheEnabled) ? 1 : 0;
307  OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
308  OrderSupport[NEG_GLYPH_INDEX_INDEX] =
309  freerdp_settings_get_uint32(settings, FreeRDP_GlyphSupportLevel) != GLYPH_SUPPORT_NONE;
310  OrderSupport[NEG_FAST_INDEX_INDEX] =
311  freerdp_settings_get_uint32(settings, FreeRDP_GlyphSupportLevel) != GLYPH_SUPPORT_NONE;
312  OrderSupport[NEG_FAST_GLYPH_INDEX] =
313  freerdp_settings_get_uint32(settings, FreeRDP_GlyphSupportLevel) != GLYPH_SUPPORT_NONE;
314  OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE;
315  OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE;
316  OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
317  OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
318  return TRUE;
319 }
320 
321 BOOL freerdp_capability_buffer_allocate(rdpSettings* settings, UINT32 count)
322 {
323  WINPR_ASSERT(settings);
324  WINPR_ASSERT(count > 0);
325  WINPR_ASSERT(count == 32);
326 
327  freerdp_capability_buffer_free(settings);
328  WINPR_ASSERT(settings->ReceivedCapabilitiesSize == 0);
329 
330  settings->ReceivedCapabilitiesSize = count;
331  void* tmp = realloc(settings->ReceivedCapabilities, count * sizeof(BYTE));
332  if (!tmp)
333  return FALSE;
334  memset(tmp, 0, count * sizeof(BYTE));
335  settings->ReceivedCapabilities = tmp;
336 
337  tmp = realloc(settings->ReceivedCapabilityData, count * sizeof(BYTE*));
338  if (!tmp)
339  return FALSE;
340  memset(tmp, 0, count * sizeof(BYTE*));
341  settings->ReceivedCapabilityData = tmp;
342 
343  tmp = realloc(settings->ReceivedCapabilityDataSizes, count * sizeof(UINT32));
344  if (!tmp)
345  return FALSE;
346  memset(tmp, 0, count * sizeof(UINT32));
347  settings->ReceivedCapabilityDataSizes = tmp;
348 
349  return (settings->ReceivedCapabilities && settings->ReceivedCapabilityData &&
350  settings->ReceivedCapabilityDataSizes);
351 }
352 
353 #if !defined(WITH_FULL_CONFIG_PATH)
354 static char* freerdp_settings_get_legacy_config_path(void)
355 {
356  char product[sizeof(FREERDP_PRODUCT_STRING)] = { 0 };
357 
358  for (size_t i = 0; i < sizeof(product); i++)
359  product[i] = tolower(FREERDP_PRODUCT_STRING[i]);
360 
361  return GetKnownSubPath(KNOWN_PATH_XDG_CONFIG_HOME, product);
362 }
363 #endif
364 
366 {
367  char* path = NULL;
368  /* For default FreeRDP continue using same config directory
369  * as in old releases.
370  * Custom builds use <Vendor>/<Product> as config folder. */
371 #if !defined(WITH_FULL_CONFIG_PATH)
372  if (_stricmp(FREERDP_VENDOR_STRING, FREERDP_PRODUCT_STRING) == 0)
373  return freerdp_settings_get_legacy_config_path();
374 #endif
375 
376  char* base = GetKnownSubPath(KNOWN_PATH_XDG_CONFIG_HOME, FREERDP_VENDOR_STRING);
377  if (base)
378  path = GetCombinedPath(base, FREERDP_PRODUCT_STRING);
379  free(base);
380 
381  return path;
382 }
383 
384 rdpSettings* freerdp_settings_new(DWORD flags)
385 {
386  char* issuers[] = { "FreeRDP", "FreeRDP-licenser" };
387  const BOOL server = (flags & FREERDP_SETTINGS_SERVER_MODE) != 0 ? TRUE : FALSE;
388  const BOOL remote = (flags & FREERDP_SETTINGS_REMOTE_MODE) != 0 ? TRUE : FALSE;
389  rdpSettings* settings = (rdpSettings*)calloc(1, sizeof(rdpSettings));
390 
391  if (!settings)
392  return NULL;
393 
394  if (!freerdp_settings_set_uint32(settings, FreeRDP_SurfaceCommandsSupported,
395  SURFCMDS_SET_SURFACE_BITS | SURFCMDS_STREAM_SURFACE_BITS |
396  SURFCMDS_FRAME_MARKER))
397  goto out_fail;
398 
399  if (!freerdp_settings_set_uint32(settings, FreeRDP_RemoteFxRlgrMode, RLGR3))
400  goto out_fail;
401 
402  if (!freerdp_settings_set_uint16(settings, FreeRDP_CapsProtocolVersion,
403  TS_CAPS_PROTOCOLVERSION))
404  goto out_fail;
405 
406  if (!freerdp_settings_set_uint32(settings, FreeRDP_ClipboardFeatureMask,
407  CLIPRDR_FLAG_DEFAULT_MASK))
408  goto out_fail;
409  if (!freerdp_settings_set_string(settings, FreeRDP_ServerLicenseCompanyName, "FreeRDP"))
410  goto out_fail;
411  if (!freerdp_settings_set_string(settings, FreeRDP_ServerLicenseProductName,
412  "FreeRDP-licensing-server"))
413  goto out_fail;
414  if (!freerdp_settings_set_uint32(settings, FreeRDP_ServerLicenseProductVersion, 1))
415  goto out_fail;
416  if (!freerdp_server_license_issuers_copy(settings, issuers, ARRAYSIZE(issuers)))
417  goto out_fail;
418 
419  if (!freerdp_settings_set_uint16(settings, FreeRDP_SupportedColorDepths,
420  RNS_UD_32BPP_SUPPORT | RNS_UD_24BPP_SUPPORT |
421  RNS_UD_16BPP_SUPPORT | RNS_UD_15BPP_SUPPORT))
422  goto out_fail;
423 
424  if (!freerdp_settings_set_bool(settings, FreeRDP_UnicodeInput, TRUE) ||
425  !freerdp_settings_set_bool(settings, FreeRDP_HasHorizontalWheel, TRUE) ||
426  !freerdp_settings_set_bool(settings, FreeRDP_HasExtendedMouseEvent, TRUE) ||
427  !freerdp_settings_set_bool(settings, FreeRDP_HasQoeEvent, TRUE) ||
428  !freerdp_settings_set_bool(settings, FreeRDP_HasRelativeMouseEvent, TRUE) ||
429  !freerdp_settings_set_bool(settings, FreeRDP_HiDefRemoteApp, TRUE) ||
431  settings, FreeRDP_RemoteApplicationSupportMask,
432  RAIL_LEVEL_SUPPORTED | RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED |
433  RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED | RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED |
434  RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED |
435  RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED | RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED |
436  RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED) ||
437  !freerdp_settings_set_uint16(settings, FreeRDP_TextANSICodePage, CP_UTF8) ||
438  !freerdp_settings_set_uint16(settings, FreeRDP_OrderSupportFlags,
439  NEGOTIATE_ORDER_SUPPORT | ZERO_BOUNDS_DELTA_SUPPORT |
440  COLOR_INDEX_SUPPORT) ||
441  !freerdp_settings_set_bool(settings, FreeRDP_SupportHeartbeatPdu, TRUE) ||
442  !freerdp_settings_set_bool(settings, FreeRDP_ServerMode, server) ||
443  !freerdp_settings_set_bool(settings, FreeRDP_WaitForOutputBufferFlush, TRUE) ||
444  !freerdp_settings_set_uint32(settings, FreeRDP_ClusterInfoFlags, REDIRECTION_SUPPORTED) ||
445  !freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, 1024) ||
446  !freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, 768) ||
447  !freerdp_settings_set_bool(settings, FreeRDP_Workarea, FALSE) ||
448  !freerdp_settings_set_bool(settings, FreeRDP_Fullscreen, FALSE) ||
449  !freerdp_settings_set_bool(settings, FreeRDP_GrabKeyboard, TRUE) ||
450  !freerdp_settings_set_bool(settings, FreeRDP_Decorations, TRUE) ||
451  !freerdp_settings_set_uint32(settings, FreeRDP_RdpVersion, RDP_VERSION_10_12) ||
452  !freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth, 32) ||
453  !freerdp_settings_set_bool(settings, FreeRDP_AadSecurity, FALSE) ||
454  !freerdp_settings_set_bool(settings, FreeRDP_ExtSecurity, FALSE) ||
455  !freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, TRUE) ||
456  !freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, TRUE) ||
457  !freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, TRUE) ||
458  !freerdp_settings_set_bool(settings, FreeRDP_RdstlsSecurity, FALSE) ||
459  !freerdp_settings_set_bool(settings, FreeRDP_NegotiateSecurityLayer, TRUE) ||
460  !freerdp_settings_set_bool(settings, FreeRDP_RestrictedAdminModeRequired, FALSE) ||
461  !freerdp_settings_set_bool(settings, FreeRDP_MstscCookieMode, FALSE) ||
462  !freerdp_settings_set_uint32(settings, FreeRDP_CookieMaxLength,
463  DEFAULT_COOKIE_MAX_LENGTH) ||
464  !freerdp_settings_set_uint32(settings, FreeRDP_ClientBuild,
465  18363) || /* Windows 10, Version 1909 */
466  !freerdp_settings_set_uint32(settings, FreeRDP_KeyboardType, 4) ||
467  !freerdp_settings_set_uint32(settings, FreeRDP_KeyboardSubType, 0) ||
468  !freerdp_settings_set_uint32(settings, FreeRDP_KeyboardFunctionKey, 12) ||
469  !freerdp_settings_set_uint32(settings, FreeRDP_KeyboardLayout, 0) ||
470  !freerdp_settings_set_uint32(settings, FreeRDP_KeyboardHook,
471  KEYBOARD_HOOK_FULLSCREEN_ONLY) ||
472  !freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, FALSE) ||
473  !freerdp_settings_set_bool(settings, FreeRDP_SaltedChecksum, TRUE) ||
474  !freerdp_settings_set_uint32(settings, FreeRDP_ServerPort, 3389) ||
475  !freerdp_settings_set_uint32(settings, FreeRDP_GatewayPort, 443) ||
476  !freerdp_settings_set_bool(settings, FreeRDP_DesktopResize, TRUE) ||
477  !freerdp_settings_set_bool(settings, FreeRDP_ToggleFullscreen, TRUE) ||
478  !freerdp_settings_set_uint32(settings, FreeRDP_DesktopPosX, UINT32_MAX) ||
479  !freerdp_settings_set_uint32(settings, FreeRDP_DesktopPosY, UINT32_MAX) ||
480  !freerdp_settings_set_bool(settings, FreeRDP_SoftwareGdi, TRUE) ||
481  !freerdp_settings_set_bool(settings, FreeRDP_UnmapButtons, FALSE) ||
482  !freerdp_settings_set_uint32(settings, FreeRDP_PerformanceFlags, PERF_FLAG_NONE) ||
483  !freerdp_settings_set_bool(settings, FreeRDP_AllowFontSmoothing, TRUE) ||
484  !freerdp_settings_set_bool(settings, FreeRDP_AllowDesktopComposition, FALSE) ||
485  !freerdp_settings_set_bool(settings, FreeRDP_DisableWallpaper, FALSE) ||
486  !freerdp_settings_set_bool(settings, FreeRDP_DisableFullWindowDrag, TRUE) ||
487  !freerdp_settings_set_bool(settings, FreeRDP_DisableMenuAnims, TRUE) ||
488  !freerdp_settings_set_bool(settings, FreeRDP_DisableThemes, FALSE) ||
489  !freerdp_settings_set_uint32(settings, FreeRDP_ConnectionType,
490  CONNECTION_TYPE_AUTODETECT) ||
491  !freerdp_settings_set_bool(settings, FreeRDP_NetworkAutoDetect, TRUE) ||
492  !freerdp_settings_set_uint32(settings, FreeRDP_EncryptionMethods, ENCRYPTION_METHOD_NONE) ||
493  !freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel, ENCRYPTION_LEVEL_NONE) ||
494  !freerdp_settings_set_bool(settings, FreeRDP_FIPSMode, FALSE) ||
495  !freerdp_settings_set_bool(settings, FreeRDP_CompressionEnabled, TRUE) ||
496  !freerdp_settings_set_bool(settings, FreeRDP_LogonNotify, TRUE) ||
497  !freerdp_settings_set_uint32(settings, FreeRDP_BrushSupportLevel, BRUSH_COLOR_FULL) ||
498  !freerdp_settings_set_uint32(settings, FreeRDP_CompressionLevel, PACKET_COMPR_TYPE_RDP61) ||
499  !freerdp_settings_set_bool(settings, FreeRDP_Authentication, TRUE) ||
500  !freerdp_settings_set_bool(settings, FreeRDP_AuthenticationOnly, FALSE) ||
501  !freerdp_settings_set_bool(settings, FreeRDP_CredentialsFromStdin, FALSE) ||
502  !freerdp_settings_set_bool(settings, FreeRDP_DisableCredentialsDelegation, FALSE) ||
503  !freerdp_settings_set_uint32(settings, FreeRDP_AuthenticationLevel, 2) ||
504  !freerdp_settings_set_uint32(settings, FreeRDP_ChannelCount, 0) ||
505  !freerdp_settings_set_bool(settings, FreeRDP_CertificateCallbackPreferPEM, FALSE) ||
506  !freerdp_settings_set_uint32(settings, FreeRDP_KeySpec, AT_KEYEXCHANGE))
507  goto out_fail;
508 
509  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ChannelDefArray, NULL,
510  CHANNEL_MAX_COUNT))
511  goto out_fail;
512 
513  if (!freerdp_settings_set_bool(settings, FreeRDP_SupportMonitorLayoutPdu, FALSE))
514  goto out_fail;
515 
516  if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, 0))
517  goto out_fail;
518 
519  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorDefArray, NULL, 32))
520  goto out_fail;
521 
522  if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftX, 0))
523  goto out_fail;
524 
525  if (!freerdp_settings_set_uint32(settings, FreeRDP_MonitorLocalShiftY, 0))
526  goto out_fail;
527 
528  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorIds, NULL, 0))
529  goto out_fail;
530 
531  if (!freerdp_settings_set_uint32(settings, FreeRDP_MultitransportFlags,
532  TRANSPORT_TYPE_UDP_FECR))
533  goto out_fail;
534  if (!freerdp_settings_set_bool(settings, FreeRDP_SupportMultitransport, TRUE))
535  goto out_fail;
536 
537  if (!settings_get_computer_name(settings))
538  goto out_fail;
539 
540  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_RdpServerCertificate, NULL, 1))
541  goto out_fail;
542 
543  if (!freerdp_capability_buffer_allocate(settings, 32))
544  goto out_fail;
545 
546  {
547  char tmp[32] = { 0 };
548  if (!freerdp_settings_set_string_len(settings, FreeRDP_ClientProductId, tmp, sizeof(tmp)))
549  goto out_fail;
550  }
551 
552  {
553  char ClientHostname[33] = { 0 };
554  DWORD size = sizeof(ClientHostname) - 2;
555  GetComputerNameA(ClientHostname, &size);
556  if (!freerdp_settings_set_string(settings, FreeRDP_ClientHostname, ClientHostname))
557  goto out_fail;
558  }
559 
560  /* [MS-RDPBCGR] 2.2.7.1.5 Pointer Capability Set (TS_POINTER_CAPABILITYSET)
561  *
562  * if we are in server mode send a reasonable large cache size,
563  * if we are in client mode just set the value to the maximum we want to
564  * support and during capability exchange that size will be limited to the
565  * sizes the server supports
566  *
567  * We have chosen 128 cursors in cache which is at worst 128 * 576kB (384x384 pixel cursor with
568  * 32bit color depth)
569  * */
570  if (freerdp_settings_get_bool(settings, FreeRDP_ServerMode))
571  {
572  if (!freerdp_settings_set_uint32(settings, FreeRDP_PointerCacheSize, 25) ||
573  !freerdp_settings_set_uint32(settings, FreeRDP_ColorPointerCacheSize, 25))
574  goto out_fail;
575  }
576  else
577  {
578  if (!freerdp_settings_set_uint32(settings, FreeRDP_PointerCacheSize, 128) ||
579  !freerdp_settings_set_uint32(settings, FreeRDP_ColorPointerCacheSize, 128))
580  goto out_fail;
581  }
582 
583  if (!freerdp_settings_set_uint32(settings, FreeRDP_LargePointerFlag,
584  (LARGE_POINTER_FLAG_96x96 | LARGE_POINTER_FLAG_384x384)) ||
585  !freerdp_settings_set_bool(settings, FreeRDP_SoundBeepsEnabled, TRUE) ||
586  !freerdp_settings_set_bool(settings, FreeRDP_DrawGdiPlusEnabled, FALSE) ||
587  !freerdp_settings_set_bool(settings, FreeRDP_DrawAllowSkipAlpha, TRUE) ||
588  !freerdp_settings_set_bool(settings, FreeRDP_DrawAllowColorSubsampling, FALSE) ||
589  !freerdp_settings_set_bool(settings, FreeRDP_DrawAllowDynamicColorFidelity, TRUE) ||
590  !freerdp_settings_set_bool(settings, FreeRDP_FrameMarkerCommandEnabled, TRUE) ||
591  !freerdp_settings_set_bool(settings, FreeRDP_SurfaceFrameMarkerEnabled, TRUE) ||
592  !freerdp_settings_set_bool(settings, FreeRDP_AllowCacheWaitingList, TRUE) ||
593  !freerdp_settings_set_uint32(settings, FreeRDP_BitmapCacheV2NumCells, 5))
594  goto out_fail;
595  settings->BitmapCacheV2CellInfo =
597 
598  if (!settings->BitmapCacheV2CellInfo)
599  goto out_fail;
600 
601  {
602  BITMAP_CACHE_V2_CELL_INFO cache = { 0 };
603  cache.numEntries = 600;
604  if (!freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 0,
605  &cache) ||
606  !freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 1, &cache))
607  goto out_fail;
608  cache.numEntries = 2048;
609  if (!freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 2,
610  &cache) ||
611  !freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 4, &cache))
612  goto out_fail;
613  cache.numEntries = 4096;
614  if (!freerdp_settings_set_pointer_array(settings, FreeRDP_BitmapCacheV2CellInfo, 3, &cache))
615  goto out_fail;
616  }
617  if (!freerdp_settings_set_bool(settings, FreeRDP_NoBitmapCompressionHeader, TRUE) ||
618  !freerdp_settings_set_bool(settings, FreeRDP_RefreshRect, TRUE) ||
619  !freerdp_settings_set_bool(settings, FreeRDP_SuppressOutput, TRUE) ||
620  !freerdp_settings_set_uint32(settings, FreeRDP_GlyphSupportLevel, GLYPH_SUPPORT_NONE))
621  goto out_fail;
622  settings->GlyphCache = calloc(10, sizeof(GLYPH_CACHE_DEFINITION));
623 
624  if (!settings->GlyphCache)
625  goto out_fail;
626 
627  settings->FragCache = calloc(1, sizeof(GLYPH_CACHE_DEFINITION));
628 
629  if (!settings->FragCache)
630  goto out_fail;
631 
632  for (size_t x = 0; x < 10; x++)
633  {
634  GLYPH_CACHE_DEFINITION cache = { 0 };
635  cache.cacheEntries = 254;
636  switch (x)
637  {
638  case 0:
639  case 1:
640  cache.cacheMaximumCellSize = 4;
641  break;
642  case 2:
643  case 3:
644  cache.cacheMaximumCellSize = 8;
645  break;
646  case 4:
647  cache.cacheMaximumCellSize = 16;
648  break;
649  case 5:
650  cache.cacheMaximumCellSize = 32;
651  break;
652  case 6:
653  cache.cacheMaximumCellSize = 64;
654  break;
655  case 7:
656  cache.cacheMaximumCellSize = 128;
657  break;
658  case 8:
659  cache.cacheMaximumCellSize = 256;
660  break;
661  case 9:
662  cache.cacheMaximumCellSize = 256;
663  break;
664  }
665 
666  if (!freerdp_settings_set_pointer_array(settings, FreeRDP_GlyphCache, x, &cache))
667  goto out_fail;
668  }
669  {
670  GLYPH_CACHE_DEFINITION cache = { 0 };
671  cache.cacheEntries = 256;
672  cache.cacheMaximumCellSize = 256;
673  if (!freerdp_settings_set_pointer_array(settings, FreeRDP_FragCache, 0, &cache))
674  goto out_fail;
675  }
676  if (!freerdp_settings_set_uint32(settings, FreeRDP_OffscreenSupportLevel, 0) ||
677  !freerdp_settings_set_uint32(settings, FreeRDP_OffscreenCacheSize, 7680) ||
678  !freerdp_settings_set_uint32(settings, FreeRDP_OffscreenCacheEntries, 2000) ||
679  !freerdp_settings_set_uint32(settings, FreeRDP_DrawNineGridCacheSize, 2560) ||
680  !freerdp_settings_set_uint32(settings, FreeRDP_DrawNineGridCacheEntries, 256) ||
681  !freerdp_settings_set_string(settings, FreeRDP_ClientDir, client_dll) ||
682  !freerdp_settings_get_string(settings, FreeRDP_ClientDir) ||
683  !freerdp_settings_set_uint32(settings, FreeRDP_RemoteWndSupportLevel,
684  WINDOW_LEVEL_SUPPORTED | WINDOW_LEVEL_SUPPORTED_EX) ||
685  !freerdp_settings_set_uint32(settings, FreeRDP_RemoteAppNumIconCaches, 3) ||
686  !freerdp_settings_set_uint32(settings, FreeRDP_RemoteAppNumIconCacheEntries, 12) ||
687  !freerdp_settings_set_uint32(settings, FreeRDP_VCChunkSize,
688  (server && !remote) ? CHANNEL_CHUNK_MAX_LENGTH
689  : CHANNEL_CHUNK_LENGTH) ||
690  /* [MS-RDPBCGR] 2.2.7.2.7 Large Pointer Capability Set (TS_LARGE_POINTER_CAPABILITYSET)
691  requires at least this size */
692  !freerdp_settings_set_uint32(settings, FreeRDP_MultifragMaxRequestSize,
693  server ? 0 : 608299) ||
694  !freerdp_settings_set_bool(settings, FreeRDP_GatewayUseSameCredentials, FALSE) ||
695  !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE) ||
696  !freerdp_settings_set_bool(settings, FreeRDP_GatewayRpcTransport, TRUE) ||
697  !freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpTransport, TRUE) ||
698  !freerdp_settings_set_bool(settings, FreeRDP_GatewayUdpTransport, TRUE) ||
699  !freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpUseWebsockets, TRUE) ||
700  !freerdp_settings_set_bool(settings, FreeRDP_GatewayHttpExtAuthSspiNtlm, FALSE) ||
701  !freerdp_settings_set_bool(settings, FreeRDP_GatewayArmTransport, FALSE) ||
702  !freerdp_settings_set_bool(settings, FreeRDP_FastPathInput, TRUE) ||
703  !freerdp_settings_set_bool(settings, FreeRDP_FastPathOutput, TRUE) ||
704  !freerdp_settings_set_bool(settings, FreeRDP_LongCredentialsSupported, TRUE) ||
705  !freerdp_settings_set_uint32(settings, FreeRDP_FrameAcknowledge, 2) ||
706  !freerdp_settings_set_bool(settings, FreeRDP_MouseMotion, TRUE) ||
707  !freerdp_settings_set_uint32(settings, FreeRDP_NSCodecColorLossLevel, 3) ||
708  !freerdp_settings_set_bool(settings, FreeRDP_NSCodecAllowSubsampling, TRUE) ||
709  !freerdp_settings_set_bool(settings, FreeRDP_NSCodecAllowDynamicColorFidelity, TRUE) ||
710  !freerdp_settings_set_bool(settings, FreeRDP_AutoReconnectionEnabled, FALSE) ||
711  !freerdp_settings_set_uint32(settings, FreeRDP_AutoReconnectMaxRetries, 20) ||
712  !freerdp_settings_set_bool(settings, FreeRDP_GfxThinClient, FALSE) ||
713  !freerdp_settings_set_bool(settings, FreeRDP_GfxSmallCache, TRUE) ||
714  !freerdp_settings_set_bool(settings, FreeRDP_GfxProgressive, FALSE) ||
715  !freerdp_settings_set_bool(settings, FreeRDP_GfxProgressiveV2, FALSE) ||
716  !freerdp_settings_set_bool(settings, FreeRDP_GfxPlanar, TRUE) ||
717  !freerdp_settings_set_bool(settings, FreeRDP_GfxH264, FALSE) ||
718  !freerdp_settings_set_bool(settings, FreeRDP_GfxAVC444, FALSE) ||
719  !freerdp_settings_set_bool(settings, FreeRDP_GfxSendQoeAck, FALSE))
720  goto out_fail;
721  {
722  ARC_CS_PRIVATE_PACKET cookie = { 0 };
723  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ClientAutoReconnectCookie, &cookie,
724  1))
725  goto out_fail;
726  }
727  {
728  ARC_SC_PRIVATE_PACKET cookie = { 0 };
729  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ServerAutoReconnectCookie, &cookie,
730  1))
731  goto out_fail;
732  }
733 
734  settings->ClientTimeZone = (LPTIME_ZONE_INFORMATION)calloc(1, sizeof(TIME_ZONE_INFORMATION));
735 
736  if (!settings->ClientTimeZone)
737  goto out_fail;
738 
739  if (!settings->ServerMode)
740  {
741  DYNAMIC_TIME_ZONE_INFORMATION dynamic = { 0 };
743  freerdp_settings_get_pointer_writable(settings, FreeRDP_ClientTimeZone);
744  WINPR_ASSERT(tz);
745 
746  GetTimeZoneInformation(tz);
747  GetDynamicTimeZoneInformation(&dynamic);
748 
749  if (!freerdp_settings_set_string_from_utf16N(settings, FreeRDP_DynamicDSTTimeZoneKeyName,
750  dynamic.TimeZoneKeyName,
751  ARRAYSIZE(dynamic.TimeZoneKeyName)))
752  goto out_fail;
753 
754  if (!freerdp_settings_set_bool(settings, FreeRDP_DynamicDaylightTimeDisabled,
755  dynamic.DynamicDaylightTimeDisabled))
756  goto out_fail;
757  }
758 
759  if (!freerdp_settings_set_bool(settings, FreeRDP_TcpKeepAlive, TRUE) ||
760  !freerdp_settings_set_uint32(settings, FreeRDP_TcpKeepAliveRetries, 3) ||
761  !freerdp_settings_set_uint32(settings, FreeRDP_TcpKeepAliveDelay, 5) ||
762  !freerdp_settings_set_uint32(settings, FreeRDP_TcpKeepAliveInterval, 2) ||
763  !freerdp_settings_set_uint32(settings, FreeRDP_TcpAckTimeout, 9000) ||
764  !freerdp_settings_set_uint32(settings, FreeRDP_TcpConnectTimeout, 15000))
765  goto out_fail;
766 
767  if (!freerdp_settings_get_bool(settings, FreeRDP_ServerMode))
768  {
769  BOOL rc = FALSE;
770  char* path = NULL;
771  if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectClipboard, TRUE))
772  goto out_fail;
773  /* these values are used only by the client part */
774  path = GetKnownPath(KNOWN_PATH_HOME);
775  rc = freerdp_settings_set_string(settings, FreeRDP_HomePath, path);
776  free(path);
777 
778  if (!rc || !freerdp_settings_get_string(settings, FreeRDP_HomePath))
779  goto out_fail;
780 
781  char* config = freerdp_settings_get_config_path();
782  rc = freerdp_settings_set_string(settings, FreeRDP_ConfigPath, config);
783  if (rc)
784  {
785  char* action = GetCombinedPath(config, "action.sh");
786  rc = freerdp_settings_set_string(settings, FreeRDP_ActionScript, action);
787  free(action);
788  }
789 
790  free(config);
791  if (!rc)
792  goto out_fail;
793  }
794 
795  settings_load_hkey_local_machine(settings);
796 
797  if (!freerdp_settings_set_bool(settings, FreeRDP_SmartcardLogon, FALSE))
798  goto out_fail;
799  if (!freerdp_settings_set_uint32(settings, FreeRDP_TlsSecLevel, 1))
800  goto out_fail;
801  settings->OrderSupport = calloc(1, 32);
802 
803  if (!freerdp_settings_set_uint16(settings, FreeRDP_TLSMinVersion, TLS1_VERSION))
804  goto out_fail;
805  if (!freerdp_settings_set_uint16(settings, FreeRDP_TLSMaxVersion, 0))
806  goto out_fail;
807 
808  if (!settings->OrderSupport)
809  goto out_fail;
810 
811  if (!freerdp_settings_set_default_order_support(settings))
812  goto out_fail;
813 
814  const BOOL enable = freerdp_settings_get_bool(settings, FreeRDP_ServerMode);
815 
816  {
817  const FreeRDP_Settings_Keys_Bool keys[] = { FreeRDP_SupportGraphicsPipeline,
818  FreeRDP_SupportStatusInfoPdu,
819  FreeRDP_SupportErrorInfoPdu,
820  FreeRDP_SupportAsymetricKeys };
821 
822  for (size_t x = 0; x < ARRAYSIZE(keys); x++)
823  {
824  if (!freerdp_settings_set_bool(settings, keys[x], enable))
825  goto out_fail;
826  }
827  }
828 
829  if (!freerdp_settings_set_bool(settings, FreeRDP_SupportDynamicTimeZone, TRUE))
830  goto out_fail;
831  if (!freerdp_settings_set_bool(settings, FreeRDP_SupportSkipChannelJoin, TRUE))
832  goto out_fail;
833 
834  return settings;
835 out_fail:
836  freerdp_settings_free(settings);
837  return NULL;
838 }
839 
840 static void freerdp_settings_free_internal(rdpSettings* settings)
841 {
842  freerdp_server_license_issuers_free(settings);
843  freerdp_target_net_addresses_free(settings);
844  freerdp_device_collection_free(settings);
845  freerdp_static_channel_collection_free(settings);
846  freerdp_dynamic_channel_collection_free(settings);
847 
848  freerdp_capability_buffer_free(settings);
849 
850  /* Free all strings, set other pointers NULL */
851  freerdp_settings_free_keys(settings, TRUE);
852 }
853 
854 void freerdp_settings_free(rdpSettings* settings)
855 {
856  if (!settings)
857  return;
858 
859  freerdp_settings_free_internal(settings);
860  free(settings);
861 }
862 
863 static BOOL freerdp_settings_int_buffer_copy(rdpSettings* _settings, const rdpSettings* settings)
864 {
865  BOOL rc = FALSE;
866 
867  if (!_settings || !settings)
868  return FALSE;
869 
870  {
871  const void* data = freerdp_settings_get_pointer(settings, FreeRDP_LoadBalanceInfo);
872  const UINT32 len = freerdp_settings_get_uint32(settings, FreeRDP_LoadBalanceInfoLength);
873  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_LoadBalanceInfo, data, len))
874  return FALSE;
875  }
876  {
877  const void* data = freerdp_settings_get_pointer(settings, FreeRDP_ServerRandom);
878  const UINT32 len = freerdp_settings_get_uint32(settings, FreeRDP_ServerRandomLength);
879  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_ServerRandom, data, len))
880  return FALSE;
881  }
882  {
883  const void* data = freerdp_settings_get_pointer(settings, FreeRDP_ClientRandom);
884  const UINT32 len = freerdp_settings_get_uint32(settings, FreeRDP_ClientRandomLength);
885  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_ClientRandom, data, len))
886  return FALSE;
887  }
888  if (!freerdp_server_license_issuers_copy(_settings, settings->ServerLicenseProductIssuers,
889  settings->ServerLicenseProductIssuersCount))
890  return FALSE;
891 
892  {
893  const void* data = freerdp_settings_get_pointer(settings, FreeRDP_ServerCertificate);
894  const UINT32 len = freerdp_settings_get_uint32(settings, FreeRDP_ServerCertificateLength);
895  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_ServerCertificate, data, len))
896  return FALSE;
897  }
898  if (settings->RdpServerCertificate)
899  {
900  rdpCertificate* cert = freerdp_certificate_clone(settings->RdpServerCertificate);
901  if (!cert)
902  goto out_fail;
903  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_RdpServerCertificate, cert, 1))
904  goto out_fail;
905  }
906  else
907  {
908  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_RdpServerCertificate, NULL, 0))
909  goto out_fail;
910  }
911 
912  if (settings->RdpServerRsaKey)
913  {
914  rdpPrivateKey* key = freerdp_key_clone(settings->RdpServerRsaKey);
915  if (!key)
916  goto out_fail;
917  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_RdpServerRsaKey, key, 1))
918  goto out_fail;
919  }
920  else
921  {
922  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_RdpServerRsaKey, NULL, 0))
923  goto out_fail;
924  }
925 
926  if (!freerdp_settings_set_uint32(_settings, FreeRDP_ChannelCount,
927  freerdp_settings_get_uint32(settings, FreeRDP_ChannelCount)))
928  goto out_fail;
930  _settings, FreeRDP_ChannelDefArraySize,
931  freerdp_settings_get_uint32(settings, FreeRDP_ChannelDefArraySize)))
932  goto out_fail;
933 
934  const UINT32 defArraySize = freerdp_settings_get_uint32(settings, FreeRDP_ChannelDefArraySize);
935  const CHANNEL_DEF* defArray = freerdp_settings_get_pointer(settings, FreeRDP_ChannelDefArray);
936  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_ChannelDefArray, defArray,
937  defArraySize))
938  goto out_fail;
939 
940  {
941  const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_MonitorDefArraySize);
942  const rdpMonitor* monitors =
943  freerdp_settings_get_pointer(settings, FreeRDP_MonitorDefArray);
944 
945  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_MonitorDefArray, monitors, count))
946  goto out_fail;
947  }
948 
949  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_MonitorIds, NULL, 16))
950  goto out_fail;
951 
952  const UINT32 monitorIdSize = freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds);
953  const UINT32* monitorIds = freerdp_settings_get_pointer(settings, FreeRDP_MonitorIds);
954  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_MonitorIds, monitorIds, monitorIdSize))
955  goto out_fail;
956 
957  _settings->OrderSupport = malloc(32);
958 
959  if (!_settings->OrderSupport)
960  goto out_fail;
961 
962  if (!freerdp_capability_buffer_copy(_settings, settings))
963  goto out_fail;
964  CopyMemory(_settings->OrderSupport, settings->OrderSupport, 32);
965 
966  const UINT32 cellInfoSize =
967  freerdp_settings_get_uint32(settings, FreeRDP_BitmapCacheV2NumCells);
968  const BITMAP_CACHE_V2_CELL_INFO* cellInfo =
969  freerdp_settings_get_pointer(settings, FreeRDP_BitmapCacheV2CellInfo);
970  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_BitmapCacheV2CellInfo, cellInfo,
971  cellInfoSize))
972  goto out_fail;
973 
974  const UINT32 glyphCacheCount = 10;
975  const GLYPH_CACHE_DEFINITION* glyphCache =
976  freerdp_settings_get_pointer(settings, FreeRDP_GlyphCache);
977  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_GlyphCache, glyphCache,
978  glyphCacheCount))
979  goto out_fail;
980 
981  const UINT32 fragCacheCount = 1;
982  const GLYPH_CACHE_DEFINITION* fragCache =
983  freerdp_settings_get_pointer(settings, FreeRDP_FragCache);
984  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_FragCache, fragCache, fragCacheCount))
985  goto out_fail;
986 
988  _settings, FreeRDP_ClientAutoReconnectCookie,
989  freerdp_settings_get_pointer(settings, FreeRDP_ClientAutoReconnectCookie), 1))
990  goto out_fail;
992  _settings, FreeRDP_ServerAutoReconnectCookie,
993  freerdp_settings_get_pointer(settings, FreeRDP_ServerAutoReconnectCookie), 1))
994  goto out_fail;
995 
996  const TIME_ZONE_INFORMATION* tz =
997  freerdp_settings_get_pointer(settings, FreeRDP_ClientTimeZone);
998  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_ClientTimeZone, tz, 1))
999  goto out_fail;
1000 
1002  _settings, FreeRDP_RedirectionPasswordLength,
1003  freerdp_settings_get_uint32(settings, FreeRDP_RedirectionPasswordLength)))
1004  goto out_fail;
1005  const UINT32 redirectionPasswordLength =
1006  freerdp_settings_get_uint32(settings, FreeRDP_RedirectionPasswordLength);
1007  const BYTE* pwd = freerdp_settings_get_pointer(settings, FreeRDP_RedirectionPassword);
1008  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_RedirectionPassword, pwd,
1009  redirectionPasswordLength))
1010  goto out_fail;
1011 
1012  const UINT32 RedirectionTsvUrlLength =
1013  freerdp_settings_get_uint32(settings, FreeRDP_RedirectionTsvUrlLength);
1014  const BYTE* RedirectionTsvUrl =
1015  freerdp_settings_get_pointer(settings, FreeRDP_RedirectionTsvUrl);
1016  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_RedirectionTsvUrl, RedirectionTsvUrl,
1017  RedirectionTsvUrlLength))
1018  goto out_fail;
1019 
1020  const UINT32 nrports = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
1021  if (!freerdp_target_net_adresses_reset(_settings, nrports))
1022  return FALSE;
1023 
1024  for (UINT32 i = 0; i < nrports; i++)
1025  {
1026  const char* address =
1027  freerdp_settings_get_pointer_array(settings, FreeRDP_TargetNetAddresses, i);
1028  const UINT32* port =
1029  freerdp_settings_get_pointer_array(settings, FreeRDP_TargetNetPorts, i);
1030  if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_TargetNetAddresses, i, address))
1031  return FALSE;
1032  if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_TargetNetPorts, i, port))
1033  return FALSE;
1034  }
1035 
1036  {
1037  const UINT32 len = freerdp_settings_get_uint32(_settings, FreeRDP_DeviceArraySize);
1038  const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_DeviceCount);
1039 
1040  if (len < count)
1041  goto out_fail;
1042  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_DeviceArray, NULL, len))
1043  goto out_fail;
1044  if (!freerdp_settings_set_uint32(_settings, FreeRDP_DeviceCount, count))
1045  goto out_fail;
1046 
1047  for (size_t index = 0; index < count; index++)
1048  {
1049  const RDPDR_DEVICE* argv =
1050  freerdp_settings_get_pointer_array(settings, FreeRDP_DeviceArray, index);
1051  if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_DeviceArray, index, argv))
1052  goto out_fail;
1053  }
1054  }
1055  {
1056  const UINT32 len = freerdp_settings_get_uint32(_settings, FreeRDP_StaticChannelArraySize);
1057  const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
1058 
1059  if (len < count)
1060  goto out_fail;
1061  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_StaticChannelArray, NULL, len))
1062  goto out_fail;
1063  if (!freerdp_settings_set_uint32(_settings, FreeRDP_StaticChannelCount, count))
1064  goto out_fail;
1065 
1066  for (size_t index = 0; index < count; index++)
1067  {
1068  const ADDIN_ARGV* argv =
1069  freerdp_settings_get_pointer_array(settings, FreeRDP_StaticChannelArray, index);
1070  if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_StaticChannelArray, index,
1071  argv))
1072  goto out_fail;
1073  }
1074  }
1075  {
1076  const UINT32 len = freerdp_settings_get_uint32(_settings, FreeRDP_DynamicChannelArraySize);
1077  const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
1078 
1079  if (len < count)
1080  goto out_fail;
1081  if (!freerdp_settings_set_pointer_len(_settings, FreeRDP_DynamicChannelArray, NULL, len))
1082  goto out_fail;
1083  if (!freerdp_settings_set_uint32(_settings, FreeRDP_DynamicChannelCount, count))
1084  goto out_fail;
1085 
1086  for (size_t index = 0; index < count; index++)
1087  {
1088  const ADDIN_ARGV* argv =
1089  freerdp_settings_get_pointer_array(settings, FreeRDP_DynamicChannelArray, index);
1090  if (!freerdp_settings_set_pointer_array(_settings, FreeRDP_DynamicChannelArray, index,
1091  argv))
1092  goto out_fail;
1093  }
1094  }
1095 
1096  rc = freerdp_settings_set_string(_settings, FreeRDP_ActionScript,
1097  freerdp_settings_get_string(settings, FreeRDP_ActionScript));
1098 
1099 out_fail:
1100  return rc;
1101 }
1102 
1103 BOOL freerdp_settings_copy(rdpSettings* _settings, const rdpSettings* settings)
1104 {
1105  BOOL rc = 0;
1106 
1107  if (!settings || !_settings)
1108  return FALSE;
1109 
1110  /* This is required to free all non string buffers */
1111  freerdp_settings_free_internal(_settings);
1112  /* This copies everything except allocated non string buffers. reset all allocated buffers to
1113  * NULL to fix issues during cleanup */
1114  rc = freerdp_settings_clone_keys(_settings, settings);
1115 
1116  _settings->LoadBalanceInfo = NULL;
1117  _settings->ServerRandom = NULL;
1118  _settings->ClientRandom = NULL;
1119  _settings->ServerCertificate = NULL;
1120  _settings->RdpServerCertificate = NULL;
1121  _settings->RdpServerRsaKey = NULL;
1122  _settings->ChannelDefArray = NULL;
1123  _settings->MonitorDefArray = NULL;
1124  _settings->MonitorIds = NULL;
1125  _settings->OrderSupport = NULL;
1126  _settings->BitmapCacheV2CellInfo = NULL;
1127  _settings->GlyphCache = NULL;
1128  _settings->FragCache = NULL;
1129  _settings->ClientAutoReconnectCookie = NULL;
1130  _settings->ServerAutoReconnectCookie = NULL;
1131  _settings->ClientTimeZone = NULL;
1132  _settings->RedirectionPassword = NULL;
1133  _settings->RedirectionTsvUrl = NULL;
1134  _settings->TargetNetAddresses = NULL;
1135  _settings->TargetNetPorts = NULL;
1136  _settings->DeviceArray = NULL;
1137  _settings->StaticChannelArray = NULL;
1138  _settings->DynamicChannelArray = NULL;
1139  _settings->ReceivedCapabilities = NULL;
1140  _settings->ReceivedCapabilityData = NULL;
1141  _settings->ReceivedCapabilityDataSizes = NULL;
1142 
1143  _settings->ServerLicenseProductIssuersCount = 0;
1144  _settings->ServerLicenseProductIssuers = NULL;
1145 
1146  if (!rc)
1147  goto out_fail;
1148 
1149  /* Begin copying */
1150  if (!freerdp_settings_int_buffer_copy(_settings, settings))
1151  goto out_fail;
1152  return TRUE;
1153 out_fail:
1154  freerdp_settings_free_internal(_settings);
1155  return FALSE;
1156 }
1157 
1158 rdpSettings* freerdp_settings_clone(const rdpSettings* settings)
1159 {
1160  rdpSettings* _settings = (rdpSettings*)calloc(1, sizeof(rdpSettings));
1161 
1162  if (!freerdp_settings_copy(_settings, settings))
1163  goto out_fail;
1164 
1165  return _settings;
1166 out_fail:
1167  freerdp_settings_free(_settings);
1168  return NULL;
1169 }
1170 #ifdef _MSC_VER
1171 #pragma warning(pop)
1172 #endif
1173 
1174 static void zfree(WCHAR* str, size_t len)
1175 {
1176  if (str)
1177  memset(str, 0, len * sizeof(WCHAR));
1178  free(str);
1179 }
1180 
1181 BOOL identity_set_from_settings_with_pwd(SEC_WINNT_AUTH_IDENTITY* identity,
1182  const rdpSettings* settings,
1183  FreeRDP_Settings_Keys_String UserId,
1184  FreeRDP_Settings_Keys_String DomainId,
1185  const WCHAR* Password, size_t pwdLen)
1186 {
1187  WINPR_ASSERT(identity);
1188  WINPR_ASSERT(settings);
1189 
1190  size_t UserLen = 0;
1191  size_t DomainLen = 0;
1192 
1193  WCHAR* Username = freerdp_settings_get_string_as_utf16(settings, UserId, &UserLen);
1194  WCHAR* Domain = freerdp_settings_get_string_as_utf16(settings, DomainId, &DomainLen);
1195 
1196  const int rc = sspi_SetAuthIdentityWithLengthW(identity, Username, UserLen, Domain, DomainLen,
1197  Password, pwdLen);
1198  zfree(Username, UserLen);
1199  zfree(Domain, DomainLen);
1200  if (rc < 0)
1201  return FALSE;
1202  return TRUE;
1203 }
1204 
1205 BOOL identity_set_from_settings(SEC_WINNT_AUTH_IDENTITY_W* identity, const rdpSettings* settings,
1206  FreeRDP_Settings_Keys_String UserId,
1207  FreeRDP_Settings_Keys_String DomainId,
1208  FreeRDP_Settings_Keys_String PwdId)
1209 {
1210  WINPR_ASSERT(identity);
1211  WINPR_ASSERT(settings);
1212 
1213  size_t PwdLen = 0;
1214 
1215  WCHAR* Password = freerdp_settings_get_string_as_utf16(settings, PwdId, &PwdLen);
1216 
1217  const BOOL rc =
1218  identity_set_from_settings_with_pwd(identity, settings, UserId, DomainId, Password, PwdLen);
1219  zfree(Password, PwdLen);
1220  return rc;
1221 }
1222 
1223 BOOL identity_set_from_smartcard_hash(SEC_WINNT_AUTH_IDENTITY_W* identity,
1224  const rdpSettings* settings,
1225  FreeRDP_Settings_Keys_String userId,
1226  FreeRDP_Settings_Keys_String domainId,
1227  FreeRDP_Settings_Keys_String pwdId, const BYTE* certSha1,
1228  size_t sha1len)
1229 {
1230 #ifdef _WIN32
1231  CERT_CREDENTIAL_INFO certInfo = { sizeof(CERT_CREDENTIAL_INFO), { 0 } };
1232  LPWSTR marshalledCredentials = NULL;
1233 
1234  memcpy(certInfo.rgbHashOfCert, certSha1, MIN(sha1len, sizeof(certInfo.rgbHashOfCert)));
1235 
1236  if (!CredMarshalCredentialW(CertCredential, &certInfo, &marshalledCredentials))
1237  {
1238  WLog_ERR(TAG, "error marshalling cert credentials");
1239  return FALSE;
1240  }
1241 
1242  size_t pwdLen = 0;
1243  WCHAR* Password = freerdp_settings_get_string_as_utf16(settings, pwdId, &pwdLen);
1244  const int rc = sspi_SetAuthIdentityWithLengthW(
1245  identity, marshalledCredentials, _wcslen(marshalledCredentials), NULL, 0, Password, pwdLen);
1246  zfree(Password, pwdLen);
1247  CredFree(marshalledCredentials);
1248  if (rc < 0)
1249  return FALSE;
1250 
1251 #else
1252  if (!identity_set_from_settings(identity, settings, userId, domainId, pwdId))
1253  return FALSE;
1254 #endif /* _WIN32 */
1255  return TRUE;
1256 }
1257 
1258 const char* freerdp_settings_glyph_level_string(UINT32 level, char* buffer, size_t size)
1259 {
1260  const char* str = "GLYPH_SUPPORT_UNKNOWN";
1261  switch (level)
1262  {
1263  case GLYPH_SUPPORT_NONE:
1264  str = "GLYPH_SUPPORT_NONE";
1265  break;
1266  case GLYPH_SUPPORT_PARTIAL:
1267  str = "GLYPH_SUPPORT_PARTIAL";
1268  break;
1269  case GLYPH_SUPPORT_FULL:
1270  str = "GLYPH_SUPPORT_FULL";
1271  break;
1272  case GLYPH_SUPPORT_ENCODE:
1273  str = "GLYPH_SUPPORT_ENCODE";
1274  break;
1275  default:
1276  break;
1277  }
1278 
1279  (void)_snprintf(buffer, size, "%s[0x%08" PRIx32 "]", str, level);
1280  return buffer;
1281 }
1282 
1283 BOOL freerdp_target_net_adresses_reset(rdpSettings* settings, size_t size)
1284 {
1285  freerdp_target_net_addresses_free(settings);
1286 
1287  if (size > 0)
1288  {
1289  if (!freerdp_settings_set_pointer_len_(settings, FreeRDP_TargetNetPorts, -1, NULL, size,
1290  sizeof(UINT32)))
1291  return FALSE;
1292  if (!freerdp_settings_set_pointer_len_(settings, FreeRDP_TargetNetAddresses,
1293  FreeRDP_TargetNetAddressCount, NULL, size,
1294  sizeof(char*)))
1295  return FALSE;
1296  }
1297  return TRUE;
1298 }
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.
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_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
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_pointer_len(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id, const void *data, size_t len)
Set a pointer to value data.
char * freerdp_settings_get_config_path(void)
return the configuration directory for the library
void freerdp_settings_free(rdpSettings *settings)
Free a settings struct with all data in it.
#define FREERDP_SETTINGS_SERVER_MODE
BOOL freerdp_settings_copy(rdpSettings *_settings, const rdpSettings *settings)
Deep copies settings from src to dst.
rdpSettings * freerdp_settings_clone(const rdpSettings *settings)
Creates a deep copy of settings.
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.
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.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL param)
Sets a BOOL settings value.
FREERDP_API void * freerdp_settings_get_pointer_writable(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a mutable pointer settings value.