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