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