FreeRDP
Loading...
Searching...
No Matches
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#include <math.h>
30
31#include <winpr/crt.h>
32#include <winpr/assert.h>
33#include <winpr/cast.h>
34
35#include "../core/settings.h"
36#include "../core/capabilities.h"
37
38#include <freerdp/crypto/certificate.h>
39#include <freerdp/settings.h>
40#include <freerdp/freerdp.h>
41#include <freerdp/log.h>
42
43#define TAG FREERDP_TAG("common")
44
45BOOL freerdp_addin_argv_add_argument_ex(ADDIN_ARGV* args, const char* argument, size_t len)
46{
47 if (!args || !argument)
48 return FALSE;
49
50 if (len == 0)
51 len = strlen(argument);
52
53 char** new_argv = (char**)realloc(
54 (void*)args->argv, sizeof(char*) * (WINPR_ASSERTING_INT_CAST(uint32_t, args->argc) + 1));
55
56 if (!new_argv)
57 return FALSE;
58
59 args->argv = new_argv;
60
61 char* 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
69BOOL 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
74BOOL freerdp_addin_argv_del_argument(ADDIN_ARGV* args, const char* argument)
75{
76 if (!args || !argument)
77 return FALSE;
78 for (int x = 0; x < args->argc; x++)
79 {
80 char* arg = args->argv[x];
81 if (strcmp(argument, arg) == 0)
82 {
83 free(arg);
84 memmove_s((void*)&args->argv[x],
85 (WINPR_ASSERTING_INT_CAST(uint32_t, args->argc - x)) * sizeof(char*),
86 (void*)&args->argv[x + 1],
87 (WINPR_ASSERTING_INT_CAST(uint32_t, args->argc - x - 1)) * sizeof(char*));
88 args->argv[args->argc - 1] = NULL;
89 args->argc--;
90 return TRUE;
91 }
92 }
93 return FALSE;
94}
95
96int freerdp_addin_set_argument(ADDIN_ARGV* args, const char* argument)
97{
98 if (!args || !argument)
99 return -2;
100
101 for (int i = 0; i < args->argc; i++)
102 {
103 if (strcmp(args->argv[i], argument) == 0)
104 {
105 return 1;
106 }
107 }
108
109 if (!freerdp_addin_argv_add_argument(args, argument))
110 return -1;
111 return 0;
112}
113
114int freerdp_addin_replace_argument(ADDIN_ARGV* args, const char* previous, const char* argument)
115{
116 if (!args || !previous || !argument)
117 return -2;
118
119 for (int i = 0; i < args->argc; i++)
120 {
121 if (strcmp(args->argv[i], previous) == 0)
122 {
123 free(args->argv[i]);
124
125 if (!(args->argv[i] = _strdup(argument)))
126 return -1;
127
128 return 1;
129 }
130 }
131
132 if (!freerdp_addin_argv_add_argument(args, argument))
133 return -1;
134 return 0;
135}
136
137int freerdp_addin_set_argument_value(ADDIN_ARGV* args, const char* option, const char* value)
138{
139 BOOL rc = 0;
140 char* p = NULL;
141 char* str = NULL;
142 size_t length = 0;
143 if (!args || !option || !value)
144 return -2;
145 length = strlen(option) + strlen(value) + 1;
146 str = (char*)calloc(length + 1, sizeof(char));
147
148 if (!str)
149 return -1;
150
151 (void)sprintf_s(str, length + 1, "%s:%s", option, value);
152
153 for (int i = 0; i < args->argc; i++)
154 {
155 p = strchr(args->argv[i], ':');
156
157 if (p)
158 {
159 if (strncmp(args->argv[i], option,
160 WINPR_ASSERTING_INT_CAST(size_t, p - args->argv[i])) == 0)
161 {
162 free(args->argv[i]);
163 args->argv[i] = str;
164 return 1;
165 }
166 }
167 }
168
169 rc = freerdp_addin_argv_add_argument(args, str);
170 free(str);
171 if (!rc)
172 return -1;
173 return 0;
174}
175
176int freerdp_addin_replace_argument_value(ADDIN_ARGV* args, const char* previous, const char* option,
177 const char* value)
178{
179 BOOL rc = 0;
180 char* str = NULL;
181 size_t length = 0;
182 if (!args || !previous || !option || !value)
183 return -2;
184 length = strlen(option) + strlen(value) + 1;
185 str = (char*)calloc(length + 1, sizeof(char));
186
187 if (!str)
188 return -1;
189
190 (void)sprintf_s(str, length + 1, "%s:%s", option, value);
191
192 for (int i = 0; i < args->argc; i++)
193 {
194 if (strcmp(args->argv[i], previous) == 0)
195 {
196 free(args->argv[i]);
197 args->argv[i] = str;
198 return 1;
199 }
200 }
201
202 rc = freerdp_addin_argv_add_argument(args, str);
203 free(str);
204 if (!rc)
205 return -1;
206 return 0;
207}
208
209BOOL freerdp_device_collection_add(rdpSettings* settings, RDPDR_DEVICE* device)
210{
211 UINT32 count = 0;
212 UINT32 old = 0;
213 WINPR_ASSERT(settings);
214 WINPR_ASSERT(device);
215
216 count = freerdp_settings_get_uint32(settings, FreeRDP_DeviceCount) + 1;
217 old = freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize);
218 if (old < count)
219 {
220 const size_t new_size = (old + 32);
221 RDPDR_DEVICE** new_array =
222 (RDPDR_DEVICE**)realloc((void*)settings->DeviceArray, new_size * sizeof(RDPDR_DEVICE*));
223
224 if (!new_array)
225 return FALSE;
226
227 settings->DeviceArray = new_array;
228 for (size_t x = old; x < new_size; x++)
229 settings->DeviceArray[x] = NULL;
230
231 if (!freerdp_settings_set_uint32(settings, FreeRDP_DeviceArraySize,
232 WINPR_ASSERTING_INT_CAST(uint32_t, new_size)))
233 return FALSE;
234 }
235
236 settings->DeviceArray[settings->DeviceCount++] = device;
237 return TRUE;
238}
239
240BOOL 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
267RDPDR_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
287RDPDR_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
303RDPDR_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
415fail:
416 freerdp_device_free(device.base);
417 return NULL;
418}
419
420void 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
462RDPDR_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
560void freerdp_device_collection_free(rdpSettings* settings)
561{
562 WINPR_ASSERT(settings);
563
564 if (settings->DeviceArray)
565 {
566 for (UINT32 index = 0; index < settings->DeviceArraySize; index++)
567 (void)freerdp_settings_set_pointer_array(settings, FreeRDP_DeviceArray, index, NULL);
568 }
569
570 free((void*)settings->DeviceArray);
571
572 (void)freerdp_settings_set_pointer(settings, FreeRDP_DeviceArray, NULL);
573 (void)freerdp_settings_set_uint32(settings, FreeRDP_DeviceArraySize, 0);
574 (void)freerdp_settings_set_uint32(settings, FreeRDP_DeviceCount, 0);
575}
576
577BOOL 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 memmove_s((void*)&settings->StaticChannelArray[x],
591 (count - x) * sizeof(ADDIN_ARGV*),
592 (void*)&settings->StaticChannelArray[x + 1],
593 (count - x - 1) * sizeof(ADDIN_ARGV*));
594 for (size_t y = count - 1; y < settings->StaticChannelArraySize; y++)
595 settings->StaticChannelArray[y] = NULL;
596
597 freerdp_addin_argv_free(cur);
598 return freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelCount, count - 1);
599 }
600 }
601 }
602 {
603 for (size_t x = count; x < settings->StaticChannelArraySize; x++)
604 settings->StaticChannelArray[x] = NULL;
605 }
606 return FALSE;
607}
608
609BOOL freerdp_static_channel_collection_add(rdpSettings* settings, ADDIN_ARGV* channel)
610{
611 UINT32 count = 0;
612
613 WINPR_ASSERT(settings);
614 WINPR_ASSERT(channel);
615
616 count = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount) + 1;
617 if (freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize) < count)
618 {
619 const UINT32 oldSize =
620 freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
621 const size_t new_size = oldSize + 32ul;
622 ADDIN_ARGV** new_array = (ADDIN_ARGV**)realloc((void*)settings->StaticChannelArray,
623 new_size * sizeof(ADDIN_ARGV*));
624
625 if (!new_array)
626 return FALSE;
627
628 settings->StaticChannelArray = new_array;
629 {
630 for (size_t x = oldSize; x < new_size; x++)
631 settings->StaticChannelArray[x] = NULL;
632 }
633 if (!freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelArraySize,
634 WINPR_ASSERTING_INT_CAST(uint32_t, new_size)))
635 return FALSE;
636 }
637
638 count = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
639
640 ADDIN_ARGV** cur = &settings->StaticChannelArray[count++];
641 freerdp_addin_argv_free(*cur);
642 *cur = channel;
643 return freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelCount, count);
644}
645
646ADDIN_ARGV* freerdp_static_channel_collection_find(rdpSettings* settings, const char* name)
647{
648 ADDIN_ARGV* channel = NULL;
649
650 WINPR_ASSERT(settings);
651 WINPR_ASSERT(name);
652
653 for (UINT32 index = 0;
654 index < freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount); index++)
655 {
656 channel = settings->StaticChannelArray[index];
657
658 if (strcmp(channel->argv[0], name) == 0)
659 return channel;
660 }
661
662 return NULL;
663}
664
665void freerdp_static_channel_collection_free(rdpSettings* settings)
666{
667 if (!settings)
668 return;
669
670 if (settings->StaticChannelArray)
671 {
672 for (UINT32 i = 0;
673 i < freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize); i++)
674 freerdp_addin_argv_free(settings->StaticChannelArray[i]);
675 }
676
677 free((void*)settings->StaticChannelArray);
678 (void)freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelArraySize, 0);
679 settings->StaticChannelArray = NULL;
680 (void)freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelCount, 0);
681}
682
683BOOL freerdp_dynamic_channel_collection_del(rdpSettings* settings, const char* name)
684{
685 const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
686 if (!settings || !settings->DynamicChannelArray)
687 return FALSE;
688
689 for (UINT32 x = 0; x < count; x++)
690 {
691 ADDIN_ARGV* cur = settings->DynamicChannelArray[x];
692 if (cur && (cur->argc > 0))
693 {
694 if (strcmp(name, cur->argv[0]) == 0)
695 {
696 memmove_s((void*)&settings->DynamicChannelArray[x],
697 (count - x) * sizeof(ADDIN_ARGV*),
698 (void*)&settings->DynamicChannelArray[x + 1],
699 (count - x - 1) * sizeof(ADDIN_ARGV*));
700 for (size_t y = count - 1; y < settings->DynamicChannelArraySize; y++)
701 settings->DynamicChannelArray[y] = NULL;
702
703 freerdp_addin_argv_free(cur);
704 return freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelCount,
705 count - 1);
706 }
707 }
708 }
709
710 return FALSE;
711}
712
713BOOL freerdp_dynamic_channel_collection_add(rdpSettings* settings, ADDIN_ARGV* channel)
714{
715 UINT32 count = 0;
716 UINT32 oldSize = 0;
717
718 WINPR_ASSERT(settings);
719 WINPR_ASSERT(channel);
720
721 count = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount) + 1;
722 oldSize = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
723 if (oldSize < count)
724 {
725
726 const size_t size = oldSize + 32;
727 ADDIN_ARGV** new_array =
728 (ADDIN_ARGV**)realloc((void*)settings->DynamicChannelArray, sizeof(ADDIN_ARGV*) * size);
729
730 if (!new_array)
731 return FALSE;
732
733 settings->DynamicChannelArray = new_array;
734 {
735 for (size_t x = oldSize; x < size; x++)
736 settings->DynamicChannelArray[x] = NULL;
737 }
738 if (!freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelArraySize,
739 WINPR_ASSERTING_INT_CAST(uint32_t, size)))
740 return FALSE;
741 }
742
743 count = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
744 settings->DynamicChannelArray[count++] = channel;
745 return freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelCount, count);
746}
747
748ADDIN_ARGV* freerdp_dynamic_channel_collection_find(const rdpSettings* settings, const char* name)
749{
750 WINPR_ASSERT(settings);
751 WINPR_ASSERT(name);
752
753 for (UINT32 index = 0;
754 index < freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount); index++)
755 {
756 ADDIN_ARGV* channel = settings->DynamicChannelArray[index];
757
758 if (strcmp(channel->argv[0], name) == 0)
759 return channel;
760 }
761
762 return NULL;
763}
764
765void freerdp_addin_argv_free(ADDIN_ARGV* args)
766{
767 if (!args)
768 return;
769
770 if (args->argv)
771 {
772 for (int index = 0; index < args->argc; index++)
773 free(args->argv[index]);
774 free((void*)args->argv);
775 }
776
777 free(args);
778}
779
780ADDIN_ARGV* freerdp_addin_argv_new(size_t argc, const char* const argv[])
781{
782 if (argc > INT32_MAX)
783 return NULL;
784
785 ADDIN_ARGV* args = calloc(1, sizeof(ADDIN_ARGV));
786 if (!args)
787 return NULL;
788 if (argc == 0)
789 return args;
790
791 args->argc = (int)argc;
792 args->argv = (char**)calloc(argc, sizeof(char*));
793 if (!args->argv)
794 goto fail;
795
796 if (argv)
797 {
798 for (size_t x = 0; x < argc; x++)
799 {
800 args->argv[x] = _strdup(argv[x]);
801 if (!args->argv[x])
802 goto fail;
803 }
804 }
805 return args;
806
807fail:
808 WINPR_PRAGMA_DIAG_PUSH
809 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
810 freerdp_addin_argv_free(args);
811 WINPR_PRAGMA_DIAG_POP
812 return NULL;
813}
814
815ADDIN_ARGV* freerdp_addin_argv_clone(const ADDIN_ARGV* args)
816{
817 union
818 {
819 char** c;
820 const char** cc;
821 } cnv;
822 if (!args)
823 return NULL;
824 cnv.c = args->argv;
825 return freerdp_addin_argv_new(WINPR_ASSERTING_INT_CAST(uint32_t, args->argc), cnv.cc);
826}
827
828void freerdp_dynamic_channel_collection_free(rdpSettings* settings)
829{
830 WINPR_ASSERT(settings);
831
832 if (settings->DynamicChannelArray)
833 {
834 for (UINT32 i = 0;
835 i < freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize); i++)
836 freerdp_addin_argv_free(settings->DynamicChannelArray[i]);
837 }
838
839 free((void*)settings->DynamicChannelArray);
840 (void)freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelArraySize, 0);
841 settings->DynamicChannelArray = NULL;
842 (void)freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelCount, 0);
843}
844
845static void freerdp_capability_data_free(rdpSettings* settings, size_t offset, BOOL full)
846{
847 WINPR_ASSERT(settings);
848
849 if (settings->ReceivedCapabilityData)
850 {
851 for (size_t x = offset; x < settings->ReceivedCapabilitiesSize; x++)
852 {
853 free(settings->ReceivedCapabilityData[x]);
854 settings->ReceivedCapabilityData[x] = NULL;
855 }
856 if (full)
857 {
858 free((void*)settings->ReceivedCapabilityData);
859 settings->ReceivedCapabilityData = NULL;
860 }
861 }
862}
863
864void freerdp_capability_buffer_free(rdpSettings* settings)
865{
866 WINPR_ASSERT(settings);
867
868 freerdp_capability_data_free(settings, 0, TRUE);
869
870 free(settings->ReceivedCapabilityDataSizes);
871 settings->ReceivedCapabilityDataSizes = NULL;
872
873 free(settings->ReceivedCapabilities);
874 settings->ReceivedCapabilities = NULL;
875
876 settings->ReceivedCapabilitiesSize = 0;
877}
878
879static BOOL resize_setting(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id, size_t oldsize,
880 size_t size, size_t base)
881{
882 void* old = freerdp_settings_get_pointer_writable(settings, id);
883 uint8_t* ptr = realloc(old, size * base);
884 if (!ptr)
885 return FALSE;
886
887 if (size > oldsize)
888 {
889 const size_t diff = size - oldsize;
890 memset(&ptr[oldsize * base], 0, diff * base);
891 }
892
893 // NOLINTNEXTLINE(clang-analyzer-unix.Malloc
894 return freerdp_settings_set_pointer(settings, id, ptr);
895}
896
897BOOL freerdp_capability_buffer_resize(rdpSettings* settings, size_t count)
898{
899 WINPR_ASSERT(settings);
900
901 const uint32_t len = settings->ReceivedCapabilitiesSize;
902 if (len == count)
903 return TRUE;
904
905 freerdp_capability_data_free(settings, count, FALSE);
906
907 if (count == 0)
908 {
909 freerdp_capability_buffer_free(settings);
910 return TRUE;
911 }
912
913 const size_t oldsize = settings->ReceivedCapabilitiesSize;
914 if (!resize_setting(settings, FreeRDP_ReceivedCapabilityDataSizes, oldsize, count,
915 sizeof(uint32_t)))
916 return FALSE;
917 if (!resize_setting(settings, FreeRDP_ReceivedCapabilityData, oldsize, count, sizeof(uint8_t*)))
918 return FALSE;
919 if (!resize_setting(settings, FreeRDP_ReceivedCapabilities, oldsize, count, sizeof(uint32_t)))
920 return FALSE;
921
922 settings->ReceivedCapabilitiesSize = WINPR_ASSERTING_INT_CAST(uint32_t, count);
923 return TRUE;
924}
925
926BOOL freerdp_capability_buffer_copy(rdpSettings* settings, const rdpSettings* src)
927{
928 WINPR_ASSERT(settings);
929 WINPR_ASSERT(src);
930
931 if (src->ReceivedCapabilitiesSize == 0)
932 return TRUE;
933
934 if (!freerdp_capability_buffer_resize(settings, src->ReceivedCapabilitiesSize))
935 return FALSE;
936
937 for (UINT32 x = 0; x < src->ReceivedCapabilitiesSize; x++)
938 {
939 WINPR_ASSERT(settings->ReceivedCapabilities);
940 settings->ReceivedCapabilities[x] = src->ReceivedCapabilities[x];
941
942 WINPR_ASSERT(settings->ReceivedCapabilityDataSizes);
943 settings->ReceivedCapabilityDataSizes[x] = src->ReceivedCapabilityDataSizes[x];
944
945 WINPR_ASSERT(settings->ReceivedCapabilityData);
946 if (src->ReceivedCapabilityDataSizes[x] > 0)
947 {
948 void* tmp = realloc(settings->ReceivedCapabilityData[x],
949 settings->ReceivedCapabilityDataSizes[x]);
950 if (!tmp)
951 return FALSE;
952 memcpy(tmp, src->ReceivedCapabilityData[x], src->ReceivedCapabilityDataSizes[x]);
953 settings->ReceivedCapabilityData[x] = tmp;
954 }
955 else
956 {
957 free(settings->ReceivedCapabilityData[x]);
958 settings->ReceivedCapabilityData[x] = NULL;
959 }
960 }
961 return TRUE;
962}
963
964static void target_net_addresses_free(rdpSettings* settings, size_t offset)
965{
966 WINPR_ASSERT(settings);
967
968 if (settings->TargetNetAddresses)
969 {
970 for (size_t index = offset; index < settings->TargetNetAddressCount; index++)
971 {
972 free(settings->TargetNetAddresses[index]);
973 settings->TargetNetAddresses[index] = NULL;
974 }
975 }
976}
977
978void freerdp_target_net_addresses_free(rdpSettings* settings)
979{
980 WINPR_ASSERT(settings);
981
982 target_net_addresses_free(settings, 0);
983
984 free((void*)settings->TargetNetAddresses);
985 settings->TargetNetAddresses = NULL;
986
987 free(settings->TargetNetPorts);
988 settings->TargetNetPorts = NULL;
989
990 settings->TargetNetAddressCount = 0;
991}
992
993BOOL freerdp_target_net_addresses_resize(rdpSettings* settings, size_t count)
994{
995 WINPR_ASSERT(settings);
996
997 if (count == 0)
998 {
999 freerdp_target_net_addresses_free(settings);
1000 return TRUE;
1001 }
1002
1003 const uint32_t len = settings->TargetNetAddressCount;
1004 size_t offset = 0;
1005 if (len > count)
1006 offset = count;
1007
1008 target_net_addresses_free(settings, offset);
1009
1010 if (!resize_setting(settings, FreeRDP_TargetNetAddresses, len, count, sizeof(char*)))
1011 return FALSE;
1012 if (!resize_setting(settings, FreeRDP_TargetNetPorts, len, count, sizeof(uint32_t)))
1013 return FALSE;
1014
1015 settings->TargetNetAddressCount = WINPR_ASSERTING_INT_CAST(uint32_t, count);
1016 return TRUE;
1017}
1018
1019void freerdp_server_license_issuers_free(rdpSettings* settings)
1020{
1021 WINPR_ASSERT(settings);
1022
1023 if (settings->ServerLicenseProductIssuers)
1024 {
1025 for (UINT32 x = 0; x < settings->ServerLicenseProductIssuersCount; x++)
1026 free(settings->ServerLicenseProductIssuers[x]);
1027 }
1028 free((void*)settings->ServerLicenseProductIssuers);
1029 settings->ServerLicenseProductIssuers = NULL;
1030 settings->ServerLicenseProductIssuersCount = 0;
1031}
1032
1033BOOL freerdp_server_license_issuers_copy(rdpSettings* settings, char** issuers, UINT32 count)
1034{
1035 WINPR_ASSERT(settings);
1036 WINPR_ASSERT(issuers || (count == 0));
1037
1038 if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ServerLicenseProductIssuers, NULL,
1039 count))
1040 return FALSE;
1041
1042 for (UINT32 x = 0; x < count; x++)
1043 {
1044 char* issuer = _strdup(issuers[x]);
1045 if (!issuer)
1046 return FALSE;
1047 settings->ServerLicenseProductIssuers[x] = issuer;
1048 }
1049
1050 return TRUE;
1051}
1052
1053void freerdp_performance_flags_make(rdpSettings* settings)
1054{
1055 UINT32 PerformanceFlags = PERF_FLAG_NONE;
1056
1057 if (freerdp_settings_get_bool(settings, FreeRDP_AllowFontSmoothing))
1058 PerformanceFlags |= PERF_ENABLE_FONT_SMOOTHING;
1059
1060 if (freerdp_settings_get_bool(settings, FreeRDP_AllowDesktopComposition))
1061 PerformanceFlags |= PERF_ENABLE_DESKTOP_COMPOSITION;
1062
1063 if (freerdp_settings_get_bool(settings, FreeRDP_DisableWallpaper))
1064 PerformanceFlags |= PERF_DISABLE_WALLPAPER;
1065
1066 if (freerdp_settings_get_bool(settings, FreeRDP_DisableFullWindowDrag))
1067 PerformanceFlags |= PERF_DISABLE_FULLWINDOWDRAG;
1068
1069 if (freerdp_settings_get_bool(settings, FreeRDP_DisableMenuAnims))
1070 PerformanceFlags |= PERF_DISABLE_MENUANIMATIONS;
1071
1072 if (freerdp_settings_get_bool(settings, FreeRDP_DisableThemes))
1073 PerformanceFlags |= PERF_DISABLE_THEMING;
1074 (void)freerdp_settings_set_uint32(settings, FreeRDP_PerformanceFlags, PerformanceFlags);
1075}
1076
1077void freerdp_performance_flags_split(rdpSettings* settings)
1078{
1080 settings, FreeRDP_AllowFontSmoothing,
1081 (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) &
1082 PERF_ENABLE_FONT_SMOOTHING)
1083 ? TRUE
1084 : FALSE);
1086 settings, FreeRDP_AllowDesktopComposition,
1087 (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) &
1088 PERF_ENABLE_DESKTOP_COMPOSITION)
1089 ? TRUE
1090 : FALSE);
1092 settings, FreeRDP_DisableWallpaper,
1093 (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) & PERF_DISABLE_WALLPAPER)
1094 ? TRUE
1095 : FALSE);
1097 settings, FreeRDP_DisableFullWindowDrag,
1098 (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) &
1099 PERF_DISABLE_FULLWINDOWDRAG)
1100 ? TRUE
1101 : FALSE);
1103 settings, FreeRDP_DisableMenuAnims,
1104 (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) &
1105 PERF_DISABLE_MENUANIMATIONS)
1106 ? TRUE
1107 : FALSE);
1109 settings, FreeRDP_DisableThemes,
1110 (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) & PERF_DISABLE_THEMING)
1111 ? TRUE
1112 : FALSE);
1113}
1114
1115BOOL freerdp_set_gateway_usage_method(rdpSettings* settings, UINT32 GatewayUsageMethod)
1116{
1117 if (!freerdp_settings_set_uint32(settings, FreeRDP_GatewayUsageMethod, GatewayUsageMethod))
1118 return FALSE;
1119
1120 if (GatewayUsageMethod == TSC_PROXY_MODE_NONE_DIRECT)
1121 {
1122 if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, FALSE) ||
1123 !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE))
1124 return FALSE;
1125 }
1126 else if (GatewayUsageMethod == TSC_PROXY_MODE_DIRECT)
1127 {
1128 if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, TRUE) ||
1129 !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE))
1130 return FALSE;
1131 }
1132 else if (GatewayUsageMethod == TSC_PROXY_MODE_DETECT)
1133 {
1134 if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, TRUE) ||
1135 !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, TRUE))
1136 return FALSE;
1137 }
1138 else if (GatewayUsageMethod == TSC_PROXY_MODE_DEFAULT)
1139 {
1145 if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, FALSE) ||
1146 !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE))
1147 return FALSE;
1148 }
1149 else if (GatewayUsageMethod == TSC_PROXY_MODE_NONE_DETECT)
1150 {
1151 if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, FALSE) ||
1152 !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE))
1153 return FALSE;
1154 }
1155
1156 return TRUE;
1157}
1158
1159void freerdp_update_gateway_usage_method(rdpSettings* settings, UINT32 GatewayEnabled,
1160 UINT32 GatewayBypassLocal)
1161{
1162 UINT32 GatewayUsageMethod = 0;
1163
1164 if (!GatewayEnabled && !GatewayBypassLocal)
1165 GatewayUsageMethod = TSC_PROXY_MODE_NONE_DIRECT;
1166 else if (GatewayEnabled && !GatewayBypassLocal)
1167 GatewayUsageMethod = TSC_PROXY_MODE_DIRECT;
1168 else if (GatewayEnabled && GatewayBypassLocal)
1169 GatewayUsageMethod = TSC_PROXY_MODE_DETECT;
1170
1171 freerdp_set_gateway_usage_method(settings, GatewayUsageMethod);
1172}
1173
1174#if defined(WITH_FREERDP_DEPRECATED)
1175BOOL freerdp_get_param_bool(const rdpSettings* settings, int id)
1176{
1177 return freerdp_settings_get_bool(settings, (FreeRDP_Settings_Keys_Bool)id);
1178}
1179
1180int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param)
1181{
1182 return freerdp_settings_set_bool(settings, (FreeRDP_Settings_Keys_Bool)id, param) ? 0 : -1;
1183}
1184
1185int freerdp_get_param_int(const rdpSettings* settings, int id)
1186{
1187 return freerdp_settings_get_int32(settings, (FreeRDP_Settings_Keys_Int32)id);
1188}
1189
1190int freerdp_set_param_int(rdpSettings* settings, int id, int param)
1191{
1192 return freerdp_settings_set_int32(settings, (FreeRDP_Settings_Keys_Int32)id, param) ? 0 : -1;
1193}
1194
1195UINT32 freerdp_get_param_uint32(const rdpSettings* settings, int id)
1196{
1197 return freerdp_settings_get_uint32(settings, (FreeRDP_Settings_Keys_UInt32)id);
1198}
1199
1200int freerdp_set_param_uint32(rdpSettings* settings, int id, UINT32 param)
1201{
1202 return freerdp_settings_set_uint32(settings, (FreeRDP_Settings_Keys_UInt32)id, param) ? 0 : -1;
1203}
1204
1205UINT64 freerdp_get_param_uint64(const rdpSettings* settings, int id)
1206{
1207 return freerdp_settings_get_uint64(settings, (FreeRDP_Settings_Keys_UInt64)id);
1208}
1209
1210int freerdp_set_param_uint64(rdpSettings* settings, int id, UINT64 param)
1211{
1212 return freerdp_settings_set_uint64(settings, (FreeRDP_Settings_Keys_UInt64)id, param) ? 0 : -1;
1213}
1214
1215char* freerdp_get_param_string(const rdpSettings* settings, int id)
1216{
1217 const char* str = freerdp_settings_get_string(settings, (FreeRDP_Settings_Keys_String)id);
1218 return WINPR_CAST_CONST_PTR_AWAY(str, char*);
1219}
1220
1221int freerdp_set_param_string(rdpSettings* settings, int id, const char* param)
1222{
1223 return freerdp_settings_set_string(settings, (FreeRDP_Settings_Keys_String)id, param) ? 0 : -1;
1224}
1225#endif
1226
1227static BOOL value_to_uint(const char* value, ULONGLONG* result, ULONGLONG min, ULONGLONG max)
1228{
1229 char* endptr = NULL;
1230 unsigned long long rc = 0;
1231
1232 if (!value || !result)
1233 return FALSE;
1234
1235 errno = 0;
1236 rc = _strtoui64(value, &endptr, 0);
1237
1238 if (errno != 0)
1239 return FALSE;
1240
1241 if (endptr == value)
1242 return FALSE;
1243
1244 if ((rc < min) || (rc > max))
1245 return FALSE;
1246
1247 *result = rc;
1248 return TRUE;
1249}
1250
1251static BOOL value_to_int(const char* value, LONGLONG* result, LONGLONG min, LONGLONG max)
1252{
1253 char* endptr = NULL;
1254 long long rc = 0;
1255
1256 if (!value || !result)
1257 return FALSE;
1258
1259 errno = 0;
1260 rc = _strtoi64(value, &endptr, 0);
1261
1262 if (errno != 0)
1263 return FALSE;
1264
1265 if (endptr == value)
1266 return FALSE;
1267
1268 if ((rc < min) || (rc > max))
1269 return FALSE;
1270
1271 *result = rc;
1272 return TRUE;
1273}
1274
1275static BOOL parsing_fail(const char* key, const char* type, const char* value)
1276{
1277 WLog_ERR(TAG, "Failed to parse key [%s] of type [%s]: value [%s]", key, type, value);
1278 return FALSE;
1279}
1280
1281BOOL freerdp_settings_set_value_for_name(rdpSettings* settings, const char* name, const char* value)
1282{
1283 ULONGLONG uval = 0;
1284 LONGLONG ival = 0;
1285 SSIZE_T type = 0;
1286
1287 if (!settings || !name)
1288 return FALSE;
1289
1290 const SSIZE_T i = freerdp_settings_get_key_for_name(name);
1291 if (i < 0)
1292 {
1293 WLog_ERR(TAG, "Invalid settings key [%s]", name);
1294 return FALSE;
1295 }
1296
1297 const SSIZE_T index = i;
1298
1300 switch (type)
1301 {
1302
1303 case RDP_SETTINGS_TYPE_BOOL:
1304 {
1305 const BOOL val = (_strnicmp(value, "TRUE", 5) == 0) || (_strnicmp(value, "ON", 5) == 0);
1306 const BOOL nval =
1307 (_strnicmp(value, "FALSE", 6) == 0) || (_strnicmp(value, "OFF", 6) == 0);
1308 if (!val && !nval)
1309 return parsing_fail(name, "BOOL", value);
1310
1311 // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1312 return freerdp_settings_set_bool(settings, (FreeRDP_Settings_Keys_Bool)index, val);
1313 }
1314 case RDP_SETTINGS_TYPE_UINT16:
1315 if (!value_to_uint(value, &uval, 0, UINT16_MAX))
1316 return parsing_fail(name, "UINT16", value);
1317
1318 // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1319 if (!freerdp_settings_set_uint16(settings, (FreeRDP_Settings_Keys_UInt16)index,
1320 (UINT16)uval))
1321 return parsing_fail(name, "UINT16", value);
1322 return TRUE;
1323
1324 case RDP_SETTINGS_TYPE_INT16:
1325 if (!value_to_int(value, &ival, INT16_MIN, INT16_MAX))
1326 return parsing_fail(name, "INT16", value);
1327
1328 // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1329 if (!freerdp_settings_set_int16(settings, (FreeRDP_Settings_Keys_Int16)index,
1330 (INT16)ival))
1331 return parsing_fail(name, "INT16", value);
1332 return TRUE;
1333 case RDP_SETTINGS_TYPE_UINT32:
1334 if (!value_to_uint(value, &uval, 0, UINT32_MAX))
1335 return parsing_fail(name, "UINT32", value);
1336
1337 // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1338 if (!freerdp_settings_set_uint32(settings, (FreeRDP_Settings_Keys_UInt32)index,
1339 (UINT32)uval))
1340 return parsing_fail(name, "UINT32", value);
1341 return TRUE;
1342 case RDP_SETTINGS_TYPE_INT32:
1343 if (!value_to_int(value, &ival, INT32_MIN, INT32_MAX))
1344 return parsing_fail(name, "INT32", value);
1345
1346 // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1347 if (!freerdp_settings_set_int32(settings, (FreeRDP_Settings_Keys_Int32)index,
1348 (INT32)ival))
1349 return parsing_fail(name, "INT32", value);
1350 return TRUE;
1351 case RDP_SETTINGS_TYPE_UINT64:
1352 if (!value_to_uint(value, &uval, 0, UINT64_MAX))
1353 return parsing_fail(name, "UINT64", value);
1354
1355 // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1356 if (!freerdp_settings_set_uint64(settings, (FreeRDP_Settings_Keys_UInt64)index, uval))
1357 return parsing_fail(name, "UINT64", value);
1358 return TRUE;
1359 case RDP_SETTINGS_TYPE_INT64:
1360 if (!value_to_int(value, &ival, INT64_MIN, INT64_MAX))
1361 return parsing_fail(name, "INT64", value);
1362
1363 // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1364 if (!freerdp_settings_set_int64(settings, (FreeRDP_Settings_Keys_Int64)index, ival))
1365 return parsing_fail(name, "INT64", value);
1366 return TRUE;
1367
1368 case RDP_SETTINGS_TYPE_STRING:
1369 // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
1370 return freerdp_settings_set_string(settings, (FreeRDP_Settings_Keys_String)index,
1371 value);
1372 case RDP_SETTINGS_TYPE_POINTER:
1373 return parsing_fail(name, "POINTER", value);
1374 default:
1375 return FALSE;
1376 }
1377 return FALSE;
1378}
1379
1380BOOL freerdp_settings_set_pointer_len_(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
1381 FreeRDP_Settings_Keys_UInt32 lenId, const void* data,
1382 size_t len, size_t size)
1383{
1384 BOOL rc = FALSE;
1385 void* copy = NULL;
1386 void* old = freerdp_settings_get_pointer_writable(settings, id);
1387 free(old);
1388 if (!freerdp_settings_set_pointer(settings, id, NULL))
1389 return FALSE;
1390 if (lenId != FreeRDP_UINT32_UNUSED)
1391 {
1392 if (!freerdp_settings_set_uint32(settings, lenId, 0))
1393 return FALSE;
1394 }
1395
1396 if (len > UINT32_MAX)
1397 return FALSE;
1398 if (len == 0)
1399 return TRUE;
1400 copy = calloc(len, size);
1401 if (!copy)
1402 return FALSE;
1403 if (data)
1404 memcpy(copy, data, len * size);
1405 rc = freerdp_settings_set_pointer(settings, id, copy);
1406 if (!rc)
1407 {
1408 free(copy);
1409 return FALSE;
1410 }
1411
1412 // freerdp_settings_set_pointer takes ownership of copy
1413 // NOLINTNEXTLINE(clang-analyzer-unix.Malloc)
1414 if (lenId == FreeRDP_UINT32_UNUSED)
1415 return TRUE;
1416 return freerdp_settings_set_uint32(settings, lenId, (UINT32)len);
1417}
1418
1419const void* freerdp_settings_get_pointer(const rdpSettings* settings,
1420 FreeRDP_Settings_Keys_Pointer id)
1421{
1422 union
1423 {
1424 const rdpSettings* pc;
1425 rdpSettings* p;
1426 } cnv;
1427 cnv.pc = settings;
1428 return freerdp_settings_get_pointer_writable(cnv.p, id);
1429}
1430
1431BOOL freerdp_settings_set_pointer_len(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
1432 const void* data, size_t len)
1433{
1434 union
1435 {
1436 const void* cv;
1437 void* v;
1438 } cnv;
1439
1440 cnv.cv = data;
1441 if (!settings)
1442 return FALSE;
1443
1444 switch (id)
1445 {
1446 case FreeRDP_RdpServerCertificate:
1447 freerdp_certificate_free(settings->RdpServerCertificate);
1448
1449 if (len > 1)
1450 {
1451 WLog_ERR(TAG, "FreeRDP_RdpServerCertificate::len must be 0 or 1");
1452 return FALSE;
1453 }
1454 settings->RdpServerCertificate = cnv.v;
1455 if (!settings->RdpServerCertificate && (len > 0))
1456 {
1457 settings->RdpServerCertificate = freerdp_certificate_new();
1458 if (!settings->RdpServerCertificate)
1459 return FALSE;
1460 }
1461 return TRUE;
1462 case FreeRDP_RdpServerRsaKey:
1463 freerdp_key_free(settings->RdpServerRsaKey);
1464 if (len > 1)
1465 {
1466 WLog_ERR(TAG, "FreeRDP_RdpServerRsaKey::len must be 0 or 1");
1467 return FALSE;
1468 }
1469 settings->RdpServerRsaKey = (rdpPrivateKey*)cnv.v;
1470 if (!settings->RdpServerRsaKey && (len > 0))
1471 {
1472 settings->RdpServerRsaKey = freerdp_key_new();
1473 if (!settings->RdpServerRsaKey)
1474 return FALSE;
1475 }
1476 return TRUE;
1477 case FreeRDP_RedirectionPassword:
1478 return freerdp_settings_set_pointer_len_(
1479 settings, id, FreeRDP_RedirectionPasswordLength, data, len, sizeof(char));
1480 case FreeRDP_RedirectionTsvUrl:
1481 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_RedirectionTsvUrlLength,
1482 data, len, sizeof(char));
1483 case FreeRDP_RedirectionTargetCertificate:
1484 freerdp_certificate_free(settings->RedirectionTargetCertificate);
1485
1486 if (len > 1)
1487 {
1488 WLog_ERR(TAG, "FreeRDP_RedirectionTargetCertificate::len must be 0 or 1");
1489 return FALSE;
1490 }
1491 settings->RedirectionTargetCertificate = cnv.v;
1492 if (!settings->RedirectionTargetCertificate && (len > 0))
1493 {
1494 settings->RedirectionTargetCertificate = freerdp_certificate_new();
1495 if (!settings->RedirectionTargetCertificate)
1496 return FALSE;
1497 }
1498 return TRUE;
1499 case FreeRDP_RedirectionGuid:
1500 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_RedirectionGuidLength,
1501 data, len, sizeof(BYTE));
1502 case FreeRDP_LoadBalanceInfo:
1503 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_LoadBalanceInfoLength,
1504 data, len, sizeof(char));
1505 case FreeRDP_ServerRandom:
1506 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ServerRandomLength, data,
1507 len, sizeof(char));
1508 case FreeRDP_ClientRandom:
1509 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ClientRandomLength, data,
1510 len, sizeof(char));
1511 case FreeRDP_ServerCertificate:
1512 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ServerCertificateLength,
1513 data, len, sizeof(char));
1514 case FreeRDP_TargetNetAddresses:
1515 if (!freerdp_target_net_addresses_resize(settings, len))
1516 return FALSE;
1517 if (data == NULL)
1518 target_net_addresses_free(settings, 0);
1519 return TRUE;
1520 case FreeRDP_ServerLicenseProductIssuers:
1521 if (data == NULL)
1522 freerdp_server_license_issuers_free(settings);
1523 return freerdp_settings_set_pointer_len_(
1524 settings, id, FreeRDP_ServerLicenseProductIssuersCount, data, len, sizeof(char*));
1525 case FreeRDP_TargetNetPorts:
1526 if (!freerdp_target_net_addresses_resize(settings, len))
1527 return FALSE;
1528 if (data == NULL)
1529 {
1530 for (size_t x = 0; x < len; x++)
1531 settings->TargetNetPorts[x] = 0;
1532 }
1533 return TRUE;
1534 case FreeRDP_DeviceArray:
1535 if (data == NULL)
1536 freerdp_device_collection_free(settings);
1537 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_DeviceArraySize, data,
1538 len, sizeof(RDPDR_DEVICE*));
1539 case FreeRDP_ChannelDefArray:
1540 if ((len > 0) && (len < CHANNEL_MAX_COUNT))
1541 WLog_WARN(TAG,
1542 "FreeRDP_ChannelDefArray::len expected to be >= %" PRIu32
1543 ", but have %" PRIu32,
1544 CHANNEL_MAX_COUNT, len);
1545 return freerdp_settings_set_pointer_len_(settings, FreeRDP_ChannelDefArray,
1546 FreeRDP_ChannelDefArraySize, data, len,
1547 sizeof(CHANNEL_DEF));
1548 case FreeRDP_MonitorDefArray:
1549 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_MonitorDefArraySize,
1550 data, len, sizeof(rdpMonitor));
1551 case FreeRDP_ClientAutoReconnectCookie:
1552 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_UINT32_UNUSED, data, len,
1553 sizeof(ARC_CS_PRIVATE_PACKET));
1554 case FreeRDP_ServerAutoReconnectCookie:
1555 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_UINT32_UNUSED, data, len,
1556 sizeof(ARC_SC_PRIVATE_PACKET));
1557 case FreeRDP_ClientTimeZone:
1558 if (len > 1)
1559 {
1560 WLog_ERR(TAG, "FreeRDP_ClientTimeZone::len must be 0 or 1");
1561 return FALSE;
1562 }
1563 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_UINT32_UNUSED, data, len,
1564 sizeof(TIME_ZONE_INFORMATION));
1565 case FreeRDP_BitmapCacheV2CellInfo:
1566 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_BitmapCacheV2NumCells,
1567 data, len, sizeof(BITMAP_CACHE_V2_CELL_INFO));
1568 case FreeRDP_GlyphCache:
1569 if ((len != 0) && (len != 10))
1570 {
1571 WLog_ERR(TAG, "FreeRDP_GlyphCache::len must be 0 or 10");
1572 return FALSE;
1573 }
1574 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_UINT32_UNUSED, data, len,
1575 sizeof(GLYPH_CACHE_DEFINITION));
1576 case FreeRDP_FragCache:
1577 if (len > 1)
1578 {
1579 WLog_ERR(TAG, "FreeRDP_FragCache::len must be 0 or 1");
1580 return FALSE;
1581 }
1582 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_UINT32_UNUSED, data, len,
1583 sizeof(GLYPH_CACHE_DEFINITION));
1584 case FreeRDP_StaticChannelArray:
1585 if (data == NULL)
1586 freerdp_static_channel_collection_free(settings);
1587 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_StaticChannelArraySize,
1588 data, len, sizeof(ADDIN_ARGV*));
1589 case FreeRDP_DynamicChannelArray:
1590 if (data == NULL)
1591 freerdp_dynamic_channel_collection_free(settings);
1592 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_DynamicChannelArraySize,
1593 data, len, sizeof(ADDIN_ARGV*));
1594 case FreeRDP_ReceivedCapabilityData:
1595 if (!freerdp_capability_buffer_resize(settings, len))
1596 return FALSE;
1597 if (data == NULL)
1598 {
1599 freerdp_capability_data_free(settings, 0, FALSE);
1600 }
1601 return TRUE;
1602 case FreeRDP_ReceivedCapabilities:
1603 if (!freerdp_capability_buffer_resize(settings, len))
1604 return FALSE;
1605 if (data == NULL)
1606 {
1607 for (size_t x = 0; x < settings->ReceivedCapabilitiesSize; x++)
1608 {
1609 settings->ReceivedCapabilities[x] = 0;
1610 }
1611 }
1612 return TRUE;
1613 case FreeRDP_OrderSupport:
1614 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_UINT32_UNUSED, data, len,
1615 sizeof(char));
1616
1617 case FreeRDP_MonitorIds:
1618 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_NumMonitorIds, data, len,
1619 sizeof(UINT32));
1620
1621 case FreeRDP_ReceivedCapabilityDataSizes:
1622 if (!freerdp_capability_buffer_resize(settings, len))
1623 return FALSE;
1624 if (data == NULL)
1625 {
1626 for (size_t x = 0; x < settings->ReceivedCapabilitiesSize; x++)
1627 settings->ReceivedCapabilityDataSizes[x] = 0;
1628 }
1629 return TRUE;
1630
1631 case FreeRDP_Password51:
1632 return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_Password51Length, data,
1633 len, sizeof(char));
1634 default:
1635 if ((data == NULL) && (len == 0))
1636 {
1637 freerdp_settings_set_pointer(settings, id, NULL);
1638 }
1639 else
1640 WLog_WARN(TAG, "Invalid id %" PRIuz, id);
1641 return FALSE;
1642 }
1643}
1644
1645void* freerdp_settings_get_pointer_array_writable(const rdpSettings* settings,
1646 FreeRDP_Settings_Keys_Pointer id, size_t offset)
1647{
1648 size_t max = 0;
1649 if (!settings)
1650 return NULL;
1651 switch (id)
1652 {
1653 case FreeRDP_ClientAutoReconnectCookie:
1654 max = 1;
1655 if ((offset >= max) || !settings->ClientAutoReconnectCookie)
1656 goto fail;
1657 return &settings->ClientAutoReconnectCookie[offset];
1658 case FreeRDP_ServerAutoReconnectCookie:
1659 max = 1;
1660 if ((offset >= max) || !settings->ServerAutoReconnectCookie)
1661 goto fail;
1662 return &settings->ServerAutoReconnectCookie[offset];
1663 case FreeRDP_ServerCertificate:
1664 max = freerdp_settings_get_uint32(settings, FreeRDP_ServerCertificateLength);
1665 if (offset >= max)
1666 goto fail;
1667 return &settings->ServerCertificate[offset];
1668 case FreeRDP_ServerRandom:
1669 max = freerdp_settings_get_uint32(settings, FreeRDP_ServerRandomLength);
1670 if (offset >= max)
1671 goto fail;
1672 return &settings->ServerRandom[offset];
1673 case FreeRDP_ClientRandom:
1674 max = freerdp_settings_get_uint32(settings, FreeRDP_ClientRandomLength);
1675 if (offset >= max)
1676 goto fail;
1677 return &settings->ClientRandom[offset];
1678 case FreeRDP_LoadBalanceInfo:
1679 max = freerdp_settings_get_uint32(settings, FreeRDP_LoadBalanceInfoLength);
1680 if (offset >= max)
1681 goto fail;
1682 return &settings->LoadBalanceInfo[offset];
1683
1684 case FreeRDP_RedirectionTsvUrl:
1685 max = freerdp_settings_get_uint32(settings, FreeRDP_RedirectionTsvUrlLength);
1686 if (offset >= max)
1687 goto fail;
1688 return &settings->RedirectionTsvUrl[offset];
1689
1690 case FreeRDP_RedirectionPassword:
1691 max = freerdp_settings_get_uint32(settings, FreeRDP_RedirectionPasswordLength);
1692 if (offset >= max)
1693 goto fail;
1694 return &settings->RedirectionPassword[offset];
1695
1696 case FreeRDP_OrderSupport:
1697 max = 32;
1698 if (offset >= max)
1699 goto fail;
1700 return &settings->OrderSupport[offset];
1701 case FreeRDP_MonitorIds:
1702 max = freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds);
1703 if (offset >= max)
1704 goto fail;
1705 return &settings->MonitorIds[offset];
1706 case FreeRDP_MonitorDefArray:
1707 max = freerdp_settings_get_uint32(settings, FreeRDP_MonitorDefArraySize);
1708 if (offset >= max)
1709 goto fail;
1710 return &settings->MonitorDefArray[offset];
1711 case FreeRDP_ChannelDefArray:
1712 max = freerdp_settings_get_uint32(settings, FreeRDP_ChannelDefArraySize);
1713 if (offset >= max)
1714 goto fail;
1715 return &settings->ChannelDefArray[offset];
1716 case FreeRDP_DeviceArray:
1717 max = freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize);
1718 if (offset >= max)
1719 goto fail;
1720 return settings->DeviceArray[offset];
1721 case FreeRDP_StaticChannelArray:
1722 max = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
1723 if (offset >= max)
1724 goto fail;
1725 return settings->StaticChannelArray[offset];
1726 case FreeRDP_DynamicChannelArray:
1727 max = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
1728 if (offset >= max)
1729 goto fail;
1730 return settings->DynamicChannelArray[offset];
1731 case FreeRDP_FragCache:
1732 max = 1;
1733 if (offset >= max)
1734 goto fail;
1735 return &settings->FragCache[offset];
1736 case FreeRDP_GlyphCache:
1737 max = 10;
1738 if (offset >= max)
1739 goto fail;
1740 return &settings->GlyphCache[offset];
1741 case FreeRDP_BitmapCacheV2CellInfo:
1742 max = freerdp_settings_get_uint32(settings, FreeRDP_BitmapCacheV2NumCells);
1743 if (offset >= max)
1744 goto fail;
1745 return &settings->BitmapCacheV2CellInfo[offset];
1746 case FreeRDP_ReceivedCapabilities:
1747 max = freerdp_settings_get_uint32(settings, FreeRDP_ReceivedCapabilitiesSize);
1748 if (offset >= max)
1749 goto fail;
1750 return &settings->ReceivedCapabilities[offset];
1751 case FreeRDP_TargetNetAddresses:
1752 max = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
1753 if (offset >= max)
1754 goto fail;
1755 WINPR_ASSERT(settings->TargetNetAddresses);
1756 return settings->TargetNetAddresses[offset];
1757 case FreeRDP_TargetNetPorts:
1758 max = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
1759 if (offset >= max)
1760 goto fail;
1761 WINPR_ASSERT(settings->TargetNetPorts);
1762 return &settings->TargetNetPorts[offset];
1763 case FreeRDP_ClientTimeZone:
1764 max = 1;
1765 if (offset >= max)
1766 goto fail;
1767 return settings->ClientTimeZone;
1768 case FreeRDP_RdpServerCertificate:
1769 max = 1;
1770 if (offset >= max)
1771 goto fail;
1772 return settings->RdpServerCertificate;
1773 case FreeRDP_RdpServerRsaKey:
1774 max = 1;
1775 if (offset >= max)
1776 goto fail;
1777 return settings->RdpServerRsaKey;
1778 case FreeRDP_ServerLicenseProductIssuers:
1779 max = freerdp_settings_get_uint32(settings, FreeRDP_ServerLicenseProductIssuersCount);
1780 if (offset >= max)
1781 goto fail;
1782 return settings->ServerLicenseProductIssuers[offset];
1783 case FreeRDP_ReceivedCapabilityData:
1784 max = freerdp_settings_get_uint32(settings, FreeRDP_ReceivedCapabilitiesSize);
1785 if (offset >= max)
1786 goto fail;
1787 WINPR_ASSERT(settings->ReceivedCapabilityData);
1788 return settings->ReceivedCapabilityData[offset];
1789
1790 case FreeRDP_ReceivedCapabilityDataSizes:
1791 max = freerdp_settings_get_uint32(settings, FreeRDP_ReceivedCapabilitiesSize);
1792 if (offset >= max)
1793 goto fail;
1794 WINPR_ASSERT(settings->ReceivedCapabilityDataSizes);
1795 return &settings->ReceivedCapabilityDataSizes[offset];
1796 default:
1797 WLog_WARN(TAG, "Invalid id %s [%" PRIuz "]", freerdp_settings_get_name_for_key(id), id);
1798 return NULL;
1799 }
1800
1801fail:
1802 WLog_WARN(TAG, "Invalid offset for %s [%" PRIuz "]: size=%" PRIuz ", offset=%" PRIuz,
1803 freerdp_settings_get_name_for_key(id), id, max, offset);
1804 return NULL;
1805}
1806
1807BOOL freerdp_settings_set_pointer_array(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
1808 size_t offset, const void* data)
1809{
1810 size_t maxOffset = 0;
1811 if (!settings)
1812 return FALSE;
1813 switch (id)
1814 {
1815 case FreeRDP_ClientAutoReconnectCookie:
1816 maxOffset = 1;
1817 if ((offset >= maxOffset) || !data || !settings->ClientAutoReconnectCookie)
1818 goto fail;
1819 settings->ClientAutoReconnectCookie[offset] = *(const ARC_CS_PRIVATE_PACKET*)data;
1820 return TRUE;
1821 case FreeRDP_ServerAutoReconnectCookie:
1822 maxOffset = 1;
1823 if ((offset >= maxOffset) || !data || !settings->ServerAutoReconnectCookie)
1824 goto fail;
1825 settings->ServerAutoReconnectCookie[offset] = *(const ARC_SC_PRIVATE_PACKET*)data;
1826 return TRUE;
1827 case FreeRDP_ServerCertificate:
1828 maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ServerCertificateLength);
1829 if ((offset >= maxOffset) || !data)
1830 goto fail;
1831 settings->ServerCertificate[offset] = *(const BYTE*)data;
1832 return TRUE;
1833 case FreeRDP_DeviceArray:
1834 maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize);
1835 if (offset >= maxOffset)
1836 goto fail;
1837 freerdp_device_free(settings->DeviceArray[offset]);
1838 settings->DeviceArray[offset] = freerdp_device_clone(data);
1839 return TRUE;
1840 case FreeRDP_TargetNetAddresses:
1841 maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
1842 if ((offset >= maxOffset) || !data)
1843 goto fail;
1844 WINPR_ASSERT(settings->TargetNetAddresses);
1845 free(settings->TargetNetAddresses[offset]);
1846 settings->TargetNetAddresses[offset] = _strdup((const char*)data);
1847 return settings->TargetNetAddresses[offset] != NULL;
1848 case FreeRDP_TargetNetPorts:
1849 maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
1850 if ((offset >= maxOffset) || !data)
1851 goto fail;
1852 WINPR_ASSERT(settings->TargetNetPorts);
1853 settings->TargetNetPorts[offset] = *((const UINT32*)data);
1854 return TRUE;
1855 case FreeRDP_StaticChannelArray:
1856 maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
1857 if ((offset >= maxOffset) || !data)
1858 goto fail;
1859 freerdp_addin_argv_free(settings->StaticChannelArray[offset]);
1860 settings->StaticChannelArray[offset] = freerdp_addin_argv_clone(data);
1861 return TRUE;
1862 case FreeRDP_DynamicChannelArray:
1863 maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
1864 if ((offset >= maxOffset) || !data)
1865 goto fail;
1866 freerdp_addin_argv_free(settings->DynamicChannelArray[offset]);
1867 settings->DynamicChannelArray[offset] = freerdp_addin_argv_clone(data);
1868 return TRUE;
1869 case FreeRDP_BitmapCacheV2CellInfo:
1870 maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_BitmapCacheV2NumCells);
1871 if ((offset >= maxOffset) || !data)
1872 goto fail;
1873 {
1874 const BITMAP_CACHE_V2_CELL_INFO* cdata = (const BITMAP_CACHE_V2_CELL_INFO*)data;
1875 settings->BitmapCacheV2CellInfo[offset] = *cdata;
1876 }
1877 return TRUE;
1878 case FreeRDP_ServerRandom:
1879 maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ServerRandomLength);
1880 if ((offset >= maxOffset) || !data)
1881 goto fail;
1882 settings->ServerRandom[offset] = *(const BYTE*)data;
1883 return TRUE;
1884 case FreeRDP_ClientRandom:
1885 maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ClientRandomLength);
1886 if ((offset >= maxOffset) || !data)
1887 goto fail;
1888 settings->ClientRandom[offset] = *(const BYTE*)data;
1889 return TRUE;
1890 case FreeRDP_LoadBalanceInfo:
1891 maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_LoadBalanceInfoLength);
1892 if ((offset >= maxOffset) || !data)
1893 goto fail;
1894 settings->LoadBalanceInfo[offset] = *(const BYTE*)data;
1895 return TRUE;
1896 case FreeRDP_RedirectionTsvUrl:
1897 maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_RedirectionTsvUrlLength);
1898 if ((offset >= maxOffset) || !data)
1899 goto fail;
1900 settings->RedirectionTsvUrl[offset] = *(const BYTE*)data;
1901 return TRUE;
1902 case FreeRDP_RedirectionPassword:
1903 maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_RedirectionPasswordLength);
1904 if ((offset >= maxOffset) || !data)
1905 goto fail;
1906 settings->RedirectionPassword[offset] = *(const BYTE*)data;
1907 return TRUE;
1908 case FreeRDP_OrderSupport:
1909 maxOffset = 32;
1910 if (!settings->OrderSupport)
1911 goto fail;
1912 if ((offset >= maxOffset) || !data)
1913 goto fail;
1914 settings->OrderSupport[offset] = *(const BOOL*)data ? 1 : 0;
1915 return TRUE;
1916 case FreeRDP_GlyphCache:
1917 maxOffset = 10;
1918 if (!settings->GlyphCache)
1919 goto fail;
1920 if ((offset >= maxOffset) || !data)
1921 goto fail;
1922 settings->GlyphCache[offset] = *(const GLYPH_CACHE_DEFINITION*)data;
1923 return TRUE;
1924 case FreeRDP_FragCache:
1925 maxOffset = 1;
1926 if (!settings->FragCache)
1927 goto fail;
1928 if ((offset >= maxOffset) || !data)
1929 goto fail;
1930 settings->FragCache[offset] = *(const GLYPH_CACHE_DEFINITION*)data;
1931 return TRUE;
1932 case FreeRDP_MonitorIds:
1933 maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds);
1934 if ((offset >= maxOffset) || !data)
1935 goto fail;
1936 settings->MonitorIds[offset] = *(const UINT32*)data;
1937 return TRUE;
1938 case FreeRDP_ChannelDefArray:
1939 maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ChannelDefArraySize);
1940 if ((offset >= maxOffset) || !data)
1941 goto fail;
1942 settings->ChannelDefArray[offset] = *(const CHANNEL_DEF*)data;
1943 return TRUE;
1944 case FreeRDP_MonitorDefArray:
1945 maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_MonitorDefArraySize);
1946 if ((offset >= maxOffset) || !data)
1947 goto fail;
1948 settings->MonitorDefArray[offset] = *(const rdpMonitor*)data;
1949 return TRUE;
1950
1951 case FreeRDP_ClientTimeZone:
1952 maxOffset = 1;
1953 if ((offset >= maxOffset) || !data || !settings->ClientTimeZone)
1954 goto fail;
1955 settings->ClientTimeZone[offset] = *(const TIME_ZONE_INFORMATION*)data;
1956 return TRUE;
1957
1958 case FreeRDP_ServerLicenseProductIssuers:
1959 maxOffset =
1960 freerdp_settings_get_uint32(settings, FreeRDP_ServerLicenseProductIssuersCount);
1961 if ((offset >= maxOffset) || !settings->ServerLicenseProductIssuers)
1962 goto fail;
1963 free(settings->ServerLicenseProductIssuers[offset]);
1964 settings->ServerLicenseProductIssuers[offset] = NULL;
1965 if (data)
1966 settings->ServerLicenseProductIssuers[offset] = _strdup((const char*)data);
1967 return TRUE;
1968
1969 case FreeRDP_ReceivedCapabilityData:
1970 maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ReceivedCapabilitiesSize);
1971 if (offset >= maxOffset)
1972 goto fail;
1973 WINPR_ASSERT(settings->ReceivedCapabilityData);
1974 settings->ReceivedCapabilityData[offset] = WINPR_CAST_CONST_PTR_AWAY(data, BYTE*);
1975 return TRUE;
1976 case FreeRDP_ReceivedCapabilityDataSizes:
1977 maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ReceivedCapabilitiesSize);
1978 if (offset >= maxOffset)
1979 goto fail;
1980 WINPR_ASSERT(settings->ReceivedCapabilityDataSizes);
1981 settings->ReceivedCapabilityDataSizes[offset] = *(const uint32_t*)data;
1982 return TRUE;
1983 default:
1984 WLog_WARN(TAG, "Invalid id %s [%" PRIuz "]", freerdp_settings_get_name_for_key(id), id);
1985 return FALSE;
1986 }
1987
1988fail:
1989 WLog_WARN(TAG, "[%s] Invalid offset=%" PRIuz " [%" PRIuz "] or NULL data=%p",
1990 freerdp_settings_get_name_for_key(id), offset, maxOffset, data);
1991 return FALSE;
1992}
1993
1994const void* freerdp_settings_get_pointer_array(const rdpSettings* settings,
1995 FreeRDP_Settings_Keys_Pointer id, size_t offset)
1996{
1997 return freerdp_settings_get_pointer_array_writable(settings, id, offset);
1998}
1999
2000UINT32 freerdp_settings_get_codecs_flags(const rdpSettings* settings)
2001{
2002 UINT32 flags = FREERDP_CODEC_ALL;
2003 if (settings->RemoteFxCodec == FALSE)
2004 {
2005 flags &= (uint32_t)~FREERDP_CODEC_REMOTEFX;
2006 }
2007 if (settings->NSCodec == FALSE)
2008 {
2009 flags &= (uint32_t)~FREERDP_CODEC_NSCODEC;
2010 }
2011 /*TODO: check other codecs flags */
2012 return flags;
2013}
2014
2015const char* freerdp_settings_get_server_name(const rdpSettings* settings)
2016{
2017 WINPR_ASSERT(settings);
2018 const char* hostname = settings->ServerHostname;
2019
2020 if (settings->UserSpecifiedServerName)
2021 hostname = settings->UserSpecifiedServerName;
2022
2023 return hostname;
2024}
2025
2026#if defined(WITH_FREERDP_DEPRECATED)
2027ADDIN_ARGV* freerdp_static_channel_clone(ADDIN_ARGV* channel)
2028{
2029 return freerdp_addin_argv_clone(channel);
2030}
2031
2032ADDIN_ARGV* freerdp_dynamic_channel_clone(ADDIN_ARGV* channel)
2033{
2034 return freerdp_addin_argv_clone(channel);
2035}
2036#endif
2037
2038BOOL freerdp_target_net_addresses_copy(rdpSettings* settings, char** addresses, UINT32 count)
2039{
2040 WINPR_ASSERT(settings);
2041 WINPR_ASSERT(addresses);
2042
2043 if (!freerdp_target_net_adresses_reset(settings, count))
2044 return FALSE;
2045
2046 for (UINT32 i = 0; i < settings->TargetNetAddressCount; i++)
2047 {
2048 const char* address = addresses[i];
2049 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_TargetNetAddresses, i, address))
2050 {
2051 freerdp_target_net_addresses_free(settings);
2052 return FALSE;
2053 }
2054 }
2055
2056 return TRUE;
2057}
2058
2059BOOL freerdp_device_equal(const RDPDR_DEVICE* what, const RDPDR_DEVICE* expect)
2060{
2061 if (!what && !expect)
2062 return TRUE;
2063 if (!what || !expect)
2064 return FALSE;
2065
2066 if (what->Id != expect->Id)
2067 return FALSE;
2068 if (what->Type != expect->Type)
2069 return FALSE;
2070 if (what->Name && expect->Name)
2071 {
2072 if (strcmp(what->Name, expect->Name) != 0)
2073 return FALSE;
2074 }
2075 else
2076 {
2077 if (what->Name != expect->Name)
2078 return FALSE;
2079 }
2080
2081 switch (what->Type)
2082 {
2083 case RDPDR_DTYP_PRINT:
2084 {
2085 const RDPDR_PRINTER* a = (const RDPDR_PRINTER*)what;
2086 const RDPDR_PRINTER* b = (const RDPDR_PRINTER*)expect;
2087 if (a->DriverName && b->DriverName)
2088 return strcmp(a->DriverName, b->DriverName) == 0;
2089 return a->DriverName == b->DriverName;
2090 }
2091
2092 case RDPDR_DTYP_SERIAL:
2093 {
2094 const RDPDR_SERIAL* a = (const RDPDR_SERIAL*)what;
2095 const RDPDR_SERIAL* b = (const RDPDR_SERIAL*)expect;
2096
2097 if (a->Path && b->Path)
2098 {
2099 if (strcmp(a->Path, b->Path) != 0)
2100 return FALSE;
2101 }
2102 else if (a->Path != b->Path)
2103 return FALSE;
2104
2105 if (a->Driver && b->Driver)
2106 {
2107 if (strcmp(a->Driver, b->Driver) != 0)
2108 return FALSE;
2109 }
2110 else if (a->Driver != b->Driver)
2111 return FALSE;
2112 if (a->Permissive && b->Permissive)
2113 return strcmp(a->Permissive, b->Permissive) == 0;
2114 return a->Permissive == b->Permissive;
2115 }
2116
2117 case RDPDR_DTYP_PARALLEL:
2118 {
2119 const RDPDR_PARALLEL* a = (const RDPDR_PARALLEL*)what;
2120 const RDPDR_PARALLEL* b = (const RDPDR_PARALLEL*)expect;
2121 if (a->Path && b->Path)
2122 return strcmp(a->Path, b->Path) == 0;
2123 return a->Path == b->Path;
2124 }
2125
2126 case RDPDR_DTYP_SMARTCARD:
2127 break;
2128 case RDPDR_DTYP_FILESYSTEM:
2129 {
2130 const RDPDR_DRIVE* a = (const RDPDR_DRIVE*)what;
2131 const RDPDR_DRIVE* b = (const RDPDR_DRIVE*)expect;
2132 if (a->automount != b->automount)
2133 return FALSE;
2134 if (a->Path && b->Path)
2135 return strcmp(a->Path, b->Path) == 0;
2136 return a->Path == b->Path;
2137 }
2138
2139 default:
2140 return FALSE;
2141 }
2142
2143 return TRUE;
2144}
2145
2146const char* freerdp_rail_support_flags_to_string(UINT32 flags, char* buffer, size_t length)
2147{
2148 const UINT32 mask =
2149 RAIL_LEVEL_SUPPORTED | RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED |
2150 RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED | RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED |
2151 RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED | RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED |
2152 RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED | RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED;
2153
2154 if (flags & RAIL_LEVEL_SUPPORTED)
2155 winpr_str_append("RAIL_LEVEL_SUPPORTED", buffer, length, "|");
2156 if (flags & RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED)
2157 winpr_str_append("RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED", buffer, length, "|");
2158 if (flags & RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED)
2159 winpr_str_append("RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED", buffer, length, "|");
2160 if (flags & RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED)
2161 winpr_str_append("RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED", buffer, length, "|");
2162 if (flags & RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED)
2163 winpr_str_append("RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED", buffer, length, "|");
2164 if (flags & RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED)
2165 winpr_str_append("RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED", buffer, length, "|");
2166 if (flags & RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED)
2167 winpr_str_append("RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED", buffer, length, "|");
2168 if (flags & RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED)
2169 winpr_str_append("RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED", buffer, length, "|");
2170 if (flags & RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED)
2171 winpr_str_append("RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED", buffer, length, "|");
2172 if ((flags & ~mask) != 0)
2173 {
2174 char tbuffer[64] = { 0 };
2175 (void)_snprintf(tbuffer, sizeof(tbuffer), "RAIL_FLAG_UNKNOWN 0x%08" PRIx32, flags & mask);
2176 winpr_str_append(tbuffer, buffer, length, "|");
2177 }
2178 return buffer;
2179}
2180
2181BOOL freerdp_settings_update_from_caps(rdpSettings* settings, const BYTE* capsFlags,
2182 const BYTE** capsData, const UINT32* capsSizes,
2183 UINT32 capsCount, BOOL serverReceivedCaps)
2184{
2185 WINPR_ASSERT(settings);
2186 WINPR_ASSERT(capsFlags || (capsCount == 0));
2187 WINPR_ASSERT(capsData || (capsCount == 0));
2188 WINPR_ASSERT(capsSizes || (capsCount == 0));
2189 WINPR_ASSERT(capsCount <= UINT16_MAX);
2190
2191 wLog* log = WLog_Get(TAG);
2192
2193 for (UINT32 x = 0; x < capsCount; x++)
2194 {
2195 if (capsFlags[x])
2196 {
2197 wStream buffer = { 0 };
2198 wStream* sub = Stream_StaticConstInit(&buffer, capsData[x], capsSizes[x]);
2199
2200 if (!rdp_read_capability_set(log, sub, (UINT16)x, settings, serverReceivedCaps))
2201 return FALSE;
2202 }
2203 }
2204
2205 return TRUE;
2206}
2207
2208const char* freerdp_rdp_version_string(UINT32 version)
2209{
2210 switch (version)
2211 {
2212 case RDP_VERSION_4:
2213 return "RDP_VERSION_4";
2214 case RDP_VERSION_5_PLUS:
2215 return "RDP_VERSION_5_PLUS";
2216 case RDP_VERSION_10_0:
2217 return "RDP_VERSION_10_0";
2218 case RDP_VERSION_10_1:
2219 return "RDP_VERSION_10_1";
2220 case RDP_VERSION_10_2:
2221 return "RDP_VERSION_10_2";
2222 case RDP_VERSION_10_3:
2223 return "RDP_VERSION_10_3";
2224 case RDP_VERSION_10_4:
2225 return "RDP_VERSION_10_4";
2226 case RDP_VERSION_10_5:
2227 return "RDP_VERSION_10_5";
2228 case RDP_VERSION_10_6:
2229 return "RDP_VERSION_10_6";
2230 case RDP_VERSION_10_7:
2231 return "RDP_VERSION_10_7";
2232 case RDP_VERSION_10_8:
2233 return "RDP_VERSION_10_8";
2234 case RDP_VERSION_10_9:
2235 return "RDP_VERSION_10_9";
2236 case RDP_VERSION_10_10:
2237 return "RDP_VERSION_10_10";
2238 case RDP_VERSION_10_11:
2239 return "RDP_VERSION_10_11";
2240 case RDP_VERSION_10_12:
2241 return "RDP_VERSION_10_12";
2242 default:
2243 return "RDP_VERSION_UNKNOWN";
2244 }
2245}
2246
2247BOOL freerdp_settings_set_string_from_utf16(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
2248 const WCHAR* param)
2249{
2250 WINPR_ASSERT(settings);
2251
2252 if (!param)
2253 return freerdp_settings_set_string_copy_(settings, id, NULL, 0, TRUE);
2254
2255 size_t len = 0;
2256
2257 char* str = ConvertWCharToUtf8Alloc(param, &len);
2258 if (!str && (len != 0))
2259 return FALSE;
2260
2261 return freerdp_settings_set_string_(settings, id, str, len);
2262}
2263
2264BOOL freerdp_settings_set_string_from_utf16N(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
2265 const WCHAR* param, size_t length)
2266{
2267 size_t len = 0;
2268
2269 WINPR_ASSERT(settings);
2270
2271 if (!param)
2272 return freerdp_settings_set_string_copy_(settings, id, NULL, length, TRUE);
2273
2274 char* str = ConvertWCharNToUtf8Alloc(param, length, &len);
2275 if (!str && (length != 0))
2276 {
2277 /* If the input string is an empty string, but length > 0
2278 * consider the conversion a success */
2279 const size_t wlen = _wcsnlen(param, length);
2280 if (wlen != 0)
2281 return FALSE;
2282 }
2283
2284 return freerdp_settings_set_string_(settings, id, str, len);
2285}
2286
2287WCHAR* freerdp_settings_get_string_as_utf16(const rdpSettings* settings,
2288 FreeRDP_Settings_Keys_String id, size_t* pCharLen)
2289{
2290 const char* str = freerdp_settings_get_string(settings, id);
2291 if (pCharLen)
2292 *pCharLen = 0;
2293 if (!str)
2294 return NULL;
2295 return ConvertUtf8ToWCharAlloc(str, pCharLen);
2296}
2297
2298const char* freerdp_rdpdr_dtyp_string(UINT32 type)
2299{
2300 switch (type)
2301 {
2302 case RDPDR_DTYP_FILESYSTEM:
2303 return "RDPDR_DTYP_FILESYSTEM";
2304 case RDPDR_DTYP_PARALLEL:
2305 return "RDPDR_DTYP_PARALLEL";
2306 case RDPDR_DTYP_PRINT:
2307 return "RDPDR_DTYP_PRINT";
2308 case RDPDR_DTYP_SERIAL:
2309 return "RDPDR_DTYP_SERIAL";
2310 case RDPDR_DTYP_SMARTCARD:
2311 return "RDPDR_DTYP_SMARTCARD";
2312 default:
2313 return "RDPDR_DTYP_UNKNOWN";
2314 }
2315}
2316
2317const char* freerdp_encryption_level_string(UINT32 EncryptionLevel)
2318{
2319 switch (EncryptionLevel)
2320 {
2321 case ENCRYPTION_LEVEL_NONE:
2322 return "ENCRYPTION_LEVEL_NONE";
2323 case ENCRYPTION_LEVEL_LOW:
2324 return "ENCRYPTION_LEVEL_LOW";
2325 case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE:
2326 return "ENCRYPTION_LEVEL_CLIENT_COMPATIBLE";
2327 case ENCRYPTION_LEVEL_HIGH:
2328 return "ENCRYPTION_LEVEL_HIGH";
2329 case ENCRYPTION_LEVEL_FIPS:
2330 return "ENCRYPTION_LEVEL_FIPS";
2331 default:
2332 return "ENCRYPTION_LEVEL_UNKNOWN";
2333 }
2334}
2335
2336const char* freerdp_encryption_methods_string(UINT32 EncryptionMethods, char* buffer, size_t size)
2337{
2338 if (EncryptionMethods == ENCRYPTION_METHOD_NONE)
2339 {
2340 winpr_str_append("ENCRYPTION_METHOD_NONE", buffer, size, "|");
2341 return buffer;
2342 }
2343
2344 if (EncryptionMethods & ENCRYPTION_METHOD_40BIT)
2345 {
2346 winpr_str_append("ENCRYPTION_METHOD_40BIT", buffer, size, "|");
2347 }
2348 if (EncryptionMethods & ENCRYPTION_METHOD_128BIT)
2349 {
2350 winpr_str_append("ENCRYPTION_METHOD_128BIT", buffer, size, "|");
2351 }
2352 if (EncryptionMethods & ENCRYPTION_METHOD_56BIT)
2353 {
2354 winpr_str_append("ENCRYPTION_METHOD_56BIT", buffer, size, "|");
2355 }
2356 if (EncryptionMethods & ENCRYPTION_METHOD_FIPS)
2357 {
2358 winpr_str_append("ENCRYPTION_METHOD_FIPS", buffer, size, "|");
2359 }
2360
2361 return buffer;
2362}
2363
2364const char* freerdp_supported_color_depths_string(UINT16 mask, char* buffer, size_t size)
2365{
2366 const UINT32 invalid = mask & ~(RNS_UD_32BPP_SUPPORT | RNS_UD_24BPP_SUPPORT |
2367 RNS_UD_16BPP_SUPPORT | RNS_UD_15BPP_SUPPORT);
2368
2369 if (mask & RNS_UD_32BPP_SUPPORT)
2370 winpr_str_append("RNS_UD_32BPP_SUPPORT", buffer, size, "|");
2371 if (mask & RNS_UD_24BPP_SUPPORT)
2372 winpr_str_append("RNS_UD_24BPP_SUPPORT", buffer, size, "|");
2373 if (mask & RNS_UD_16BPP_SUPPORT)
2374 winpr_str_append("RNS_UD_16BPP_SUPPORT", buffer, size, "|");
2375 if (mask & RNS_UD_15BPP_SUPPORT)
2376 winpr_str_append("RNS_UD_15BPP_SUPPORT", buffer, size, "|");
2377
2378 if (invalid != 0)
2379 {
2380 char str[32] = { 0 };
2381 (void)_snprintf(str, sizeof(str), "RNS_UD_INVALID[0x%04" PRIx32 "]", invalid);
2382 winpr_str_append(str, buffer, size, "|");
2383 }
2384 char hex[32] = { 0 };
2385 (void)_snprintf(hex, sizeof(hex), "[0x%04" PRIx16 "]", mask);
2386 return buffer;
2387}
2388
2389BOOL freerdp_settings_append_string(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
2390 const char* separator, const char* param)
2391{
2392 const char* old = freerdp_settings_get_string(settings, id);
2393
2394 size_t len = 0;
2395 char* str = NULL;
2396
2397 if (!old)
2398 winpr_asprintf(&str, &len, "%s", param);
2399 else if (!separator)
2400 winpr_asprintf(&str, &len, "%s%s", old, param);
2401 else
2402 winpr_asprintf(&str, &len, "%s%s%s", old, separator, param);
2403
2404 const BOOL rc = freerdp_settings_set_string_len(settings, id, str, len);
2405 free(str);
2406 return rc;
2407}
2408
2409BOOL freerdp_settings_are_valid(const rdpSettings* settings)
2410{
2411 return settings != NULL;
2412}
2413
2414/* Function to sort rdpMonitor arrays:
2415 * 1. first element is primary monitor
2416 * 2. all others are sorted by coordinates of x/y
2417 */
2418static int sort_monitor_fn(const void* pva, const void* pvb)
2419{
2420 const rdpMonitor* a = pva;
2421 const rdpMonitor* b = pvb;
2422 WINPR_ASSERT(a);
2423 WINPR_ASSERT(b);
2424 if (a->is_primary && b->is_primary)
2425 return 0;
2426 if (a->is_primary)
2427 return -1;
2428 if (b->is_primary)
2429 return 1;
2430
2431 if (a->x != b->x)
2432 return a->x - b->x;
2433 if (a->y != b->y)
2434 return a->y - b->y;
2435 return 0;
2436}
2437
2439 const rdpMonitor* monitors, size_t count)
2440{
2441 WINPR_ASSERT(monitors || (count == 0));
2442 if (count == 0)
2443 {
2444 if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftX, 0))
2445 return FALSE;
2446 if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftY, 0))
2447 return FALSE;
2448 if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorDefArray, NULL, 0))
2449 return FALSE;
2450 return freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount, 0);
2451 return TRUE;
2452 }
2453
2454 // Find primary or alternatively the monitor at 0/0
2455 const rdpMonitor* primary = NULL;
2456 for (size_t x = 0; x < count; x++)
2457 {
2458 const rdpMonitor* cur = &monitors[x];
2459 if (cur->is_primary)
2460 {
2461 primary = cur;
2462 break;
2463 }
2464 }
2465 if (!primary)
2466 {
2467 for (size_t x = 0; x < count; x++)
2468 {
2469 const rdpMonitor* cur = &monitors[x];
2470 if ((cur->x == 0) && (cur->y == 0))
2471 {
2472 primary = cur;
2473 break;
2474 }
2475 }
2476 }
2477
2478 if (!primary)
2479 {
2480 WLog_ERR(TAG, "Could not find primary monitor, aborting");
2481 return FALSE;
2482 }
2483
2484 if (!freerdp_settings_set_pointer_len(settings, FreeRDP_MonitorDefArray, NULL, count))
2485 return FALSE;
2486 rdpMonitor* sorted = freerdp_settings_get_pointer_writable(settings, FreeRDP_MonitorDefArray);
2487 WINPR_ASSERT(sorted);
2488
2489 size_t sortpos = 0;
2490
2491 /* Set primary. Ensure left/top is at 0/0 and flags contains MONITOR_PRIMARY */
2492 sorted[sortpos] = *primary;
2493 sorted[sortpos].x = 0;
2494 sorted[sortpos].y = 0;
2495 sorted[sortpos].is_primary = TRUE;
2496 sortpos++;
2497
2498 /* Set monitor shift to original layout */
2499 const INT32 offsetX = primary->x;
2500 const INT32 offsetY = primary->y;
2501 if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftX, offsetX))
2502 return FALSE;
2503 if (!freerdp_settings_set_int32(settings, FreeRDP_MonitorLocalShiftY, offsetY))
2504 return FALSE;
2505
2506 for (size_t x = 0; x < count; x++)
2507 {
2508 const rdpMonitor* cur = &monitors[x];
2509 if (cur == primary)
2510 continue;
2511
2512 rdpMonitor m = monitors[x];
2513 m.x -= offsetX;
2514 m.y -= offsetY;
2515 sorted[sortpos++] = m;
2516 }
2517
2518 // Sort remaining monitors by x/y ?
2519 qsort(sorted, count, sizeof(rdpMonitor), sort_monitor_fn);
2520
2521 return freerdp_settings_set_uint32(settings, FreeRDP_MonitorCount,
2522 WINPR_ASSERTING_INT_CAST(uint32_t, count));
2523}
2524
2525static BOOL fill_array(WINPR_JSON* array, const void* data, size_t length)
2526{
2527 const BYTE* pdata = data;
2528 for (size_t x = 0; x < length; x++)
2529 {
2530 BYTE val = pdata[x];
2532 return FALSE;
2533 }
2534 return TRUE;
2535}
2536
2537static BOOL fill_uint32_array(WINPR_JSON* array, const uint32_t* data, size_t length)
2538{
2539 for (size_t x = 0; x < length; x++)
2540 {
2541 uint32_t val = data[x];
2543 return FALSE;
2544 }
2545 return TRUE;
2546}
2547
2548static WINPR_JSON* json_from_addin_item(const ADDIN_ARGV* val)
2549{
2550 WINPR_JSON* obj = WINPR_JSON_CreateObject();
2551 if (!obj)
2552 goto fail;
2553
2554 if (val)
2555 {
2556 if (!WINPR_JSON_AddNumberToObject(obj, "argc", val->argc))
2557 goto fail;
2558
2559 WINPR_JSON* array = WINPR_JSON_AddArrayToObject(obj, "argv");
2560 if (!array)
2561 goto fail;
2562 for (int x = 0; x < val->argc; x++)
2563 {
2564 const char* str = val->argv[x];
2565
2566 WINPR_JSON* item = NULL;
2567 if (!str)
2568 {
2569 item = WINPR_JSON_CreateNull();
2570 }
2571 else
2572 {
2573 item = WINPR_JSON_CreateString(str);
2574 }
2575
2576 if (!WINPR_JSON_AddItemToArray(array, item))
2577 goto fail;
2578 }
2579 }
2580 return obj;
2581
2582fail:
2583 WINPR_JSON_Delete(obj);
2584 return NULL;
2585}
2586
2587static BOOL json_from_addin_item_array(WINPR_JSON* json, const rdpSettings* settings,
2588 FreeRDP_Settings_Keys_Pointer key, size_t count)
2589{
2590 if (!json)
2591 return FALSE;
2592
2593 for (uint32_t x = 0; x < count; x++)
2594 {
2595 const ADDIN_ARGV* cval = freerdp_settings_get_pointer_array(settings, key, x);
2596 if (!WINPR_JSON_AddItemToArray(json, json_from_addin_item(cval)))
2597 return FALSE;
2598 }
2599 return TRUE;
2600}
2601
2602static BOOL add_string_or_null(WINPR_JSON* json, const char* key, const char* value)
2603{
2604 if (value)
2605 return WINPR_JSON_AddStringToObject(json, key, value) != NULL;
2606
2607 (void)WINPR_JSON_AddNullToObject(json, key);
2608 return TRUE;
2609}
2610
2611static WINPR_JSON* json_from_device_item(const RDPDR_DEVICE* val)
2612{
2613 WINPR_JSON* obj = WINPR_JSON_CreateObject();
2614 if (!obj)
2615 goto fail;
2616
2617 if (val)
2618 {
2619 union
2620 {
2621 const RDPDR_DEVICE* base;
2622 const RDPDR_PARALLEL* parallel;
2623 const RDPDR_SERIAL* serial;
2624 const RDPDR_SMARTCARD* smartcard;
2625 const RDPDR_PRINTER* printer;
2626 const RDPDR_DRIVE* drive;
2627 const RDPDR_DEVICE* device;
2628 } device;
2629
2630 device.base = val;
2631
2632 if (!WINPR_JSON_AddNumberToObject(obj, "Id", val->Id))
2633 goto fail;
2634 if (!WINPR_JSON_AddNumberToObject(obj, "Type", val->Type))
2635 goto fail;
2636 if (!add_string_or_null(obj, "Name", val->Name))
2637 goto fail;
2638 switch (val->Type)
2639 {
2640 case RDPDR_DTYP_SERIAL:
2641 if (!add_string_or_null(obj, "Path", device.serial->Path))
2642 goto fail;
2643 if (!add_string_or_null(obj, "Driver", device.serial->Driver))
2644 goto fail;
2645 if (!add_string_or_null(obj, "Permissive", device.serial->Permissive))
2646 goto fail;
2647 break;
2648 case RDPDR_DTYP_PARALLEL:
2649 if (!add_string_or_null(obj, "Path", device.parallel->Path))
2650 goto fail;
2651 break;
2652 case RDPDR_DTYP_PRINT:
2653 if (!add_string_or_null(obj, "DriverName", device.printer->DriverName))
2654 goto fail;
2655 if (!WINPR_JSON_AddBoolToObject(obj, "IsDefault", device.printer->IsDefault))
2656 goto fail;
2657 break;
2658 case RDPDR_DTYP_FILESYSTEM:
2659 if (!add_string_or_null(obj, "Path", device.drive->Path))
2660 goto fail;
2661 if (!WINPR_JSON_AddBoolToObject(obj, "IsDefault", device.drive->automount))
2662 goto fail;
2663 break;
2664 case RDPDR_DTYP_SMARTCARD:
2665 default:
2666 break;
2667 }
2668 }
2669 return obj;
2670
2671fail:
2672 WINPR_JSON_Delete(obj);
2673 return NULL;
2674}
2675
2676static BOOL json_from_device_item_array(WINPR_JSON* json, const rdpSettings* settings,
2677 FreeRDP_Settings_Keys_Pointer key, size_t count)
2678{
2679 if (!json)
2680 return FALSE;
2681
2682 for (uint32_t x = 0; x < count; x++)
2683 {
2684 const RDPDR_DEVICE* cval = freerdp_settings_get_pointer_array(settings, key, x);
2685 if (!WINPR_JSON_AddItemToArray(json, json_from_device_item(cval)))
2686 return FALSE;
2687 }
2688 return TRUE;
2689}
2690
2691static BOOL string_array_to_json(WINPR_JSON* json, const rdpSettings* settings, uint32_t argc,
2692 FreeRDP_Settings_Keys_Pointer key)
2693{
2694 for (uint32_t x = 0; x < argc; x++)
2695 {
2696 const char* cval = freerdp_settings_get_pointer_array(settings, key, x);
2697
2698 WINPR_JSON* item = NULL;
2699 if (!cval)
2700 item = WINPR_JSON_CreateNull();
2701 else
2702 item = WINPR_JSON_CreateString(cval);
2703 if (!WINPR_JSON_AddItemToArray(json, item))
2704 return FALSE;
2705 }
2706 return TRUE;
2707}
2708
2709static BOOL wchar_to_json(WINPR_JSON* obj, const char* key, const WCHAR* wstr, size_t len)
2710{
2711 if (len == 0)
2712 return WINPR_JSON_AddStringToObject(obj, key, "") != NULL;
2713
2714 const size_t slen = len * 6;
2715 char* str = calloc(1, slen);
2716 if (!str)
2717 return FALSE;
2718
2719 WINPR_JSON* jstr = NULL;
2720 SSIZE_T rc = ConvertWCharNToUtf8(wstr, len, str, slen);
2721 if (rc >= 0)
2722 jstr = WINPR_JSON_AddStringToObject(obj, key, str);
2723 free(str);
2724 return jstr != NULL;
2725}
2726
2727static BOOL wchar_from_json(WCHAR* wstr, size_t len, const WINPR_JSON* obj, const char* key)
2728{
2729 if (!obj || !WINPR_JSON_IsObject(obj))
2730 return FALSE;
2731 WINPR_JSON* item = WINPR_JSON_GetObjectItem(obj, key);
2732 if (!item || !WINPR_JSON_IsString(item))
2733 return FALSE;
2734
2735 const char* str = WINPR_JSON_GetStringValue(item);
2736 if (!str)
2737 {
2738 memset(wstr, 0, sizeof(WCHAR) * len);
2739 return TRUE;
2740 }
2741
2742 SSIZE_T rc = ConvertUtf8ToWChar(str, wstr, len);
2743 return rc >= 0;
2744}
2745
2746static int64_t int_from_json_item(const WINPR_JSON* item, int64_t min, int64_t max)
2747{
2748 if (!item || !WINPR_JSON_IsNumber(item))
2749 {
2750 errno = EINVAL;
2751 return 0;
2752 }
2753
2754 const double val = WINPR_JSON_GetNumberValue(item);
2755 if (isinf(val) || isnan(val))
2756 {
2757 errno = ERANGE;
2758 return 0;
2759 }
2760
2761 const int64_t ival = (int64_t)val;
2762 if ((ival < min) || (ival > max))
2763 {
2764 errno = ERANGE;
2765 return 0;
2766 }
2767
2768 return ival;
2769}
2770
2771static int64_t int_from_json(const WINPR_JSON* obj, const char* key, int64_t min, int64_t max)
2772{
2773 if (!obj || !WINPR_JSON_IsObject(obj))
2774 {
2775 errno = EINVAL;
2776 return 0;
2777 }
2778 WINPR_JSON* item = WINPR_JSON_GetObjectItem(obj, key);
2779 return int_from_json_item(item, min, max);
2780}
2781
2782static uint64_t uint_from_json_item(const WINPR_JSON* item, uint64_t max)
2783{
2784 if (!item || !WINPR_JSON_IsNumber(item))
2785 {
2786 errno = EINVAL;
2787 return 0;
2788 }
2789
2790 const double val = WINPR_JSON_GetNumberValue(item);
2791 if (isinf(val) || isnan(val) || (val < 0.0))
2792 {
2793 errno = ERANGE;
2794 return 0;
2795 }
2796
2797 const uint64_t uval = (uint64_t)val;
2798 if (uval > max)
2799 {
2800 errno = ERANGE;
2801 return 0;
2802 }
2803 return uval;
2804}
2805
2806static uint64_t uint_from_json(const WINPR_JSON* obj, const char* key, uint64_t max)
2807{
2808 if (!obj || !WINPR_JSON_IsObject(obj))
2809 {
2810 errno = EINVAL;
2811 return 0;
2812 }
2813
2814 WINPR_JSON* item = WINPR_JSON_GetObjectItem(obj, key);
2815 return uint_from_json_item(item, max);
2816}
2817
2818static WINPR_JSON* systemtime_to_json(WINPR_JSON* parent, const char* key, const SYSTEMTIME* st)
2819{
2820 WINPR_ASSERT(st);
2821
2822 WINPR_JSON* obj = WINPR_JSON_AddObjectToObject(parent, key);
2823 if (!obj)
2824 return NULL;
2825
2826 if (!WINPR_JSON_AddNumberToObject(obj, "wYear", st->wYear))
2827 goto fail;
2828 if (!WINPR_JSON_AddNumberToObject(obj, "wMonth", st->wMonth))
2829 goto fail;
2830 if (!WINPR_JSON_AddNumberToObject(obj, "wDayOfWeek", st->wDayOfWeek))
2831 goto fail;
2832 if (!WINPR_JSON_AddNumberToObject(obj, "wDay", st->wDay))
2833 goto fail;
2834 if (!WINPR_JSON_AddNumberToObject(obj, "wHour", st->wHour))
2835 goto fail;
2836 if (!WINPR_JSON_AddNumberToObject(obj, "wMinute", st->wMinute))
2837 goto fail;
2838 if (!WINPR_JSON_AddNumberToObject(obj, "wSecond", st->wSecond))
2839 goto fail;
2840 if (!WINPR_JSON_AddNumberToObject(obj, "wMilliseconds", st->wMilliseconds))
2841 goto fail;
2842
2843 return obj;
2844fail:
2845 WINPR_JSON_Delete(obj);
2846 return NULL;
2847}
2848
2849static BOOL systemtime_from_json(const WINPR_JSON* pobj, const char* key, SYSTEMTIME* st)
2850{
2851 WINPR_ASSERT(st);
2852
2853 if (!pobj || !WINPR_JSON_IsObject(pobj))
2854 return FALSE;
2855
2856 WINPR_JSON* obj = WINPR_JSON_GetObjectItem(pobj, key);
2857 if (!obj || !WINPR_JSON_IsObject(obj))
2858 return FALSE;
2859
2860 errno = 0;
2861 st->wYear = (uint16_t)uint_from_json(obj, "wYear", UINT16_MAX);
2862 st->wMonth = (uint16_t)uint_from_json(obj, "wMonth", UINT16_MAX);
2863 st->wDayOfWeek = (uint16_t)uint_from_json(obj, "wDayOfWeek", UINT16_MAX);
2864 st->wDay = (uint16_t)uint_from_json(obj, "wDay", UINT16_MAX);
2865 st->wHour = (uint16_t)uint_from_json(obj, "wHour", UINT16_MAX);
2866 st->wMinute = (uint16_t)uint_from_json(obj, "wMinute", UINT16_MAX);
2867 st->wSecond = (uint16_t)uint_from_json(obj, "wSecond", UINT16_MAX);
2868 st->wMilliseconds = (uint16_t)uint_from_json(obj, "wMilliseconds", UINT16_MAX);
2869 return errno == 0;
2870}
2871
2872static BOOL ts_info_from_json(TIME_ZONE_INFORMATION* tz, const WINPR_JSON* json)
2873{
2874 WINPR_ASSERT(tz);
2875
2876 if (!json || !WINPR_JSON_IsObject(json))
2877 return FALSE;
2878
2879 errno = 0;
2880 tz->Bias = (int32_t)int_from_json(json, "Bias", INT32_MIN, INT32_MAX);
2881 tz->StandardBias = (int32_t)int_from_json(json, "StandardBias", INT32_MIN, INT32_MAX);
2882 tz->DaylightBias = (int32_t)int_from_json(json, "DaylightBias", INT32_MIN, INT32_MAX);
2883 if (errno != 0)
2884 return FALSE;
2885
2886 if (!systemtime_from_json(json, "StandardDate", &tz->StandardDate))
2887 return FALSE;
2888 if (!systemtime_from_json(json, "DaylightDate", &tz->DaylightDate))
2889 return FALSE;
2890
2891 if (!wchar_from_json(tz->StandardName, ARRAYSIZE(tz->StandardName), json, "StandardName"))
2892 return FALSE;
2893 if (!wchar_from_json(tz->DaylightName, ARRAYSIZE(tz->DaylightName), json, "DaylightName"))
2894 return FALSE;
2895
2896 return TRUE;
2897}
2898
2899static BOOL ts_info_array_from_json(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer key,
2900 const WINPR_JSON* json)
2901{
2902 if (!json || !WINPR_JSON_IsArray(json))
2903 return FALSE;
2904
2905 const size_t count = WINPR_JSON_GetArraySize(json);
2906 if (!freerdp_settings_set_pointer_len(settings, key, NULL, count))
2907 return FALSE;
2908
2909 for (size_t x = 0; x < count; x++)
2910 {
2911 TIME_ZONE_INFORMATION* tz = freerdp_settings_get_pointer_array_writable(settings, key, x);
2912 WINPR_JSON* obj = WINPR_JSON_GetArrayItem(json, x);
2913 if (!ts_info_from_json(tz, obj))
2914 return FALSE;
2915 }
2916 return TRUE;
2917}
2918
2919static BOOL tz_info_to_json(WINPR_JSON* json, const TIME_ZONE_INFORMATION* ptz)
2920{
2921 WINPR_JSON* obj = WINPR_JSON_CreateObject();
2922 if (!obj)
2923 return FALSE;
2924 if (!WINPR_JSON_AddItemToArray(json, obj))
2925 return FALSE;
2926
2927 TIME_ZONE_INFORMATION tz = { 0 };
2928 if (ptz)
2929 tz = *ptz;
2930
2931 if (!WINPR_JSON_AddNumberToObject(obj, "Bias", tz.Bias))
2932 return FALSE;
2933
2934 if (!wchar_to_json(obj, "StandardName", tz.StandardName, ARRAYSIZE(tz.StandardName)))
2935 return FALSE;
2936
2937 if (!systemtime_to_json(obj, "StandardDate", &tz.StandardDate))
2938 return FALSE;
2939
2940 if (!WINPR_JSON_AddNumberToObject(obj, "StandardBias", tz.Bias))
2941 return FALSE;
2942
2943 if (!wchar_to_json(obj, "DaylightName", tz.DaylightName, ARRAYSIZE(tz.DaylightName)))
2944 return FALSE;
2945
2946 if (!systemtime_to_json(obj, "DaylightDate", &tz.DaylightDate))
2947 return FALSE;
2948
2949 if (!WINPR_JSON_AddNumberToObject(obj, "DaylightBias", tz.Bias))
2950 return FALSE;
2951 return TRUE;
2952}
2953
2954static BOOL glyph_cache_def_to_json(WINPR_JSON* json, const GLYPH_CACHE_DEFINITION* def)
2955{
2956 WINPR_ASSERT(def);
2957 if (!json || !WINPR_JSON_IsArray(json))
2958 return FALSE;
2959
2960 WINPR_JSON* obj = WINPR_JSON_CreateObject();
2961 if (!obj)
2962 return FALSE;
2963 if (!WINPR_JSON_AddItemToArray(json, obj))
2964 return FALSE;
2965
2966 if (!WINPR_JSON_AddNumberToObject(obj, "cacheEntries", def->cacheEntries))
2967 return FALSE;
2968 if (!WINPR_JSON_AddNumberToObject(obj, "cacheMaximumCellSize", def->cacheMaximumCellSize))
2969 return FALSE;
2970 return TRUE;
2971}
2972
2973static BOOL glyph_cache_def_array_to_json(WINPR_JSON* json, const GLYPH_CACHE_DEFINITION* def,
2974 size_t count)
2975{
2976 if (!json || !WINPR_JSON_IsArray(json))
2977 return FALSE;
2978
2979 for (size_t x = 0; x < count; x++)
2980 {
2981 if (!glyph_cache_def_to_json(json, &def[x]))
2982 return FALSE;
2983 }
2984 return TRUE;
2985}
2986
2987static BOOL glyph_cache_def_from_json(GLYPH_CACHE_DEFINITION* def, const WINPR_JSON* json)
2988{
2989 WINPR_ASSERT(def);
2990 WINPR_ASSERT(json);
2991
2992 if (!WINPR_JSON_IsObject(json))
2993 return FALSE;
2994
2995 errno = 0;
2996 def->cacheEntries = (uint16_t)uint_from_json(json, "cacheEntries", UINT16_MAX);
2997 def->cacheMaximumCellSize = (uint16_t)uint_from_json(json, "cacheMaximumCellSize", UINT16_MAX);
2998 return errno == 0;
2999}
3000
3001static BOOL glyph_cache_def_array_from_json(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
3002 const WINPR_JSON* json)
3003{
3004 if (!json || !WINPR_JSON_IsArray(json))
3005 return FALSE;
3006
3007 const size_t count = WINPR_JSON_GetArraySize(json);
3008 if (!freerdp_settings_set_pointer_len(settings, id, NULL, count))
3009 return FALSE;
3010
3011 for (size_t x = 0; x < count; x++)
3012 {
3013 GLYPH_CACHE_DEFINITION* cache =
3014 freerdp_settings_get_pointer_array_writable(settings, id, x);
3015 WINPR_JSON* obj = WINPR_JSON_GetArrayItem(json, x);
3016 if (!glyph_cache_def_from_json(cache, obj))
3017 return FALSE;
3018 }
3019 return TRUE;
3020}
3021
3022static BOOL bitmap_cache_v2_from_json(BITMAP_CACHE_V2_CELL_INFO* info, const WINPR_JSON* json)
3023{
3024 WINPR_ASSERT(info);
3025
3026 if (!json || !WINPR_JSON_IsObject(json))
3027 return FALSE;
3028
3029 errno = 0;
3030 info->numEntries = (uint32_t)uint_from_json(json, "numEntries", UINT32_MAX);
3031 if (errno != 0)
3032 return FALSE;
3033
3034 WINPR_JSON* item = WINPR_JSON_GetObjectItem(json, "persistent");
3035 if (!item || !WINPR_JSON_IsBool(item))
3036 return FALSE;
3037
3038 info->persistent = WINPR_JSON_IsTrue(item);
3039 return TRUE;
3040}
3041
3042static BOOL bitmap_cache_v2_array_from_json(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
3043 const WINPR_JSON* json)
3044{
3045 if (!json || !WINPR_JSON_IsArray(json))
3046 return FALSE;
3047
3048 const size_t count = WINPR_JSON_GetArraySize(json);
3049 if (!freerdp_settings_set_pointer_len(settings, id, NULL, count))
3050 return FALSE;
3051
3052 for (size_t x = 0; x < count; x++)
3053 {
3055 freerdp_settings_get_pointer_array_writable(settings, id, x);
3056 WINPR_JSON* obj = WINPR_JSON_GetArrayItem(json, x);
3057 if (!bitmap_cache_v2_from_json(cache, obj))
3058 return FALSE;
3059 }
3060 return TRUE;
3061}
3062
3063static BOOL client_cookie_from_json(ARC_CS_PRIVATE_PACKET* cookie, const WINPR_JSON* json)
3064{
3065 WINPR_ASSERT(cookie);
3066 WINPR_ASSERT(json);
3067
3068 if (!WINPR_JSON_IsObject(json))
3069 return FALSE;
3070
3071 errno = 0;
3072 cookie->cbLen = (uint32_t)uint_from_json(json, "cbLen", UINT32_MAX);
3073 cookie->version = (uint32_t)uint_from_json(json, "version", UINT32_MAX);
3074 cookie->logonId = (uint32_t)uint_from_json(json, "logonId", UINT32_MAX);
3075 if (errno != 0)
3076 return FALSE;
3077
3078 WINPR_JSON* item = WINPR_JSON_GetObjectItem(json, "securityVerifier");
3079 if (!item || !WINPR_JSON_IsArray(item))
3080 return FALSE;
3081
3082 const size_t len = WINPR_JSON_GetArraySize(item);
3083 if (len != ARRAYSIZE(cookie->securityVerifier))
3084 return FALSE;
3085
3086 errno = 0;
3087 for (size_t x = 0; x < len; x++)
3088 {
3089 WINPR_JSON* citem = WINPR_JSON_GetArrayItem(item, x);
3090 const uint64_t val = uint_from_json_item(citem, UINT8_MAX);
3091 cookie->securityVerifier[x] = (uint8_t)val;
3092 }
3093 return errno == 0;
3094}
3095
3096static BOOL client_cookie_array_from_json(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
3097 const WINPR_JSON* json)
3098{
3099 if (!json || !WINPR_JSON_IsArray(json))
3100 return FALSE;
3101
3102 const size_t count = WINPR_JSON_GetArraySize(json);
3103 if (!freerdp_settings_set_pointer_len(settings, id, NULL, count))
3104 return FALSE;
3105
3106 for (size_t x = 0; x < count; x++)
3107 {
3108 ARC_CS_PRIVATE_PACKET* cache = freerdp_settings_get_pointer_array_writable(settings, id, x);
3109 WINPR_JSON* obj = WINPR_JSON_GetArrayItem(json, x);
3110 if (!client_cookie_from_json(cache, obj))
3111 return FALSE;
3112 }
3113 return TRUE;
3114}
3115
3116static BOOL server_cookie_from_json(ARC_SC_PRIVATE_PACKET* cookie, const WINPR_JSON* json)
3117{
3118 WINPR_ASSERT(cookie);
3119
3120 if (!json || !WINPR_JSON_IsObject(json))
3121 return FALSE;
3122
3123 errno = 0;
3124 cookie->cbLen = (uint32_t)uint_from_json(json, "cbLen", UINT32_MAX);
3125 cookie->version = (uint32_t)uint_from_json(json, "version", UINT32_MAX);
3126 cookie->logonId = (uint32_t)uint_from_json(json, "logonId", UINT32_MAX);
3127 if (errno != 0)
3128 return FALSE;
3129
3130 WINPR_JSON* item = WINPR_JSON_GetObjectItem(json, "arcRandomBits");
3131 if (!item || !WINPR_JSON_IsArray(item))
3132 return FALSE;
3133
3134 const size_t len = WINPR_JSON_GetArraySize(item);
3135 if (len != ARRAYSIZE(cookie->arcRandomBits))
3136 return FALSE;
3137
3138 errno = 0;
3139 for (size_t x = 0; x < len; x++)
3140 {
3141 WINPR_JSON* citem = WINPR_JSON_GetArrayItem(item, x);
3142 cookie->arcRandomBits[x] = (uint8_t)uint_from_json_item(citem, UINT8_MAX);
3143 }
3144 return errno == 0;
3145}
3146
3147static BOOL server_cookie_array_from_json(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
3148 const WINPR_JSON* json)
3149{
3150 if (!json || !WINPR_JSON_IsArray(json))
3151 return FALSE;
3152
3153 const size_t count = WINPR_JSON_GetArraySize(json);
3154 if (!freerdp_settings_set_pointer_len(settings, id, NULL, count))
3155 return FALSE;
3156
3157 for (size_t x = 0; x < count; x++)
3158 {
3159 ARC_SC_PRIVATE_PACKET* cache = freerdp_settings_get_pointer_array_writable(settings, id, x);
3160 WINPR_JSON* obj = WINPR_JSON_GetArrayItem(json, x);
3161 if (!server_cookie_from_json(cache, obj))
3162 return FALSE;
3163 }
3164 return TRUE;
3165}
3166
3167static BOOL channel_def_from_json(CHANNEL_DEF* cookie, const WINPR_JSON* json)
3168{
3169 WINPR_ASSERT(cookie);
3170 WINPR_ASSERT(json);
3171
3172 if (!WINPR_JSON_IsObject(json))
3173 return FALSE;
3174
3175 errno = 0;
3176 cookie->options = (uint32_t)uint_from_json(json, "options", UINT32_MAX);
3177 if (errno != 0)
3178 return FALSE;
3179
3180 WINPR_JSON* item = WINPR_JSON_GetObjectItem(json, "name");
3181 if (!item || !WINPR_JSON_IsString(item))
3182 return FALSE;
3183
3184 const char* str = WINPR_JSON_GetStringValue(item);
3185 if (!str)
3186 memset(cookie->name, 0, sizeof(cookie->name));
3187 else
3188 {
3189 strncpy(cookie->name, str, strnlen(str, ARRAYSIZE(cookie->name)));
3190 }
3191 return TRUE;
3192}
3193
3194static BOOL channel_def_array_from_json(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
3195 const WINPR_JSON* json)
3196{
3197 if (!json || !WINPR_JSON_IsArray(json))
3198 return FALSE;
3199
3200 const size_t count = WINPR_JSON_GetArraySize(json);
3201 if (!freerdp_settings_set_pointer_len(settings, id, NULL, count))
3202 return FALSE;
3203
3204 for (size_t x = 0; x < count; x++)
3205 {
3206 CHANNEL_DEF* cache = freerdp_settings_get_pointer_array_writable(settings, id, x);
3207 WINPR_JSON* obj = WINPR_JSON_GetArrayItem(json, x);
3208 if (!channel_def_from_json(cache, obj))
3209 return FALSE;
3210 }
3211 return TRUE;
3212}
3213
3214static BOOL monitor_attributes_from_json(MONITOR_ATTRIBUTES* attributes, const WINPR_JSON* json)
3215{
3216 WINPR_ASSERT(attributes);
3217 if (!json || !WINPR_JSON_IsObject(json))
3218 return FALSE;
3219
3220 WINPR_JSON* obj = WINPR_JSON_GetObjectItem(json, "attributes");
3221 if (!obj || !WINPR_JSON_IsObject(obj))
3222 return FALSE;
3223
3224 errno = 0;
3225 attributes->physicalWidth = (uint32_t)uint_from_json(obj, "physicalWidth", UINT32_MAX);
3226 attributes->physicalHeight = (uint32_t)uint_from_json(obj, "physicalHeight", UINT32_MAX);
3227 attributes->orientation = (uint32_t)uint_from_json(obj, "orientation", UINT32_MAX);
3228 attributes->desktopScaleFactor =
3229 (uint32_t)uint_from_json(obj, "desktopScaleFactor", UINT32_MAX);
3230 attributes->deviceScaleFactor = (uint32_t)uint_from_json(obj, "deviceScaleFactor", UINT32_MAX);
3231 return errno == 0;
3232}
3233
3234static BOOL monitor_def_from_json(rdpMonitor* monitor, const WINPR_JSON* json)
3235{
3236 WINPR_ASSERT(monitor);
3237
3238 if (!json || !WINPR_JSON_IsObject(json))
3239 return FALSE;
3240
3241 errno = 0;
3242 monitor->x = (int32_t)int_from_json(json, "x", INT32_MIN, INT32_MAX);
3243 monitor->y = (int32_t)int_from_json(json, "y", INT32_MIN, INT32_MAX);
3244 monitor->width = (int32_t)int_from_json(json, "width", 0, INT32_MAX);
3245 monitor->height = (int32_t)int_from_json(json, "height", 0, INT32_MAX);
3246 monitor->orig_screen = (uint32_t)uint_from_json(json, "orig_screen", UINT32_MAX);
3247 if (errno != 0)
3248 return FALSE;
3249
3250 WINPR_JSON* item = WINPR_JSON_GetObjectItem(json, "is_primary");
3251 if (!item)
3252 return FALSE;
3253 if (!WINPR_JSON_IsBool(item))
3254 return FALSE;
3255 monitor->is_primary = WINPR_JSON_IsTrue(item) ? 1 : 0;
3256
3257 return monitor_attributes_from_json(&monitor->attributes, json);
3258}
3259
3260static BOOL monitor_def_array_from_json(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
3261 const WINPR_JSON* json)
3262{
3263 if (!json || !WINPR_JSON_IsArray(json))
3264 return FALSE;
3265
3266 const size_t count = WINPR_JSON_GetArraySize(json);
3267 if (!freerdp_settings_set_pointer_len(settings, id, NULL, count))
3268 return FALSE;
3269
3270 for (size_t x = 0; x < count; x++)
3271 {
3272 rdpMonitor* cache = freerdp_settings_get_pointer_array_writable(settings, id, x);
3273 WINPR_JSON* obj = WINPR_JSON_GetArrayItem(json, x);
3274 if (!monitor_def_from_json(cache, obj))
3275 return FALSE;
3276 }
3277 return TRUE;
3278}
3279
3280static BOOL client_cookie_to_json(WINPR_JSON* json, const ARC_CS_PRIVATE_PACKET* cs)
3281{
3282 WINPR_JSON* obj = WINPR_JSON_CreateObject();
3283 if (!obj)
3284 return FALSE;
3285 if (!WINPR_JSON_AddItemToArray(json, obj))
3286 return FALSE;
3287
3288 if (!WINPR_JSON_AddNumberToObject(obj, "cbLen", cs->cbLen))
3289 return FALSE;
3290 if (!WINPR_JSON_AddNumberToObject(obj, "version", cs->version))
3291 return FALSE;
3292 if (!WINPR_JSON_AddNumberToObject(obj, "logonId", cs->logonId))
3293 return FALSE;
3294 WINPR_JSON* array = WINPR_JSON_AddArrayToObject(obj, "securityVerifier");
3295 if (!array)
3296 return FALSE;
3297
3298 for (size_t x = 0; x < ARRAYSIZE(cs->securityVerifier); x++)
3299 {
3300 WINPR_JSON* item = WINPR_JSON_CreateNumber(cs->securityVerifier[x]);
3301 if (!item)
3302 return FALSE;
3303 if (!WINPR_JSON_AddItemToArray(array, item))
3304 return FALSE;
3305 }
3306 return TRUE;
3307}
3308
3309static BOOL client_cookie_array_to_json(WINPR_JSON* json, const ARC_CS_PRIVATE_PACKET* cs,
3310 size_t count)
3311{
3312 for (size_t x = 0; x < count; x++)
3313 {
3314 if (!client_cookie_to_json(json, &cs[x]))
3315 return FALSE;
3316 }
3317 return TRUE;
3318}
3319
3320static BOOL server_cookie_to_json(WINPR_JSON* json, const ARC_SC_PRIVATE_PACKET* cs)
3321{
3322 WINPR_JSON* obj = WINPR_JSON_CreateObject();
3323 if (!obj)
3324 return FALSE;
3325 if (!WINPR_JSON_AddItemToArray(json, obj))
3326 return FALSE;
3327
3328 if (!WINPR_JSON_AddNumberToObject(obj, "cbLen", cs->cbLen))
3329 return FALSE;
3330 if (!WINPR_JSON_AddNumberToObject(obj, "version", cs->version))
3331 return FALSE;
3332 if (!WINPR_JSON_AddNumberToObject(obj, "logonId", cs->logonId))
3333 return FALSE;
3334 WINPR_JSON* array = WINPR_JSON_AddArrayToObject(obj, "arcRandomBits");
3335 if (!array)
3336 return FALSE;
3337
3338 for (size_t x = 0; x < ARRAYSIZE(cs->arcRandomBits); x++)
3339 {
3340 WINPR_JSON* item = WINPR_JSON_CreateNumber(cs->arcRandomBits[x]);
3341 if (!item)
3342 return FALSE;
3343 if (!WINPR_JSON_AddItemToArray(array, item))
3344 return FALSE;
3345 }
3346 return TRUE;
3347}
3348
3349static BOOL server_cookie_array_to_json(WINPR_JSON* json, const ARC_SC_PRIVATE_PACKET* cs,
3350 size_t count)
3351{
3352 for (size_t x = 0; x < count; x++)
3353 {
3354 if (!server_cookie_to_json(json, &cs[x]))
3355 return FALSE;
3356 }
3357 return TRUE;
3358}
3359
3360static BOOL bitmap_cache_v2_to_json(WINPR_JSON* json, const BITMAP_CACHE_V2_CELL_INFO* info)
3361{
3362 WINPR_JSON* obj = WINPR_JSON_CreateObject();
3363 if (!obj)
3364 return FALSE;
3365 if (!WINPR_JSON_AddItemToArray(json, obj))
3366 return FALSE;
3367
3368 if (!WINPR_JSON_AddNumberToObject(obj, "numEntries", info->numEntries))
3369 return FALSE;
3370 if (!WINPR_JSON_AddBoolToObject(obj, "persistent", info->persistent))
3371 return FALSE;
3372 return TRUE;
3373}
3374
3375static BOOL bitmap_cache_v2_array_to_json(WINPR_JSON* json, const BITMAP_CACHE_V2_CELL_INFO* info,
3376 size_t count)
3377{
3378 for (size_t x = 0; x < count; x++)
3379 {
3380 if (!bitmap_cache_v2_to_json(json, &info[x]))
3381 return FALSE;
3382 }
3383 return TRUE;
3384}
3385
3386static BOOL monitor_attributes_to_json(WINPR_JSON* pobj, const MONITOR_ATTRIBUTES* attributes)
3387{
3388 WINPR_ASSERT(attributes);
3389 WINPR_JSON* obj = WINPR_JSON_AddObjectToObject(pobj, "attributes");
3390 if (!obj)
3391 return FALSE;
3392 if (!WINPR_JSON_AddNumberToObject(obj, "physicalWidth", attributes->physicalWidth))
3393 return FALSE;
3394 if (!WINPR_JSON_AddNumberToObject(obj, "physicalHeight", attributes->physicalHeight))
3395 return FALSE;
3396 if (!WINPR_JSON_AddNumberToObject(obj, "orientation", attributes->orientation))
3397 return FALSE;
3398 if (!WINPR_JSON_AddNumberToObject(obj, "desktopScaleFactor", attributes->desktopScaleFactor))
3399 return FALSE;
3400 if (!WINPR_JSON_AddNumberToObject(obj, "deviceScaleFactor", attributes->deviceScaleFactor))
3401 return FALSE;
3402 return TRUE;
3403}
3404
3405static BOOL monitor_def_to_json(WINPR_JSON* json, const rdpMonitor* monitor)
3406{
3407 WINPR_ASSERT(monitor);
3408 WINPR_JSON* obj = WINPR_JSON_CreateObject();
3409 if (!obj)
3410 return FALSE;
3411 if (!WINPR_JSON_AddItemToArray(json, obj))
3412 return FALSE;
3413
3414 if (!WINPR_JSON_AddNumberToObject(obj, "x", monitor->x))
3415 return FALSE;
3416 if (!WINPR_JSON_AddNumberToObject(obj, "y", monitor->y))
3417 return FALSE;
3418 if (!WINPR_JSON_AddNumberToObject(obj, "width", monitor->width))
3419 return FALSE;
3420 if (!WINPR_JSON_AddNumberToObject(obj, "height", monitor->height))
3421 return FALSE;
3422 if (!WINPR_JSON_AddBoolToObject(obj, "is_primary", monitor->is_primary != 0))
3423 return FALSE;
3424 if (!WINPR_JSON_AddNumberToObject(obj, "orig_screen", monitor->orig_screen))
3425 return FALSE;
3426 return monitor_attributes_to_json(obj, &monitor->attributes);
3427}
3428
3429static BOOL monitor_def_array_to_json(WINPR_JSON* json, const rdpMonitor* monitors, size_t count)
3430{
3431 for (size_t x = 0; x < count; x++)
3432 {
3433 if (!monitor_def_to_json(json, &monitors[x]))
3434 return FALSE;
3435 }
3436 return TRUE;
3437}
3438
3439static BOOL channel_def_to_json(WINPR_JSON* json, const CHANNEL_DEF* channel)
3440{
3441 WINPR_ASSERT(channel);
3442 WINPR_JSON* obj = WINPR_JSON_CreateObject();
3443 if (!obj)
3444 return FALSE;
3445 if (!WINPR_JSON_AddItemToArray(json, obj))
3446 return FALSE;
3447
3448 if (!WINPR_JSON_AddStringToObject(obj, "name", channel->name))
3449 return FALSE;
3450 if (!WINPR_JSON_AddNumberToObject(obj, "options", channel->options))
3451 return FALSE;
3452 return TRUE;
3453}
3454
3455static BOOL channel_def_array_to_json(WINPR_JSON* json, const CHANNEL_DEF* channels, size_t count)
3456{
3457 for (size_t x = 0; x < count; x++)
3458 {
3459 if (!channel_def_to_json(json, &channels[x]))
3460 return FALSE;
3461 }
3462 return TRUE;
3463}
3464
3465static BOOL serialize_pointer(const rdpSettings* settings, WINPR_JSON* json,
3466 FreeRDP_Settings_Keys_Pointer id)
3467{
3468 const char* name = freerdp_settings_get_name_for_key(id);
3469 if (!name)
3470 return FALSE;
3471
3472 WINPR_JSON* jval = WINPR_JSON_AddArrayToObject(json, name);
3473 if (!jval)
3474 return FALSE;
3475
3476 const void* val = freerdp_settings_get_pointer(settings, id);
3477 if (!val)
3478 return TRUE;
3479
3480 switch (id)
3481 {
3482 case FreeRDP_instance:
3483 {
3484 union
3485 {
3486 const void* v;
3487 uintptr_t u;
3488 } ptr;
3489
3490 ptr.v = val;
3491 return fill_array(jval, &ptr.u, sizeof(ptr.u));
3492 }
3493 case FreeRDP_ServerRandom:
3494 {
3495 const uint32_t len = freerdp_settings_get_uint32(settings, FreeRDP_ServerRandomLength);
3496 return fill_array(jval, val, len);
3497 }
3498 case FreeRDP_ServerCertificate:
3499 {
3500 const uint32_t len =
3501 freerdp_settings_get_uint32(settings, FreeRDP_ServerCertificateLength);
3502 return fill_array(jval, val, len);
3503 }
3504 case FreeRDP_ClientRandom:
3505 {
3506 const uint32_t len = freerdp_settings_get_uint32(settings, FreeRDP_ClientRandomLength);
3507 return fill_array(jval, val, len);
3508 }
3509 case FreeRDP_ServerLicenseProductIssuers:
3510 {
3511 const uint32_t len =
3512 freerdp_settings_get_uint32(settings, FreeRDP_ServerLicenseProductIssuersCount);
3513 return string_array_to_json(jval, settings, len, FreeRDP_ServerLicenseProductIssuers);
3514 }
3515 case FreeRDP_RedirectionPassword:
3516 {
3517 const uint32_t len =
3518 freerdp_settings_get_uint32(settings, FreeRDP_RedirectionPasswordLength);
3519 return fill_array(jval, val, len);
3520 }
3521 case FreeRDP_RedirectionGuid:
3522 {
3523 const uint32_t len =
3524 freerdp_settings_get_uint32(settings, FreeRDP_RedirectionGuidLength);
3525 return fill_array(jval, val, len);
3526 }
3527 case FreeRDP_LoadBalanceInfo:
3528 {
3529 const uint32_t len =
3530 freerdp_settings_get_uint32(settings, FreeRDP_LoadBalanceInfoLength);
3531 return fill_array(jval, val, len);
3532 }
3533 case FreeRDP_ClientTimeZone:
3534 {
3535 return tz_info_to_json(jval, val);
3536 }
3537 case FreeRDP_RedirectionTsvUrl:
3538 {
3539 const uint32_t len =
3540 freerdp_settings_get_uint32(settings, FreeRDP_RedirectionTsvUrlLength);
3541 return fill_array(jval, val, len);
3542 }
3543 case FreeRDP_GlyphCache:
3544 {
3545 return glyph_cache_def_array_to_json(jval, val, val ? 10 : 0);
3546 }
3547 case FreeRDP_FragCache:
3548 {
3549 return glyph_cache_def_array_to_json(jval, val, val ? 1 : 0);
3550 }
3551 case FreeRDP_BitmapCacheV2CellInfo:
3552 {
3553 const uint32_t len =
3554 freerdp_settings_get_uint32(settings, FreeRDP_BitmapCacheV2NumCells);
3555 return bitmap_cache_v2_array_to_json(jval, val, len);
3556 }
3557 case FreeRDP_OrderSupport:
3558 {
3559 const uint32_t len = 32;
3560 return fill_array(jval, val, len);
3561 }
3562 case FreeRDP_ClientAutoReconnectCookie:
3563 {
3564 return client_cookie_array_to_json(jval, val, 1);
3565 }
3566 case FreeRDP_ServerAutoReconnectCookie:
3567 {
3568 return server_cookie_array_to_json(jval, val, 1);
3569 }
3570 case FreeRDP_Password51:
3571 {
3572 const uint32_t len = freerdp_settings_get_uint32(settings, FreeRDP_Password51Length);
3573 return fill_array(jval, val, len);
3574 }
3575 case FreeRDP_ReceivedCapabilities:
3576 {
3577 const uint32_t len =
3578 freerdp_settings_get_uint32(settings, FreeRDP_ReceivedCapabilitiesSize);
3579 return fill_array(jval, val, len);
3580 }
3581 case FreeRDP_MonitorIds:
3582 {
3583 const uint32_t len = freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds);
3584 return fill_uint32_array(jval, val, len);
3585 }
3586 case FreeRDP_TargetNetPorts:
3587 {
3588 const uint32_t len =
3589 freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
3590 return fill_uint32_array(jval, val, len);
3591 }
3592 case FreeRDP_MonitorDefArray:
3593 {
3594 const uint32_t len = freerdp_settings_get_uint32(settings, FreeRDP_MonitorDefArraySize);
3595 return monitor_def_array_to_json(jval, val, len);
3596 }
3597 case FreeRDP_ChannelDefArray:
3598 {
3599 const uint32_t len = freerdp_settings_get_uint32(settings, FreeRDP_ChannelDefArraySize);
3600 return channel_def_array_to_json(jval, val, len);
3601 }
3602 case FreeRDP_ReceivedCapabilityDataSizes:
3603 {
3604 const uint32_t len =
3605 freerdp_settings_get_uint32(settings, FreeRDP_ReceivedCapabilitiesSize);
3606 return fill_uint32_array(jval, val, len);
3607 }
3608 case FreeRDP_ReceivedCapabilityData:
3609 {
3610 const uint32_t len =
3611 freerdp_settings_get_uint32(settings, FreeRDP_ReceivedCapabilitiesSize);
3612 const UINT32* pclen =
3613 freerdp_settings_get_pointer(settings, FreeRDP_ReceivedCapabilityDataSizes);
3614 if (!pclen)
3615 return FALSE;
3616
3617 for (uint32_t x = 0; x < len; x++)
3618 {
3619 const char* cval = freerdp_settings_get_pointer_array(settings, id, x);
3620
3621 WINPR_JSON* item = WINPR_JSON_CreateArray();
3622 if (!item)
3623 return FALSE;
3624 if (!WINPR_JSON_AddItemToArray(jval, item))
3625 return FALSE;
3626 if (!fill_array(item, cval, pclen[x]))
3627 return FALSE;
3628 }
3629 return TRUE;
3630 }
3631 case FreeRDP_TargetNetAddresses:
3632 {
3633 const uint32_t len =
3634 freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
3635 return string_array_to_json(jval, settings, len, id);
3636 }
3637 case FreeRDP_RedirectionTargetCertificate:
3638 case FreeRDP_RdpServerCertificate:
3639 {
3640 WINPR_JSON* item = NULL;
3641 size_t len = 0;
3642 char* pem = freerdp_certificate_get_pem(val, &len);
3643 if (pem)
3644 item = WINPR_JSON_CreateString(pem);
3645 else if (val)
3646 item = WINPR_JSON_CreateString("");
3647 else
3648 item = WINPR_JSON_CreateNull();
3649 free(pem);
3650 if (!item)
3651 return TRUE;
3652
3653 return WINPR_JSON_AddItemToArray(jval, item);
3654 }
3655 case FreeRDP_RdpServerRsaKey:
3656 {
3657 WINPR_JSON* item = NULL;
3658 size_t len = 0;
3659 char* pem = freerdp_key_get_pem(val, &len, NULL);
3660 if (pem)
3661 item = WINPR_JSON_CreateString(pem);
3662 free(pem);
3663 if (!item)
3664 return TRUE;
3665
3666 return WINPR_JSON_AddItemToArray(jval, item);
3667 }
3668 case FreeRDP_DeviceArray:
3669 {
3670 const uint32_t len = freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize);
3671 return json_from_device_item_array(jval, settings, id, len);
3672 }
3673 case FreeRDP_StaticChannelArray:
3674 {
3675 const uint32_t len =
3676 freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
3677 return json_from_addin_item_array(jval, settings, id, len);
3678 }
3679 case FreeRDP_DynamicChannelArray:
3680 {
3681 const uint32_t len =
3682 freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
3683 return json_from_addin_item_array(jval, settings, id, len);
3684 }
3685 case FreeRDP_POINTER_UNUSED:
3686 default:
3687 return FALSE;
3688 }
3689}
3690
3691char* freerdp_settings_serialize(const rdpSettings* settings, BOOL pretty, size_t* plength)
3692{
3693 char* str = NULL;
3694
3695 if (plength)
3696 *plength = 0;
3697
3698 if (!settings)
3699 return NULL;
3700
3701 WINPR_JSON* json = WINPR_JSON_CreateObject();
3702 if (!json)
3703 return NULL;
3704
3705 WINPR_JSON* jbool = WINPR_JSON_AddObjectToObject(
3706 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_BOOL));
3707 if (!jbool)
3708 goto fail;
3709 WINPR_JSON* juint16 = WINPR_JSON_AddObjectToObject(
3710 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_UINT16));
3711 if (!juint16)
3712 goto fail;
3713 WINPR_JSON* jint16 = WINPR_JSON_AddObjectToObject(
3714 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_INT16));
3715 if (!jint16)
3716 goto fail;
3717 WINPR_JSON* juint32 = WINPR_JSON_AddObjectToObject(
3718 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_UINT32));
3719 if (!juint32)
3720 goto fail;
3721 WINPR_JSON* jint32 = WINPR_JSON_AddObjectToObject(
3722 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_INT32));
3723 if (!jint32)
3724 goto fail;
3725 WINPR_JSON* juint64 = WINPR_JSON_AddObjectToObject(
3726 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_UINT64));
3727 if (!juint64)
3728 goto fail;
3729 WINPR_JSON* jint64 = WINPR_JSON_AddObjectToObject(
3730 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_INT64));
3731 if (!jint64)
3732 goto fail;
3733 WINPR_JSON* jstring = WINPR_JSON_AddObjectToObject(
3734 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_STRING));
3735 if (!jstring)
3736 goto fail;
3737 WINPR_JSON* jpointer = WINPR_JSON_AddObjectToObject(
3738 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_POINTER));
3739 if (!jpointer)
3740 goto fail;
3741
3742 for (SSIZE_T x = 0; x < FreeRDP_Settings_StableAPI_MAX; x++)
3743 {
3744 union
3745 {
3746
3747 int i;
3748 SSIZE_T s;
3749 FreeRDP_Settings_Keys_Bool b;
3750 FreeRDP_Settings_Keys_Int16 i16;
3751 FreeRDP_Settings_Keys_UInt16 u16;
3752 FreeRDP_Settings_Keys_Int32 i32;
3753 FreeRDP_Settings_Keys_UInt32 u32;
3754 FreeRDP_Settings_Keys_Int64 i64;
3755 FreeRDP_Settings_Keys_UInt64 u64;
3756 FreeRDP_Settings_Keys_String str;
3757 FreeRDP_Settings_Keys_Pointer ptr;
3758 } iter;
3759 iter.s = x;
3760
3761 const char* name = freerdp_settings_get_name_for_key(iter.s);
3762 SSIZE_T type = freerdp_settings_get_type_for_key(iter.s);
3763 switch (type)
3764 {
3765 case RDP_SETTINGS_TYPE_BOOL:
3766 {
3767 const BOOL val = freerdp_settings_get_bool(settings, iter.b);
3768 if (!WINPR_JSON_AddBoolToObject(jbool, name, val))
3769 goto fail;
3770 }
3771 break;
3772 case RDP_SETTINGS_TYPE_UINT16:
3773 {
3774 const uint16_t val = freerdp_settings_get_uint16(settings, iter.u16);
3775 if (!WINPR_JSON_AddNumberToObject(juint16, name, (double)val))
3776 goto fail;
3777 }
3778 break;
3779 case RDP_SETTINGS_TYPE_INT16:
3780 {
3781 const int16_t val = freerdp_settings_get_int16(settings, iter.i16);
3782 if (!WINPR_JSON_AddNumberToObject(jint16, name, (double)val))
3783 goto fail;
3784 }
3785 break;
3786 case RDP_SETTINGS_TYPE_UINT32:
3787 {
3788 const uint32_t val = freerdp_settings_get_uint32(settings, iter.u32);
3789 if (!WINPR_JSON_AddNumberToObject(juint32, name, (double)val))
3790 goto fail;
3791 }
3792 break;
3793 case RDP_SETTINGS_TYPE_INT32:
3794 {
3795 const int32_t val = freerdp_settings_get_int32(settings, iter.i32);
3796 if (!WINPR_JSON_AddNumberToObject(jint32, name, (double)val))
3797 goto fail;
3798 }
3799 break;
3800 case RDP_SETTINGS_TYPE_UINT64:
3801 {
3802 const uint64_t val = freerdp_settings_get_uint64(settings, iter.u64);
3803 if (!WINPR_JSON_AddNumberToObject(juint64, name, (double)val))
3804 goto fail;
3805 }
3806 break;
3807 case RDP_SETTINGS_TYPE_INT64:
3808 {
3809 const int64_t val = freerdp_settings_get_int64(settings, iter.i64);
3810 if (!WINPR_JSON_AddNumberToObject(jint64, name, (double)val))
3811 goto fail;
3812 }
3813 break;
3814 case RDP_SETTINGS_TYPE_STRING:
3815 {
3816 const char* val = freerdp_settings_get_string(settings, iter.str);
3817 if (val)
3818 {
3819 if (!WINPR_JSON_AddStringToObject(jstring, name, val))
3820 goto fail;
3821 }
3822 else
3823 {
3824 (void)WINPR_JSON_AddNullToObject(jstring, name);
3825 }
3826 }
3827 break;
3828 case RDP_SETTINGS_TYPE_POINTER:
3829 if (!serialize_pointer(settings, jpointer, iter.ptr))
3830 goto fail;
3831 break;
3832 default:
3833 break;
3834 }
3835 }
3836
3837 if (pretty)
3838 str = WINPR_JSON_Print(json);
3839 else
3840 str = WINPR_JSON_PrintUnformatted(json);
3841
3842 if (!str)
3843 goto fail;
3844 if (plength)
3845 *plength = strlen(str);
3846
3847fail:
3848 WINPR_JSON_Delete(json);
3849 return str;
3850}
3851
3852static BOOL val_from_array(rdpSettings* settings, const WINPR_JSON* json,
3853 FreeRDP_Settings_Keys_Pointer key, size_t esize)
3854{
3855 if (WINPR_JSON_IsNull(json))
3856 return freerdp_settings_set_pointer(settings, key, NULL);
3857 if (!WINPR_JSON_IsArray(json))
3858 return FALSE;
3859
3860 size_t len = WINPR_JSON_GetArraySize(json);
3861 if (len == 0)
3862 return freerdp_settings_set_pointer(settings, key, NULL);
3863
3864 size_t count = len / esize;
3865 if (count * esize != len)
3866 return FALSE;
3867
3868 if (!freerdp_settings_set_pointer_len(settings, key, NULL, count))
3869 return FALSE;
3870
3871 BYTE* data = freerdp_settings_get_pointer_writable(settings, key);
3872 if (!data)
3873 return FALSE;
3874
3875 errno = 0;
3876 for (size_t x = 0; x < len; x++)
3877 {
3878 WINPR_JSON* val = WINPR_JSON_GetArrayItem(json, x);
3879 data[x] = (uint8_t)uint_from_json_item(val, UINT8_MAX);
3880 }
3881
3882 return errno == 0;
3883}
3884
3885static BOOL uintptr_from_array(rdpSettings* settings, const WINPR_JSON* json)
3886{
3887 FreeRDP_Settings_Keys_Pointer key = FreeRDP_instance;
3888 if (!json || !WINPR_JSON_IsArray(json))
3889 return FALSE;
3890
3891 size_t len = WINPR_JSON_GetArraySize(json);
3892 if (len > sizeof(void*))
3893 return FALSE;
3894
3895 if (len == 0)
3896 return freerdp_settings_set_pointer(settings, key, NULL);
3897
3898 union
3899 {
3900 void* v;
3901 uint8_t u[sizeof(void*)];
3902 } ptr;
3903
3904 errno = 0;
3905 for (size_t x = 0; x < len; x++)
3906 {
3907 WINPR_JSON* val = WINPR_JSON_GetArrayItem(json, x);
3908 ptr.u[x] = (uint8_t)uint_from_json_item(val, UINT8_MAX);
3909 }
3910 if (errno != 0)
3911 return FALSE;
3912 return freerdp_settings_set_pointer(settings, key, ptr.v);
3913}
3914
3915static BOOL val_from_uint32_array(rdpSettings* settings, const WINPR_JSON* json,
3916 FreeRDP_Settings_Keys_Pointer key,
3917 FreeRDP_Settings_Keys_UInt32 keyId)
3918{
3919 if (WINPR_JSON_IsNull(json))
3920 return freerdp_settings_set_pointer(settings, key, NULL);
3921 if (!WINPR_JSON_IsArray(json))
3922 return FALSE;
3923
3924 const size_t len = WINPR_JSON_GetArraySize(json);
3925 if ((FreeRDP_UINT32_UNUSED != keyId) && (freerdp_settings_get_uint32(settings, keyId) != len))
3926 {
3927 if (!freerdp_settings_set_pointer_len(settings, key, NULL, len))
3928 return FALSE;
3929 }
3930
3931 errno = 0;
3932 for (size_t x = 0; x < len; x++)
3933 {
3934 UINT32* data = freerdp_settings_get_pointer_array_writable(settings, key, x);
3935 if (!data)
3936 return FALSE;
3937
3938 WINPR_JSON* val = WINPR_JSON_GetArrayItem(json, x);
3939 data[0] = (uint32_t)uint_from_json_item(val, UINT32_MAX);
3940 }
3941 return errno == 0;
3942}
3943
3944static BOOL caps_data_entry_from_json(rdpSettings* settings, size_t offset, const WINPR_JSON* json)
3945{
3946 if (!json || !WINPR_JSON_IsArray(json))
3947 return FALSE;
3948
3949 const size_t size = WINPR_JSON_GetArraySize(json);
3950 if (size == 0)
3951 {
3952 return freerdp_settings_set_pointer_array(settings, FreeRDP_ReceivedCapabilityData, offset,
3953 NULL);
3954 }
3955
3956 uint8_t* data = calloc(size, sizeof(uint8_t));
3957 if (!data)
3958 return FALSE;
3959
3960 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_ReceivedCapabilityData, offset, data))
3961 {
3962 free(data);
3963 return FALSE;
3964 }
3965
3966 errno = 0;
3967 for (size_t x = 0; x < size; x++)
3968 {
3969 WINPR_JSON* item = WINPR_JSON_GetArrayItem(json, x);
3970 data[x] = (uint8_t)uint_from_json_item(item, UINT8_MAX);
3971 }
3972
3973 // NOLINTNEXTLINE(clang-analyzer-unix.Malloc)
3974 return errno == 0;
3975}
3976
3977static BOOL caps_data_array_from_json(rdpSettings* settings, const WINPR_JSON* json)
3978{
3979 if (!json || !WINPR_JSON_IsArray(json))
3980 return FALSE;
3981
3982 const size_t count = WINPR_JSON_GetArraySize(json);
3983 if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ReceivedCapabilityData, NULL, count))
3984 return FALSE;
3985
3986 for (uint32_t x = 0; x < count; x++)
3987 {
3988 WINPR_JSON* array = WINPR_JSON_GetArrayItem(json, x);
3989 if (!caps_data_entry_from_json(settings, x, array))
3990 return FALSE;
3991 }
3992 return TRUE;
3993}
3994
3995static BOOL str_array_from_json(rdpSettings* settings, const WINPR_JSON* json,
3996 FreeRDP_Settings_Keys_Pointer key)
3997{
3998 if (WINPR_JSON_IsNull(json))
3999 return freerdp_settings_set_pointer_len(settings, key, NULL, 0);
4000 if (!WINPR_JSON_IsArray(json))
4001 return FALSE;
4002
4003 size_t len = WINPR_JSON_GetArraySize(json);
4004 if (!freerdp_settings_set_pointer_len(settings, key, NULL, len))
4005 return FALSE;
4006
4007 for (size_t x = 0; x < len; x++)
4008 {
4009 WINPR_JSON* cval = WINPR_JSON_GetArrayItem(json, x);
4010 if (!cval)
4011 return FALSE;
4012 if (!WINPR_JSON_IsString(cval))
4013 return FALSE;
4014
4015 const char* val = WINPR_JSON_GetStringValue(cval);
4016 if (!freerdp_settings_set_pointer_array(settings, key, x, val))
4017 return FALSE;
4018 }
4019 return TRUE;
4020}
4021
4022static BOOL addin_argv_from_json(rdpSettings* settings, const WINPR_JSON* json,
4023 FreeRDP_Settings_Keys_Pointer key)
4024{
4025 if (WINPR_JSON_IsNull(json))
4026 return freerdp_settings_set_pointer(settings, key, NULL);
4027
4028 if (!WINPR_JSON_IsArray(json))
4029 return FALSE;
4030
4031 size_t len = WINPR_JSON_GetArraySize(json);
4032 if (!freerdp_settings_set_pointer_len(settings, key, NULL, len))
4033 return FALSE;
4034
4035 for (size_t x = 0; x < len; x++)
4036 {
4037 WINPR_JSON* val = WINPR_JSON_GetArrayItem(json, x);
4038 if (val && WINPR_JSON_IsObject(val))
4039 {
4040 WINPR_JSON* jargc = WINPR_JSON_GetObjectItem(val, "argc");
4041 WINPR_JSON* array = WINPR_JSON_GetObjectItem(val, "argv");
4042 if (!jargc || !array)
4043 continue;
4044 if (!WINPR_JSON_IsNumber(jargc) || !WINPR_JSON_IsArray(array))
4045 continue;
4046
4047 const int argc = (int)int_from_json_item(jargc, INT32_MIN, INT32_MAX);
4048 if (errno != 0)
4049 return FALSE;
4050 const size_t jlen = WINPR_JSON_GetArraySize(array);
4051 if (jlen != (size_t)argc)
4052 return FALSE;
4053 if (jlen == 0)
4054 continue;
4055
4056 const char** argv = (const char**)calloc(jlen, sizeof(char*));
4057 if (!argv)
4058 return FALSE;
4059 for (size_t y = 0; y < jlen; y++)
4060 {
4061 WINPR_JSON* item = WINPR_JSON_GetArrayItem(array, y);
4062 if (!item || !WINPR_JSON_IsString(item))
4063 {
4064 free((void*)argv);
4065 return FALSE;
4066 }
4067 argv[y] = WINPR_JSON_GetStringValue(item);
4068 }
4069
4070 ADDIN_ARGV* cval = freerdp_addin_argv_new(jlen, argv);
4071 free((void*)argv);
4072 if (!cval)
4073 return FALSE;
4074 const BOOL rc = freerdp_settings_set_pointer_array(settings, key, x, cval);
4075 freerdp_addin_argv_free(cval);
4076 if (!rc)
4077 return FALSE;
4078 }
4079 }
4080 return TRUE;
4081}
4082
4083static char* get_string(const WINPR_JSON* json, const char* key)
4084{
4085 WINPR_JSON* item = WINPR_JSON_GetObjectItem(json, key);
4086 if (!item || !WINPR_JSON_IsString(item))
4087 return NULL;
4088 const char* str = WINPR_JSON_GetStringValue(item);
4089 return WINPR_CAST_CONST_PTR_AWAY(str, char*);
4090}
4091
4092static BOOL get_bool(const WINPR_JSON* json, const char* key)
4093{
4094 WINPR_JSON* item = WINPR_JSON_GetObjectItem(json, key);
4095 if (!item || !WINPR_JSON_IsBool(item))
4096 return FALSE;
4097 return WINPR_JSON_IsTrue(item);
4098}
4099
4100static BOOL device_from_json_item(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer key,
4101 size_t offset, const WINPR_JSON* val)
4102{
4103 if (!val || !WINPR_JSON_IsObject(val))
4104 return FALSE;
4105
4106 union
4107 {
4108 RDPDR_DEVICE base;
4109 RDPDR_PARALLEL parallel;
4110 RDPDR_SERIAL serial;
4111 RDPDR_SMARTCARD smartcard;
4112 RDPDR_PRINTER printer;
4113 RDPDR_DRIVE drive;
4114 RDPDR_DEVICE device;
4115 } device;
4116
4117 memset(&device, 0, sizeof(device));
4118
4119 errno = 0;
4120 device.base.Id = (uint32_t)uint_from_json(val, "Id", UINT32_MAX);
4121 device.base.Type = (uint32_t)uint_from_json(val, "Type", UINT32_MAX);
4122 if (errno != 0)
4123 return FALSE;
4124 device.base.Name = get_string(val, "Name");
4125 if (!device.base.Name)
4126 return FALSE;
4127
4128 switch (device.base.Type)
4129 {
4130 case RDPDR_DTYP_SERIAL:
4131 device.serial.Path = get_string(val, "Path");
4132 device.serial.Driver = get_string(val, "Driver");
4133 device.serial.Permissive = get_string(val, "Permissive");
4134 break;
4135 case RDPDR_DTYP_PARALLEL:
4136 device.parallel.Path = get_string(val, "Path");
4137 break;
4138 case RDPDR_DTYP_PRINT:
4139 device.printer.DriverName = get_string(val, "DriverName");
4140 device.printer.IsDefault = get_bool(val, "IsDefault");
4141 break;
4142 case RDPDR_DTYP_FILESYSTEM:
4143 device.drive.Path = get_string(val, "Path");
4144 device.drive.automount = get_bool(val, "automount");
4145 break;
4146 case RDPDR_DTYP_SMARTCARD:
4147 default:
4148 break;
4149 }
4150 return freerdp_settings_set_pointer_array(settings, key, offset, &device);
4151}
4152
4153static BOOL device_array_from_json(rdpSettings* settings, const WINPR_JSON* json,
4154 FreeRDP_Settings_Keys_Pointer key)
4155{
4156 if (WINPR_JSON_IsNull(json))
4157 return freerdp_settings_set_pointer(settings, key, NULL);
4158
4159 if (!WINPR_JSON_IsArray(json))
4160 return FALSE;
4161
4162 size_t len = WINPR_JSON_GetArraySize(json);
4163 if (!freerdp_settings_set_pointer_len(settings, key, NULL, len))
4164 return FALSE;
4165
4166 for (size_t x = 0; x < len; x++)
4167 {
4168 WINPR_JSON* val = WINPR_JSON_GetArrayItem(json, x);
4169 if (!device_from_json_item(settings, key, x, val))
4170 return FALSE;
4171 }
4172 return TRUE;
4173}
4174
4175static const char* pem_from_json(const WINPR_JSON* jval, size_t* plen, BOOL* pvalid)
4176{
4177 WINPR_ASSERT(jval);
4178 WINPR_ASSERT(plen);
4179 WINPR_ASSERT(pvalid);
4180
4181 *pvalid = FALSE;
4182 *plen = 0;
4183
4184 if (WINPR_JSON_IsNull(jval))
4185 return NULL;
4186
4187 size_t len = WINPR_JSON_GetArraySize(jval);
4188 if (len == 0)
4189 {
4190 *pvalid = TRUE;
4191 return NULL;
4192 }
4193
4194 WINPR_JSON* item = WINPR_JSON_GetArrayItem(jval, 0);
4195 if (!item)
4196 return NULL;
4197 if (!WINPR_JSON_IsString(item))
4198 return NULL;
4199
4200 *plen = len;
4201 *pvalid = TRUE;
4202 return WINPR_JSON_GetStringValue(item);
4203}
4204
4205static BOOL deserialize_pointer(const WINPR_JSON* json, rdpSettings* settings,
4206 FreeRDP_Settings_Keys_Pointer id)
4207{
4208 const char* name = freerdp_settings_get_name_for_key(id);
4209 if (!name)
4210 return FALSE;
4211
4212 if (!WINPR_JSON_HasObjectItem(json, name))
4213 return FALSE;
4214
4215 WINPR_JSON* jval = WINPR_JSON_GetObjectItem(json, name);
4216 if (!WINPR_JSON_IsNull(jval) && !WINPR_JSON_IsArray(jval))
4217 return FALSE;
4218
4219 switch (id)
4220 {
4221 case FreeRDP_instance:
4222 return uintptr_from_array(settings, jval);
4223 case FreeRDP_ServerRandom:
4224 case FreeRDP_ServerCertificate:
4225 case FreeRDP_ClientRandom:
4226 case FreeRDP_RedirectionPassword:
4227 case FreeRDP_RedirectionGuid:
4228 case FreeRDP_LoadBalanceInfo:
4229 case FreeRDP_RedirectionTsvUrl:
4230 case FreeRDP_OrderSupport:
4231 case FreeRDP_Password51:
4232 return val_from_array(settings, jval, id, 1);
4233 case FreeRDP_ReceivedCapabilities:
4234 return val_from_array(settings, jval, id, 1);
4235 case FreeRDP_ClientTimeZone:
4236 return ts_info_array_from_json(settings, id, jval);
4237 case FreeRDP_GlyphCache:
4238 return glyph_cache_def_array_from_json(settings, id, jval);
4239 case FreeRDP_FragCache:
4240 return glyph_cache_def_array_from_json(settings, id, jval);
4241 case FreeRDP_BitmapCacheV2CellInfo:
4242 return bitmap_cache_v2_array_from_json(settings, id, jval);
4243 case FreeRDP_ClientAutoReconnectCookie:
4244 return client_cookie_array_from_json(settings, id, jval);
4245 case FreeRDP_ServerAutoReconnectCookie:
4246 return server_cookie_array_from_json(settings, id, jval);
4247 case FreeRDP_MonitorDefArray:
4248 return monitor_def_array_from_json(settings, id, jval);
4249 case FreeRDP_ChannelDefArray:
4250 return channel_def_array_from_json(settings, id, jval);
4251 case FreeRDP_MonitorIds:
4252 return val_from_uint32_array(settings, jval, id, FreeRDP_NumMonitorIds);
4253 case FreeRDP_TargetNetPorts:
4254 return val_from_uint32_array(settings, jval, id, FreeRDP_TargetNetAddressCount);
4255 case FreeRDP_ServerLicenseProductIssuers:
4256 case FreeRDP_TargetNetAddresses:
4257 return str_array_from_json(settings, jval, id);
4258 case FreeRDP_ReceivedCapabilityDataSizes:
4259 return val_from_uint32_array(settings, jval, id, FreeRDP_ReceivedCapabilitiesSize);
4260 case FreeRDP_ReceivedCapabilityData:
4261 return caps_data_array_from_json(settings, jval);
4262 case FreeRDP_RedirectionTargetCertificate:
4263 case FreeRDP_RdpServerCertificate:
4264 {
4265 size_t len = 0;
4266 BOOL valid = FALSE;
4267 const char* pem = pem_from_json(jval, &len, &valid);
4268 if (!valid)
4269 return FALSE;
4270 if (!freerdp_settings_set_pointer_len(settings, id, NULL, len))
4271 return FALSE;
4272
4273 rdpCertificate* cert = NULL;
4274 if (!pem)
4275 return TRUE;
4276
4277 if (strnlen(pem, 2) == 0)
4278 cert = freerdp_certificate_new();
4279 else
4280 cert = freerdp_certificate_new_from_pem(pem);
4281 if (!cert)
4282 return FALSE;
4283 return freerdp_settings_set_pointer_len(settings, id, cert, 1);
4284 }
4285 case FreeRDP_RdpServerRsaKey:
4286 {
4287 size_t len = 0;
4288 BOOL valid = FALSE;
4289 const char* pem = pem_from_json(jval, &len, &valid);
4290 if (!valid)
4291 return FALSE;
4292 if (!freerdp_settings_set_pointer_len(settings, id, NULL, len))
4293 return FALSE;
4294 if (!pem)
4295 return TRUE;
4296
4297 rdpPrivateKey* key = freerdp_key_new_from_pem_enc(pem, NULL);
4298 if (!key)
4299 return FALSE;
4300 return freerdp_settings_set_pointer_len(settings, id, key, 1);
4301 }
4302 case FreeRDP_DeviceArray:
4303 return device_array_from_json(settings, jval, id);
4304 case FreeRDP_StaticChannelArray:
4305 case FreeRDP_DynamicChannelArray:
4306 return addin_argv_from_json(settings, jval, id);
4307 case FreeRDP_POINTER_UNUSED:
4308 default:
4309 return TRUE;
4310 }
4311}
4312
4313rdpSettings* freerdp_settings_deserialize(const char* jstr, size_t length)
4314{
4315 WINPR_JSON* json = WINPR_JSON_ParseWithLength(jstr, length);
4316 if (!json)
4317 return NULL;
4318 rdpSettings* settings = freerdp_settings_new(0);
4319 if (!settings)
4320 goto fail;
4321
4322 WINPR_JSON* jbool = WINPR_JSON_GetObjectItem(
4323 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_BOOL));
4324 if (!jbool)
4325 goto fail;
4326 WINPR_JSON* juint16 = WINPR_JSON_GetObjectItem(
4327 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_UINT16));
4328 if (!juint16)
4329 goto fail;
4330 WINPR_JSON* jint16 = WINPR_JSON_GetObjectItem(
4331 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_INT16));
4332 if (!jint16)
4333 goto fail;
4334 WINPR_JSON* juint32 = WINPR_JSON_GetObjectItem(
4335 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_UINT32));
4336 if (!juint32)
4337 goto fail;
4338 WINPR_JSON* jint32 = WINPR_JSON_GetObjectItem(
4339 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_INT32));
4340 if (!jint32)
4341 goto fail;
4342 WINPR_JSON* juint64 = WINPR_JSON_GetObjectItem(
4343 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_UINT64));
4344 if (!juint64)
4345 goto fail;
4346 WINPR_JSON* jint64 = WINPR_JSON_GetObjectItem(
4347 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_INT64));
4348 if (!jint64)
4349 goto fail;
4350 WINPR_JSON* jstring = WINPR_JSON_GetObjectItem(
4351 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_STRING));
4352 if (!jstring)
4353 goto fail;
4354 WINPR_JSON* jpointer = WINPR_JSON_GetObjectItem(
4355 json, freerdp_settings_get_type_name_for_type(RDP_SETTINGS_TYPE_POINTER));
4356 if (!jpointer)
4357 goto fail;
4358
4359 for (SSIZE_T x = 0; x < FreeRDP_Settings_StableAPI_MAX; x++)
4360 {
4361 union
4362 {
4363
4364 int i;
4365 SSIZE_T s;
4366 FreeRDP_Settings_Keys_Bool b;
4367 FreeRDP_Settings_Keys_Int16 i16;
4368 FreeRDP_Settings_Keys_UInt16 u16;
4369 FreeRDP_Settings_Keys_Int32 i32;
4370 FreeRDP_Settings_Keys_UInt32 u32;
4371 FreeRDP_Settings_Keys_Int64 i64;
4372 FreeRDP_Settings_Keys_UInt64 u64;
4373 FreeRDP_Settings_Keys_String str;
4374 FreeRDP_Settings_Keys_Pointer ptr;
4375 } iter;
4376 iter.s = x;
4377
4378 SSIZE_T type = freerdp_settings_get_type_for_key(iter.s);
4379 switch (type)
4380 {
4381 case RDP_SETTINGS_TYPE_POINTER:
4382 if (!deserialize_pointer(jpointer, settings, iter.ptr))
4383 goto fail;
4384 break;
4385 default:
4386 break;
4387 }
4388 }
4389
4390 for (SSIZE_T x = 0; x < FreeRDP_Settings_StableAPI_MAX; x++)
4391 {
4392 union
4393 {
4394
4395 int i;
4396 SSIZE_T s;
4397 FreeRDP_Settings_Keys_Bool b;
4398 FreeRDP_Settings_Keys_Int16 i16;
4399 FreeRDP_Settings_Keys_UInt16 u16;
4400 FreeRDP_Settings_Keys_Int32 i32;
4401 FreeRDP_Settings_Keys_UInt32 u32;
4402 FreeRDP_Settings_Keys_Int64 i64;
4403 FreeRDP_Settings_Keys_UInt64 u64;
4404 FreeRDP_Settings_Keys_String str;
4405 FreeRDP_Settings_Keys_Pointer ptr;
4406 } iter;
4407 iter.s = x;
4408
4409 const char* name = freerdp_settings_get_name_for_key(iter.s);
4410 SSIZE_T type = freerdp_settings_get_type_for_key(iter.s);
4411 switch (type)
4412 {
4413 case RDP_SETTINGS_TYPE_BOOL:
4414 {
4415 WINPR_JSON* item = WINPR_JSON_GetObjectItem(jbool, name);
4416 if (!item)
4417 goto fail;
4418 if (!WINPR_JSON_IsBool(item))
4419 goto fail;
4420 const BOOL val = WINPR_JSON_IsTrue(item);
4421 if (!freerdp_settings_set_bool(settings, iter.b, val))
4422 goto fail;
4423 }
4424 break;
4425 case RDP_SETTINGS_TYPE_UINT16:
4426 {
4427 WINPR_JSON* item = WINPR_JSON_GetObjectItem(juint16, name);
4428 const uint16_t val = (uint16_t)uint_from_json_item(item, UINT16_MAX);
4429 if (errno != 0)
4430 goto fail;
4431 if (!freerdp_settings_set_uint16(settings, iter.u16, val))
4432 goto fail;
4433 }
4434 break;
4435 case RDP_SETTINGS_TYPE_INT16:
4436 {
4437 WINPR_JSON* item = WINPR_JSON_GetObjectItem(jint16, name);
4438 const int16_t val = (int16_t)int_from_json_item(item, INT16_MIN, INT16_MAX);
4439 if (errno != 0)
4440 goto fail;
4441 if (!freerdp_settings_set_int16(settings, iter.i16, val))
4442 goto fail;
4443 }
4444 break;
4445 case RDP_SETTINGS_TYPE_UINT32:
4446 {
4447 WINPR_JSON* item = WINPR_JSON_GetObjectItem(juint32, name);
4448 const uint32_t val = (uint32_t)uint_from_json_item(item, UINT32_MAX);
4449 if (errno != 0)
4450 goto fail;
4451 if (!freerdp_settings_set_uint32(settings, iter.u32, val))
4452 goto fail;
4453 }
4454 break;
4455 case RDP_SETTINGS_TYPE_INT32:
4456 {
4457 const int64_t val = int_from_json(jint32, name, INT32_MIN, INT32_MAX);
4458 if (errno != 0)
4459 goto fail;
4460 if (!freerdp_settings_set_int32(settings, iter.i32, (int32_t)val))
4461 goto fail;
4462 }
4463 break;
4464 case RDP_SETTINGS_TYPE_UINT64:
4465 {
4466 const uint64_t val = uint_from_json(juint64, name, UINT64_MAX);
4467 if (errno != 0)
4468 goto fail;
4469 if (!freerdp_settings_set_uint64(settings, iter.u64, val))
4470 goto fail;
4471 }
4472 break;
4473 case RDP_SETTINGS_TYPE_INT64:
4474 {
4475 WINPR_JSON* item = WINPR_JSON_GetObjectItem(jint64, name);
4476 const int64_t val = int_from_json_item(item, INT64_MIN, INT64_MAX);
4477 if (errno != 0)
4478 goto fail;
4479 if (!freerdp_settings_set_int64(settings, iter.i64, val))
4480 goto fail;
4481 }
4482 break;
4483 case RDP_SETTINGS_TYPE_STRING:
4484 {
4485 const char* val = NULL;
4486 WINPR_JSON* item = WINPR_JSON_GetObjectItem(jstring, name);
4487 if (item && !WINPR_JSON_IsNull(item))
4488 {
4489 if (!WINPR_JSON_IsString(item))
4490 goto fail;
4491 val = WINPR_JSON_GetStringValue(item);
4492 if (!val)
4493 goto fail;
4494 }
4495 if (!freerdp_settings_set_string(settings, iter.str, val))
4496 goto fail;
4497 }
4498 break;
4499 case RDP_SETTINGS_TYPE_POINTER:
4500 default:
4501 break;
4502 }
4503 }
4504
4505 WINPR_JSON_Delete(json);
4506 return settings;
4507
4508fail:
4509 freerdp_settings_free(settings);
4510 WINPR_JSON_Delete(json);
4511 return NULL;
4512}
WINPR_API WINPR_JSON * WINPR_JSON_CreateString(const char *string)
WINPR_JSON_CreateString.
Definition json.c:441
WINPR_API BOOL WINPR_JSON_HasObjectItem(const WINPR_JSON *object, const char *string)
Check if JSON has an object matching the name.
Definition json.c:209
WINPR_API WINPR_JSON * WINPR_JSON_AddNumberToObject(WINPR_JSON *object, const char *name, double number)
WINPR_JSON_AddNumberToObject.
Definition json.c:552
WINPR_API BOOL WINPR_JSON_IsNull(const WINPR_JSON *item)
Check if JSON item is Null.
Definition json.c:323
WINPR_API WINPR_JSON * WINPR_JSON_GetObjectItem(const WINPR_JSON *object, const char *string)
Return a pointer to an JSON object item.
Definition json.c:183
WINPR_API BOOL WINPR_JSON_IsString(const WINPR_JSON *item)
Check if JSON item is of type String.
Definition json.c:348
WINPR_API BOOL WINPR_JSON_AddItemToArray(WINPR_JSON *array, WINPR_JSON *item)
Add an item to an existing array.
Definition json.c:611
WINPR_API WINPR_JSON * WINPR_JSON_AddArrayToObject(WINPR_JSON *object, const char *name)
WINPR_JSON_AddArrayToObject.
Definition json.c:634
WINPR_API BOOL WINPR_JSON_IsBool(const WINPR_JSON *item)
Check if JSON item is of type BOOL.
Definition json.c:311
WINPR_API double WINPR_JSON_GetNumberValue(const WINPR_JSON *item)
Return the Number value of a JSON item.
Definition json.c:245
WINPR_API WINPR_JSON * WINPR_JSON_CreateObject(void)
WINPR_JSON_CreateObject.
Definition json.c:464
WINPR_API WINPR_JSON * WINPR_JSON_CreateArray(void)
WINPR_JSON_CreateArray.
Definition json.c:453
WINPR_API char * WINPR_JSON_Print(WINPR_JSON *item)
Serialize a JSON instance to string for minimal size without formatting see WINPR_JSON_PrintUnformatt...
Definition json.c:653
WINPR_API BOOL WINPR_JSON_IsNumber(const WINPR_JSON *item)
Check if JSON item is of type Number.
Definition json.c:335
WINPR_API WINPR_JSON * WINPR_JSON_GetArrayItem(const WINPR_JSON *array, size_t index)
Return a pointer to an item in the array.
Definition json.c:154
WINPR_API WINPR_JSON * WINPR_JSON_AddStringToObject(WINPR_JSON *object, const char *name, const char *string)
WINPR_JSON_AddStringToObject.
Definition json.c:572
WINPR_API WINPR_JSON * WINPR_JSON_ParseWithLength(const char *value, size_t buffer_length)
Parse a JSON string.
Definition json.c:124
WINPR_API WINPR_JSON * WINPR_JSON_CreateNumber(double num)
WINPR_JSON_CreateNumber.
Definition json.c:429
WINPR_API BOOL WINPR_JSON_IsObject(const WINPR_JSON *item)
Check if JSON item is of type Object.
Definition json.c:372
WINPR_API WINPR_JSON * WINPR_JSON_AddBoolToObject(WINPR_JSON *object, const char *name, BOOL boolean)
WINPR_JSON_AddBoolToObject.
Definition json.c:532
WINPR_API char * WINPR_JSON_PrintUnformatted(WINPR_JSON *item)
Serialize a JSON instance to string without formatting for human readable formatted output see WINPR_...
Definition json.c:668
WINPR_API WINPR_JSON * WINPR_JSON_CreateNull(void)
WINPR_JSON_CreateNull.
Definition json.c:384
WINPR_API const char * WINPR_JSON_GetStringValue(WINPR_JSON *item)
Return the String value of a JSON item.
Definition json.c:233
WINPR_API WINPR_JSON * WINPR_JSON_AddNullToObject(WINPR_JSON *object, const char *name)
WINPR_JSON_AddNullToObject.
Definition json.c:475
WINPR_API void WINPR_JSON_Delete(WINPR_JSON *item)
Delete a WinPR JSON wrapper object.
Definition json.c:143
WINPR_API size_t WINPR_JSON_GetArraySize(const WINPR_JSON *array)
Get the number of arrayitems from an array.
Definition json.c:168
WINPR_API BOOL WINPR_JSON_IsArray(const WINPR_JSON *item)
Check if JSON item is of type Array.
Definition json.c:360
WINPR_API WINPR_JSON * WINPR_JSON_AddObjectToObject(WINPR_JSON *object, const char *name)
WINPR_JSON_AddObjectToObject.
Definition json.c:592
WINPR_API BOOL WINPR_JSON_IsTrue(const WINPR_JSON *item)
Check if JSON item is BOOL value True.
Definition json.c:296
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
FREERDP_API rdpSettings * freerdp_settings_new(DWORD flags)
creates a new setting struct
FREERDP_API INT64 freerdp_settings_get_int64(const rdpSettings *settings, FreeRDP_Settings_Keys_Int64 id)
Returns a INT64 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.
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.
char * freerdp_settings_serialize(const rdpSettings *settings, BOOL pretty, size_t *plength)
A function that converts a rdpSettings struct to a JSON serialized string.
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_*.
FREERDP_API void freerdp_settings_free(rdpSettings *settings)
Free a settings struct with all data in it.
BOOL freerdp_settings_set_monitor_def_array_sorted(rdpSettings *settings, const rdpMonitor *monitors, size_t count)
Sort monitor array according to:
FREERDP_API UINT16 freerdp_settings_get_uint16(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt16 id)
Returns a UINT16 settings value.
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 const char * freerdp_settings_get_type_name_for_type(SSIZE_T type)
Returns the type name for a type.
FREERDP_API INT16 freerdp_settings_get_int16(const rdpSettings *settings, FreeRDP_Settings_Keys_Int16 id)
Returns a INT16 settings value.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL param)
Sets a BOOL settings value.
rdpSettings * freerdp_settings_deserialize(const char *jstr, size_t length)
A function that converts a JSON string to a rdpSettings struct.