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