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