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(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(&args->argv[x], (args->argc - x) * sizeof(char*), &args->argv[x + 1],
85  (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(settings->DeviceArray, new_size * sizeof(RDPDR_DEVICE*));
225 
226  if (!new_array)
227  return FALSE;
228 
229  settings->DeviceArray = new_array;
230  memset(&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(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(&settings->StaticChannelArray[x], (count - x) * sizeof(ADDIN_ARGV*),
592  &settings->StaticChannelArray[x + 1],
593  (count - x - 1) * sizeof(ADDIN_ARGV*));
594  memset(&settings->StaticChannelArray[count - 1], 0, sizeof(ADDIN_ARGV*) * rem);
595 
596  freerdp_addin_argv_free(cur);
597  return freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelCount, count - 1);
598  }
599  }
600  }
601  {
602  const size_t rem = settings->StaticChannelArraySize - count;
603  memset(&settings->StaticChannelArray[count], 0, sizeof(ADDIN_ARGV*) * rem);
604  }
605  return FALSE;
606 }
607 
608 BOOL freerdp_static_channel_collection_add(rdpSettings* settings, ADDIN_ARGV* channel)
609 {
610  UINT32 count = 0;
611 
612  WINPR_ASSERT(settings);
613  WINPR_ASSERT(channel);
614 
615  count = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount) + 1;
616  if (freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize) < count)
617  {
618  const UINT32 oldSize =
619  freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
620  UINT32 new_size = oldSize * 2ul;
621  ADDIN_ARGV** new_array = NULL;
622  if (new_size == 0)
623  new_size = count * 2ul;
624 
625  new_array =
626  (ADDIN_ARGV**)realloc(settings->StaticChannelArray, new_size * sizeof(ADDIN_ARGV*));
627 
628  if (!new_array)
629  return FALSE;
630 
631  settings->StaticChannelArray = new_array;
632  {
633  const size_t rem = new_size - oldSize;
634  memset(&settings->StaticChannelArray[oldSize], 0, sizeof(ADDIN_ARGV*) * rem);
635  }
636  if (!freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelArraySize, new_size))
637  return FALSE;
638  }
639 
640  count = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
641 
642  ADDIN_ARGV** cur = &settings->StaticChannelArray[count++];
643  freerdp_addin_argv_free(*cur);
644  *cur = channel;
645  return freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelCount, count);
646 }
647 
648 ADDIN_ARGV* freerdp_static_channel_collection_find(rdpSettings* settings, const char* name)
649 {
650  ADDIN_ARGV* channel = NULL;
651 
652  WINPR_ASSERT(settings);
653  WINPR_ASSERT(name);
654 
655  for (UINT32 index = 0;
656  index < freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount); index++)
657  {
658  channel = settings->StaticChannelArray[index];
659 
660  if (strcmp(channel->argv[0], name) == 0)
661  return channel;
662  }
663 
664  return NULL;
665 }
666 
667 void freerdp_static_channel_collection_free(rdpSettings* settings)
668 {
669  if (!settings)
670  return;
671 
672  if (settings->StaticChannelArray)
673  {
674  for (UINT32 i = 0;
675  i < freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize); i++)
676  freerdp_addin_argv_free(settings->StaticChannelArray[i]);
677  }
678 
679  free(settings->StaticChannelArray);
680  (void)freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelArraySize, 0);
681  settings->StaticChannelArray = NULL;
682  (void)freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelCount, 0);
683 }
684 
685 BOOL freerdp_dynamic_channel_collection_del(rdpSettings* settings, const char* name)
686 {
687  const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
688  if (!settings || !settings->DynamicChannelArray)
689  return FALSE;
690 
691  for (UINT32 x = 0; x < count; x++)
692  {
693  ADDIN_ARGV* cur = settings->DynamicChannelArray[x];
694  if (cur && (cur->argc > 0))
695  {
696  if (strcmp(name, cur->argv[0]) == 0)
697  {
698  const size_t rem = settings->DynamicChannelArraySize - count + 1;
699  memmove_s(&settings->DynamicChannelArray[x], (count - x) * sizeof(ADDIN_ARGV*),
700  &settings->DynamicChannelArray[x + 1],
701  (count - x - 1) * sizeof(ADDIN_ARGV*));
702  memset(&settings->DynamicChannelArray[count - 1], 0, sizeof(ADDIN_ARGV*) * rem);
703 
704  freerdp_addin_argv_free(cur);
705  return freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelCount,
706  count - 1);
707  }
708  }
709  }
710 
711  return FALSE;
712 }
713 
714 BOOL freerdp_dynamic_channel_collection_add(rdpSettings* settings, ADDIN_ARGV* channel)
715 {
716  UINT32 count = 0;
717  UINT32 oldSize = 0;
718 
719  WINPR_ASSERT(settings);
720  WINPR_ASSERT(channel);
721 
722  count = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount) + 1;
723  oldSize = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
724  if (oldSize < count)
725  {
726  ADDIN_ARGV** new_array = NULL;
727  UINT32 size = oldSize * 2;
728  if (size == 0)
729  size = count * 2;
730 
731  new_array = realloc(settings->DynamicChannelArray, sizeof(ADDIN_ARGV*) * size);
732 
733  if (!new_array)
734  return FALSE;
735 
736  settings->DynamicChannelArray = new_array;
737  {
738  const size_t rem = size - oldSize;
739  memset(&settings->DynamicChannelArray[oldSize], 0, sizeof(ADDIN_ARGV*) * rem);
740  }
741  if (!freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelArraySize, size))
742  return FALSE;
743  }
744 
745  count = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
746  settings->DynamicChannelArray[count++] = channel;
747  return freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelCount, count);
748 }
749 
750 ADDIN_ARGV* freerdp_dynamic_channel_collection_find(const rdpSettings* settings, const char* name)
751 {
752  WINPR_ASSERT(settings);
753  WINPR_ASSERT(name);
754 
755  for (UINT32 index = 0;
756  index < freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount); index++)
757  {
758  ADDIN_ARGV* channel = settings->DynamicChannelArray[index];
759 
760  if (strcmp(channel->argv[0], name) == 0)
761  return channel;
762  }
763 
764  return NULL;
765 }
766 
767 void freerdp_addin_argv_free(ADDIN_ARGV* args)
768 {
769  if (!args)
770  return;
771 
772  if (args->argv)
773  {
774  for (int index = 0; index < args->argc; index++)
775  free(args->argv[index]);
776  free(args->argv);
777  }
778 
779  free(args);
780 }
781 
782 ADDIN_ARGV* freerdp_addin_argv_new(size_t argc, const char* const argv[])
783 {
784  if (argc > INT32_MAX)
785  return NULL;
786 
787  ADDIN_ARGV* args = calloc(1, sizeof(ADDIN_ARGV));
788  if (!args)
789  return NULL;
790  if (argc == 0)
791  return args;
792 
793  args->argc = (int)argc;
794  args->argv = calloc(argc, sizeof(char*));
795  if (!args->argv)
796  goto fail;
797 
798  if (argv)
799  {
800  for (size_t x = 0; x < argc; x++)
801  {
802  args->argv[x] = _strdup(argv[x]);
803  if (!args->argv[x])
804  goto fail;
805  }
806  }
807  return args;
808 
809 fail:
810  WINPR_PRAGMA_DIAG_PUSH
811  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
812  freerdp_addin_argv_free(args);
813  WINPR_PRAGMA_DIAG_POP
814  return NULL;
815 }
816 
817 ADDIN_ARGV* freerdp_addin_argv_clone(const ADDIN_ARGV* args)
818 {
819  union
820  {
821  char** c;
822  const char** cc;
823  } cnv;
824  if (!args)
825  return NULL;
826  cnv.c = args->argv;
827  return freerdp_addin_argv_new(args->argc, cnv.cc);
828 }
829 
830 void freerdp_dynamic_channel_collection_free(rdpSettings* settings)
831 {
832  WINPR_ASSERT(settings);
833 
834  if (settings->DynamicChannelArray)
835  {
836  for (UINT32 i = 0;
837  i < freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize); i++)
838  freerdp_addin_argv_free(settings->DynamicChannelArray[i]);
839  }
840 
841  free(settings->DynamicChannelArray);
842  (void)freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelArraySize, 0);
843  settings->DynamicChannelArray = NULL;
844  (void)freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelCount, 0);
845 }
846 
847 void freerdp_capability_buffer_free(rdpSettings* settings)
848 {
849  WINPR_ASSERT(settings);
850 
851  if (settings->ReceivedCapabilityData)
852  {
853  for (UINT32 x = 0; x < settings->ReceivedCapabilitiesSize; x++)
854  {
855  free(settings->ReceivedCapabilityData[x]);
856  settings->ReceivedCapabilityData[x] = NULL;
857  }
858  }
859  settings->ReceivedCapabilitiesSize = 0;
860 
861  free(settings->ReceivedCapabilityDataSizes);
862  settings->ReceivedCapabilityDataSizes = NULL;
863 
864  free(settings->ReceivedCapabilityData);
865  settings->ReceivedCapabilityData = NULL;
866  free(settings->ReceivedCapabilities);
867  settings->ReceivedCapabilities = NULL;
868 }
869 
870 BOOL freerdp_capability_buffer_copy(rdpSettings* settings, const rdpSettings* src)
871 {
872  WINPR_ASSERT(settings);
873  WINPR_ASSERT(src);
874 
875  if (!freerdp_capability_buffer_allocate(settings, src->ReceivedCapabilitiesSize))
876  return FALSE;
877 
878  for (UINT32 x = 0; x < src->ReceivedCapabilitiesSize; x++)
879  {
880  WINPR_ASSERT(settings->ReceivedCapabilities);
881  settings->ReceivedCapabilities[x] = src->ReceivedCapabilities[x];
882 
883  WINPR_ASSERT(settings->ReceivedCapabilityDataSizes);
884  settings->ReceivedCapabilityDataSizes[x] = src->ReceivedCapabilityDataSizes[x];
885 
886  WINPR_ASSERT(settings->ReceivedCapabilityData);
887  if (src->ReceivedCapabilityDataSizes[x] > 0)
888  {
889  void* tmp = realloc(settings->ReceivedCapabilityData[x],
890  settings->ReceivedCapabilityDataSizes[x]);
891  if (!tmp)
892  return FALSE;
893  memcpy(tmp, src->ReceivedCapabilityData[x], src->ReceivedCapabilityDataSizes[x]);
894  settings->ReceivedCapabilityData[x] = tmp;
895  }
896  else
897  {
898  free(settings->ReceivedCapabilityData[x]);
899  settings->ReceivedCapabilityData[x] = NULL;
900  }
901  }
902  return TRUE;
903 }
904 
905 void freerdp_target_net_addresses_free(rdpSettings* settings)
906 {
907  WINPR_ASSERT(settings);
908 
909  if (settings->TargetNetAddresses)
910  {
911  for (UINT32 index = 0; index < settings->TargetNetAddressCount; index++)
912  free(settings->TargetNetAddresses[index]);
913  }
914 
915  free(settings->TargetNetAddresses);
916  free(settings->TargetNetPorts);
917  settings->TargetNetAddressCount = 0;
918  settings->TargetNetAddresses = NULL;
919  settings->TargetNetPorts = NULL;
920 }
921 
922 void freerdp_server_license_issuers_free(rdpSettings* settings)
923 {
924  WINPR_ASSERT(settings);
925 
926  if (settings->ServerLicenseProductIssuers)
927  {
928  for (UINT32 x = 0; x < settings->ServerLicenseProductIssuersCount; x++)
929  free(settings->ServerLicenseProductIssuers[x]);
930  }
931  free(settings->ServerLicenseProductIssuers);
932  settings->ServerLicenseProductIssuers = NULL;
933  settings->ServerLicenseProductIssuersCount = 0;
934 }
935 
936 BOOL freerdp_server_license_issuers_copy(rdpSettings* settings, char** issuers, UINT32 count)
937 {
938  WINPR_ASSERT(settings);
939  WINPR_ASSERT(issuers || (count == 0));
940 
941  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ServerLicenseProductIssuers, NULL,
942  count))
943  return FALSE;
944 
945  for (UINT32 x = 0; x < count; x++)
946  {
947  char* issuer = _strdup(issuers[x]);
948  if (!issuer)
949  return FALSE;
950  settings->ServerLicenseProductIssuers[x] = issuer;
951  }
952 
953  return TRUE;
954 }
955 
956 void freerdp_performance_flags_make(rdpSettings* settings)
957 {
958  UINT32 PerformanceFlags = PERF_FLAG_NONE;
959 
960  if (freerdp_settings_get_bool(settings, FreeRDP_AllowFontSmoothing))
961  PerformanceFlags |= PERF_ENABLE_FONT_SMOOTHING;
962 
963  if (freerdp_settings_get_bool(settings, FreeRDP_AllowDesktopComposition))
964  PerformanceFlags |= PERF_ENABLE_DESKTOP_COMPOSITION;
965 
966  if (freerdp_settings_get_bool(settings, FreeRDP_DisableWallpaper))
967  PerformanceFlags |= PERF_DISABLE_WALLPAPER;
968 
969  if (freerdp_settings_get_bool(settings, FreeRDP_DisableFullWindowDrag))
970  PerformanceFlags |= PERF_DISABLE_FULLWINDOWDRAG;
971 
972  if (freerdp_settings_get_bool(settings, FreeRDP_DisableMenuAnims))
973  PerformanceFlags |= PERF_DISABLE_MENUANIMATIONS;
974 
975  if (freerdp_settings_get_bool(settings, FreeRDP_DisableThemes))
976  PerformanceFlags |= PERF_DISABLE_THEMING;
977  (void)freerdp_settings_set_uint32(settings, FreeRDP_PerformanceFlags, PerformanceFlags);
978 }
979 
980 void freerdp_performance_flags_split(rdpSettings* settings)
981 {
983  settings, FreeRDP_AllowFontSmoothing,
984  (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) &
985  PERF_ENABLE_FONT_SMOOTHING)
986  ? TRUE
987  : FALSE);
989  settings, FreeRDP_AllowDesktopComposition,
990  (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) &
991  PERF_ENABLE_DESKTOP_COMPOSITION)
992  ? TRUE
993  : FALSE);
995  settings, FreeRDP_DisableWallpaper,
996  (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) & PERF_DISABLE_WALLPAPER)
997  ? TRUE
998  : FALSE);
1000  settings, FreeRDP_DisableFullWindowDrag,
1001  (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) &
1002  PERF_DISABLE_FULLWINDOWDRAG)
1003  ? TRUE
1004  : FALSE);
1006  settings, FreeRDP_DisableMenuAnims,
1007  (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) &
1008  PERF_DISABLE_MENUANIMATIONS)
1009  ? TRUE
1010  : FALSE);
1012  settings, FreeRDP_DisableThemes,
1013  (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) & PERF_DISABLE_THEMING)
1014  ? TRUE
1015  : FALSE);
1016 }
1017 
1018 BOOL freerdp_set_gateway_usage_method(rdpSettings* settings, UINT32 GatewayUsageMethod)
1019 {
1020  if (!freerdp_settings_set_uint32(settings, FreeRDP_GatewayUsageMethod, GatewayUsageMethod))
1021  return FALSE;
1022 
1023  if (GatewayUsageMethod == TSC_PROXY_MODE_NONE_DIRECT)
1024  {
1025  if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, FALSE) ||
1026  !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE))
1027  return FALSE;
1028  }
1029  else if (GatewayUsageMethod == TSC_PROXY_MODE_DIRECT)
1030  {
1031  if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, TRUE) ||
1032  !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE))
1033  return FALSE;
1034  }
1035  else if (GatewayUsageMethod == TSC_PROXY_MODE_DETECT)
1036  {
1037  if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, TRUE) ||
1038  !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, TRUE))
1039  return FALSE;
1040  }
1041  else if (GatewayUsageMethod == TSC_PROXY_MODE_DEFAULT)
1042  {
1048  if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, FALSE) ||
1049  !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE))
1050  return FALSE;
1051  }
1052  else if (GatewayUsageMethod == TSC_PROXY_MODE_NONE_DETECT)
1053  {
1054  if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, FALSE) ||
1055  !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE))
1056  return FALSE;
1057  }
1058 
1059  return TRUE;
1060 }
1061 
1062 void freerdp_update_gateway_usage_method(rdpSettings* settings, UINT32 GatewayEnabled,
1063  UINT32 GatewayBypassLocal)
1064 {
1065  UINT32 GatewayUsageMethod = 0;
1066 
1067  if (!GatewayEnabled && !GatewayBypassLocal)
1068  GatewayUsageMethod = TSC_PROXY_MODE_NONE_DIRECT;
1069  else if (GatewayEnabled && !GatewayBypassLocal)
1070  GatewayUsageMethod = TSC_PROXY_MODE_DIRECT;
1071  else if (GatewayEnabled && GatewayBypassLocal)
1072  GatewayUsageMethod = TSC_PROXY_MODE_DETECT;
1073 
1074  freerdp_set_gateway_usage_method(settings, GatewayUsageMethod);
1075 }
1076 
1077 #if defined(WITH_FREERDP_DEPRECATED)
1078 BOOL freerdp_get_param_bool(const rdpSettings* settings, int id)
1079 {
1080  return freerdp_settings_get_bool(settings, (FreeRDP_Settings_Keys_Bool)id);
1081 }
1082 
1083 int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param)
1084 {
1085  return freerdp_settings_set_bool(settings, (FreeRDP_Settings_Keys_Bool)id, param) ? 0 : -1;
1086 }
1087 
1088 int freerdp_get_param_int(const rdpSettings* settings, int id)
1089 {
1090  return freerdp_settings_get_int32(settings, (FreeRDP_Settings_Keys_Int32)id);
1091 }
1092 
1093 int freerdp_set_param_int(rdpSettings* settings, int id, int param)
1094 {
1095  return freerdp_settings_set_int32(settings, (FreeRDP_Settings_Keys_Int32)id, param) ? 0 : -1;
1096 }
1097 
1098 UINT32 freerdp_get_param_uint32(const rdpSettings* settings, int id)
1099 {
1100  return freerdp_settings_get_uint32(settings, (FreeRDP_Settings_Keys_UInt32)id);
1101 }
1102 
1103 int freerdp_set_param_uint32(rdpSettings* settings, int id, UINT32 param)
1104 {
1105  return freerdp_settings_set_uint32(settings, (FreeRDP_Settings_Keys_UInt32)id, param) ? 0 : -1;
1106 }
1107 
1108 UINT64 freerdp_get_param_uint64(const rdpSettings* settings, int id)
1109 {
1110  return freerdp_settings_get_uint64(settings, (FreeRDP_Settings_Keys_UInt64)id);
1111 }
1112 
1113 int freerdp_set_param_uint64(rdpSettings* settings, int id, UINT64 param)
1114 {
1115  return freerdp_settings_set_uint64(settings, (FreeRDP_Settings_Keys_UInt64)id, param) ? 0 : -1;
1116 }
1117 
1118 char* freerdp_get_param_string(const rdpSettings* settings, int id)
1119 {
1120  const char* str = freerdp_settings_get_string(settings, (FreeRDP_Settings_Keys_String)id);
1121  return WINPR_CAST_CONST_PTR_AWAY(str, char*);
1122 }
1123 
1124 int freerdp_set_param_string(rdpSettings* settings, int id, const char* param)
1125 {
1126  return freerdp_settings_set_string(settings, (FreeRDP_Settings_Keys_String)id, param) ? 0 : -1;
1127 }
1128 #endif
1129 
1130 static BOOL value_to_uint(const char* value, ULONGLONG* result, ULONGLONG min, ULONGLONG max)
1131 {
1132  char* endptr = NULL;
1133  unsigned long long rc = 0;
1134 
1135  if (!value || !result)
1136  return FALSE;
1137 
1138  errno = 0;
1139  rc = _strtoui64(value, &endptr, 0);
1140 
1141  if (errno != 0)
1142  return FALSE;
1143 
1144  if (endptr == value)
1145  return FALSE;
1146 
1147  if ((rc < min) || (rc > max))
1148  return FALSE;
1149 
1150  *result = rc;
1151  return TRUE;
1152 }
1153 
1154 static BOOL value_to_int(const char* value, LONGLONG* result, LONGLONG min, LONGLONG max)
1155 {
1156  char* endptr = NULL;
1157  long long rc = 0;
1158 
1159  if (!value || !result)
1160  return FALSE;
1161 
1162  errno = 0;
1163  rc = _strtoi64(value, &endptr, 0);
1164 
1165  if (errno != 0)
1166  return FALSE;
1167 
1168  if (endptr == value)
1169  return FALSE;
1170 
1171  if ((rc < min) || (rc > max))
1172  return FALSE;
1173 
1174  *result = rc;
1175  return TRUE;
1176 }
1177 
1178 static BOOL parsing_fail(const char* key, const char* type, const char* value)
1179 {
1180  WLog_ERR(TAG, "Failed to parse key [%s] of type [%s]: value [%s]", key, type, value);
1181  return FALSE;
1182 }
1183 
1184 BOOL freerdp_settings_set_value_for_name(rdpSettings* settings, const char* name, const char* value)
1185 {
1186  ULONGLONG uval = 0;
1187  LONGLONG ival = 0;
1188  SSIZE_T type = 0;
1189 
1190  if (!settings || !name)
1191  return FALSE;
1192 
1193  const SSIZE_T i = freerdp_settings_get_key_for_name(name);
1194  if (i < 0)
1195  {
1196  WLog_ERR(TAG, "Invalid settings key [%s]", name);
1197  return FALSE;
1198  }
1199 
1200  const SSIZE_T index = i;
1201 
1202  type = freerdp_settings_get_type_for_key(index);
1203  switch (type)
1204  {
1205 
1206  case RDP_SETTINGS_TYPE_BOOL:
1207  {
1208  const BOOL val = (_strnicmp(value, "TRUE", 5) == 0) || (_strnicmp(value, "ON", 5) == 0);
1209  const BOOL nval =
1210  (_strnicmp(value, "FALSE", 6) == 0) || (_strnicmp(value, "OFF", 6) == 0);
1211  if (!val && !nval)
1212  return parsing_fail(name, "BOOL", value);
1213 
1214  // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1215  return freerdp_settings_set_bool(settings, (FreeRDP_Settings_Keys_Bool)index, val);
1216  }
1217  case RDP_SETTINGS_TYPE_UINT16:
1218  if (!value_to_uint(value, &uval, 0, UINT16_MAX))
1219  return parsing_fail(name, "UINT16", value);
1220 
1221  // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1222  if (!freerdp_settings_set_uint16(settings, (FreeRDP_Settings_Keys_UInt16)index,
1223  (UINT16)uval))
1224  return parsing_fail(name, "UINT16", value);
1225  return TRUE;
1226 
1227  case RDP_SETTINGS_TYPE_INT16:
1228  if (!value_to_int(value, &ival, INT16_MIN, INT16_MAX))
1229  return parsing_fail(name, "INT16", value);
1230 
1231  // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1232  if (!freerdp_settings_set_int16(settings, (FreeRDP_Settings_Keys_Int16)index,
1233  (INT16)ival))
1234  return parsing_fail(name, "INT16", value);
1235  return TRUE;
1236  case RDP_SETTINGS_TYPE_UINT32:
1237  if (!value_to_uint(value, &uval, 0, UINT32_MAX))
1238  return parsing_fail(name, "UINT32", value);
1239 
1240  // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1241  if (!freerdp_settings_set_uint32(settings, (FreeRDP_Settings_Keys_UInt32)index,
1242  (UINT32)uval))
1243  return parsing_fail(name, "UINT32", value);
1244  return TRUE;
1245  case RDP_SETTINGS_TYPE_INT32:
1246  if (!value_to_int(value, &ival, INT32_MIN, INT32_MAX))
1247  return parsing_fail(name, "INT32", value);
1248 
1249  // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1250  if (!freerdp_settings_set_int32(settings, (FreeRDP_Settings_Keys_Int32)index,
1251  (INT32)ival))
1252  return parsing_fail(name, "INT32", value);
1253  return TRUE;
1254  case RDP_SETTINGS_TYPE_UINT64:
1255  if (!value_to_uint(value, &uval, 0, UINT64_MAX))
1256  return parsing_fail(name, "UINT64", value);
1257 
1258  // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1259  if (!freerdp_settings_set_uint64(settings, (FreeRDP_Settings_Keys_UInt64)index, uval))
1260  return parsing_fail(name, "UINT64", value);
1261  return TRUE;
1262  case RDP_SETTINGS_TYPE_INT64:
1263  if (!value_to_int(value, &ival, INT64_MIN, INT64_MAX))
1264  return parsing_fail(name, "INT64", value);
1265 
1266  // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1267  if (!freerdp_settings_set_int64(settings, (FreeRDP_Settings_Keys_Int64)index, ival))
1268  return parsing_fail(name, "INT64", value);
1269  return TRUE;
1270 
1271  case RDP_SETTINGS_TYPE_STRING:
1272  // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1273  return freerdp_settings_set_string(settings, (FreeRDP_Settings_Keys_String)index,
1274  value);
1275  case RDP_SETTINGS_TYPE_POINTER:
1276  return parsing_fail(name, "POINTER", value);
1277  default:
1278  return FALSE;
1279  }
1280  return FALSE;
1281 }
1282 
1283 BOOL freerdp_settings_set_pointer_len_(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
1284  SSIZE_T lenId, const void* data, size_t len, size_t size)
1285 {
1286  BOOL rc = FALSE;
1287  void* copy = NULL;
1288  void* old = freerdp_settings_get_pointer_writable(settings, id);
1289  free(old);
1290  if (!freerdp_settings_set_pointer(settings, id, NULL))
1291  return FALSE;
1292  if (lenId >= 0)
1293  {
1294  if (!freerdp_settings_set_uint32(settings, (FreeRDP_Settings_Keys_UInt32)lenId, 0))
1295  return FALSE;
1296  }
1297 
1298  if (len > UINT32_MAX)
1299  return FALSE;
1300  if (len == 0)
1301  return TRUE;
1302  copy = calloc(len, size);
1303  if (!copy)
1304  return FALSE;
1305  if (data)
1306  memcpy(copy, data, len * size);
1307  rc = freerdp_settings_set_pointer(settings, id, copy);
1308  if (!rc)
1309  {
1310  free(copy);
1311  return FALSE;
1312  }
1313 
1314  // freerdp_settings_set_pointer takes ownership of copy
1315  // NOLINTNEXTLINE(clang-analyzer-unix.Malloc)
1316  if (lenId < 0)
1317  return TRUE;
1318  return freerdp_settings_set_uint32(settings, (FreeRDP_Settings_Keys_UInt32)lenId, (UINT32)len);
1319 }
1320 
1321 const void* freerdp_settings_get_pointer(const rdpSettings* settings,
1322  FreeRDP_Settings_Keys_Pointer id)
1323 {
1324  union
1325  {
1326  const rdpSettings* pc;
1327  rdpSettings* p;
1328  } cnv;
1329  cnv.pc = settings;
1330  return freerdp_settings_get_pointer_writable(cnv.p, id);
1331 }
1332 
1333 BOOL freerdp_settings_set_pointer_len(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
1334  const void* data, size_t len)
1335 {
1336  union
1337  {
1338  const void* cv;
1339  void* v;
1340  } cnv;
1341 
1342  cnv.cv = data;
1343  if (!settings)
1344  return FALSE;
1345 
1346  switch (id)
1347  {
1348  case FreeRDP_RdpServerCertificate:
1349  freerdp_certificate_free(settings->RdpServerCertificate);
1350 
1351  if (len > 1)
1352  {
1353  WLog_ERR(TAG, "FreeRDP_RdpServerCertificate::len must be 0 or 1");
1354  return FALSE;
1355  }
1356  settings->RdpServerCertificate = cnv.v;
1357  if (!settings->RdpServerCertificate && (len > 0))
1358  {
1359  settings->RdpServerCertificate = freerdp_certificate_new();
1360  if (!settings->RdpServerCertificate)
1361  return FALSE;
1362  }
1363  return TRUE;
1364  case FreeRDP_RdpServerRsaKey:
1365  freerdp_key_free(settings->RdpServerRsaKey);
1366  if (len > 1)
1367  {
1368  WLog_ERR(TAG, "FreeRDP_RdpServerRsaKey::len must be 0 or 1");
1369  return FALSE;
1370  }
1371  settings->RdpServerRsaKey = (rdpPrivateKey*)cnv.v;
1372  if (!settings->RdpServerRsaKey && (len > 0))
1373  {
1374  settings->RdpServerRsaKey = freerdp_key_new();
1375  if (!settings->RdpServerRsaKey)
1376  return FALSE;
1377  }
1378  return TRUE;
1379  case FreeRDP_RedirectionPassword:
1380  return freerdp_settings_set_pointer_len_(
1381  settings, id, FreeRDP_RedirectionPasswordLength, data, len, sizeof(char));
1382  case FreeRDP_RedirectionTsvUrl:
1383  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_RedirectionTsvUrlLength,
1384  data, len, sizeof(char));
1385  case FreeRDP_RedirectionTargetCertificate:
1386  freerdp_certificate_free(settings->RedirectionTargetCertificate);
1387 
1388  if (len > 1)
1389  {
1390  WLog_ERR(TAG, "FreeRDP_RedirectionTargetCertificate::len must be 0 or 1");
1391  return FALSE;
1392  }
1393  settings->RedirectionTargetCertificate = cnv.v;
1394  if (!settings->RedirectionTargetCertificate && (len > 0))
1395  {
1396  settings->RedirectionTargetCertificate = freerdp_certificate_new();
1397  if (!settings->RedirectionTargetCertificate)
1398  return FALSE;
1399  }
1400  return TRUE;
1401  case FreeRDP_RedirectionGuid:
1402  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_RedirectionGuidLength,
1403  data, len, sizeof(BYTE));
1404  case FreeRDP_LoadBalanceInfo:
1405  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_LoadBalanceInfoLength,
1406  data, len, sizeof(char));
1407  case FreeRDP_ServerRandom:
1408  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ServerRandomLength, data,
1409  len, sizeof(char));
1410  case FreeRDP_ClientRandom:
1411  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ClientRandomLength, data,
1412  len, sizeof(char));
1413  case FreeRDP_ServerCertificate:
1414  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ServerCertificateLength,
1415  data, len, sizeof(char));
1416  case FreeRDP_TargetNetAddresses:
1417  if ((data == NULL) && (len == 0))
1418  {
1419  freerdp_target_net_addresses_free(settings);
1420  return TRUE;
1421  }
1422  WLog_WARN(
1423  TAG,
1424  "[BUG] FreeRDP_TargetNetAddresses must not be resized from outside the library!");
1425  return FALSE;
1426  case FreeRDP_ServerLicenseProductIssuers:
1427  if (data == NULL)
1428  freerdp_server_license_issuers_free(settings);
1429  return freerdp_settings_set_pointer_len_(settings, FreeRDP_ServerLicenseProductIssuers,
1430  FreeRDP_ServerLicenseProductIssuersCount, data,
1431  len, sizeof(char*));
1432  case FreeRDP_TargetNetPorts:
1433  if ((data == NULL) && (len == 0))
1434  {
1435  freerdp_target_net_addresses_free(settings);
1436  return TRUE;
1437  }
1438  WLog_WARN(TAG,
1439  "[BUG] FreeRDP_TargetNetPorts must not be resized from outside the library!");
1440  return FALSE;
1441  case FreeRDP_DeviceArray:
1442  if (data == NULL)
1443  freerdp_device_collection_free(settings);
1444  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_DeviceArraySize, data,
1445  len, sizeof(ADDIN_ARGV*));
1446  case FreeRDP_ChannelDefArray:
1447  if ((len > 0) && (len < CHANNEL_MAX_COUNT))
1448  WLog_WARN(TAG,
1449  "FreeRDP_ChannelDefArray::len expected to be >= %" PRIu32
1450  ", but have %" PRIu32,
1451  CHANNEL_MAX_COUNT, len);
1452  return freerdp_settings_set_pointer_len_(settings, FreeRDP_ChannelDefArray,
1453  FreeRDP_ChannelDefArraySize, data, len,
1454  sizeof(CHANNEL_DEF));
1455  case FreeRDP_MonitorDefArray:
1456  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_MonitorDefArraySize,
1457  data, len, sizeof(rdpMonitor));
1458  case FreeRDP_ClientAutoReconnectCookie:
1459  return freerdp_settings_set_pointer_len_(settings, id, -1, data, len,
1460  sizeof(ARC_CS_PRIVATE_PACKET));
1461  case FreeRDP_ServerAutoReconnectCookie:
1462  return freerdp_settings_set_pointer_len_(settings, id, -1, data, len,
1463  sizeof(ARC_SC_PRIVATE_PACKET));
1464  case FreeRDP_ClientTimeZone:
1465  if (len > 1)
1466  {
1467  WLog_ERR(TAG, "FreeRDP_ClientTimeZone::len must be 0 or 1");
1468  return FALSE;
1469  }
1470  return freerdp_settings_set_pointer_len_(settings, id, -1, data, len,
1471  sizeof(TIME_ZONE_INFORMATION));
1472  case FreeRDP_BitmapCacheV2CellInfo:
1473  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_BitmapCacheV2NumCells,
1474  data, len, sizeof(BITMAP_CACHE_V2_CELL_INFO));
1475  case FreeRDP_GlyphCache:
1476  if ((len != 0) && (len != 10))
1477  {
1478  WLog_ERR(TAG, "FreeRDP_GlyphCache::len must be 0 or 10");
1479  return FALSE;
1480  }
1481  return freerdp_settings_set_pointer_len_(settings, id, -1, data, len,
1482  sizeof(GLYPH_CACHE_DEFINITION));
1483  case FreeRDP_FragCache:
1484  if (len > 1)
1485  {
1486  WLog_ERR(TAG, "FreeRDP_FragCache::len must be 0 or 1");
1487  return FALSE;
1488  }
1489  return freerdp_settings_set_pointer_len_(settings, id, -1, data, len,
1490  sizeof(GLYPH_CACHE_DEFINITION));
1491  case FreeRDP_StaticChannelArray:
1492  if (data == NULL)
1493  freerdp_static_channel_collection_free(settings);
1494  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_StaticChannelArraySize,
1495  data, len, sizeof(ADDIN_ARGV*));
1496  case FreeRDP_DynamicChannelArray:
1497  if (data == NULL)
1498  freerdp_dynamic_channel_collection_free(settings);
1499  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_DynamicChannelArraySize,
1500  data, len, sizeof(ADDIN_ARGV*));
1501  case FreeRDP_ReceivedCapabilityData:
1502  if (data == NULL)
1503  freerdp_capability_buffer_free(settings);
1504  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ReceivedCapabilitiesSize,
1505  data, len, sizeof(BYTE*));
1506  case FreeRDP_ReceivedCapabilities:
1507  if (data == NULL)
1508  freerdp_capability_buffer_free(settings);
1509  return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ReceivedCapabilitiesSize,
1510  data, len, sizeof(char));
1511  case FreeRDP_OrderSupport:
1512  return freerdp_settings_set_pointer_len_(settings, id, -1, data, len, sizeof(char));
1513 
1514  case FreeRDP_MonitorIds:
1515  return freerdp_settings_set_pointer_len_(
1516  settings, FreeRDP_MonitorIds, FreeRDP_NumMonitorIds, data, len, sizeof(UINT32));
1517 
1518  default:
1519  if ((data == NULL) && (len == 0))
1520  {
1521  freerdp_settings_set_pointer(settings, id, NULL);
1522  }
1523  else
1524  WLog_WARN(TAG, "Invalid id %" PRIuz, id);
1525  return FALSE;
1526  }
1527 }
1528 
1529 void* freerdp_settings_get_pointer_array_writable(const rdpSettings* settings,
1530  FreeRDP_Settings_Keys_Pointer id, size_t offset)
1531 {
1532  size_t max = 0;
1533  if (!settings)
1534  return NULL;
1535  switch (id)
1536  {
1537  case FreeRDP_ClientAutoReconnectCookie:
1538  max = 1;
1539  if ((offset >= max) || !settings->ClientAutoReconnectCookie)
1540  goto fail;
1541  return &settings->ClientAutoReconnectCookie[offset];
1542  case FreeRDP_ServerAutoReconnectCookie:
1543  max = 1;
1544  if ((offset >= max) || !settings->ServerAutoReconnectCookie)
1545  goto fail;
1546  return &settings->ServerAutoReconnectCookie[offset];
1547  case FreeRDP_ServerCertificate:
1548  max = freerdp_settings_get_uint32(settings, FreeRDP_ServerCertificateLength);
1549  if (offset >= max)
1550  goto fail;
1551  return &settings->ServerCertificate[offset];
1552  case FreeRDP_ServerRandom:
1553  max = freerdp_settings_get_uint32(settings, FreeRDP_ServerRandomLength);
1554  if (offset >= max)
1555  goto fail;
1556  return &settings->ServerRandom[offset];
1557  case FreeRDP_ClientRandom:
1558  max = freerdp_settings_get_uint32(settings, FreeRDP_ClientRandomLength);
1559  if (offset >= max)
1560  goto fail;
1561  return &settings->ClientRandom[offset];
1562  case FreeRDP_LoadBalanceInfo:
1563  max = freerdp_settings_get_uint32(settings, FreeRDP_LoadBalanceInfoLength);
1564  if (offset >= max)
1565  goto fail;
1566  return &settings->LoadBalanceInfo[offset];
1567 
1568  case FreeRDP_RedirectionTsvUrl:
1569  max = freerdp_settings_get_uint32(settings, FreeRDP_RedirectionTsvUrlLength);
1570  if (offset >= max)
1571  goto fail;
1572  return &settings->RedirectionTsvUrl[offset];
1573 
1574  case FreeRDP_RedirectionPassword:
1575  max = freerdp_settings_get_uint32(settings, FreeRDP_RedirectionPasswordLength);
1576  if (offset >= max)
1577  goto fail;
1578  return &settings->RedirectionPassword[offset];
1579 
1580  case FreeRDP_OrderSupport:
1581  max = 32;
1582  if (offset >= max)
1583  goto fail;
1584  return &settings->OrderSupport[offset];
1585  case FreeRDP_MonitorIds:
1586  max = freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds);
1587  if (offset >= max)
1588  goto fail;
1589  return &settings->MonitorIds[offset];
1590  case FreeRDP_MonitorDefArray:
1591  max = freerdp_settings_get_uint32(settings, FreeRDP_MonitorDefArraySize);
1592  if (offset >= max)
1593  goto fail;
1594  return &settings->MonitorDefArray[offset];
1595  case FreeRDP_ChannelDefArray:
1596  max = freerdp_settings_get_uint32(settings, FreeRDP_ChannelDefArraySize);
1597  if (offset >= max)
1598  goto fail;
1599  return &settings->ChannelDefArray[offset];
1600  case FreeRDP_DeviceArray:
1601  max = freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize);
1602  if (offset >= max)
1603  goto fail;
1604  return settings->DeviceArray[offset];
1605  case FreeRDP_StaticChannelArray:
1606  max = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
1607  if (offset >= max)
1608  goto fail;
1609  return settings->StaticChannelArray[offset];
1610  case FreeRDP_DynamicChannelArray:
1611  max = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
1612  if (offset >= max)
1613  goto fail;
1614  return settings->DynamicChannelArray[offset];
1615  case FreeRDP_FragCache:
1616  max = 1;
1617  if (offset >= max)
1618  goto fail;
1619  return &settings->FragCache[offset];
1620  case FreeRDP_GlyphCache:
1621  max = 10;
1622  if (offset >= max)
1623  goto fail;
1624  return &settings->GlyphCache[offset];
1625  case FreeRDP_BitmapCacheV2CellInfo:
1626  max = freerdp_settings_get_uint32(settings, FreeRDP_BitmapCacheV2NumCells);
1627  if (offset >= max)
1628  goto fail;
1629  return &settings->BitmapCacheV2CellInfo[offset];
1630  case FreeRDP_ReceivedCapabilities:
1631  max = freerdp_settings_get_uint32(settings, FreeRDP_ReceivedCapabilitiesSize);
1632  if (offset >= max)
1633  goto fail;
1634  return &settings->ReceivedCapabilities[offset];
1635  case FreeRDP_TargetNetAddresses:
1636  max = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
1637  if (offset >= max)
1638  goto fail;
1639  return settings->TargetNetAddresses[offset];
1640  case FreeRDP_TargetNetPorts:
1641  max = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
1642  if (offset >= max)
1643  goto fail;
1644  return &settings->TargetNetPorts[offset];
1645  case FreeRDP_ClientTimeZone:
1646  max = 1;
1647  if (offset >= max)
1648  goto fail;
1649  return settings->ClientTimeZone;
1650  case FreeRDP_RdpServerCertificate:
1651  max = 1;
1652  if (offset >= max)
1653  goto fail;
1654  return settings->RdpServerCertificate;
1655  case FreeRDP_RdpServerRsaKey:
1656  max = 1;
1657  if (offset >= max)
1658  goto fail;
1659  return settings->RdpServerRsaKey;
1660  default:
1661  WLog_WARN(TAG, "Invalid id %s [%" PRIuz "]", freerdp_settings_get_name_for_key(id), id);
1662  return NULL;
1663  }
1664 
1665 fail:
1666  WLog_WARN(TAG, "Invalid offset for %s [%" PRIuz "]: size=%" PRIuz ", offset=%" PRIuz,
1667  freerdp_settings_get_name_for_key(id), id, max, offset);
1668  return NULL;
1669 }
1670 
1671 BOOL freerdp_settings_set_pointer_array(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
1672  size_t offset, const void* data)
1673 {
1674  size_t maxOffset = 0;
1675  if (!settings)
1676  return FALSE;
1677  switch (id)
1678  {
1679  case FreeRDP_ClientAutoReconnectCookie:
1680  maxOffset = 1;
1681  if ((offset >= maxOffset) || !data || !settings->ClientAutoReconnectCookie)
1682  goto fail;
1683  settings->ClientAutoReconnectCookie[offset] = *(const ARC_CS_PRIVATE_PACKET*)data;
1684  return TRUE;
1685  case FreeRDP_ServerAutoReconnectCookie:
1686  maxOffset = 1;
1687  if ((offset >= maxOffset) || !data || !settings->ServerAutoReconnectCookie)
1688  goto fail;
1689  settings->ServerAutoReconnectCookie[offset] = *(const ARC_SC_PRIVATE_PACKET*)data;
1690  return TRUE;
1691  case FreeRDP_ServerCertificate:
1692  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ServerCertificateLength);
1693  if ((offset >= maxOffset) || !data)
1694  goto fail;
1695  settings->ServerCertificate[offset] = *(const BYTE*)data;
1696  return TRUE;
1697  case FreeRDP_DeviceArray:
1698  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize);
1699  if (offset >= maxOffset)
1700  goto fail;
1701  freerdp_device_free(settings->DeviceArray[offset]);
1702  settings->DeviceArray[offset] = freerdp_device_clone(data);
1703  return TRUE;
1704  case FreeRDP_TargetNetAddresses:
1705  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
1706  if ((offset >= maxOffset) || !data)
1707  goto fail;
1708  free(settings->TargetNetAddresses[offset]);
1709  settings->TargetNetAddresses[offset] = _strdup((const char*)data);
1710  return settings->TargetNetAddresses[offset] != NULL;
1711  case FreeRDP_TargetNetPorts:
1712  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
1713  if ((offset >= maxOffset) || !data)
1714  goto fail;
1715  settings->TargetNetPorts[offset] = *((const UINT32*)data);
1716  return TRUE;
1717  case FreeRDP_StaticChannelArray:
1718  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
1719  if ((offset >= maxOffset) || !data)
1720  goto fail;
1721  freerdp_addin_argv_free(settings->StaticChannelArray[offset]);
1722  settings->StaticChannelArray[offset] = freerdp_addin_argv_clone(data);
1723  return TRUE;
1724  case FreeRDP_DynamicChannelArray:
1725  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
1726  if ((offset >= maxOffset) || !data)
1727  goto fail;
1728  freerdp_addin_argv_free(settings->DynamicChannelArray[offset]);
1729  settings->DynamicChannelArray[offset] = freerdp_addin_argv_clone(data);
1730  return TRUE;
1731  case FreeRDP_BitmapCacheV2CellInfo:
1732  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_BitmapCacheV2NumCells);
1733  if ((offset >= maxOffset) || !data)
1734  goto fail;
1735  {
1736  const BITMAP_CACHE_V2_CELL_INFO* cdata = (const BITMAP_CACHE_V2_CELL_INFO*)data;
1737  settings->BitmapCacheV2CellInfo[offset] = *cdata;
1738  }
1739  return TRUE;
1740  case FreeRDP_ServerRandom:
1741  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ServerRandomLength);
1742  if ((offset >= maxOffset) || !data)
1743  goto fail;
1744  settings->ServerRandom[offset] = *(const BYTE*)data;
1745  return TRUE;
1746  case FreeRDP_ClientRandom:
1747  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ClientRandomLength);
1748  if ((offset >= maxOffset) || !data)
1749  goto fail;
1750  settings->ClientRandom[offset] = *(const BYTE*)data;
1751  return TRUE;
1752  case FreeRDP_LoadBalanceInfo:
1753  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_LoadBalanceInfoLength);
1754  if ((offset >= maxOffset) || !data)
1755  goto fail;
1756  settings->LoadBalanceInfo[offset] = *(const BYTE*)data;
1757  return TRUE;
1758  case FreeRDP_RedirectionTsvUrl:
1759  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_RedirectionTsvUrlLength);
1760  if ((offset >= maxOffset) || !data)
1761  goto fail;
1762  settings->RedirectionTsvUrl[offset] = *(const BYTE*)data;
1763  return TRUE;
1764  case FreeRDP_RedirectionPassword:
1765  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_RedirectionPasswordLength);
1766  if ((offset >= maxOffset) || !data)
1767  goto fail;
1768  settings->RedirectionPassword[offset] = *(const BYTE*)data;
1769  return TRUE;
1770  case FreeRDP_OrderSupport:
1771  maxOffset = 32;
1772  if (!settings->OrderSupport)
1773  goto fail;
1774  if ((offset >= maxOffset) || !data)
1775  goto fail;
1776  settings->OrderSupport[offset] = *(const BOOL*)data;
1777  return TRUE;
1778  case FreeRDP_GlyphCache:
1779  maxOffset = 10;
1780  if (!settings->GlyphCache)
1781  goto fail;
1782  if ((offset >= maxOffset) || !data)
1783  goto fail;
1784  settings->GlyphCache[offset] = *(const GLYPH_CACHE_DEFINITION*)data;
1785  return TRUE;
1786  case FreeRDP_FragCache:
1787  maxOffset = 1;
1788  if (!settings->FragCache)
1789  goto fail;
1790  if ((offset >= maxOffset) || !data)
1791  goto fail;
1792  settings->FragCache[offset] = *(const GLYPH_CACHE_DEFINITION*)data;
1793  return TRUE;
1794  case FreeRDP_MonitorIds:
1795  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds);
1796  if ((offset >= maxOffset) || !data)
1797  goto fail;
1798  settings->MonitorIds[offset] = *(const UINT32*)data;
1799  return TRUE;
1800  case FreeRDP_ChannelDefArray:
1801  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ChannelDefArraySize);
1802  if ((offset >= maxOffset) || !data)
1803  goto fail;
1804  settings->ChannelDefArray[offset] = *(const CHANNEL_DEF*)data;
1805  return TRUE;
1806  case FreeRDP_MonitorDefArray:
1807  maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_MonitorDefArraySize);
1808  if ((offset >= maxOffset) || !data)
1809  goto fail;
1810  settings->MonitorDefArray[offset] = *(const rdpMonitor*)data;
1811  return TRUE;
1812 
1813  case FreeRDP_ClientTimeZone:
1814  maxOffset = 1;
1815  if ((offset >= maxOffset) || !data || !settings->ClientTimeZone)
1816  goto fail;
1817  settings->ClientTimeZone[0] = *(const TIME_ZONE_INFORMATION*)data;
1818  return TRUE;
1819 
1820  default:
1821  WLog_WARN(TAG, "Invalid id %s [%" PRIuz "]", freerdp_settings_get_name_for_key(id), id);
1822  return FALSE;
1823  }
1824 
1825 fail:
1826  WLog_WARN(TAG, "[%s] Invalid offset=%" PRIuz " [%" PRIuz "] or NULL data=%p",
1827  freerdp_settings_get_name_for_key(id), offset, maxOffset, data);
1828  return FALSE;
1829 }
1830 
1831 const void* freerdp_settings_get_pointer_array(const rdpSettings* settings,
1832  FreeRDP_Settings_Keys_Pointer id, size_t offset)
1833 {
1834  return freerdp_settings_get_pointer_array_writable(settings, id, offset);
1835 }
1836 
1837 UINT32 freerdp_settings_get_codecs_flags(const rdpSettings* settings)
1838 {
1839  UINT32 flags = FREERDP_CODEC_ALL;
1840  if (settings->RemoteFxCodec == FALSE)
1841  {
1842  flags &= ~FREERDP_CODEC_REMOTEFX;
1843  }
1844  if (settings->NSCodec == FALSE)
1845  {
1846  flags &= ~FREERDP_CODEC_NSCODEC;
1847  }
1848  /*TODO: check other codecs flags */
1849  return flags;
1850 }
1851 
1852 const char* freerdp_settings_get_server_name(const rdpSettings* settings)
1853 {
1854  WINPR_ASSERT(settings);
1855  const char* hostname = settings->ServerHostname;
1856 
1857  if (settings->UserSpecifiedServerName)
1858  hostname = settings->UserSpecifiedServerName;
1859 
1860  return hostname;
1861 }
1862 
1863 #if defined(WITH_FREERDP_DEPRECATED)
1864 ADDIN_ARGV* freerdp_static_channel_clone(ADDIN_ARGV* channel)
1865 {
1866  return freerdp_addin_argv_clone(channel);
1867 }
1868 
1869 ADDIN_ARGV* freerdp_dynamic_channel_clone(ADDIN_ARGV* channel)
1870 {
1871  return freerdp_addin_argv_clone(channel);
1872 }
1873 #endif
1874 
1875 BOOL freerdp_target_net_addresses_copy(rdpSettings* settings, char** addresses, UINT32 count)
1876 {
1877  WINPR_ASSERT(settings);
1878  WINPR_ASSERT(addresses);
1879 
1880  if (!freerdp_target_net_adresses_reset(settings, count))
1881  return FALSE;
1882 
1883  for (UINT32 i = 0; i < settings->TargetNetAddressCount; i++)
1884  {
1885  if (!freerdp_settings_set_pointer_array(settings, FreeRDP_TargetNetAddresses, i,
1886  addresses[i]))
1887  {
1888  freerdp_target_net_addresses_free(settings);
1889  return FALSE;
1890  }
1891  }
1892 
1893  return TRUE;
1894 }
1895 
1896 BOOL freerdp_device_equal(const RDPDR_DEVICE* what, const RDPDR_DEVICE* expect)
1897 {
1898  if (!what && !expect)
1899  return TRUE;
1900  if (!what || !expect)
1901  return FALSE;
1902 
1903  if (what->Id != expect->Id)
1904  return FALSE;
1905  if (what->Type != expect->Type)
1906  return FALSE;
1907  if (what->Name && expect->Name)
1908  {
1909  if (strcmp(what->Name, expect->Name) != 0)
1910  return FALSE;
1911  }
1912  else
1913  {
1914  if (what->Name != expect->Name)
1915  return FALSE;
1916  }
1917 
1918  switch (what->Type)
1919  {
1920  case RDPDR_DTYP_PRINT:
1921  {
1922  const RDPDR_PRINTER* a = (const RDPDR_PRINTER*)what;
1923  const RDPDR_PRINTER* b = (const RDPDR_PRINTER*)expect;
1924  if (a->DriverName && b->DriverName)
1925  return strcmp(a->DriverName, b->DriverName) == 0;
1926  return a->DriverName == b->DriverName;
1927  }
1928 
1929  case RDPDR_DTYP_SERIAL:
1930  {
1931  const RDPDR_SERIAL* a = (const RDPDR_SERIAL*)what;
1932  const RDPDR_SERIAL* b = (const RDPDR_SERIAL*)expect;
1933 
1934  if (a->Path && b->Path)
1935  {
1936  if (strcmp(a->Path, b->Path) != 0)
1937  return FALSE;
1938  }
1939  else if (a->Path != b->Path)
1940  return FALSE;
1941 
1942  if (a->Driver && b->Driver)
1943  {
1944  if (strcmp(a->Driver, b->Driver) != 0)
1945  return FALSE;
1946  }
1947  else if (a->Driver != b->Driver)
1948  return FALSE;
1949  if (a->Permissive && b->Permissive)
1950  return strcmp(a->Permissive, b->Permissive) == 0;
1951  return a->Permissive == b->Permissive;
1952  }
1953 
1954  case RDPDR_DTYP_PARALLEL:
1955  {
1956  const RDPDR_PARALLEL* a = (const RDPDR_PARALLEL*)what;
1957  const RDPDR_PARALLEL* b = (const RDPDR_PARALLEL*)expect;
1958  if (a->Path && b->Path)
1959  return strcmp(a->Path, b->Path) == 0;
1960  return a->Path == b->Path;
1961  }
1962 
1963  case RDPDR_DTYP_SMARTCARD:
1964  break;
1965  case RDPDR_DTYP_FILESYSTEM:
1966  {
1967  const RDPDR_DRIVE* a = (const RDPDR_DRIVE*)what;
1968  const RDPDR_DRIVE* b = (const RDPDR_DRIVE*)expect;
1969  if (a->automount != b->automount)
1970  return FALSE;
1971  if (a->Path && b->Path)
1972  return strcmp(a->Path, b->Path) == 0;
1973  return a->Path == b->Path;
1974  }
1975 
1976  default:
1977  return FALSE;
1978  }
1979 
1980  return TRUE;
1981 }
1982 
1983 const char* freerdp_rail_support_flags_to_string(UINT32 flags, char* buffer, size_t length)
1984 {
1985  const UINT32 mask =
1986  RAIL_LEVEL_SUPPORTED | RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED |
1987  RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED | RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED |
1988  RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED | RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED |
1989  RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED | RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED;
1990 
1991  if (flags & RAIL_LEVEL_SUPPORTED)
1992  winpr_str_append("RAIL_LEVEL_SUPPORTED", buffer, length, "|");
1993  if (flags & RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED)
1994  winpr_str_append("RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED", buffer, length, "|");
1995  if (flags & RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED)
1996  winpr_str_append("RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED", buffer, length, "|");
1997  if (flags & RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED)
1998  winpr_str_append("RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED", buffer, length, "|");
1999  if (flags & RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED)
2000  winpr_str_append("RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED", buffer, length, "|");
2001  if (flags & RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED)
2002  winpr_str_append("RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED", buffer, length, "|");
2003  if (flags & RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED)
2004  winpr_str_append("RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED", buffer, length, "|");
2005  if (flags & RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED)
2006  winpr_str_append("RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED", buffer, length, "|");
2007  if (flags & RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED)
2008  winpr_str_append("RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED", buffer, length, "|");
2009  if ((flags & ~mask) != 0)
2010  {
2011  char tbuffer[64] = { 0 };
2012  (void)_snprintf(tbuffer, sizeof(tbuffer), "RAIL_FLAG_UNKNOWN 0x%08" PRIx32, flags & mask);
2013  winpr_str_append(tbuffer, buffer, length, "|");
2014  }
2015  return buffer;
2016 }
2017 
2018 BOOL freerdp_settings_update_from_caps(rdpSettings* settings, const BYTE* capsFlags,
2019  const BYTE** capsData, const UINT32* capsSizes,
2020  UINT32 capsCount, BOOL serverReceivedCaps)
2021 {
2022  WINPR_ASSERT(settings);
2023  WINPR_ASSERT(capsFlags || (capsCount == 0));
2024  WINPR_ASSERT(capsData || (capsCount == 0));
2025  WINPR_ASSERT(capsSizes || (capsCount == 0));
2026  WINPR_ASSERT(capsCount <= UINT16_MAX);
2027 
2028  for (UINT32 x = 0; x < capsCount; x++)
2029  {
2030  if (capsFlags[x])
2031  {
2032  wStream buffer;
2033  wStream* sub = Stream_StaticConstInit(&buffer, capsData[x], capsSizes[x]);
2034 
2035  if (!rdp_read_capability_set(sub, (UINT16)x, settings, serverReceivedCaps))
2036  return FALSE;
2037  }
2038  }
2039 
2040  return TRUE;
2041 }
2042 
2043 const char* freerdp_rdp_version_string(UINT32 version)
2044 {
2045  switch (version)
2046  {
2047  case RDP_VERSION_4:
2048  return "RDP_VERSION_4";
2049  case RDP_VERSION_5_PLUS:
2050  return "RDP_VERSION_5_PLUS";
2051  case RDP_VERSION_10_0:
2052  return "RDP_VERSION_10_0";
2053  case RDP_VERSION_10_1:
2054  return "RDP_VERSION_10_1";
2055  case RDP_VERSION_10_2:
2056  return "RDP_VERSION_10_2";
2057  case RDP_VERSION_10_3:
2058  return "RDP_VERSION_10_3";
2059  case RDP_VERSION_10_4:
2060  return "RDP_VERSION_10_4";
2061  case RDP_VERSION_10_5:
2062  return "RDP_VERSION_10_5";
2063  case RDP_VERSION_10_6:
2064  return "RDP_VERSION_10_6";
2065  case RDP_VERSION_10_7:
2066  return "RDP_VERSION_10_7";
2067  case RDP_VERSION_10_8:
2068  return "RDP_VERSION_10_8";
2069  case RDP_VERSION_10_9:
2070  return "RDP_VERSION_10_9";
2071  case RDP_VERSION_10_10:
2072  return "RDP_VERSION_10_10";
2073  case RDP_VERSION_10_11:
2074  return "RDP_VERSION_10_11";
2075  case RDP_VERSION_10_12:
2076  return "RDP_VERSION_10_12";
2077  default:
2078  return "RDP_VERSION_UNKNOWN";
2079  }
2080 }
2081 
2082 BOOL freerdp_settings_set_string_from_utf16(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
2083  const WCHAR* param)
2084 {
2085  WINPR_ASSERT(settings);
2086 
2087  if (!param)
2088  return freerdp_settings_set_string_copy_(settings, id, NULL, 0, TRUE);
2089 
2090  size_t len = 0;
2091 
2092  char* str = ConvertWCharToUtf8Alloc(param, &len);
2093  if (!str && (len != 0))
2094  return FALSE;
2095 
2096  return freerdp_settings_set_string_(settings, id, str, len);
2097 }
2098 
2099 BOOL freerdp_settings_set_string_from_utf16N(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
2100  const WCHAR* param, size_t length)
2101 {
2102  size_t len = 0;
2103 
2104  WINPR_ASSERT(settings);
2105 
2106  if (!param)
2107  return freerdp_settings_set_string_copy_(settings, id, NULL, length, TRUE);
2108 
2109  char* str = ConvertWCharNToUtf8Alloc(param, length, &len);
2110  if (!str && (length != 0))
2111  {
2112  /* If the input string is an empty string, but length > 0
2113  * consider the conversion a success */
2114  const size_t wlen = _wcsnlen(param, length);
2115  if (wlen != 0)
2116  return FALSE;
2117  }
2118 
2119  return freerdp_settings_set_string_(settings, id, str, len);
2120 }
2121 
2122 WCHAR* freerdp_settings_get_string_as_utf16(const rdpSettings* settings,
2123  FreeRDP_Settings_Keys_String id, size_t* pCharLen)
2124 {
2125  const char* str = freerdp_settings_get_string(settings, id);
2126  if (pCharLen)
2127  *pCharLen = 0;
2128  if (!str)
2129  return NULL;
2130  return ConvertUtf8ToWCharAlloc(str, pCharLen);
2131 }
2132 
2133 const char* freerdp_rdpdr_dtyp_string(UINT32 type)
2134 {
2135  switch (type)
2136  {
2137  case RDPDR_DTYP_FILESYSTEM:
2138  return "RDPDR_DTYP_FILESYSTEM";
2139  case RDPDR_DTYP_PARALLEL:
2140  return "RDPDR_DTYP_PARALLEL";
2141  case RDPDR_DTYP_PRINT:
2142  return "RDPDR_DTYP_PRINT";
2143  case RDPDR_DTYP_SERIAL:
2144  return "RDPDR_DTYP_SERIAL";
2145  case RDPDR_DTYP_SMARTCARD:
2146  return "RDPDR_DTYP_SMARTCARD";
2147  default:
2148  return "RDPDR_DTYP_UNKNOWN";
2149  }
2150 }
2151 
2152 const char* freerdp_encryption_level_string(UINT32 EncryptionLevel)
2153 {
2154  switch (EncryptionLevel)
2155  {
2156  case ENCRYPTION_LEVEL_NONE:
2157  return "ENCRYPTION_LEVEL_NONE";
2158  case ENCRYPTION_LEVEL_LOW:
2159  return "ENCRYPTION_LEVEL_LOW";
2160  case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE:
2161  return "ENCRYPTION_LEVEL_CLIENT_COMPATIBLE";
2162  case ENCRYPTION_LEVEL_HIGH:
2163  return "ENCRYPTION_LEVEL_HIGH";
2164  case ENCRYPTION_LEVEL_FIPS:
2165  return "ENCRYPTION_LEVEL_FIPS";
2166  default:
2167  return "ENCRYPTION_LEVEL_UNKNOWN";
2168  }
2169 }
2170 
2171 const char* freerdp_encryption_methods_string(UINT32 EncryptionMethods, char* buffer, size_t size)
2172 {
2173  if (EncryptionMethods == ENCRYPTION_METHOD_NONE)
2174  {
2175  winpr_str_append("ENCRYPTION_METHOD_NONE", buffer, size, "|");
2176  return buffer;
2177  }
2178 
2179  if (EncryptionMethods & ENCRYPTION_METHOD_40BIT)
2180  {
2181  winpr_str_append("ENCRYPTION_METHOD_40BIT", buffer, size, "|");
2182  }
2183  if (EncryptionMethods & ENCRYPTION_METHOD_128BIT)
2184  {
2185  winpr_str_append("ENCRYPTION_METHOD_128BIT", buffer, size, "|");
2186  }
2187  if (EncryptionMethods & ENCRYPTION_METHOD_56BIT)
2188  {
2189  winpr_str_append("ENCRYPTION_METHOD_56BIT", buffer, size, "|");
2190  }
2191  if (EncryptionMethods & ENCRYPTION_METHOD_FIPS)
2192  {
2193  winpr_str_append("ENCRYPTION_METHOD_FIPS", buffer, size, "|");
2194  }
2195 
2196  return buffer;
2197 }
2198 
2199 const char* freerdp_supported_color_depths_string(UINT16 mask, char* buffer, size_t size)
2200 {
2201  const UINT32 invalid = mask & ~(RNS_UD_32BPP_SUPPORT | RNS_UD_24BPP_SUPPORT |
2202  RNS_UD_16BPP_SUPPORT | RNS_UD_15BPP_SUPPORT);
2203 
2204  if (mask & RNS_UD_32BPP_SUPPORT)
2205  winpr_str_append("RNS_UD_32BPP_SUPPORT", buffer, size, "|");
2206  if (mask & RNS_UD_24BPP_SUPPORT)
2207  winpr_str_append("RNS_UD_24BPP_SUPPORT", buffer, size, "|");
2208  if (mask & RNS_UD_16BPP_SUPPORT)
2209  winpr_str_append("RNS_UD_16BPP_SUPPORT", buffer, size, "|");
2210  if (mask & RNS_UD_15BPP_SUPPORT)
2211  winpr_str_append("RNS_UD_15BPP_SUPPORT", buffer, size, "|");
2212 
2213  if (invalid != 0)
2214  {
2215  char str[32] = { 0 };
2216  (void)_snprintf(str, sizeof(str), "RNS_UD_INVALID[0x%04" PRIx32 "]", invalid);
2217  winpr_str_append(str, buffer, size, "|");
2218  }
2219  char hex[32] = { 0 };
2220  (void)_snprintf(hex, sizeof(hex), "[0x%04" PRIx16 "]", mask);
2221  return buffer;
2222 }
2223 
2224 BOOL freerdp_settings_append_string(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
2225  const char* separator, const char* param)
2226 {
2227  const char* old = freerdp_settings_get_string(settings, id);
2228 
2229  size_t len = 0;
2230  char* str = NULL;
2231 
2232  if (!old)
2233  winpr_asprintf(&str, &len, "%s", param);
2234  else if (!separator)
2235  winpr_asprintf(&str, &len, "%s%s", old, param);
2236  else
2237  winpr_asprintf(&str, &len, "%s%s%s", old, separator, param);
2238 
2239  const BOOL rc = freerdp_settings_set_string_len(settings, id, str, len);
2240  free(str);
2241  return rc;
2242 }
2243 
2244 BOOL freerdp_settings_are_valid(const rdpSettings* settings)
2245 {
2246  return settings != NULL;
2247 }
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