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