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