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