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