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