FreeRDP
common/settings.c
1 
23 #include <freerdp/config.h>
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29 
30 #include <winpr/crt.h>
31 #include <winpr/assert.h>
32 
33 #include "../core/settings.h"
34 #include "../core/capabilities.h"
35 
36 #include <freerdp/crypto/certificate.h>
37 #include <freerdp/settings.h>
38 #include <freerdp/freerdp.h>
39 #include <freerdp/log.h>
40 
41 #define TAG FREERDP_TAG("common")
42 
43 BOOL freerdp_addin_argv_add_argument_ex(ADDIN_ARGV* args, const char* argument, size_t len)
44 {
45  char* str = NULL;
46  char** new_argv = NULL;
47 
48  if (!args || !argument)
49  return FALSE;
50 
51  if (len == 0)
52  len = strlen(argument);
53 
54  new_argv = (char**)realloc((void*)args->argv, sizeof(char*) * (args->argc + 1));
55 
56  if (!new_argv)
57  return FALSE;
58 
59  args->argv = new_argv;
60 
61  str = calloc(len + 1, sizeof(char));
62  if (!str)
63  return FALSE;
64  memcpy(str, argument, len);
65  args->argv[args->argc++] = str;
66  return TRUE;
67 }
68 
69 BOOL freerdp_addin_argv_add_argument(ADDIN_ARGV* args, const char* argument)
70 {
71  return freerdp_addin_argv_add_argument_ex(args, argument, 0);
72 }
73 
74 BOOL freerdp_addin_argv_del_argument(ADDIN_ARGV* args, const char* argument)
75 {
76  if (!args || !argument)
77  return FALSE;
78  for (int x = 0; x < args->argc; x++)
79  {
80  char* arg = args->argv[x];
81  if (strcmp(argument, arg) == 0)
82  {
83  free(arg);
84  memmove_s((void*)&args->argv[x], (args->argc - x) * sizeof(char*),
85  (void*)&args->argv[x + 1], (args->argc - x - 1) * sizeof(char*));
86  args->argv[args->argc - 1] = NULL;
87  args->argc--;
88  return TRUE;
89  }
90  }
91  return FALSE;
92 }
93 
94 int freerdp_addin_set_argument(ADDIN_ARGV* args, const char* argument)
95 {
96  if (!args || !argument)
97  return -2;
98 
99  for (int i = 0; i < args->argc; i++)
100  {
101  if (strcmp(args->argv[i], argument) == 0)
102  {
103  return 1;
104  }
105  }
106 
107  if (!freerdp_addin_argv_add_argument(args, argument))
108  return -1;
109  return 0;
110 }
111 
112 int freerdp_addin_replace_argument(ADDIN_ARGV* args, const char* previous, const char* argument)
113 {
114  if (!args || !previous || !argument)
115  return -2;
116 
117  for (int i = 0; i < args->argc; i++)
118  {
119  if (strcmp(args->argv[i], previous) == 0)
120  {
121  free(args->argv[i]);
122 
123  if (!(args->argv[i] = _strdup(argument)))
124  return -1;
125 
126  return 1;
127  }
128  }
129 
130  if (!freerdp_addin_argv_add_argument(args, argument))
131  return -1;
132  return 0;
133 }
134 
135 int freerdp_addin_set_argument_value(ADDIN_ARGV* args, const char* option, const char* value)
136 {
137  BOOL rc = 0;
138  char* p = NULL;
139  char* str = NULL;
140  size_t length = 0;
141  if (!args || !option || !value)
142  return -2;
143  length = strlen(option) + strlen(value) + 1;
144  str = (char*)calloc(length + 1, sizeof(char));
145 
146  if (!str)
147  return -1;
148 
149  (void)sprintf_s(str, length + 1, "%s:%s", option, value);
150 
151  for (int i = 0; i < args->argc; i++)
152  {
153  p = strchr(args->argv[i], ':');
154 
155  if (p)
156  {
157  if (strncmp(args->argv[i], option, p - args->argv[i]) == 0)
158  {
159  free(args->argv[i]);
160  args->argv[i] = str;
161  return 1;
162  }
163  }
164  }
165 
166  rc = freerdp_addin_argv_add_argument(args, str);
167  free(str);
168  if (!rc)
169  return -1;
170  return 0;
171 }
172 
173 int freerdp_addin_replace_argument_value(ADDIN_ARGV* args, const char* previous, const char* option,
174  const char* value)
175 {
176  BOOL rc = 0;
177  char* str = NULL;
178  size_t length = 0;
179  if (!args || !previous || !option || !value)
180  return -2;
181  length = strlen(option) + strlen(value) + 1;
182  str = (char*)calloc(length + 1, sizeof(char));
183 
184  if (!str)
185  return -1;
186 
187  (void)sprintf_s(str, length + 1, "%s:%s", option, value);
188 
189  for (int i = 0; i < args->argc; i++)
190  {
191  if (strcmp(args->argv[i], previous) == 0)
192  {
193  free(args->argv[i]);
194  args->argv[i] = str;
195  return 1;
196  }
197  }
198 
199  rc = freerdp_addin_argv_add_argument(args, str);
200  free(str);
201  if (!rc)
202  return -1;
203  return 0;
204 }
205 
206 BOOL freerdp_device_collection_add(rdpSettings* settings, RDPDR_DEVICE* device)
207 {
208  UINT32 count = 0;
209  UINT32 old = 0;
210  WINPR_ASSERT(settings);
211  WINPR_ASSERT(device);
212 
213  count = freerdp_settings_get_uint32(settings, FreeRDP_DeviceCount) + 1;
214  old = freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize);
215  if (old < count)
216  {
217  UINT32 new_size = old * 2;
218  RDPDR_DEVICE** new_array = NULL;
219 
220  if (new_size == 0)
221  new_size = count * 2;
222 
223  new_array =
224  (RDPDR_DEVICE**)realloc((void*)settings->DeviceArray, new_size * sizeof(RDPDR_DEVICE*));
225 
226  if (!new_array)
227  return FALSE;
228 
229  settings->DeviceArray = new_array;
230  memset((void*)&settings->DeviceArray[old], 0, (new_size - old) * sizeof(RDPDR_DEVICE*));
231 
232  if (!freerdp_settings_set_uint32(settings, FreeRDP_DeviceArraySize, new_size))
233  return FALSE;
234  }
235 
236  settings->DeviceArray[settings->DeviceCount++] = device;
237  return TRUE;
238 }
239 
240 BOOL freerdp_device_collection_del(rdpSettings* settings, const RDPDR_DEVICE* device)
241 {
242  WINPR_ASSERT(settings);
243 
244  if (!device)
245  return FALSE;
246 
247  const UINT32 count = settings->DeviceCount;
248  for (size_t x = 0; x < count; x++)
249  {
250  const RDPDR_DEVICE* cur = settings->DeviceArray[x];
251  if (cur == device)
252  {
253  for (size_t y = x + 1; y < count; y++)
254  {
255  RDPDR_DEVICE* next = settings->DeviceArray[y];
256  settings->DeviceArray[y - 1] = next;
257  }
258  settings->DeviceArray[count - 1] = NULL;
259  settings->DeviceCount--;
260  return TRUE;
261  }
262  }
263 
264  return FALSE;
265 }
266 
267 RDPDR_DEVICE* freerdp_device_collection_find(rdpSettings* settings, const char* name)
268 {
269  RDPDR_DEVICE* device = NULL;
270 
271  WINPR_ASSERT(settings);
272  WINPR_ASSERT(name);
273  for (UINT32 index = 0; index < settings->DeviceCount; index++)
274  {
275  device = settings->DeviceArray[index];
276 
277  if (!device->Name)
278  continue;
279 
280  if (strcmp(device->Name, name) == 0)
281  return device;
282  }
283 
284  return NULL;
285 }
286 
287 RDPDR_DEVICE* freerdp_device_collection_find_type(rdpSettings* settings, UINT32 type)
288 {
289  RDPDR_DEVICE* device = NULL;
290  WINPR_ASSERT(settings);
291 
292  for (UINT32 index = 0; index < settings->DeviceCount; index++)
293  {
294  device = settings->DeviceArray[index];
295 
296  if (device->Type == type)
297  return device;
298  }
299 
300  return NULL;
301 }
302 
303 RDPDR_DEVICE* freerdp_device_new(UINT32 Type, size_t count, const char* const args[])
304 {
305  size_t size = 0;
306  union
307  {
308  RDPDR_DEVICE* base;
309  RDPDR_DRIVE* drive;
310  RDPDR_SERIAL* serial;
311  RDPDR_PRINTER* printer;
312  RDPDR_PARALLEL* parallel;
313  RDPDR_SMARTCARD* smartcard;
314  } device;
315 
316  device.base = NULL;
317  WINPR_ASSERT(args || (count == 0));
318 
319  switch (Type)
320  {
321  case RDPDR_DTYP_PRINT:
322  size = sizeof(RDPDR_PRINTER);
323  break;
324  case RDPDR_DTYP_SERIAL:
325  size = sizeof(RDPDR_SERIAL);
326  break;
327  case RDPDR_DTYP_PARALLEL:
328  size = sizeof(RDPDR_PARALLEL);
329  break;
330  case RDPDR_DTYP_SMARTCARD:
331  size = sizeof(RDPDR_SMARTCARD);
332  break;
333  case RDPDR_DTYP_FILESYSTEM:
334  size = sizeof(RDPDR_DRIVE);
335  break;
336  default:
337  goto fail;
338  }
339 
340  device.base = calloc(1, size);
341  if (!device.base)
342  goto fail;
343  device.base->Id = 0;
344  device.base->Type = Type;
345 
346  if (count > 0)
347  {
348  device.base->Name = _strdup(args[0]);
349  if (!device.base->Name)
350  goto fail;
351 
352  switch (Type)
353  {
354  case RDPDR_DTYP_PRINT:
355  if (count > 1)
356  {
357  device.printer->DriverName = _strdup(args[1]);
358  if (!device.printer->DriverName)
359  goto fail;
360  }
361 
362  if (count > 2)
363  {
364  device.printer->IsDefault = _stricmp(args[2], "default") == 0;
365  }
366  break;
367  case RDPDR_DTYP_SERIAL:
368  if (count > 1)
369  {
370  device.serial->Path = _strdup(args[1]);
371  if (!device.serial->Path)
372  goto fail;
373  }
374 
375  if (count > 2)
376  {
377  device.serial->Driver = _strdup(args[2]);
378  if (!device.serial->Driver)
379  goto fail;
380  }
381 
382  if (count > 3)
383  {
384  device.serial->Permissive = _strdup(args[3]);
385  if (!device.serial->Permissive)
386  goto fail;
387  }
388  break;
389  case RDPDR_DTYP_PARALLEL:
390  if (count > 1)
391  {
392  device.parallel->Path = _strdup(args[1]);
393  if (!device.serial->Path)
394  goto fail;
395  }
396  break;
397  case RDPDR_DTYP_SMARTCARD:
398  break;
399  case RDPDR_DTYP_FILESYSTEM:
400  if (count > 1)
401  {
402  device.drive->Path = _strdup(args[1]);
403  if (!device.drive->Path)
404  goto fail;
405  }
406  if (count > 2)
407  device.drive->automount = (args[2] == NULL) ? TRUE : FALSE;
408  break;
409  default:
410  goto fail;
411  }
412  }
413  return device.base;
414 
415 fail:
416  freerdp_device_free(device.base);
417  return NULL;
418 }
419 
420 void freerdp_device_free(RDPDR_DEVICE* device)
421 {
422  if (!device)
423  return;
424 
425  union
426  {
427  RDPDR_DEVICE* dev;
428  RDPDR_DRIVE* drive;
429  RDPDR_SERIAL* serial;
430  RDPDR_PRINTER* printer;
431  RDPDR_PARALLEL* parallel;
432  RDPDR_SMARTCARD* smartcard;
433  } cnv;
434 
435  cnv.dev = device;
436 
437  switch (device->Type)
438  {
439  case RDPDR_DTYP_PRINT:
440  free(cnv.printer->DriverName);
441  break;
442  case RDPDR_DTYP_SERIAL:
443  free(cnv.serial->Path);
444  free(cnv.serial->Driver);
445  free(cnv.serial->Permissive);
446  break;
447  case RDPDR_DTYP_PARALLEL:
448  free(cnv.parallel->Path);
449  break;
450  case RDPDR_DTYP_SMARTCARD:
451  break;
452  case RDPDR_DTYP_FILESYSTEM:
453  free(cnv.drive->Path);
454  break;
455  default:
456  break;
457  }
458  free(cnv.dev->Name);
459  free(cnv.dev);
460 }
461 
462 RDPDR_DEVICE* freerdp_device_clone(const RDPDR_DEVICE* device)
463 {
464  union
465  {
466  const RDPDR_DEVICE* dev;
467  const RDPDR_DRIVE* drive;
468  const RDPDR_SERIAL* serial;
469  const RDPDR_PRINTER* printer;
470  const RDPDR_PARALLEL* parallel;
471  const RDPDR_SMARTCARD* smartcard;
472  } src;
473 
474  union
475  {
476  RDPDR_DEVICE* dev;
477  RDPDR_DRIVE* drive;
478  RDPDR_SERIAL* serial;
479  RDPDR_PRINTER* printer;
480  RDPDR_PARALLEL* parallel;
481  RDPDR_SMARTCARD* smartcard;
482  } copy;
483  size_t count = 0;
484  const char* args[4] = { 0 };
485 
486  copy.dev = NULL;
487  src.dev = device;
488 
489  if (!device)
490  return NULL;
491 
492  if (device->Name)
493  {
494  count = 1;
495  args[0] = device->Name;
496  }
497 
498  switch (device->Type)
499  {
500  case RDPDR_DTYP_FILESYSTEM:
501  if (src.drive->Path)
502  {
503  args[1] = src.drive->Path;
504  count = 2;
505  }
506  break;
507 
508  case RDPDR_DTYP_PRINT:
509  if (src.printer->DriverName)
510  {
511  args[1] = src.printer->DriverName;
512  count = 2;
513  }
514  break;
515 
516  case RDPDR_DTYP_SMARTCARD:
517  break;
518 
519  case RDPDR_DTYP_SERIAL:
520  if (src.serial->Path)
521  {
522  args[1] = src.serial->Path;
523  count = 2;
524  }
525 
526  if (src.serial->Driver)
527  {
528  args[2] = src.serial->Driver;
529  count = 3;
530  }
531 
532  if (src.serial->Permissive)
533  {
534  args[3] = src.serial->Permissive;
535  count = 4;
536  }
537  break;
538 
539  case RDPDR_DTYP_PARALLEL:
540  if (src.parallel->Path)
541  {
542  args[1] = src.parallel->Path;
543  count = 2;
544  }
545  break;
546  default:
547  WLog_ERR(TAG, "unknown device type %" PRIu32 "", device->Type);
548  break;
549  }
550 
551  copy.dev = freerdp_device_new(device->Type, count, args);
552  if (!copy.dev)
553  return NULL;
554 
555  copy.dev->Id = device->Id;
556 
557  return copy.dev;
558 }
559 
560 void freerdp_device_collection_free(rdpSettings* settings)
561 {
562  WINPR_ASSERT(settings);
563 
564  if (settings->DeviceArray)
565  {
566  for (UINT32 index = 0; index < settings->DeviceArraySize; index++)
567  (void)freerdp_settings_set_pointer_array(settings, FreeRDP_DeviceArray, index, NULL);
568  }
569 
570  free((void*)settings->DeviceArray);
571 
572  (void)freerdp_settings_set_pointer(settings, FreeRDP_DeviceArray, NULL);
573  (void)freerdp_settings_set_uint32(settings, FreeRDP_DeviceArraySize, 0);
574  (void)freerdp_settings_set_uint32(settings, FreeRDP_DeviceCount, 0);
575 }
576 
577 BOOL freerdp_static_channel_collection_del(rdpSettings* settings, const char* name)
578 {
579  const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
580  if (!settings || !settings->StaticChannelArray)
581  return FALSE;
582 
583  for (UINT32 x = 0; x < count; x++)
584  {
585  ADDIN_ARGV* cur = settings->StaticChannelArray[x];
586  if (cur && (cur->argc > 0))
587  {
588  if (strcmp(name, cur->argv[0]) == 0)
589  {
590  const size_t rem = settings->StaticChannelArraySize - count + 1;
591  memmove_s((void*)&settings->StaticChannelArray[x],
592  (count - x) * sizeof(ADDIN_ARGV*),
593  (void*)&settings->StaticChannelArray[x + 1],
594  (count - x - 1) * sizeof(ADDIN_ARGV*));
595  memset((void*)&settings->StaticChannelArray[count - 1], 0,
596  sizeof(ADDIN_ARGV*) * rem);
597 
598  freerdp_addin_argv_free(cur);
599  return freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelCount, count - 1);
600  }
601  }
602  }
603  {
604  const size_t rem = settings->StaticChannelArraySize - count;
605  memset((void*)&settings->StaticChannelArray[count], 0, sizeof(ADDIN_ARGV*) * rem);
606  }
607  return FALSE;
608 }
609 
610 BOOL freerdp_static_channel_collection_add(rdpSettings* settings, ADDIN_ARGV* channel)
611 {
612  UINT32 count = 0;
613 
614  WINPR_ASSERT(settings);
615  WINPR_ASSERT(channel);
616 
617  count = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount) + 1;
618  if (freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize) < count)
619  {
620  const UINT32 oldSize =
621  freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
622  UINT32 new_size = oldSize * 2ul;
623  ADDIN_ARGV** new_array = NULL;
624  if (new_size == 0)
625  new_size = count * 2ul;
626 
627  new_array = (ADDIN_ARGV**)realloc((void*)settings->StaticChannelArray,
628  new_size * sizeof(ADDIN_ARGV*));
629 
630  if (!new_array)
631  return FALSE;
632 
633  settings->StaticChannelArray = new_array;
634  {
635  const size_t rem = new_size - oldSize;
636  memset((void*)&settings->StaticChannelArray[oldSize], 0, sizeof(ADDIN_ARGV*) * rem);
637  }
638  if (!freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelArraySize, new_size))
639  return FALSE;
640  }
641 
642  count = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
643 
644  ADDIN_ARGV** cur = &settings->StaticChannelArray[count++];
645  freerdp_addin_argv_free(*cur);
646  *cur = channel;
647  return freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelCount, count);
648 }
649 
650 ADDIN_ARGV* freerdp_static_channel_collection_find(rdpSettings* settings, const char* name)
651 {
652  ADDIN_ARGV* channel = NULL;
653 
654  WINPR_ASSERT(settings);
655  WINPR_ASSERT(name);
656 
657  for (UINT32 index = 0;
658  index < freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount); index++)
659  {
660  channel = settings->StaticChannelArray[index];
661 
662  if (strcmp(channel->argv[0], name) == 0)
663  return channel;
664  }
665 
666  return NULL;
667 }
668 
669 void freerdp_static_channel_collection_free(rdpSettings* settings)
670 {
671  if (!settings)
672  return;
673 
674  if (settings->StaticChannelArray)
675  {
676  for (UINT32 i = 0;
677  i < freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize); i++)
678  freerdp_addin_argv_free(settings->StaticChannelArray[i]);
679  }
680 
681  free((void*)settings->StaticChannelArray);
682  (void)freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelArraySize, 0);
683  settings->StaticChannelArray = NULL;
684  (void)freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelCount, 0);
685 }
686 
687 BOOL freerdp_dynamic_channel_collection_del(rdpSettings* settings, const char* name)
688 {
689  const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
690  if (!settings || !settings->DynamicChannelArray)
691  return FALSE;
692 
693  for (UINT32 x = 0; x < count; x++)
694  {
695  ADDIN_ARGV* cur = settings->DynamicChannelArray[x];
696  if (cur && (cur->argc > 0))
697  {
698  if (strcmp(name, cur->argv[0]) == 0)
699  {
700  const size_t rem = settings->DynamicChannelArraySize - count + 1;
701  memmove_s((void*)&settings->DynamicChannelArray[x],
702  (count - x) * sizeof(ADDIN_ARGV*),
703  (void*)&settings->DynamicChannelArray[x + 1],
704  (count - x - 1) * sizeof(ADDIN_ARGV*));
705  memset((void*)&settings->DynamicChannelArray[count - 1], 0,
706  sizeof(ADDIN_ARGV*) * rem);
707 
708  freerdp_addin_argv_free(cur);
709  return freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelCount,
710  count - 1);
711  }
712  }
713  }
714 
715  return FALSE;
716 }
717 
718 BOOL freerdp_dynamic_channel_collection_add(rdpSettings* settings, ADDIN_ARGV* channel)
719 {
720  UINT32 count = 0;
721  UINT32 oldSize = 0;
722 
723  WINPR_ASSERT(settings);
724  WINPR_ASSERT(channel);
725 
726  count = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount) + 1;
727  oldSize = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
728  if (oldSize < count)
729  {
730  ADDIN_ARGV** new_array = NULL;
731  UINT32 size = oldSize * 2;
732  if (size == 0)
733  size = count * 2;
734 
735  new_array =
736  (ADDIN_ARGV**)realloc((void*)settings->DynamicChannelArray, sizeof(ADDIN_ARGV*) * size);
737 
738  if (!new_array)
739  return FALSE;
740 
741  settings->DynamicChannelArray = new_array;
742  {
743  const size_t rem = size - oldSize;
744  memset((void*)&settings->DynamicChannelArray[oldSize], 0, sizeof(ADDIN_ARGV*) * rem);
745  }
746  if (!freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelArraySize, size))
747  return FALSE;
748  }
749 
750  count = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
751  settings->DynamicChannelArray[count++] = channel;
752  return freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelCount, count);
753 }
754 
755 ADDIN_ARGV* freerdp_dynamic_channel_collection_find(const rdpSettings* settings, const char* name)
756 {
757  WINPR_ASSERT(settings);
758  WINPR_ASSERT(name);
759 
760  for (UINT32 index = 0;
761  index < freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount); index++)
762  {
763  ADDIN_ARGV* channel = settings->DynamicChannelArray[index];
764 
765  if (strcmp(channel->argv[0], name) == 0)
766  return channel;
767  }
768 
769  return NULL;
770 }
771 
772 void freerdp_addin_argv_free(ADDIN_ARGV* args)
773 {
774  if (!args)
775  return;
776 
777  if (args->argv)
778  {
779  for (int index = 0; index < args->argc; index++)
780  free(args->argv[index]);
781  free((void*)args->argv);
782  }
783 
784  free(args);
785 }
786 
787 ADDIN_ARGV* freerdp_addin_argv_new(size_t argc, const char* const argv[])
788 {
789  if (argc > INT32_MAX)
790  return NULL;
791 
792  ADDIN_ARGV* args = calloc(1, sizeof(ADDIN_ARGV));
793  if (!args)
794  return NULL;
795  if (argc == 0)
796  return args;
797 
798  args->argc = (int)argc;
799  args->argv = (char**)calloc(argc, sizeof(char*));
800  if (!args->argv)
801  goto fail;
802 
803  if (argv)
804  {
805  for (size_t x = 0; x < argc; x++)
806  {
807  args->argv[x] = _strdup(argv[x]);
808  if (!args->argv[x])
809  goto fail;
810  }
811  }
812  return args;
813 
814 fail:
815  WINPR_PRAGMA_DIAG_PUSH
816  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
817  freerdp_addin_argv_free(args);
818  WINPR_PRAGMA_DIAG_POP
819  return NULL;
820 }
821 
822 ADDIN_ARGV* freerdp_addin_argv_clone(const ADDIN_ARGV* args)
823 {
824  union
825  {
826  char** c;
827  const char** cc;
828  } cnv;
829  if (!args)
830  return NULL;
831  cnv.c = args->argv;
832  return freerdp_addin_argv_new(args->argc, cnv.cc);
833 }
834 
835 void freerdp_dynamic_channel_collection_free(rdpSettings* settings)
836 {
837  WINPR_ASSERT(settings);
838 
839  if (settings->DynamicChannelArray)
840  {
841  for (UINT32 i = 0;
842  i < freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize); i++)
843  freerdp_addin_argv_free(settings->DynamicChannelArray[i]);
844  }
845 
846  free((void*)settings->DynamicChannelArray);
847  (void)freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelArraySize, 0);
848  settings->DynamicChannelArray = NULL;
849  (void)freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelCount, 0);
850 }
851 
852 void freerdp_capability_buffer_free(rdpSettings* settings)
853 {
854  WINPR_ASSERT(settings);
855 
856  if (settings->ReceivedCapabilityData)
857  {
858  for (UINT32 x = 0; x < settings->ReceivedCapabilitiesSize; x++)
859  {
860  free(settings->ReceivedCapabilityData[x]);
861  settings->ReceivedCapabilityData[x] = NULL;
862  }
863  }
864  settings->ReceivedCapabilitiesSize = 0;
865 
866  free(settings->ReceivedCapabilityDataSizes);
867  settings->ReceivedCapabilityDataSizes = NULL;
868 
869  free((void*)settings->ReceivedCapabilityData);
870  settings->ReceivedCapabilityData = NULL;
871  free(settings->ReceivedCapabilities);
872  settings->ReceivedCapabilities = NULL;
873 }
874 
875 BOOL freerdp_capability_buffer_copy(rdpSettings* settings, const rdpSettings* src)
876 {
877  WINPR_ASSERT(settings);
878  WINPR_ASSERT(src);
879 
880  if (!freerdp_capability_buffer_allocate(settings, src->ReceivedCapabilitiesSize))
881  return FALSE;
882 
883  for (UINT32 x = 0; x < src->ReceivedCapabilitiesSize; x++)
884  {
885  WINPR_ASSERT(settings->ReceivedCapabilities);
886  settings->ReceivedCapabilities[x] = src->ReceivedCapabilities[x];
887 
888  WINPR_ASSERT(settings->ReceivedCapabilityDataSizes);
889  settings->ReceivedCapabilityDataSizes[x] = src->ReceivedCapabilityDataSizes[x];
890 
891  WINPR_ASSERT(settings->ReceivedCapabilityData);
892  if (src->ReceivedCapabilityDataSizes[x] > 0)
893  {
894  void* tmp = realloc(settings->ReceivedCapabilityData[x],
895  settings->ReceivedCapabilityDataSizes[x]);
896  if (!tmp)
897  return FALSE;
898  memcpy(tmp, src->ReceivedCapabilityData[x], src->ReceivedCapabilityDataSizes[x]);
899  settings->ReceivedCapabilityData[x] = tmp;
900  }
901  else
902  {
903  free(settings->ReceivedCapabilityData[x]);
904  settings->ReceivedCapabilityData[x] = NULL;
905  }
906  }
907  return TRUE;
908 }
909 
910 void freerdp_target_net_addresses_free(rdpSettings* settings)
911 {
912  WINPR_ASSERT(settings);
913 
914  if (settings->TargetNetAddresses)
915  {
916  for (UINT32 index = 0; index < settings->TargetNetAddressCount; index++)
917  free(settings->TargetNetAddresses[index]);
918  }
919 
920  free((void*)settings->TargetNetAddresses);
921  free(settings->TargetNetPorts);
922  settings->TargetNetAddressCount = 0;
923  settings->TargetNetAddresses = NULL;
924  settings->TargetNetPorts = NULL;
925 }
926 
927 void freerdp_server_license_issuers_free(rdpSettings* settings)
928 {
929  WINPR_ASSERT(settings);
930 
931  if (settings->ServerLicenseProductIssuers)
932  {
933  for (UINT32 x = 0; x < settings->ServerLicenseProductIssuersCount; x++)
934  free(settings->ServerLicenseProductIssuers[x]);
935  }
936  free((void*)settings->ServerLicenseProductIssuers);
937  settings->ServerLicenseProductIssuers = NULL;
938  settings->ServerLicenseProductIssuersCount = 0;
939 }
940 
941 BOOL freerdp_server_license_issuers_copy(rdpSettings* settings, char** issuers, UINT32 count)
942 {
943  WINPR_ASSERT(settings);
944  WINPR_ASSERT(issuers || (count == 0));
945 
946  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ServerLicenseProductIssuers, NULL,
947  count))
948  return FALSE;
949 
950  for (UINT32 x = 0; x < count; x++)
951  {
952  char* issuer = _strdup(issuers[x]);
953  if (!issuer)
954  return FALSE;
955  settings->ServerLicenseProductIssuers[x] = issuer;
956  }
957 
958  return TRUE;
959 }
960 
961 void freerdp_performance_flags_make(rdpSettings* settings)
962 {
963  UINT32 PerformanceFlags = PERF_FLAG_NONE;
964 
965  if (freerdp_settings_get_bool(settings, FreeRDP_AllowFontSmoothing))
966  PerformanceFlags |= PERF_ENABLE_FONT_SMOOTHING;
967 
968  if (freerdp_settings_get_bool(settings, FreeRDP_AllowDesktopComposition))
969  PerformanceFlags |= PERF_ENABLE_DESKTOP_COMPOSITION;
970 
971  if (freerdp_settings_get_bool(settings, FreeRDP_DisableWallpaper))
972  PerformanceFlags |= PERF_DISABLE_WALLPAPER;
973 
974  if (freerdp_settings_get_bool(settings, FreeRDP_DisableFullWindowDrag))
975  PerformanceFlags |= PERF_DISABLE_FULLWINDOWDRAG;
976 
977  if (freerdp_settings_get_bool(settings, FreeRDP_DisableMenuAnims))
978  PerformanceFlags |= PERF_DISABLE_MENUANIMATIONS;
979 
980  if (freerdp_settings_get_bool(settings, FreeRDP_DisableThemes))
981  PerformanceFlags |= PERF_DISABLE_THEMING;
982  (void)freerdp_settings_set_uint32(settings, FreeRDP_PerformanceFlags, PerformanceFlags);
983 }
984 
985 void freerdp_performance_flags_split(rdpSettings* settings)
986 {
988  settings, FreeRDP_AllowFontSmoothing,
989  (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) &
990  PERF_ENABLE_FONT_SMOOTHING)
991  ? TRUE
992  : FALSE);
994  settings, FreeRDP_AllowDesktopComposition,
995  (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) &
996  PERF_ENABLE_DESKTOP_COMPOSITION)
997  ? TRUE
998  : FALSE);
1000  settings, FreeRDP_DisableWallpaper,
1001  (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) & PERF_DISABLE_WALLPAPER)
1002  ? TRUE
1003  : FALSE);
1005  settings, FreeRDP_DisableFullWindowDrag,
1006  (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) &
1007  PERF_DISABLE_FULLWINDOWDRAG)
1008  ? TRUE
1009  : FALSE);
1011  settings, FreeRDP_DisableMenuAnims,
1012  (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) &
1013  PERF_DISABLE_MENUANIMATIONS)
1014  ? TRUE
1015  : FALSE);
1017  settings, FreeRDP_DisableThemes,
1018  (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) & PERF_DISABLE_THEMING)
1019  ? TRUE
1020  : FALSE);
1021 }
1022 
1023 BOOL freerdp_set_gateway_usage_method(rdpSettings* settings, UINT32 GatewayUsageMethod)
1024 {
1025  if (!freerdp_settings_set_uint32(settings, FreeRDP_GatewayUsageMethod, GatewayUsageMethod))
1026  return FALSE;
1027 
1028  if (GatewayUsageMethod == TSC_PROXY_MODE_NONE_DIRECT)
1029  {
1030  if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, FALSE) ||
1031  !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE))
1032  return FALSE;
1033  }
1034  else if (GatewayUsageMethod == TSC_PROXY_MODE_DIRECT)
1035  {
1036  if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, TRUE) ||
1037  !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE))
1038  return FALSE;
1039  }
1040  else if (GatewayUsageMethod == TSC_PROXY_MODE_DETECT)
1041  {
1042  if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, TRUE) ||
1043  !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, TRUE))
1044  return FALSE;
1045  }
1046  else if (GatewayUsageMethod == TSC_PROXY_MODE_DEFAULT)
1047  {
1053  if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, FALSE) ||
1054  !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE))
1055  return FALSE;
1056  }
1057  else if (GatewayUsageMethod == TSC_PROXY_MODE_NONE_DETECT)
1058  {
1059  if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, FALSE) ||
1060  !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE))
1061  return FALSE;
1062  }
1063 
1064  return TRUE;
1065 }
1066 
1067 void freerdp_update_gateway_usage_method(rdpSettings* settings, UINT32 GatewayEnabled,
1068  UINT32 GatewayBypassLocal)
1069 {
1070  UINT32 GatewayUsageMethod = 0;
1071 
1072  if (!GatewayEnabled && !GatewayBypassLocal)
1073  GatewayUsageMethod = TSC_PROXY_MODE_NONE_DIRECT;
1074  else if (GatewayEnabled && !GatewayBypassLocal)
1075  GatewayUsageMethod = TSC_PROXY_MODE_DIRECT;
1076  else if (GatewayEnabled && GatewayBypassLocal)
1077  GatewayUsageMethod = TSC_PROXY_MODE_DETECT;
1078 
1079  freerdp_set_gateway_usage_method(settings, GatewayUsageMethod);
1080 }
1081 
1082 #if defined(WITH_FREERDP_DEPRECATED)
1083 BOOL freerdp_get_param_bool(const rdpSettings* settings, int id)
1084 {
1085  return freerdp_settings_get_bool(settings, (FreeRDP_Settings_Keys_Bool)id);
1086 }
1087 
1088 int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param)
1089 {
1090  return freerdp_settings_set_bool(settings, (FreeRDP_Settings_Keys_Bool)id, param) ? 0 : -1;
1091 }
1092 
1093 int freerdp_get_param_int(const rdpSettings* settings, int id)
1094 {
1095  return freerdp_settings_get_int32(settings, (FreeRDP_Settings_Keys_Int32)id);
1096 }
1097 
1098 int freerdp_set_param_int(rdpSettings* settings, int id, int param)
1099 {
1100  return freerdp_settings_set_int32(settings, (FreeRDP_Settings_Keys_Int32)id, param) ? 0 : -1;
1101 }
1102 
1103 UINT32 freerdp_get_param_uint32(const rdpSettings* settings, int id)
1104 {
1105  return freerdp_settings_get_uint32(settings, (FreeRDP_Settings_Keys_UInt32)id);
1106 }
1107 
1108 int freerdp_set_param_uint32(rdpSettings* settings, int id, UINT32 param)
1109 {
1110  return freerdp_settings_set_uint32(settings, (FreeRDP_Settings_Keys_UInt32)id, param) ? 0 : -1;
1111 }
1112 
1113 UINT64 freerdp_get_param_uint64(const rdpSettings* settings, int id)
1114 {
1115  return freerdp_settings_get_uint64(settings, (FreeRDP_Settings_Keys_UInt64)id);
1116 }
1117 
1118 int freerdp_set_param_uint64(rdpSettings* settings, int id, UINT64 param)
1119 {
1120  return freerdp_settings_set_uint64(settings, (FreeRDP_Settings_Keys_UInt64)id, param) ? 0 : -1;
1121 }
1122 
1123 char* freerdp_get_param_string(const rdpSettings* settings, int id)
1124 {
1125  const char* str = freerdp_settings_get_string(settings, (FreeRDP_Settings_Keys_String)id);
1126  return WINPR_CAST_CONST_PTR_AWAY(str, char*);
1127 }
1128 
1129 int freerdp_set_param_string(rdpSettings* settings, int id, const char* param)
1130 {
1131  return freerdp_settings_set_string(settings, (FreeRDP_Settings_Keys_String)id, param) ? 0 : -1;
1132 }
1133 #endif
1134 
1135 static BOOL value_to_uint(const char* value, ULONGLONG* result, ULONGLONG min, ULONGLONG max)
1136 {
1137  char* endptr = NULL;
1138  unsigned long long rc = 0;
1139 
1140  if (!value || !result)
1141  return FALSE;
1142 
1143  errno = 0;
1144  rc = _strtoui64(value, &endptr, 0);
1145 
1146  if (errno != 0)
1147  return FALSE;
1148 
1149  if (endptr == value)
1150  return FALSE;
1151 
1152  if ((rc < min) || (rc > max))
1153  return FALSE;
1154 
1155  *result = rc;
1156  return TRUE;
1157 }
1158 
1159 static BOOL value_to_int(const char* value, LONGLONG* result, LONGLONG min, LONGLONG max)
1160 {
1161  char* endptr = NULL;
1162  long long rc = 0;
1163 
1164  if (!value || !result)
1165  return FALSE;
1166 
1167  errno = 0;
1168  rc = _strtoi64(value, &endptr, 0);
1169 
1170  if (errno != 0)
1171  return FALSE;
1172 
1173  if (endptr == value)
1174  return FALSE;
1175 
1176  if ((rc < min) || (rc > max))
1177  return FALSE;
1178 
1179  *result = rc;
1180  return TRUE;
1181 }
1182 
1183 static BOOL parsing_fail(const char* key, const char* type, const char* value)
1184 {
1185  WLog_ERR(TAG, "Failed to parse key [%s] of type [%s]: value [%s]", key, type, value);
1186  return FALSE;
1187 }
1188 
1189 BOOL freerdp_settings_set_value_for_name(rdpSettings* settings, const char* name, const char* value)
1190 {
1191  ULONGLONG uval = 0;
1192  LONGLONG ival = 0;
1193  SSIZE_T type = 0;
1194 
1195  if (!settings || !name)
1196  return FALSE;
1197 
1198  const SSIZE_T i = freerdp_settings_get_key_for_name(name);
1199  if (i < 0)
1200  {
1201  WLog_ERR(TAG, "Invalid settings key [%s]", name);
1202  return FALSE;
1203  }
1204 
1205  const SSIZE_T index = i;
1206 
1207  type = freerdp_settings_get_type_for_key(index);
1208  switch (type)
1209  {
1210 
1211  case RDP_SETTINGS_TYPE_BOOL:
1212  {
1213  const BOOL val = (_strnicmp(value, "TRUE", 5) == 0) || (_strnicmp(value, "ON", 5) == 0);
1214  const BOOL nval =
1215  (_strnicmp(value, "FALSE", 6) == 0) || (_strnicmp(value, "OFF", 6) == 0);
1216  if (!val && !nval)
1217  return parsing_fail(name, "BOOL", value);
1218 
1219  // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1220  return freerdp_settings_set_bool(settings, (FreeRDP_Settings_Keys_Bool)index, val);
1221  }
1222  case RDP_SETTINGS_TYPE_UINT16:
1223  if (!value_to_uint(value, &uval, 0, UINT16_MAX))
1224  return parsing_fail(name, "UINT16", value);
1225 
1226  // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1227  if (!freerdp_settings_set_uint16(settings, (FreeRDP_Settings_Keys_UInt16)index,
1228  (UINT16)uval))
1229  return parsing_fail(name, "UINT16", value);
1230  return TRUE;
1231 
1232  case RDP_SETTINGS_TYPE_INT16:
1233  if (!value_to_int(value, &ival, INT16_MIN, INT16_MAX))
1234  return parsing_fail(name, "INT16", value);
1235 
1236  // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1237  if (!freerdp_settings_set_int16(settings, (FreeRDP_Settings_Keys_Int16)index,
1238  (INT16)ival))
1239  return parsing_fail(name, "INT16", value);
1240  return TRUE;
1241  case RDP_SETTINGS_TYPE_UINT32:
1242  if (!value_to_uint(value, &uval, 0, UINT32_MAX))
1243  return parsing_fail(name, "UINT32", value);
1244 
1245  // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1246  if (!freerdp_settings_set_uint32(settings, (FreeRDP_Settings_Keys_UInt32)index,
1247  (UINT32)uval))
1248  return parsing_fail(name, "UINT32", value);
1249  return TRUE;
1250  case RDP_SETTINGS_TYPE_INT32:
1251  if (!value_to_int(value, &ival, INT32_MIN, INT32_MAX))
1252  return parsing_fail(name, "INT32", value);
1253 
1254  // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1255  if (!freerdp_settings_set_int32(settings, (FreeRDP_Settings_Keys_Int32)index,
1256  (INT32)ival))
1257  return parsing_fail(name, "INT32", value);
1258  return TRUE;
1259  case RDP_SETTINGS_TYPE_UINT64:
1260  if (!value_to_uint(value, &uval, 0, UINT64_MAX))
1261  return parsing_fail(name, "UINT64", value);
1262 
1263  // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1264  if (!freerdp_settings_set_uint64(settings, (FreeRDP_Settings_Keys_UInt64)index, uval))
1265  return parsing_fail(name, "UINT64", value);
1266  return TRUE;
1267  case RDP_SETTINGS_TYPE_INT64:
1268  if (!value_to_int(value, &ival, INT64_MIN, INT64_MAX))
1269  return parsing_fail(name, "INT64", value);
1270 
1271  // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1272  if (!freerdp_settings_set_int64(settings, (FreeRDP_Settings_Keys_Int64)index, ival))
1273  return parsing_fail(name, "INT64", value);
1274  return TRUE;
1275 
1276  case RDP_SETTINGS_TYPE_STRING:
1277  // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1278  return freerdp_settings_set_string(settings, (FreeRDP_Settings_Keys_String)index,
1279  value);
1280  case RDP_SETTINGS_TYPE_POINTER:
1281  return parsing_fail(name, "POINTER", value);
1282  default:
1283  return FALSE;
1284  }
1285  return FALSE;
1286 }
1287 
1288 BOOL freerdp_settings_set_pointer_len_(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
1289  FreeRDP_Settings_Keys_UInt32 lenId, const void* data,
1290  size_t len, size_t size)
1291 {
1292  BOOL rc = FALSE;
1293  void* copy = NULL;
1294  void* old = freerdp_settings_get_pointer_writable(settings, id);
1295  free(old);
1296  if (!freerdp_settings_set_pointer(settings, id, NULL))
1297  return FALSE;
1298  if (lenId != FreeRDP_UINT32_UNUSED)
1299  {
1300  if (!freerdp_settings_set_uint32(settings, lenId, 0))
1301  return FALSE;
1302  }
1303 
1304  if (len > UINT32_MAX)
1305  return FALSE;
1306  if (len == 0)
1307  return TRUE;
1308  copy = calloc(len, size);
1309  if (!copy)
1310  return FALSE;
1311  if (data)
1312  memcpy(copy, data, len * size);
1313  rc = freerdp_settings_set_pointer(settings, id, copy);
1314  if (!rc)
1315  {
1316  free(copy);
1317  return FALSE;
1318  }
1319 
1320  // freerdp_settings_set_pointer takes ownership of copy
1321  // NOLINTNEXTLINE(clang-analyzer-unix.Malloc)
1322  if (lenId == FreeRDP_UINT32_UNUSED)
1323  return TRUE;
1324  return freerdp_settings_set_uint32(settings, lenId, (UINT32)len);
1325 }
1326 
1327 const void* freerdp_settings_get_pointer(const rdpSettings* settings,
1328  FreeRDP_Settings_Keys_Pointer id)
1329 {
1330  union
1331  {
1332  const rdpSettings* pc;
1333  rdpSettings* p;
1334  } cnv;
1335  cnv.pc = settings;
1336  return freerdp_settings_get_pointer_writable(cnv.p, id);
1337 }
1338 
1339 BOOL freerdp_settings_set_pointer_len(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
1340  const void* data, size_t len)
1341 {
1342  union
1343  {
1344  const void* cv;
1345  void* v;
1346  } cnv;
1347 
1348  cnv.cv = data;
1349  if (!settings)
1350  return FALSE;
1351 
1352  switch (id)
1353  {
1354  case FreeRDP_RdpServerCertificate:
1355  freerdp_certificate_free(settings->RdpServerCertificate);
1356 
1357  if (len > 1)
1358  {
1359  WLog_ERR(TAG, "FreeRDP_RdpServerCertificate::len must be 0 or 1");
1360  return FALSE;
1361  }
1362  settings->RdpServerCertificate = cnv.v;
1363  if (!settings->RdpServerCertificate && (len > 0))
1364  {
1365  settings->RdpServerCertificate = freerdp_certificate_new();
1366  if (!settings->RdpServerCertificate)
1367  return FALSE;
1368  }
1369  return TRUE;
1370  case FreeRDP_RdpServerRsaKey:
1371  freerdp_key_free(settings->RdpServerRsaKey);
1372  if (len > 1)
1373  {
1374  WLog_ERR(TAG, "FreeRDP_RdpServerRsaKey::len must be 0 or 1");
1375  return FALSE;
1376  }
1377  settings->RdpServerRsaKey = (rdpPrivateKey*)cnv.v;
1378  if (!settings->RdpServerRsaKey && (len > 0))
1379  {
1380  settings->RdpServerRsaKey = freerdp_key_new();
1381  if (!settings->RdpServerRsaKey)
1382  return FALSE;
1383  }
1384  return TRUE;
1385  case FreeRDP_RedirectionPassword:
1386  return freerdp_settings_set_pointer_len_(
1387  settings, id, FreeRDP_RedirectionPasswordLength, data, len, sizeof(char));
1388  case FreeRDP_RedirectionTsvUrl:
1389  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_RedirectionTsvUrlLength,
1390  data, len, sizeof(char));
1391  case FreeRDP_RedirectionTargetCertificate:
1392  freerdp_certificate_free(settings->RedirectionTargetCertificate);
1393 
1394  if (len > 1)
1395  {
1396  WLog_ERR(TAG, "FreeRDP_RedirectionTargetCertificate::len must be 0 or 1");
1397  return FALSE;
1398  }
1399  settings->RedirectionTargetCertificate = cnv.v;
1400  if (!settings->RedirectionTargetCertificate && (len > 0))
1401  {
1402  settings->RedirectionTargetCertificate = freerdp_certificate_new();
1403  if (!settings->RedirectionTargetCertificate)
1404  return FALSE;
1405  }
1406  return TRUE;
1407  case FreeRDP_RedirectionGuid:
1408  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_RedirectionGuidLength,
1409  data, len, sizeof(BYTE));
1410  case FreeRDP_LoadBalanceInfo:
1411  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_LoadBalanceInfoLength,
1412  data, len, sizeof(char));
1413  case FreeRDP_ServerRandom:
1414  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ServerRandomLength, data,
1415  len, sizeof(char));
1416  case FreeRDP_ClientRandom:
1417  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ClientRandomLength, data,
1418  len, sizeof(char));
1419  case FreeRDP_ServerCertificate:
1420  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ServerCertificateLength,
1421  data, len, sizeof(char));
1422  case FreeRDP_TargetNetAddresses:
1423  if ((data == NULL) && (len == 0))
1424  {
1425  freerdp_target_net_addresses_free(settings);
1426  return TRUE;
1427  }
1428  WLog_WARN(
1429  TAG,
1430  "[BUG] FreeRDP_TargetNetAddresses must not be resized from outside the library!");
1431  return FALSE;
1432  case FreeRDP_ServerLicenseProductIssuers:
1433  if (data == NULL)
1434  freerdp_server_license_issuers_free(settings);
1435  return freerdp_settings_set_pointer_len_(settings, FreeRDP_ServerLicenseProductIssuers,
1436  FreeRDP_ServerLicenseProductIssuersCount, data,
1437  len, sizeof(char*));
1438  case FreeRDP_TargetNetPorts:
1439  if ((data == NULL) && (len == 0))
1440  {
1441  freerdp_target_net_addresses_free(settings);
1442  return TRUE;
1443  }
1444  WLog_WARN(TAG,
1445  "[BUG] FreeRDP_TargetNetPorts must not be resized from outside the library!");
1446  return FALSE;
1447  case FreeRDP_DeviceArray:
1448  if (data == NULL)
1449  freerdp_device_collection_free(settings);
1450  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_DeviceArraySize, data,
1451  len, sizeof(ADDIN_ARGV*));
1452  case FreeRDP_ChannelDefArray:
1453  if ((len > 0) && (len < CHANNEL_MAX_COUNT))
1454  WLog_WARN(TAG,
1455  "FreeRDP_ChannelDefArray::len expected to be >= %" PRIu32
1456  ", but have %" PRIu32,
1457  CHANNEL_MAX_COUNT, len);
1458  return freerdp_settings_set_pointer_len_(settings, FreeRDP_ChannelDefArray,
1459  FreeRDP_ChannelDefArraySize, data, len,
1460  sizeof(CHANNEL_DEF));
1461  case FreeRDP_MonitorDefArray:
1462  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_MonitorDefArraySize,
1463  data, len, sizeof(rdpMonitor));
1464  case FreeRDP_ClientAutoReconnectCookie:
1465  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_UINT32_UNUSED, data, len,
1466  sizeof(ARC_CS_PRIVATE_PACKET));
1467  case FreeRDP_ServerAutoReconnectCookie:
1468  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_UINT32_UNUSED, data, len,
1469  sizeof(ARC_SC_PRIVATE_PACKET));
1470  case FreeRDP_ClientTimeZone:
1471  if (len > 1)
1472  {
1473  WLog_ERR(TAG, "FreeRDP_ClientTimeZone::len must be 0 or 1");
1474  return FALSE;
1475  }
1476  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_UINT32_UNUSED, data, len,
1477  sizeof(TIME_ZONE_INFORMATION));
1478  case FreeRDP_BitmapCacheV2CellInfo:
1479  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_BitmapCacheV2NumCells,
1480  data, len, sizeof(BITMAP_CACHE_V2_CELL_INFO));
1481  case FreeRDP_GlyphCache:
1482  if ((len != 0) && (len != 10))
1483  {
1484  WLog_ERR(TAG, "FreeRDP_GlyphCache::len must be 0 or 10");
1485  return FALSE;
1486  }
1487  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_UINT32_UNUSED, data, len,
1488  sizeof(GLYPH_CACHE_DEFINITION));
1489  case FreeRDP_FragCache:
1490  if (len > 1)
1491  {
1492  WLog_ERR(TAG, "FreeRDP_FragCache::len must be 0 or 1");
1493  return FALSE;
1494  }
1495  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_UINT32_UNUSED, data, len,
1496  sizeof(GLYPH_CACHE_DEFINITION));
1497  case FreeRDP_StaticChannelArray:
1498  if (data == NULL)
1499  freerdp_static_channel_collection_free(settings);
1500  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_StaticChannelArraySize,
1501  data, len, sizeof(ADDIN_ARGV*));
1502  case FreeRDP_DynamicChannelArray:
1503  if (data == NULL)
1504  freerdp_dynamic_channel_collection_free(settings);
1505  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_DynamicChannelArraySize,
1506  data, len, sizeof(ADDIN_ARGV*));
1507  case FreeRDP_ReceivedCapabilityData:
1508  if (data == NULL)
1509  freerdp_capability_buffer_free(settings);
1510  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ReceivedCapabilitiesSize,
1511  data, len, sizeof(BYTE*));
1512  case FreeRDP_ReceivedCapabilities:
1513  if (data == NULL)
1514  freerdp_capability_buffer_free(settings);
1515  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ReceivedCapabilitiesSize,
1516  data, len, sizeof(char));
1517  case FreeRDP_OrderSupport:
1518  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_UINT32_UNUSED, data, len,
1519  sizeof(char));
1520 
1521  case FreeRDP_MonitorIds:
1522  return freerdp_settings_set_pointer_len_(
1523  settings, FreeRDP_MonitorIds, FreeRDP_NumMonitorIds, data, len, sizeof(UINT32));
1524 
1525  default:
1526  if ((data == NULL) && (len == 0))
1527  {
1528  freerdp_settings_set_pointer(settings, id, NULL);
1529  }
1530  else
1531  WLog_WARN(TAG, "Invalid id %" PRIuz, id);
1532  return FALSE;
1533  }
1534 }
1535 
1536 void* freerdp_settings_get_pointer_array_writable(const rdpSettings* settings,
1537  FreeRDP_Settings_Keys_Pointer id, size_t offset)
1538 {
1539  size_t max = 0;
1540  if (!settings)
1541  return NULL;
1542  switch (id)
1543  {
1544  case FreeRDP_ClientAutoReconnectCookie:
1545  max = 1;
1546  if ((offset >= max) || !settings->ClientAutoReconnectCookie)
1547  goto fail;
1548  return &settings->ClientAutoReconnectCookie[offset];
1549  case FreeRDP_ServerAutoReconnectCookie:
1550  max = 1;
1551  if ((offset >= max) || !settings->ServerAutoReconnectCookie)
1552  goto fail;
1553  return &settings->ServerAutoReconnectCookie[offset];
1554  case FreeRDP_ServerCertificate:
1555  max = freerdp_settings_get_uint32(settings, FreeRDP_ServerCertificateLength);
1556  if (offset >= max)
1557  goto fail;
1558  return &settings->ServerCertificate[offset];
1559  case FreeRDP_ServerRandom:
1560  max = freerdp_settings_get_uint32(settings, FreeRDP_ServerRandomLength);
1561  if (offset >= max)
1562  goto fail;
1563  return &settings->ServerRandom[offset];
1564  case FreeRDP_ClientRandom:
1565  max = freerdp_settings_get_uint32(settings, FreeRDP_ClientRandomLength);
1566  if (offset >= max)
1567  goto fail;
1568  return &settings->ClientRandom[offset];
1569  case FreeRDP_LoadBalanceInfo:
1570  max = freerdp_settings_get_uint32(settings, FreeRDP_LoadBalanceInfoLength);
1571  if (offset >= max)
1572  goto fail;
1573  return &settings->LoadBalanceInfo[offset];
1574 
1575  case FreeRDP_RedirectionTsvUrl:
1576  max = freerdp_settings_get_uint32(settings, FreeRDP_RedirectionTsvUrlLength);
1577  if (offset >= max)
1578  goto fail;
1579  return &settings->RedirectionTsvUrl[offset];
1580 
1581  case FreeRDP_RedirectionPassword:
1582  max = freerdp_settings_get_uint32(settings, FreeRDP_RedirectionPasswordLength);
1583  if (offset >= max)
1584  goto fail;
1585  return &settings->RedirectionPassword[offset];
1586 
1587  case FreeRDP_OrderSupport:
1588  max = 32;
1589  if (offset >= max)
1590  goto fail;
1591  return &settings->OrderSupport[offset];
1592  case FreeRDP_MonitorIds:
1593  max = freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds);
1594  if (offset >= max)
1595  goto fail;
1596  return &settings->MonitorIds[offset];
1597  case FreeRDP_MonitorDefArray:
1598  max = freerdp_settings_get_uint32(settings, FreeRDP_MonitorDefArraySize);
1599  if (offset >= max)
1600  goto fail;
1601  return &settings->MonitorDefArray[offset];
1602  case FreeRDP_ChannelDefArray:
1603  max = freerdp_settings_get_uint32(settings, FreeRDP_ChannelDefArraySize);
1604  if (offset >= max)
1605  goto fail;
1606  return &settings->ChannelDefArray[offset];
1607  case FreeRDP_DeviceArray:
1608  max = freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize);
1609  if (offset >= max)
1610  goto fail;
1611  return settings->DeviceArray[offset];
1612  case FreeRDP_StaticChannelArray:
1613  max = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
1614  if (offset >= max)
1615  goto fail;
1616  return settings->StaticChannelArray[offset];
1617  case FreeRDP_DynamicChannelArray:
1618  max = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
1619  if (offset >= max)
1620  goto fail;
1621  return settings->DynamicChannelArray[offset];
1622  case FreeRDP_FragCache:
1623  max = 1;
1624  if (offset >= max)
1625  goto fail;
1626  return &settings->FragCache[offset];
1627  case FreeRDP_GlyphCache:
1628  max = 10;
1629  if (offset >= max)
1630  goto fail;
1631  return &settings->GlyphCache[offset];
1632  case FreeRDP_BitmapCacheV2CellInfo:
1633  max = freerdp_settings_get_uint32(settings, FreeRDP_BitmapCacheV2NumCells);
1634  if (offset >= max)
1635  goto fail;
1636  return &settings->BitmapCacheV2CellInfo[offset];
1637  case FreeRDP_ReceivedCapabilities:
1638  max = freerdp_settings_get_uint32(settings, FreeRDP_ReceivedCapabilitiesSize);
1639  if (offset >= max)
1640  goto fail;
1641  return &settings->ReceivedCapabilities[offset];
1642  case FreeRDP_TargetNetAddresses:
1643  max = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
1644  if (offset >= max)
1645  goto fail;
1646  return settings->TargetNetAddresses[offset];
1647  case FreeRDP_TargetNetPorts:
1648  max = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
1649  if (offset >= max)
1650  goto fail;
1651  return &settings->TargetNetPorts[offset];
1652  case FreeRDP_ClientTimeZone:
1653  max = 1;
1654  if (offset >= max)
1655  goto fail;
1656  return settings->ClientTimeZone;
1657  case FreeRDP_RdpServerCertificate:
1658  max = 1;
1659  if (offset >= max)
1660  goto fail;
1661  return settings->RdpServerCertificate;
1662  case FreeRDP_RdpServerRsaKey:
1663  max = 1;
1664  if (offset >= max)
1665  goto fail;
1666  return settings->RdpServerRsaKey;
1667  default:
1668  WLog_WARN(TAG, "Invalid id %s [%" PRIuz "]", freerdp_settings_get_name_for_key(id), id);
1669  return NULL;
1670  }
1671 
1672 fail:
1673  WLog_WARN(TAG, "Invalid offset for %s [%" PRIuz "]: size=%" PRIuz ", offset=%" PRIuz,
1674  freerdp_settings_get_name_for_key(id), id, max, offset);
1675  return NULL;
1676 }
1677 
1678 BOOL freerdp_settings_set_pointer_array(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
1679  size_t offset, const void* data)
1680 {
1681  size_t maxOffset = 0;
1682  if (!settings)
1683  return FALSE;
1684  switch (id)
1685  {
1686  case FreeRDP_ClientAutoReconnectCookie:
1687  maxOffset = 1;
1688  if ((offset >= maxOffset) || !data || !settings->ClientAutoReconnectCookie)
1689  goto fail;
1690  settings->ClientAutoReconnectCookie[offset] = *(const ARC_CS_PRIVATE_PACKET*)data;
1691  return TRUE;
1692  case FreeRDP_ServerAutoReconnectCookie:
1693  maxOffset = 1;
1694  if ((offset >= maxOffset) || !data || !settings->ServerAutoReconnectCookie)
1695  goto fail;
1696  settings->ServerAutoReconnectCookie[offset] = *(const ARC_SC_PRIVATE_PACKET*)data;
1697  return TRUE;
1698  case FreeRDP_ServerCertificate:
1699  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ServerCertificateLength);
1700  if ((offset >= maxOffset) || !data)
1701  goto fail;
1702  settings->ServerCertificate[offset] = *(const BYTE*)data;
1703  return TRUE;
1704  case FreeRDP_DeviceArray:
1705  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize);
1706  if (offset >= maxOffset)
1707  goto fail;
1708  freerdp_device_free(settings->DeviceArray[offset]);
1709  settings->DeviceArray[offset] = freerdp_device_clone(data);
1710  return TRUE;
1711  case FreeRDP_TargetNetAddresses:
1712  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
1713  if ((offset >= maxOffset) || !data)
1714  goto fail;
1715  free(settings->TargetNetAddresses[offset]);
1716  settings->TargetNetAddresses[offset] = _strdup((const char*)data);
1717  return settings->TargetNetAddresses[offset] != NULL;
1718  case FreeRDP_TargetNetPorts:
1719  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
1720  if ((offset >= maxOffset) || !data)
1721  goto fail;
1722  settings->TargetNetPorts[offset] = *((const UINT32*)data);
1723  return TRUE;
1724  case FreeRDP_StaticChannelArray:
1725  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
1726  if ((offset >= maxOffset) || !data)
1727  goto fail;
1728  freerdp_addin_argv_free(settings->StaticChannelArray[offset]);
1729  settings->StaticChannelArray[offset] = freerdp_addin_argv_clone(data);
1730  return TRUE;
1731  case FreeRDP_DynamicChannelArray:
1732  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
1733  if ((offset >= maxOffset) || !data)
1734  goto fail;
1735  freerdp_addin_argv_free(settings->DynamicChannelArray[offset]);
1736  settings->DynamicChannelArray[offset] = freerdp_addin_argv_clone(data);
1737  return TRUE;
1738  case FreeRDP_BitmapCacheV2CellInfo:
1739  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_BitmapCacheV2NumCells);
1740  if ((offset >= maxOffset) || !data)
1741  goto fail;
1742  {
1743  const BITMAP_CACHE_V2_CELL_INFO* cdata = (const BITMAP_CACHE_V2_CELL_INFO*)data;
1744  settings->BitmapCacheV2CellInfo[offset] = *cdata;
1745  }
1746  return TRUE;
1747  case FreeRDP_ServerRandom:
1748  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ServerRandomLength);
1749  if ((offset >= maxOffset) || !data)
1750  goto fail;
1751  settings->ServerRandom[offset] = *(const BYTE*)data;
1752  return TRUE;
1753  case FreeRDP_ClientRandom:
1754  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ClientRandomLength);
1755  if ((offset >= maxOffset) || !data)
1756  goto fail;
1757  settings->ClientRandom[offset] = *(const BYTE*)data;
1758  return TRUE;
1759  case FreeRDP_LoadBalanceInfo:
1760  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_LoadBalanceInfoLength);
1761  if ((offset >= maxOffset) || !data)
1762  goto fail;
1763  settings->LoadBalanceInfo[offset] = *(const BYTE*)data;
1764  return TRUE;
1765  case FreeRDP_RedirectionTsvUrl:
1766  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_RedirectionTsvUrlLength);
1767  if ((offset >= maxOffset) || !data)
1768  goto fail;
1769  settings->RedirectionTsvUrl[offset] = *(const BYTE*)data;
1770  return TRUE;
1771  case FreeRDP_RedirectionPassword:
1772  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_RedirectionPasswordLength);
1773  if ((offset >= maxOffset) || !data)
1774  goto fail;
1775  settings->RedirectionPassword[offset] = *(const BYTE*)data;
1776  return TRUE;
1777  case FreeRDP_OrderSupport:
1778  maxOffset = 32;
1779  if (!settings->OrderSupport)
1780  goto fail;
1781  if ((offset >= maxOffset) || !data)
1782  goto fail;
1783  settings->OrderSupport[offset] = *(const BOOL*)data;
1784  return TRUE;
1785  case FreeRDP_GlyphCache:
1786  maxOffset = 10;
1787  if (!settings->GlyphCache)
1788  goto fail;
1789  if ((offset >= maxOffset) || !data)
1790  goto fail;
1791  settings->GlyphCache[offset] = *(const GLYPH_CACHE_DEFINITION*)data;
1792  return TRUE;
1793  case FreeRDP_FragCache:
1794  maxOffset = 1;
1795  if (!settings->FragCache)
1796  goto fail;
1797  if ((offset >= maxOffset) || !data)
1798  goto fail;
1799  settings->FragCache[offset] = *(const GLYPH_CACHE_DEFINITION*)data;
1800  return TRUE;
1801  case FreeRDP_MonitorIds:
1802  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds);
1803  if ((offset >= maxOffset) || !data)
1804  goto fail;
1805  settings->MonitorIds[offset] = *(const UINT32*)data;
1806  return TRUE;
1807  case FreeRDP_ChannelDefArray:
1808  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ChannelDefArraySize);
1809  if ((offset >= maxOffset) || !data)
1810  goto fail;
1811  settings->ChannelDefArray[offset] = *(const CHANNEL_DEF*)data;
1812  return TRUE;
1813  case FreeRDP_MonitorDefArray:
1814  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_MonitorDefArraySize);
1815  if ((offset >= maxOffset) || !data)
1816  goto fail;
1817  settings->MonitorDefArray[offset] = *(const rdpMonitor*)data;
1818  return TRUE;
1819 
1820  case FreeRDP_ClientTimeZone:
1821  maxOffset = 1;
1822  if ((offset >= maxOffset) || !data || !settings->ClientTimeZone)
1823  goto fail;
1824  settings->ClientTimeZone[0] = *(const TIME_ZONE_INFORMATION*)data;
1825  return TRUE;
1826 
1827  default:
1828  WLog_WARN(TAG, "Invalid id %s [%" PRIuz "]", freerdp_settings_get_name_for_key(id), id);
1829  return FALSE;
1830  }
1831 
1832 fail:
1833  WLog_WARN(TAG, "[%s] Invalid offset=%" PRIuz " [%" PRIuz "] or NULL data=%p",
1834  freerdp_settings_get_name_for_key(id), offset, maxOffset, data);
1835  return FALSE;
1836 }
1837 
1838 const void* freerdp_settings_get_pointer_array(const rdpSettings* settings,
1839  FreeRDP_Settings_Keys_Pointer id, size_t offset)
1840 {
1841  return freerdp_settings_get_pointer_array_writable(settings, id, offset);
1842 }
1843 
1844 UINT32 freerdp_settings_get_codecs_flags(const rdpSettings* settings)
1845 {
1846  UINT32 flags = FREERDP_CODEC_ALL;
1847  if (settings->RemoteFxCodec == FALSE)
1848  {
1849  flags &= ~FREERDP_CODEC_REMOTEFX;
1850  }
1851  if (settings->NSCodec == FALSE)
1852  {
1853  flags &= ~FREERDP_CODEC_NSCODEC;
1854  }
1855  /*TODO: check other codecs flags */
1856  return flags;
1857 }
1858 
1859 const char* freerdp_settings_get_server_name(const rdpSettings* settings)
1860 {
1861  WINPR_ASSERT(settings);
1862  const char* hostname = settings->ServerHostname;
1863 
1864  if (settings->UserSpecifiedServerName)
1865  hostname = settings->UserSpecifiedServerName;
1866 
1867  return hostname;
1868 }
1869 
1870 #if defined(WITH_FREERDP_DEPRECATED)
1871 ADDIN_ARGV* freerdp_static_channel_clone(ADDIN_ARGV* channel)
1872 {
1873  return freerdp_addin_argv_clone(channel);
1874 }
1875 
1876 ADDIN_ARGV* freerdp_dynamic_channel_clone(ADDIN_ARGV* channel)
1877 {
1878  return freerdp_addin_argv_clone(channel);
1879 }
1880 #endif
1881 
1882 BOOL freerdp_target_net_addresses_copy(rdpSettings* settings, char** addresses, UINT32 count)
1883 {
1884  WINPR_ASSERT(settings);
1885  WINPR_ASSERT(addresses);
1886 
1887  if (!freerdp_target_net_adresses_reset(settings, count))
1888  return FALSE;
1889 
1890  for (UINT32 i = 0; i < settings->TargetNetAddressCount; i++)
1891  {
1892  if (!freerdp_settings_set_pointer_array(settings, FreeRDP_TargetNetAddresses, i,
1893  addresses[i]))
1894  {
1895  freerdp_target_net_addresses_free(settings);
1896  return FALSE;
1897  }
1898  }
1899 
1900  return TRUE;
1901 }
1902 
1903 BOOL freerdp_device_equal(const RDPDR_DEVICE* what, const RDPDR_DEVICE* expect)
1904 {
1905  if (!what && !expect)
1906  return TRUE;
1907  if (!what || !expect)
1908  return FALSE;
1909 
1910  if (what->Id != expect->Id)
1911  return FALSE;
1912  if (what->Type != expect->Type)
1913  return FALSE;
1914  if (what->Name && expect->Name)
1915  {
1916  if (strcmp(what->Name, expect->Name) != 0)
1917  return FALSE;
1918  }
1919  else
1920  {
1921  if (what->Name != expect->Name)
1922  return FALSE;
1923  }
1924 
1925  switch (what->Type)
1926  {
1927  case RDPDR_DTYP_PRINT:
1928  {
1929  const RDPDR_PRINTER* a = (const RDPDR_PRINTER*)what;
1930  const RDPDR_PRINTER* b = (const RDPDR_PRINTER*)expect;
1931  if (a->DriverName && b->DriverName)
1932  return strcmp(a->DriverName, b->DriverName) == 0;
1933  return a->DriverName == b->DriverName;
1934  }
1935 
1936  case RDPDR_DTYP_SERIAL:
1937  {
1938  const RDPDR_SERIAL* a = (const RDPDR_SERIAL*)what;
1939  const RDPDR_SERIAL* b = (const RDPDR_SERIAL*)expect;
1940 
1941  if (a->Path && b->Path)
1942  {
1943  if (strcmp(a->Path, b->Path) != 0)
1944  return FALSE;
1945  }
1946  else if (a->Path != b->Path)
1947  return FALSE;
1948 
1949  if (a->Driver && b->Driver)
1950  {
1951  if (strcmp(a->Driver, b->Driver) != 0)
1952  return FALSE;
1953  }
1954  else if (a->Driver != b->Driver)
1955  return FALSE;
1956  if (a->Permissive && b->Permissive)
1957  return strcmp(a->Permissive, b->Permissive) == 0;
1958  return a->Permissive == b->Permissive;
1959  }
1960 
1961  case RDPDR_DTYP_PARALLEL:
1962  {
1963  const RDPDR_PARALLEL* a = (const RDPDR_PARALLEL*)what;
1964  const RDPDR_PARALLEL* b = (const RDPDR_PARALLEL*)expect;
1965  if (a->Path && b->Path)
1966  return strcmp(a->Path, b->Path) == 0;
1967  return a->Path == b->Path;
1968  }
1969 
1970  case RDPDR_DTYP_SMARTCARD:
1971  break;
1972  case RDPDR_DTYP_FILESYSTEM:
1973  {
1974  const RDPDR_DRIVE* a = (const RDPDR_DRIVE*)what;
1975  const RDPDR_DRIVE* b = (const RDPDR_DRIVE*)expect;
1976  if (a->automount != b->automount)
1977  return FALSE;
1978  if (a->Path && b->Path)
1979  return strcmp(a->Path, b->Path) == 0;
1980  return a->Path == b->Path;
1981  }
1982 
1983  default:
1984  return FALSE;
1985  }
1986 
1987  return TRUE;
1988 }
1989 
1990 const char* freerdp_rail_support_flags_to_string(UINT32 flags, char* buffer, size_t length)
1991 {
1992  const UINT32 mask =
1993  RAIL_LEVEL_SUPPORTED | RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED |
1994  RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED | RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED |
1995  RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED | RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED |
1996  RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED | RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED;
1997 
1998  if (flags & RAIL_LEVEL_SUPPORTED)
1999  winpr_str_append("RAIL_LEVEL_SUPPORTED", buffer, length, "|");
2000  if (flags & RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED)
2001  winpr_str_append("RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED", buffer, length, "|");
2002  if (flags & RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED)
2003  winpr_str_append("RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED", buffer, length, "|");
2004  if (flags & RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED)
2005  winpr_str_append("RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED", buffer, length, "|");
2006  if (flags & RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED)
2007  winpr_str_append("RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED", buffer, length, "|");
2008  if (flags & RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED)
2009  winpr_str_append("RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED", buffer, length, "|");
2010  if (flags & RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED)
2011  winpr_str_append("RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED", buffer, length, "|");
2012  if (flags & RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED)
2013  winpr_str_append("RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED", buffer, length, "|");
2014  if (flags & RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED)
2015  winpr_str_append("RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED", buffer, length, "|");
2016  if ((flags & ~mask) != 0)
2017  {
2018  char tbuffer[64] = { 0 };
2019  (void)_snprintf(tbuffer, sizeof(tbuffer), "RAIL_FLAG_UNKNOWN 0x%08" PRIx32, flags & mask);
2020  winpr_str_append(tbuffer, buffer, length, "|");
2021  }
2022  return buffer;
2023 }
2024 
2025 BOOL freerdp_settings_update_from_caps(rdpSettings* settings, const BYTE* capsFlags,
2026  const BYTE** capsData, const UINT32* capsSizes,
2027  UINT32 capsCount, BOOL serverReceivedCaps)
2028 {
2029  WINPR_ASSERT(settings);
2030  WINPR_ASSERT(capsFlags || (capsCount == 0));
2031  WINPR_ASSERT(capsData || (capsCount == 0));
2032  WINPR_ASSERT(capsSizes || (capsCount == 0));
2033  WINPR_ASSERT(capsCount <= UINT16_MAX);
2034 
2035  for (UINT32 x = 0; x < capsCount; x++)
2036  {
2037  if (capsFlags[x])
2038  {
2039  wStream buffer;
2040  wStream* sub = Stream_StaticConstInit(&buffer, capsData[x], capsSizes[x]);
2041 
2042  if (!rdp_read_capability_set(sub, (UINT16)x, settings, serverReceivedCaps))
2043  return FALSE;
2044  }
2045  }
2046 
2047  return TRUE;
2048 }
2049 
2050 const char* freerdp_rdp_version_string(UINT32 version)
2051 {
2052  switch (version)
2053  {
2054  case RDP_VERSION_4:
2055  return "RDP_VERSION_4";
2056  case RDP_VERSION_5_PLUS:
2057  return "RDP_VERSION_5_PLUS";
2058  case RDP_VERSION_10_0:
2059  return "RDP_VERSION_10_0";
2060  case RDP_VERSION_10_1:
2061  return "RDP_VERSION_10_1";
2062  case RDP_VERSION_10_2:
2063  return "RDP_VERSION_10_2";
2064  case RDP_VERSION_10_3:
2065  return "RDP_VERSION_10_3";
2066  case RDP_VERSION_10_4:
2067  return "RDP_VERSION_10_4";
2068  case RDP_VERSION_10_5:
2069  return "RDP_VERSION_10_5";
2070  case RDP_VERSION_10_6:
2071  return "RDP_VERSION_10_6";
2072  case RDP_VERSION_10_7:
2073  return "RDP_VERSION_10_7";
2074  case RDP_VERSION_10_8:
2075  return "RDP_VERSION_10_8";
2076  case RDP_VERSION_10_9:
2077  return "RDP_VERSION_10_9";
2078  case RDP_VERSION_10_10:
2079  return "RDP_VERSION_10_10";
2080  case RDP_VERSION_10_11:
2081  return "RDP_VERSION_10_11";
2082  case RDP_VERSION_10_12:
2083  return "RDP_VERSION_10_12";
2084  default:
2085  return "RDP_VERSION_UNKNOWN";
2086  }
2087 }
2088 
2089 BOOL freerdp_settings_set_string_from_utf16(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
2090  const WCHAR* param)
2091 {
2092  WINPR_ASSERT(settings);
2093 
2094  if (!param)
2095  return freerdp_settings_set_string_copy_(settings, id, NULL, 0, TRUE);
2096 
2097  size_t len = 0;
2098 
2099  char* str = ConvertWCharToUtf8Alloc(param, &len);
2100  if (!str && (len != 0))
2101  return FALSE;
2102 
2103  return freerdp_settings_set_string_(settings, id, str, len);
2104 }
2105 
2106 BOOL freerdp_settings_set_string_from_utf16N(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
2107  const WCHAR* param, size_t length)
2108 {
2109  size_t len = 0;
2110 
2111  WINPR_ASSERT(settings);
2112 
2113  if (!param)
2114  return freerdp_settings_set_string_copy_(settings, id, NULL, length, TRUE);
2115 
2116  char* str = ConvertWCharNToUtf8Alloc(param, length, &len);
2117  if (!str && (length != 0))
2118  {
2119  /* If the input string is an empty string, but length > 0
2120  * consider the conversion a success */
2121  const size_t wlen = _wcsnlen(param, length);
2122  if (wlen != 0)
2123  return FALSE;
2124  }
2125 
2126  return freerdp_settings_set_string_(settings, id, str, len);
2127 }
2128 
2129 WCHAR* freerdp_settings_get_string_as_utf16(const rdpSettings* settings,
2130  FreeRDP_Settings_Keys_String id, size_t* pCharLen)
2131 {
2132  const char* str = freerdp_settings_get_string(settings, id);
2133  if (pCharLen)
2134  *pCharLen = 0;
2135  if (!str)
2136  return NULL;
2137  return ConvertUtf8ToWCharAlloc(str, pCharLen);
2138 }
2139 
2140 const char* freerdp_rdpdr_dtyp_string(UINT32 type)
2141 {
2142  switch (type)
2143  {
2144  case RDPDR_DTYP_FILESYSTEM:
2145  return "RDPDR_DTYP_FILESYSTEM";
2146  case RDPDR_DTYP_PARALLEL:
2147  return "RDPDR_DTYP_PARALLEL";
2148  case RDPDR_DTYP_PRINT:
2149  return "RDPDR_DTYP_PRINT";
2150  case RDPDR_DTYP_SERIAL:
2151  return "RDPDR_DTYP_SERIAL";
2152  case RDPDR_DTYP_SMARTCARD:
2153  return "RDPDR_DTYP_SMARTCARD";
2154  default:
2155  return "RDPDR_DTYP_UNKNOWN";
2156  }
2157 }
2158 
2159 const char* freerdp_encryption_level_string(UINT32 EncryptionLevel)
2160 {
2161  switch (EncryptionLevel)
2162  {
2163  case ENCRYPTION_LEVEL_NONE:
2164  return "ENCRYPTION_LEVEL_NONE";
2165  case ENCRYPTION_LEVEL_LOW:
2166  return "ENCRYPTION_LEVEL_LOW";
2167  case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE:
2168  return "ENCRYPTION_LEVEL_CLIENT_COMPATIBLE";
2169  case ENCRYPTION_LEVEL_HIGH:
2170  return "ENCRYPTION_LEVEL_HIGH";
2171  case ENCRYPTION_LEVEL_FIPS:
2172  return "ENCRYPTION_LEVEL_FIPS";
2173  default:
2174  return "ENCRYPTION_LEVEL_UNKNOWN";
2175  }
2176 }
2177 
2178 const char* freerdp_encryption_methods_string(UINT32 EncryptionMethods, char* buffer, size_t size)
2179 {
2180  if (EncryptionMethods == ENCRYPTION_METHOD_NONE)
2181  {
2182  winpr_str_append("ENCRYPTION_METHOD_NONE", buffer, size, "|");
2183  return buffer;
2184  }
2185 
2186  if (EncryptionMethods & ENCRYPTION_METHOD_40BIT)
2187  {
2188  winpr_str_append("ENCRYPTION_METHOD_40BIT", buffer, size, "|");
2189  }
2190  if (EncryptionMethods & ENCRYPTION_METHOD_128BIT)
2191  {
2192  winpr_str_append("ENCRYPTION_METHOD_128BIT", buffer, size, "|");
2193  }
2194  if (EncryptionMethods & ENCRYPTION_METHOD_56BIT)
2195  {
2196  winpr_str_append("ENCRYPTION_METHOD_56BIT", buffer, size, "|");
2197  }
2198  if (EncryptionMethods & ENCRYPTION_METHOD_FIPS)
2199  {
2200  winpr_str_append("ENCRYPTION_METHOD_FIPS", buffer, size, "|");
2201  }
2202 
2203  return buffer;
2204 }
2205 
2206 const char* freerdp_supported_color_depths_string(UINT16 mask, char* buffer, size_t size)
2207 {
2208  const UINT32 invalid = mask & ~(RNS_UD_32BPP_SUPPORT | RNS_UD_24BPP_SUPPORT |
2209  RNS_UD_16BPP_SUPPORT | RNS_UD_15BPP_SUPPORT);
2210 
2211  if (mask & RNS_UD_32BPP_SUPPORT)
2212  winpr_str_append("RNS_UD_32BPP_SUPPORT", buffer, size, "|");
2213  if (mask & RNS_UD_24BPP_SUPPORT)
2214  winpr_str_append("RNS_UD_24BPP_SUPPORT", buffer, size, "|");
2215  if (mask & RNS_UD_16BPP_SUPPORT)
2216  winpr_str_append("RNS_UD_16BPP_SUPPORT", buffer, size, "|");
2217  if (mask & RNS_UD_15BPP_SUPPORT)
2218  winpr_str_append("RNS_UD_15BPP_SUPPORT", buffer, size, "|");
2219 
2220  if (invalid != 0)
2221  {
2222  char str[32] = { 0 };
2223  (void)_snprintf(str, sizeof(str), "RNS_UD_INVALID[0x%04" PRIx32 "]", invalid);
2224  winpr_str_append(str, buffer, size, "|");
2225  }
2226  char hex[32] = { 0 };
2227  (void)_snprintf(hex, sizeof(hex), "[0x%04" PRIx16 "]", mask);
2228  return buffer;
2229 }
2230 
2231 BOOL freerdp_settings_append_string(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
2232  const char* separator, const char* param)
2233 {
2234  const char* old = freerdp_settings_get_string(settings, id);
2235 
2236  size_t len = 0;
2237  char* str = NULL;
2238 
2239  if (!old)
2240  winpr_asprintf(&str, &len, "%s", param);
2241  else if (!separator)
2242  winpr_asprintf(&str, &len, "%s%s", old, param);
2243  else
2244  winpr_asprintf(&str, &len, "%s%s%s", old, separator, param);
2245 
2246  const BOOL rc = freerdp_settings_set_string_len(settings, id, str, len);
2247  free(str);
2248  return rc;
2249 }
2250 
2251 BOOL freerdp_settings_are_valid(const rdpSettings* settings)
2252 {
2253  return settings != NULL;
2254 }
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
BOOL freerdp_settings_update_from_caps(rdpSettings *settings, const BYTE *capsFlags, const BYTE **capsData, const UINT32 *capsSizes, UINT32 capsCount, BOOL serverReceivedCaps)
Parse capability data and apply to settings.
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.
const void * freerdp_settings_get_pointer(const rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a immutable pointer settings value.
BOOL freerdp_settings_set_string_from_utf16N(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const WCHAR *param, size_t length)
Sets a string settings value. The param is converted to UTF-8 and the copy stored.
FREERDP_API SSIZE_T freerdp_settings_get_type_for_key(SSIZE_T key)
Get a key type for the key index.
Definition: settings_str.c:407
BOOL freerdp_settings_are_valid(const rdpSettings *settings)
Returns TRUE if settings are in a valid state, FALSE otherwise.
FREERDP_API UINT64 freerdp_settings_get_uint64(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt64 id)
Returns a UINT64 settings value.
FREERDP_API SSIZE_T freerdp_settings_get_key_for_name(const char *value)
Get a key index for the name string of that key.
Definition: settings_str.c:348
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
const char * freerdp_rail_support_flags_to_string(UINT32 flags, char *buffer, size_t length)
Returns a stringified representation of RAIL support flags.
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.
const char * freerdp_supported_color_depths_string(UINT16 mask, char *buffer, size_t size)
returns a string representation of RNS_UD_XXBPP_SUPPORT values
FREERDP_API BOOL freerdp_settings_set_int32(rdpSettings *settings, FreeRDP_Settings_Keys_Int32 id, INT32 param)
Sets a INT32 settings value.
const char * freerdp_rdpdr_dtyp_string(UINT32 type)
Returns a string representation of RDPDR_DTYP_*.
const char * freerdp_settings_get_server_name(const rdpSettings *settings)
A helper function to return the correct server name.
BOOL freerdp_device_collection_del(rdpSettings *settings, const RDPDR_DEVICE *device)
Removed a device from the settings, returns ownership of the allocated device to caller.
BOOL freerdp_set_gateway_usage_method(rdpSettings *settings, UINT32 GatewayUsageMethod)
FREERDP_API BOOL freerdp_settings_set_uint64(rdpSettings *settings, FreeRDP_Settings_Keys_UInt64 id, UINT64 param)
Sets a UINT64 settings value.
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_int16(rdpSettings *settings, FreeRDP_Settings_Keys_Int16 id, INT16 param)
Sets a INT16 settings value.
FREERDP_API BOOL freerdp_settings_set_int64(rdpSettings *settings, FreeRDP_Settings_Keys_Int64 id, INT64 param)
Sets a INT64 settings value.
BOOL freerdp_settings_set_string_from_utf16(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const WCHAR *param)
Sets a string settings value. The param is converted to UTF-8 and the copy stored.
FREERDP_API BOOL freerdp_settings_set_pointer(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id, const void *data)
Set a pointer to value data.
FREERDP_API INT32 freerdp_settings_get_int32(const rdpSettings *settings, FreeRDP_Settings_Keys_Int32 id)
Returns a INT32 settings value.
UINT32 freerdp_settings_get_codecs_flags(const rdpSettings *settings)
helper function to get a mask of supported codec flags.
const char * freerdp_rdp_version_string(UINT32 version)
Returns a stringified representation of the RDP protocol version.
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.
BOOL freerdp_settings_append_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *separator, const char *param)
appends a string to a settings value. The param is copied. If the initial value of the setting was no...
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.
FREERDP_API const char * freerdp_settings_get_name_for_key(SSIZE_T key)
Returns the type name for a key.
Definition: settings_str.c:418