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