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