FreeRDP
Loading...
Searching...
No Matches
TestSettings.c
1#include <stdio.h>
2
3#include <winpr/user.h>
4#include <winpr/crypto.h>
5#include <winpr/json.h>
6
7#include <freerdp/crypto/crypto.h>
8#include <freerdp/settings.h>
9#include <freerdp/codecs.h>
10
11#include "settings_property_lists.h"
12#include "../settings.h"
13
14#define log_start() log_start_(__func__)
15static void log_start_(const char* fkt, ...)
16{
17 (void)fprintf(stderr, "TestSettings [");
18 va_list ap = WINPR_C_ARRAY_INIT;
19 va_start(ap, fkt);
20 (void)vfprintf(stderr, fkt, ap);
21 va_end(ap);
22 (void)fprintf(stderr, "] started...\n");
23 (void)fflush(stderr);
24}
25
26#define log_result(value) log_result_((value), __func__)
27static BOOL log_result_(BOOL value, const char* fkt, ...)
28{
29 (void)fprintf(stderr, "TestSettings [");
30 va_list ap = WINPR_C_ARRAY_INIT;
31 va_start(ap, fkt);
32 (void)vfprintf(stderr, fkt, ap);
33 va_end(ap);
34 (void)fprintf(stderr, "] returned %s\n", value ? "TRUE" : "FALSE");
35 (void)fflush(stderr);
36 return value;
37}
38
39static BOOL log_result_case(BOOL value, const char* fkt, size_t testcase)
40{
41 (void)fprintf(stderr, "TestSettings [%s] testcase %" PRIuz " returned %s\n", fkt, testcase,
42 value ? "TRUE" : "FALSE");
43 (void)fflush(stderr);
44 return value;
45}
46
47static BOOL compare(const ADDIN_ARGV* got, const ADDIN_ARGV* expect)
48{
49 BOOL rc = TRUE;
50 if (!got && !expect)
51 return FALSE;
52 if (!got && expect)
53 return FALSE;
54 if (got && !expect)
55 return FALSE;
56 if (got->argc != expect->argc)
57 return FALSE;
58
59 for (int x = 0; x < expect->argc; x++)
60 {
61 if (strcmp(got->argv[x], expect->argv[x]) != 0)
62 rc = FALSE;
63 }
64 return log_result(rc);
65}
66
67static BOOL test_dyn_channels(void)
68{
69 log_start();
70 BOOL rc = FALSE;
71 BOOL test = 0;
72 UINT32 u32 = 0;
73 rdpSettings* settings = freerdp_settings_new(0);
74 const char* argv1[] = { "foobar" };
75 ADDIN_ARGV* args1 = nullptr;
76 const ADDIN_ARGV* cmp1 = nullptr;
77 const char* argv2[] = { "gaga", "abba", "foo" };
78 ADDIN_ARGV* args2 = nullptr;
79 const ADDIN_ARGV* cmp2 = nullptr;
80 const ADDIN_ARGV* got = nullptr;
81
82 if (!settings)
83 goto fail;
84
85 u32 = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
86 if (u32 != 0)
87 goto fail;
88
89 /* Test the function return an error for unknown channels */
90 test = freerdp_dynamic_channel_collection_del(settings, "foobar");
91 if (test)
92 goto fail;
93 got = freerdp_dynamic_channel_collection_find(settings, "foobar");
94 if (got)
95 goto fail;
96
97 /* Add the channel */
98 cmp1 = args1 = freerdp_addin_argv_new(ARRAYSIZE(argv1), argv1);
99 test = freerdp_dynamic_channel_collection_add(settings, args1);
100 if (!test)
101 goto fail;
102 args1 = nullptr; /* settings have taken ownership */
103
104 u32 = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
105 if (u32 != 1)
106 goto fail;
107 u32 = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
108 if (u32 < 1)
109 goto fail;
110
111 cmp2 = args2 = freerdp_addin_argv_new(ARRAYSIZE(argv2), argv2);
112 test = freerdp_dynamic_channel_collection_add(settings, args2);
113 if (!test)
114 goto fail;
115 args2 = nullptr; /* settings have taken ownership */
116
117 u32 = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
118 if (u32 != 2)
119 goto fail;
120 u32 = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
121 if (u32 < 2)
122 goto fail;
123
124 /* Test the function return success for known channels */
125 got = freerdp_dynamic_channel_collection_find(settings, "foobar");
126 if (!compare(got, cmp1))
127 goto fail;
128 got = freerdp_dynamic_channel_collection_find(settings, "gaga");
129 if (!compare(got, cmp2))
130 goto fail;
131 test = freerdp_dynamic_channel_collection_del(settings, "foobar");
132 if (!test)
133 goto fail;
134 u32 = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
135 if (u32 != 1)
136 goto fail;
137 u32 = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
138 if (u32 < 1)
139 goto fail;
140 got = freerdp_dynamic_channel_collection_find(settings, "foobar");
141 if (compare(got, cmp1))
142 goto fail;
143 got = freerdp_dynamic_channel_collection_find(settings, "gaga");
144 if (!compare(got, cmp2))
145 goto fail;
146 test = freerdp_dynamic_channel_collection_del(settings, "gaga");
147 if (!test)
148 goto fail;
149 u32 = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
150 if (u32 != 0)
151 goto fail;
152 got = freerdp_dynamic_channel_collection_find(settings, "foobar");
153 if (compare(got, cmp1))
154 goto fail;
155 got = freerdp_dynamic_channel_collection_find(settings, "gaga");
156 if (compare(got, cmp2))
157 goto fail;
158
159 rc = TRUE;
160
161fail:
162 freerdp_settings_free(settings);
163 freerdp_addin_argv_free(args1);
164 freerdp_addin_argv_free(args2);
165 return log_result(rc);
166}
167
168static BOOL test_static_channels(void)
169{
170 log_start();
171 BOOL rc = FALSE;
172 BOOL test = 0;
173 UINT32 u32 = 0;
174 rdpSettings* settings = freerdp_settings_new(0);
175 const char* argv1[] = { "foobar" };
176 ADDIN_ARGV* args1 = nullptr;
177 const ADDIN_ARGV* cmp1 = nullptr;
178 const char* argv2[] = { "gaga", "abba", "foo" };
179 ADDIN_ARGV* args2 = nullptr;
180 const ADDIN_ARGV* cmp2 = nullptr;
181 const ADDIN_ARGV* got = nullptr;
182
183 if (!settings)
184 goto fail;
185
186 u32 = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
187 if (u32 != 0)
188 goto fail;
189
190 /* Test the function return an error for unknown channels */
191 test = freerdp_static_channel_collection_del(settings, "foobar");
192 if (test)
193 goto fail;
194 got = freerdp_static_channel_collection_find(settings, "foobar");
195 if (got)
196 goto fail;
197
198 /* Add the channel */
199 cmp1 = args1 = freerdp_addin_argv_new(ARRAYSIZE(argv1), argv1);
200 test = freerdp_static_channel_collection_add(settings, args1);
201 if (!test)
202 goto fail;
203 args1 = nullptr; /* settings have taken ownership */
204
205 u32 = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
206 if (u32 != 1)
207 goto fail;
208 u32 = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
209 if (u32 < 1)
210 goto fail;
211
212 cmp2 = args2 = freerdp_addin_argv_new(ARRAYSIZE(argv2), argv2);
213 test = freerdp_static_channel_collection_add(settings, args2);
214 if (!test)
215 goto fail;
216 args2 = nullptr; /* settings have taken ownership */
217
218 u32 = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
219 if (u32 != 2)
220 goto fail;
221 u32 = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
222 if (u32 < 2)
223 goto fail;
224
225 /* Test the function return success for known channels */
226 got = freerdp_static_channel_collection_find(settings, "foobar");
227 if (!compare(got, cmp1))
228 goto fail;
229 got = freerdp_static_channel_collection_find(settings, "gaga");
230 if (!compare(got, cmp2))
231 goto fail;
232 test = freerdp_static_channel_collection_del(settings, "foobar");
233 if (!test)
234 goto fail;
235 u32 = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
236 if (u32 != 1)
237 goto fail;
238 u32 = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
239 if (u32 < 1)
240 goto fail;
241 got = freerdp_static_channel_collection_find(settings, "foobar");
242 if (compare(got, cmp1))
243 goto fail;
244 got = freerdp_static_channel_collection_find(settings, "gaga");
245 if (!compare(got, cmp2))
246 goto fail;
247 test = freerdp_static_channel_collection_del(settings, "gaga");
248 if (!test)
249 goto fail;
250 u32 = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
251 if (u32 != 0)
252 goto fail;
253 got = freerdp_static_channel_collection_find(settings, "foobar");
254 if (compare(got, cmp1))
255 goto fail;
256 got = freerdp_static_channel_collection_find(settings, "gaga");
257 if (compare(got, cmp2))
258 goto fail;
259
260 rc = TRUE;
261
262fail:
263 freerdp_settings_free(settings);
264 freerdp_addin_argv_free(args1);
265 freerdp_addin_argv_free(args2);
266 return log_result(rc);
267}
268
269static BOOL test_copy(void)
270{
271 log_start();
272 BOOL rc = FALSE;
273 wLog* log = WLog_Get(__func__);
274 rdpSettings* settings = freerdp_settings_new(0);
275 rdpSettings* copy = freerdp_settings_clone(settings);
276 rdpSettings* modified = freerdp_settings_clone(settings);
277
278 if (!settings || !copy || !modified)
279 goto fail;
280 if (!freerdp_settings_set_string(modified, FreeRDP_ServerHostname, "somerandomname"))
281 goto fail;
282 if (freerdp_settings_print_diff(log, WLOG_WARN, settings, copy))
283 goto fail;
284 if (!freerdp_settings_print_diff(log, WLOG_INFO, settings, modified))
285 goto fail;
286
287 rc = TRUE;
288
289fail:
290 freerdp_settings_free(settings);
292 freerdp_settings_free(modified);
293 return log_result(rc);
294}
295
296static BOOL test_helpers(void)
297{
298 log_start();
299 BOOL rc = FALSE;
300 UINT32 flags = 0;
301 rdpSettings* settings = freerdp_settings_new(0);
302 if (!settings)
303 goto fail;
304 if (!freerdp_settings_set_bool(settings, FreeRDP_RemoteFxCodec, TRUE))
305 goto fail;
306 if (!freerdp_settings_set_bool(settings, FreeRDP_NSCodec, TRUE))
307 goto fail;
308 flags = freerdp_settings_get_codecs_flags(settings);
309 if (flags != FREERDP_CODEC_ALL)
310 goto fail;
311
312 if (!freerdp_settings_set_bool(settings, FreeRDP_NSCodec, FALSE))
313 goto fail;
314 flags = freerdp_settings_get_codecs_flags(settings);
315 if (flags != (FREERDP_CODEC_ALL & ~FREERDP_CODEC_NSCODEC))
316 goto fail;
317
318 if (!freerdp_settings_set_bool(settings, FreeRDP_RemoteFxCodec, FALSE))
319 goto fail;
320 flags = freerdp_settings_get_codecs_flags(settings);
321 if (flags != (FREERDP_CODEC_ALL & ~(FREERDP_CODEC_NSCODEC | FREERDP_CODEC_REMOTEFX)))
322 goto fail;
323
324 if (!freerdp_settings_set_bool(settings, FreeRDP_NSCodec, TRUE))
325 goto fail;
326 flags = freerdp_settings_get_codecs_flags(settings);
327 if (flags != (FREERDP_CODEC_ALL & ~FREERDP_CODEC_REMOTEFX))
328 goto fail;
329
330 rc = TRUE;
331fail:
332 freerdp_settings_free(settings);
333 return log_result(rc);
334}
335
336static BOOL format_uint(char* buffer, size_t size, UINT64 value, UINT16 intType, UINT64 max)
337{
338 const UINT64 lvalue = value > max ? max : value;
339 intType = intType % 3;
340 switch (intType)
341 {
342 case 0:
343 (void)_snprintf(buffer, size, "%" PRIu64, lvalue);
344 return TRUE;
345 case 1:
346 (void)_snprintf(buffer, size, "0x%" PRIx64, lvalue);
347 return TRUE;
348 case 2:
349 if (max < UINT64_MAX)
350 (void)_snprintf(buffer, size, "%" PRIu64, max + 1);
351 else
352 (void)_snprintf(buffer, size, "too large a number");
353 return FALSE;
354 default:
355 (void)_snprintf(buffer, size, "not a number value");
356 return FALSE;
357 }
358}
359
360static BOOL print_negative(char* buffer, size_t size, INT64 value, INT64 min)
361{
362 switch (min)
363 {
364 case INT16_MIN:
365 (void)_snprintf(buffer, size, "%" PRId16, (INT16)value);
366 return FALSE;
367 case INT32_MIN:
368 (void)_snprintf(buffer, size, "%" PRId32, (INT32)value);
369 return FALSE;
370 case INT64_MIN:
371 (void)_snprintf(buffer, size, "%" PRId64, value);
372 return FALSE;
373 default:
374 (void)_snprintf(buffer, size, "too small a number");
375 return FALSE;
376 }
377}
378
379static BOOL print_xpositive(char* buffer, size_t size, INT64 value, INT64 max)
380{
381 if (value < 0)
382 {
383 (void)_snprintf(buffer, size, "%" PRId64, value);
384 return TRUE;
385 }
386
387 switch (max)
388 {
389 case INT16_MAX:
390 (void)_snprintf(buffer, size, "%" PRIx16, (INT16)value);
391 return FALSE;
392 case INT32_MAX:
393 (void)_snprintf(buffer, size, "%" PRIx32, (INT32)value);
394 return FALSE;
395 case INT64_MAX:
396 (void)_snprintf(buffer, size, "%" PRIx64, value);
397 return FALSE;
398 default:
399 (void)_snprintf(buffer, size, "too small a number");
400 return FALSE;
401 }
402}
403
404static BOOL format_int(char* buffer, size_t size, INT64 value, UINT16 intType, INT64 max, INT64 min)
405{
406 const INT64 lvalue = (value > max) ? max : ((value < min) ? min : value);
407 intType = intType % 4;
408
409 switch (intType)
410 {
411 case 0:
412 (void)_snprintf(buffer, size, "%" PRId64, lvalue);
413 return TRUE;
414 case 1:
415 print_xpositive(buffer, size, lvalue, max);
416 return TRUE;
417 case 2:
418 if (max < INT64_MAX)
419 (void)_snprintf(buffer, size, "%" PRId64, max + 1);
420 else
421 (void)_snprintf(buffer, size, "too large a number");
422 return FALSE;
423 case 3:
424 if (min < INT64_MIN)
425 print_negative(buffer, size, min - 1, INT64_MIN);
426 else
427 (void)_snprintf(buffer, size, "too small a number");
428 return FALSE;
429 default:
430 (void)_snprintf(buffer, size, "not a number value");
431 return FALSE;
432 }
433}
434
435static BOOL format_bool(char* buffer, size_t size, UINT16 intType)
436{
437 intType = intType % 10;
438 switch (intType)
439 {
440 case 0:
441 (void)_snprintf(buffer, size, "FALSE");
442 return TRUE;
443 case 1:
444 (void)_snprintf(buffer, size, "FaLsE");
445 return TRUE;
446 case 2:
447 (void)_snprintf(buffer, size, "False");
448 return TRUE;
449 case 3:
450 (void)_snprintf(buffer, size, "false");
451 return TRUE;
452 case 4:
453 (void)_snprintf(buffer, size, "falseentry");
454 return FALSE;
455 case 5:
456 (void)_snprintf(buffer, size, "TRUE");
457 return TRUE;
458 case 6:
459 (void)_snprintf(buffer, size, "TrUe");
460 return TRUE;
461 case 7:
462 (void)_snprintf(buffer, size, "True");
463 return TRUE;
464 case 8:
465 (void)_snprintf(buffer, size, "true");
466 return TRUE;
467 case 9:
468 (void)_snprintf(buffer, size, "someentry");
469 return FALSE;
470 default:
471 (void)_snprintf(buffer, size, "ok");
472 return FALSE;
473 }
474}
475
476static BOOL check_key_helpers(size_t key, const char* stype)
477{
478 log_start();
479 int test_rounds = 100;
480 BOOL res = FALSE;
481 rdpSettings* settings = nullptr;
482 SSIZE_T rc = 0;
483 SSIZE_T tkey = 0;
484 SSIZE_T type = 0;
485 const size_t clear_keys[] = { FreeRDP_RdpServerCertificate,
486 FreeRDP_RdpServerRsaKey,
487 FreeRDP_RedirectionPassword,
488 FreeRDP_RedirectionTsvUrl,
489 FreeRDP_LoadBalanceInfo,
490 FreeRDP_ServerRandom,
491 FreeRDP_ClientRandom,
492 FreeRDP_ServerCertificate,
493 FreeRDP_TargetNetAddresses,
494 FreeRDP_ReceivedCapabilities,
495 FreeRDP_ServerLicenseProductIssuers,
496 FreeRDP_TargetNetPorts,
497 FreeRDP_DeviceArray,
498 FreeRDP_ChannelDefArray,
499 FreeRDP_MonitorDefArray,
500 FreeRDP_ClientAutoReconnectCookie,
501 FreeRDP_ServerAutoReconnectCookie,
502 FreeRDP_ClientTimeZone,
503 FreeRDP_BitmapCacheV2CellInfo,
504 FreeRDP_GlyphCache,
505 FreeRDP_FragCache,
506 FreeRDP_StaticChannelArray,
507 FreeRDP_DynamicChannelArray,
508 FreeRDP_ReceivedCapabilities,
509 FreeRDP_OrderSupport,
510 FreeRDP_MonitorIds };
511 const char* name = freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
512 if (!name)
513 {
514 printf("[%s] missing name for key %" PRIuz "\n", stype, key);
515 return FALSE;
516 }
518 if (tkey < 0)
519 {
520 printf("[%s] missing reverse name for key %s [%" PRIuz "]\n", stype, name, key);
521 return FALSE;
522 }
523 if ((size_t)tkey != key)
524 {
525 printf("[%s] mismatch reverse name for key %s [%" PRIuz "]: %" PRIdz "\n", stype, name, key,
526 tkey);
527 return FALSE;
528 }
530 if (type < 0)
531 {
532 printf("[%s] missing reverse type for key %s [%" PRIuz "]\n", stype, name, key);
533 return FALSE;
534 }
535 rc = freerdp_settings_get_type_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
536 if (rc < 0)
537 {
538 printf("[%s] missing reverse name for key %s [%" PRIuz "]\n", stype, name, key);
539 return FALSE;
540 }
541
542 if (rc != type)
543 {
544 printf("[%s] mismatch reverse type for key %s [%" PRIuz "]: %" PRIdz " <--> %" PRIdz "\n",
545 stype, name, key, rc, type);
546 return FALSE;
547 }
548
549 settings = freerdp_settings_new(0);
550 if (!settings)
551 {
552 printf("[%s] freerdp_settings_new failed\n", stype);
553 goto fail;
554 }
555 for (size_t x = 0; x < ARRAYSIZE(clear_keys); x++)
556 {
557 const size_t id = clear_keys[x];
558 const char* foo = freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, id));
559 if (!freerdp_settings_set_pointer_len(settings, id, nullptr, 0))
560 {
561 printf("[%s] freerdp_settings_set_pointer_len(%s, nullptr, 0) failed\n", stype, foo);
562 goto fail;
563 }
564 }
565 do
566 {
567 UINT16 intEntryType = 0;
568 BOOL expect = 0;
569 BOOL have = 0;
570 char value[8192] = WINPR_C_ARRAY_INIT;
571 union
572 {
573 UINT64 u64;
574 INT64 i64;
575 UINT32 u32;
576 INT32 i32;
577 UINT16 u16;
578 INT16 i16;
579 void* pv;
580 } val;
581
582 if (winpr_RAND(&intEntryType, sizeof(intEntryType)) < 0)
583 goto fail;
584 if (winpr_RAND(&val.u64, sizeof(val.u64)) < 0)
585 goto fail;
586
587 switch (key)
588 {
589 case FreeRDP_ReceivedCapabilitiesSize:
590 case FreeRDP_TargetNetAddressCount:
591 val.u64 %= 512;
592 break;
593 default:
594 break;
595 }
596
597 switch (type)
598 {
599 case RDP_SETTINGS_TYPE_BOOL:
600 expect = format_bool(value, sizeof(value), intEntryType);
601 break;
602 case RDP_SETTINGS_TYPE_UINT16:
603 expect = format_uint(value, sizeof(value), val.u64, intEntryType, UINT16_MAX);
604 break;
605 case RDP_SETTINGS_TYPE_INT16:
606 expect =
607 format_int(value, sizeof(value), val.i64, intEntryType, INT16_MAX, INT16_MIN);
608 break;
609 case RDP_SETTINGS_TYPE_UINT32:
610 expect = format_uint(value, sizeof(value), val.u64, intEntryType, UINT32_MAX);
611 break;
612 case RDP_SETTINGS_TYPE_INT32:
613 expect =
614 format_int(value, sizeof(value), val.i64, intEntryType, INT32_MAX, INT32_MIN);
615 break;
616 case RDP_SETTINGS_TYPE_UINT64:
617 expect = format_uint(value, sizeof(value), val.u64, intEntryType, UINT64_MAX);
618 break;
619 case RDP_SETTINGS_TYPE_INT64:
620 expect =
621 format_int(value, sizeof(value), val.i64, intEntryType, INT64_MAX, INT64_MIN);
622 break;
623 case RDP_SETTINGS_TYPE_STRING:
624 expect = TRUE;
625 (void)_snprintf(value, sizeof(value), "somerandomstring");
626 break;
627 case RDP_SETTINGS_TYPE_POINTER:
628 expect = FALSE;
629 break;
630
631 default:
632 printf("[%s] invalid type for key %s [%" PRIuz "]: %" PRIdz " <--> %" PRIdz "\n",
633 stype, name, key, rc, type);
634 goto fail;
635 }
636
637 have = freerdp_settings_set_value_for_name(settings, name, value);
638 if (have != expect)
639 {
640 printf("[%s] %s=%s have [%s] != expect[%s]\n", stype, name, value,
641 have ? "TRUE" : "FALSE", expect ? "TRUE" : "FALSE");
642 goto fail;
643 }
644
645 } while (test_rounds-- > 0);
646
647 res = TRUE;
648fail:
649 freerdp_settings_free(settings);
650 return log_result(res);
651}
652
653static BOOL check_args(const RDPDR_DEVICE* what, size_t count, const char* args[])
654{
655 WINPR_ASSERT(what);
656
657 if (count > 0)
658 {
659 if (strcmp(what->Name, args[0]) != 0)
660 return FALSE;
661 }
662
663 switch (what->Type)
664 {
665 case RDPDR_DTYP_PRINT:
666 {
667 const RDPDR_PRINTER* a = (const RDPDR_PRINTER*)what;
668 if (count <= 1)
669 return TRUE;
670 if (!a->DriverName)
671 return FALSE;
672 return strcmp(a->DriverName, args[1]) == 0;
673 }
674
675 case RDPDR_DTYP_SERIAL:
676 {
677 const RDPDR_SERIAL* a = (const RDPDR_SERIAL*)what;
678
679 if (count > 1)
680 {
681 if (!a->Path)
682 return FALSE;
683 if (strcmp(a->Path, args[1]) != 0)
684 return FALSE;
685 }
686
687 if (count > 2)
688 {
689 if (!a->Driver)
690 return FALSE;
691 if (strcmp(a->Driver, args[2]) != 0)
692 return FALSE;
693 }
694
695 if (count > 3)
696 {
697 if (!a->Permissive)
698 return FALSE;
699 if (strcmp(a->Permissive, args[3]) != 0)
700 return FALSE;
701 }
702 return TRUE;
703 }
704
705 case RDPDR_DTYP_PARALLEL:
706 {
707 const RDPDR_PARALLEL* a = (const RDPDR_PARALLEL*)what;
708 if (count <= 1)
709 return TRUE;
710 if (!a->Path)
711 return FALSE;
712 return strcmp(a->Path, args[1]) == 0;
713 }
714
715 case RDPDR_DTYP_SMARTCARD:
716 return TRUE;
717
718 case RDPDR_DTYP_FILESYSTEM:
719 {
720 const RDPDR_DRIVE* a = (const RDPDR_DRIVE*)what;
721 if (count > 1)
722 {
723 if (!a->Path)
724 return FALSE;
725 if (strcmp(a->Path, args[1]) != 0)
726 return FALSE;
727 }
728 if (count > 2)
729 {
730 return (a->automount == (args[2] == nullptr));
731 }
732 else
733 return !a->automount;
734 }
735
736 default:
737 return FALSE;
738 }
739}
740
741static int check_device_type_arg(UINT32 Type, size_t count, const char* args[])
742{
743 int rc = -3;
744 RDPDR_DEVICE* device = freerdp_device_new(Type, count, args);
745 RDPDR_DEVICE* clone = freerdp_device_clone(device);
746
747 if (!device)
748 goto fail;
749
750 rc++;
751 if (!clone)
752 goto fail;
753
754 rc++;
755 if (!check_args(device, count, args))
756 goto fail;
757
758 rc++;
759 if (!freerdp_device_equal(clone, device))
760 goto fail;
761 rc++;
762
763fail:
764 freerdp_device_free(device);
765 freerdp_device_free(clone);
766 return log_result(rc);
767}
768
769static BOOL check_device_type(void)
770{
771 log_start();
772 struct test_entry
773 {
774 int expect;
775 UINT32 type;
776 size_t count;
777 const char** args;
778 };
779 const char* args[] = { "somename", "anothername", "3rdname", "4thname" };
780 const struct test_entry tests[] = {
781 { 1, RDPDR_DTYP_SERIAL, 0, nullptr },
782 { 1, RDPDR_DTYP_SERIAL, 0, args },
783 { 1, RDPDR_DTYP_SERIAL, 1, args },
784 { 1, RDPDR_DTYP_SERIAL, 2, args },
785 { 1, RDPDR_DTYP_SERIAL, 3, args },
786 { 1, RDPDR_DTYP_SERIAL, 4, args },
787 { 1, RDPDR_DTYP_PARALLEL, 0, nullptr },
788 { 1, RDPDR_DTYP_PARALLEL, 0, args },
789 { 1, RDPDR_DTYP_PARALLEL, 1, args },
790 { 1, RDPDR_DTYP_PARALLEL, 2, args },
791 { 1, RDPDR_DTYP_PARALLEL, 3, args },
792 { 1, RDPDR_DTYP_PARALLEL, 4, args },
793 { 1, RDPDR_DTYP_PRINT, 0, nullptr },
794 { 1, RDPDR_DTYP_PRINT, 0, args },
795 { 1, RDPDR_DTYP_PRINT, 1, args },
796 { 1, RDPDR_DTYP_PRINT, 2, args },
797 { 1, RDPDR_DTYP_PRINT, 3, args },
798 { 1, RDPDR_DTYP_PRINT, 4, args },
799 { 1, RDPDR_DTYP_FILESYSTEM, 0, nullptr },
800 { 1, RDPDR_DTYP_FILESYSTEM, 0, args },
801 { 1, RDPDR_DTYP_FILESYSTEM, 1, args },
802 { 1, RDPDR_DTYP_FILESYSTEM, 2, args },
803 { 1, RDPDR_DTYP_FILESYSTEM, 3, args },
804 { 1, RDPDR_DTYP_FILESYSTEM, 4, args },
805 { 1, RDPDR_DTYP_SMARTCARD, 0, nullptr },
806 { 1, RDPDR_DTYP_SMARTCARD, 0, args },
807 { 1, RDPDR_DTYP_SMARTCARD, 1, args },
808 { 1, RDPDR_DTYP_SMARTCARD, 2, args },
809 { 1, RDPDR_DTYP_SMARTCARD, 3, args },
810 { 1, RDPDR_DTYP_SMARTCARD, 4, args },
811 { -3, 0x123, 0, nullptr },
812 { -3, 0x123, 0, args },
813 { -3, 0x123, 1, args },
814 { -3, 0x123, 2, args },
815 { -3, 0x123, 3, args },
816 { -3, 0x123, 4, args },
817 };
818 BOOL rc = TRUE;
819 for (size_t x = 0; x < ARRAYSIZE(tests); x++)
820 {
821 const struct test_entry* cur = &tests[x];
822 int got = check_device_type_arg(cur->type, cur->count, cur->args);
823 if (got != cur->expect)
824 rc = FALSE;
825 }
826 return log_result(rc);
827}
828
829static BOOL check_offsets(rdpSettings* settings, size_t id, size_t min, size_t max, BOOL checkPtr)
830{
831 BOOL rc = TRUE;
832
833 WINPR_ASSERT(settings);
834
835 if (!freerdp_settings_get_pointer(settings, id))
836 return FALSE;
837
838 for (size_t x = min; x < max; x++)
839 {
840 const void* ptr = freerdp_settings_get_pointer_array(settings, id, x);
841 if (!ptr && checkPtr)
842 rc = FALSE;
843 }
844 return log_result(rc);
845}
846
847static BOOL test_write_offsets(rdpSettings* settings, size_t id, size_t elementSize, size_t min,
848 size_t max)
849{
850 WINPR_ASSERT(settings);
851
852 for (size_t x = min; x < max; x++)
853 {
854 const void* ptr = nullptr;
855 char buffer[8192] = WINPR_C_ARRAY_INIT;
856
857 if (winpr_RAND(buffer, sizeof(buffer)) < 0)
858 return FALSE;
859 if (!freerdp_settings_set_pointer_array(settings, id, x, buffer))
860 return FALSE;
861 ptr = freerdp_settings_get_pointer_array(settings, id, x);
862 if (!ptr)
863 return FALSE;
864 if (memcmp(ptr, buffer, elementSize) != 0)
865 return FALSE;
866 }
867 return TRUE;
868}
869
870static BOOL test_pointer_array(void)
871{
872 struct pointer_test_case
873 {
874 BOOL checkPtr;
875 BOOL write;
876 size_t id;
877 SSIZE_T sizeId;
878 size_t size;
879 size_t elementSize;
880 };
881 const struct pointer_test_case tests[] = {
882 { FALSE, FALSE, FreeRDP_DeviceArray, FreeRDP_DeviceArraySize, 32, sizeof(RDPDR_DEVICE*) },
883 { FALSE, FALSE, FreeRDP_StaticChannelArray, FreeRDP_StaticChannelArraySize, 32,
884 sizeof(ADDIN_ARGV*) },
885 { FALSE, FALSE, FreeRDP_DynamicChannelArray, FreeRDP_DynamicChannelArraySize, 33,
886 sizeof(ADDIN_ARGV*) },
887 { TRUE, TRUE, FreeRDP_BitmapCacheV2CellInfo, FreeRDP_BitmapCacheV2NumCells, 5,
889 { FALSE, FALSE, FreeRDP_OrderSupport, -1, 32, sizeof(BYTE) },
890 { FALSE, FALSE, FreeRDP_ReceivedCapabilities, -1, 32, sizeof(BYTE) },
891 { TRUE, TRUE, FreeRDP_GlyphCache, -1, 10, sizeof(GLYPH_CACHE_DEFINITION) },
892 { TRUE, TRUE, FreeRDP_FragCache, -1, 1, sizeof(GLYPH_CACHE_DEFINITION) },
893 { TRUE, TRUE, FreeRDP_MonitorIds, FreeRDP_NumMonitorIds, 33, sizeof(UINT32) },
894 { TRUE, TRUE, FreeRDP_ChannelDefArray, FreeRDP_ChannelDefArraySize, 42,
895 sizeof(CHANNEL_DEF) },
896 { TRUE, TRUE, FreeRDP_MonitorDefArray, FreeRDP_MonitorDefArraySize, 33,
897 sizeof(rdpMonitor) },
898 { TRUE, TRUE, FreeRDP_ClientTimeZone, -1, 1, sizeof(TIME_ZONE_INFORMATION) },
899 { FALSE, FALSE, FreeRDP_RdpServerCertificate, -1, 1, sizeof(rdpCertificate*) },
900 //{ FALSE, FALSE, FreeRDP_RdpServerRsaKey, -1, 1, sizeof(rdpPrivateKey*) },
901 { TRUE, TRUE, FreeRDP_RedirectionPassword, FreeRDP_RedirectionPasswordLength, 42,
902 sizeof(char) },
903 { TRUE, TRUE, FreeRDP_RedirectionTsvUrl, FreeRDP_RedirectionTsvUrlLength, 42,
904 sizeof(char) },
905 { TRUE, TRUE, FreeRDP_LoadBalanceInfo, FreeRDP_LoadBalanceInfoLength, 42, sizeof(char) },
906 { TRUE, TRUE, FreeRDP_ServerRandom, FreeRDP_ServerRandomLength, 42, sizeof(char) },
907 { TRUE, TRUE, FreeRDP_ClientRandom, FreeRDP_ClientRandomLength, 42, sizeof(char) },
908 { TRUE, TRUE, FreeRDP_ServerCertificate, FreeRDP_ServerCertificateLength, 42,
909 sizeof(char) },
910 { TRUE, TRUE, FreeRDP_ClientAutoReconnectCookie, -1, 1, sizeof(ARC_CS_PRIVATE_PACKET) },
911 { TRUE, TRUE, FreeRDP_ServerAutoReconnectCookie, -1, 1, sizeof(ARC_SC_PRIVATE_PACKET) }
912 };
913 BOOL rc = FALSE;
914 rdpSettings* settings = freerdp_settings_new(0);
915 if (!settings)
916 goto fail;
917
918 for (size_t x = 0; x < ARRAYSIZE(tests); x++)
919 {
920 const struct pointer_test_case* cur = &tests[x];
921 if (!freerdp_settings_set_pointer_len(settings, cur->id, nullptr, cur->size))
922 goto fail;
923 if (cur->sizeId >= 0)
924 {
925 const UINT32 s = freerdp_settings_get_uint32(settings, (size_t)cur->sizeId);
926 if (s != cur->size)
927 goto fail;
928 }
929 if (!check_offsets(settings, cur->id, 0, cur->size, cur->checkPtr))
930 goto fail;
931 if (check_offsets(settings, cur->id, cur->size, cur->size + 5, TRUE))
932 goto fail;
933 if (cur->write)
934 {
935 if (!test_write_offsets(settings, cur->id, cur->elementSize, 0, cur->size))
936 goto fail;
937 if (test_write_offsets(settings, cur->id, cur->elementSize, cur->size, cur->size + 5))
938 goto fail;
939 }
940 if (!freerdp_settings_set_pointer_len(settings, cur->id, nullptr, 0))
941 goto fail;
942 if (cur->sizeId >= 0)
943 {
944 const UINT32 s = freerdp_settings_get_uint32(settings, (size_t)cur->sizeId);
945 if (s != 0)
946 goto fail;
947 }
948 if (check_offsets(settings, cur->id, 0, cur->size, cur->checkPtr))
949 goto fail;
950 if (cur->write)
951 {
952 if (test_write_offsets(settings, cur->id, cur->elementSize, 0, cur->size))
953 goto fail;
954 }
955 if (!freerdp_settings_set_pointer_len(settings, cur->id, nullptr, cur->size))
956 goto fail;
957 if (cur->sizeId >= 0)
958 {
959 const UINT32 s = freerdp_settings_get_uint32(settings, (size_t)cur->sizeId);
960 if (s != cur->size)
961 goto fail;
962 }
963 if (!check_offsets(settings, cur->id, 0, cur->size, cur->checkPtr))
964 goto fail;
965 if (check_offsets(settings, cur->id, cur->size + 1, cur->size + 5, TRUE))
966 goto fail;
967 if (cur->write)
968 {
969 if (!test_write_offsets(settings, cur->id, cur->elementSize, 0, cur->size))
970 goto fail;
971 if (test_write_offsets(settings, cur->id, cur->elementSize, cur->size, cur->size + 5))
972 goto fail;
973 }
974 }
975
976 rc = TRUE;
977
978fail:
979 freerdp_settings_free(settings);
980 return log_result(rc);
981}
982
983struct validity_test_case
984{
985 BOOL expected;
986 size_t count;
987 const rdpMonitor* monitors;
988};
989
990static BOOL prepare_monitor_array(rdpSettings* settings, const struct validity_test_case* testcase)
991{
992 WINPR_ASSERT(settings);
993 WINPR_ASSERT(testcase);
994
995 return freerdp_settings_set_monitor_def_array_sorted(settings, testcase->monitors,
996 testcase->count);
997}
998
999static BOOL check_primary_offset(const rdpSettings* settings, const rdpMonitor* monitors,
1000 size_t count)
1001{
1002 const rdpMonitor* cprimary = nullptr;
1003 for (size_t x = 0; x < count; x++)
1004 {
1005 const rdpMonitor* cur = &monitors[x];
1006 if (cur->is_primary)
1007 cprimary = cur;
1008 }
1009 if (!cprimary)
1010 {
1011 for (size_t x = 0; x < count; x++)
1012 {
1013 const rdpMonitor* cur = &monitors[x];
1014 if ((cur->x == 0) && (cur->y == 0))
1015 cprimary = cur;
1016 }
1017 }
1018 const rdpMonitor* sprimary = nullptr;
1019 for (size_t x = 0; x < count; x++)
1020 {
1021 const rdpMonitor* cur =
1022 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
1023 if (!cur)
1024 return FALSE;
1025 if (cur->is_primary)
1026 sprimary = cur;
1027 }
1028
1029 if (!sprimary || !cprimary)
1030 return FALSE;
1031
1032 const INT32 xoff = cprimary->x;
1033 const INT32 yoff = cprimary->y;
1034 const INT32 sxoff = freerdp_settings_get_int32(settings, FreeRDP_MonitorLocalShiftX);
1035 const INT32 syoff = freerdp_settings_get_int32(settings, FreeRDP_MonitorLocalShiftY);
1036 if (xoff != sxoff)
1037 return FALSE;
1038 if (yoff != syoff)
1039 return FALSE;
1040 return TRUE;
1041}
1042
1043static BOOL test_validity_check(void)
1044{
1045 log_start();
1046 BOOL rc = FALSE;
1047 rdpSettings* settings = freerdp_settings_new(0);
1048 if (!settings)
1049 goto fail;
1050
1051 const rdpMonitor single_monitor_valid[] = {
1052 { .x = 0,
1053 .y = 0,
1054 .width = 1920,
1055 .height = 1080,
1056 .is_primary = TRUE,
1057 .orig_screen = 0,
1058 .attributes = { .physicalWidth = 100,
1059 .physicalHeight = 100,
1060 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1061 .desktopScaleFactor = 100,
1062 .deviceScaleFactor = 100 } }
1063 };
1064 const rdpMonitor single_monitor_invalid_1[] = {
1065 { .x = 0,
1066 .y = 0,
1067 .width = 192,
1068 .height = 1080,
1069 .is_primary = TRUE,
1070 .orig_screen = 0,
1071 .attributes = { .physicalWidth = 100,
1072 .physicalHeight = 100,
1073 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1074 .desktopScaleFactor = 100,
1075 .deviceScaleFactor = 100 } }
1076 };
1077 const rdpMonitor single_monitor_invalid_2[] = {
1078 { .x = 0,
1079 .y = 0,
1080 .width = 192,
1081 .height = 1080,
1082 .is_primary = TRUE,
1083 .orig_screen = 0,
1084 .attributes = { .physicalWidth = 100,
1085 .physicalHeight = 100,
1086 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1087 .desktopScaleFactor = 100,
1088 .deviceScaleFactor = 100 } }
1089 };
1090 const rdpMonitor single_monitor_invalid_3[] = {
1091 { .x = 0,
1092 .y = 0,
1093 .width = 192,
1094 .height = 1080,
1095 .is_primary = TRUE,
1096 .orig_screen = 0,
1097 .attributes = { .physicalWidth = 100,
1098 .physicalHeight = 100,
1099 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1100 .desktopScaleFactor = 100,
1101 .deviceScaleFactor = 100 } }
1102 };
1103 const rdpMonitor single_monitor_invalid_4[] = {
1104 { .x = 0,
1105 .y = 0,
1106 .width = 192,
1107 .height = 1080,
1108 .is_primary = TRUE,
1109 .orig_screen = 0,
1110 .attributes = { .physicalWidth = 100,
1111 .physicalHeight = 100,
1112 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1113 .desktopScaleFactor = 100,
1114 .deviceScaleFactor = 100 } }
1115 };
1116 const rdpMonitor multi_monitor_valid[] = {
1117 { .x = 0,
1118 .y = 0,
1119 .width = 1920,
1120 .height = 1080,
1121 .is_primary = FALSE,
1122 .orig_screen = 0,
1123 .attributes = { .physicalWidth = 100,
1124 .physicalHeight = 100,
1125 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1126 .desktopScaleFactor = 100,
1127 .deviceScaleFactor = 100 } },
1128 { .x = 1920,
1129 .y = 0,
1130 .width = 1920,
1131 .height = 1080,
1132 .is_primary = FALSE,
1133 .orig_screen = 0,
1134 .attributes = { .physicalWidth = 100,
1135 .physicalHeight = 100,
1136 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1137 .desktopScaleFactor = 100,
1138 .deviceScaleFactor = 100 } },
1139 { .x = 0,
1140 .y = 1080,
1141 .width = 1920,
1142 .height = 1080,
1143 .is_primary = FALSE,
1144 .orig_screen = 0,
1145 .attributes = { .physicalWidth = 100,
1146 .physicalHeight = 100,
1147 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1148 .desktopScaleFactor = 100,
1149 .deviceScaleFactor = 100 } },
1150 { .x = -1920,
1151 .y = 0,
1152 .width = 1920,
1153 .height = 1080,
1154 .is_primary = FALSE,
1155 .orig_screen = 0,
1156 .attributes = { .physicalWidth = 100,
1157 .physicalHeight = 100,
1158 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1159 .desktopScaleFactor = 100,
1160 .deviceScaleFactor = 100 } },
1161 { .x = 0,
1162 .y = -1080,
1163 .width = 1920,
1164 .height = 1080,
1165 .is_primary = TRUE,
1166 .orig_screen = 0,
1167 .attributes = { .physicalWidth = 100,
1168 .physicalHeight = 100,
1169 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1170 .desktopScaleFactor = 100,
1171 .deviceScaleFactor = 100 } },
1172 { .x = 3840,
1173 .y = 0,
1174 .width = 1920,
1175 .height = 1080,
1176 .is_primary = FALSE,
1177 .orig_screen = 0,
1178 .attributes = { .physicalWidth = 100,
1179 .physicalHeight = 100,
1180 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1181 .desktopScaleFactor = 100,
1182 .deviceScaleFactor = 100 } },
1183 { .x = 5760,
1184 .y = -1079,
1185 .width = 1920,
1186 .height = 1080,
1187 .is_primary = FALSE,
1188 .orig_screen = 0,
1189 .attributes = { .physicalWidth = 100,
1190 .physicalHeight = 100,
1191 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1192 .desktopScaleFactor = 100,
1193 .deviceScaleFactor = 100 } },
1194 { .x = 7680,
1195 .y = 0,
1196 .width = 1920,
1197 .height = 1080,
1198 .is_primary = FALSE,
1199 .orig_screen = 0,
1200 .attributes = { .physicalWidth = 100,
1201 .physicalHeight = 100,
1202 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1203 .desktopScaleFactor = 100,
1204 .deviceScaleFactor = 100 } },
1205 { .x = 7680,
1206 .y = 1080,
1207 .width = 1920,
1208 .height = 1080,
1209 .is_primary = FALSE,
1210 .orig_screen = 0,
1211 .attributes = { .physicalWidth = 100,
1212 .physicalHeight = 100,
1213 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1214 .desktopScaleFactor = 100,
1215 .deviceScaleFactor = 100 } },
1216 { .x = 7680,
1217 .y = -1080,
1218 .width = 1920,
1219 .height = 1080,
1220 .is_primary = FALSE,
1221 .orig_screen = 0,
1222 .attributes = { .physicalWidth = 100,
1223 .physicalHeight = 100,
1224 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1225 .desktopScaleFactor = 100,
1226 .deviceScaleFactor = 100 } },
1227 { .x = 7680,
1228 .y = -2160,
1229 .width = 1920,
1230 .height = 1080,
1231 .is_primary = FALSE,
1232 .orig_screen = 0,
1233 .attributes = { .physicalWidth = 100,
1234 .physicalHeight = 100,
1235 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1236 .desktopScaleFactor = 100,
1237 .deviceScaleFactor = 100 } },
1238 { .x = 9599,
1239 .y = -3240,
1240 .width = 1920,
1241 .height = 1080,
1242 .is_primary = FALSE,
1243 .orig_screen = 0,
1244 .attributes = { .physicalWidth = 100,
1245 .physicalHeight = 100,
1246 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1247 .desktopScaleFactor = 100,
1248 .deviceScaleFactor = 100 } },
1249 };
1250 const rdpMonitor multi_monitor_invalid_1[] = {
1251 { .x = 0,
1252 .y = 0,
1253 .width = 1920,
1254 .height = 1080,
1255 .is_primary = FALSE,
1256 .orig_screen = 0,
1257 .attributes = { .physicalWidth = 100,
1258 .physicalHeight = 100,
1259 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1260 .desktopScaleFactor = 100,
1261 .deviceScaleFactor = 100 } },
1262 { .x = 1920,
1263 .y = 0,
1264 .width = 1920,
1265 .height = 1080,
1266 .is_primary = FALSE,
1267 .orig_screen = 0,
1268 .attributes = { .physicalWidth = 100,
1269 .physicalHeight = 100,
1270 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1271 .desktopScaleFactor = 100,
1272 .deviceScaleFactor = 100 } }
1273 };
1274 const rdpMonitor multi_monitor_invalid_2[] = {
1275 { .x = 1,
1276 .y = 0,
1277 .width = 1920,
1278 .height = 1080,
1279 .is_primary = FALSE,
1280 .orig_screen = 0,
1281 .attributes = { .physicalWidth = 100,
1282 .physicalHeight = 100,
1283 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1284 .desktopScaleFactor = 100,
1285 .deviceScaleFactor = 100 } },
1286 { .x = 1920,
1287 .y = 0,
1288 .width = 1920,
1289 .height = 1080,
1290 .is_primary = TRUE,
1291 .orig_screen = 0,
1292 .attributes = { .physicalWidth = 100,
1293 .physicalHeight = 100,
1294 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1295 .desktopScaleFactor = 100,
1296 .deviceScaleFactor = 100 } }
1297 };
1298 const rdpMonitor multi_monitor_invalid_3[] = {
1299 { .x = 0,
1300 .y = 0,
1301 .width = 1920,
1302 .height = 1080,
1303 .is_primary = FALSE,
1304 .orig_screen = 0,
1305 .attributes = { .physicalWidth = 100,
1306 .physicalHeight = 100,
1307 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1308 .desktopScaleFactor = 100,
1309 .deviceScaleFactor = 100 } },
1310 { .x = 1921,
1311 .y = 0,
1312 .width = 1920,
1313 .height = 1080,
1314 .is_primary = TRUE,
1315 .orig_screen = 0,
1316 .attributes = { .physicalWidth = 100,
1317 .physicalHeight = 100,
1318 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1319 .desktopScaleFactor = 100,
1320 .deviceScaleFactor = 100 } }
1321 };
1322 const rdpMonitor multi_monitor_invalid_4[] = {
1323 { .x = 0,
1324 .y = 0,
1325 .width = 1920,
1326 .height = 1080,
1327 .is_primary = FALSE,
1328 .orig_screen = 0,
1329 .attributes = { .physicalWidth = 100,
1330 .physicalHeight = 100,
1331 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1332 .desktopScaleFactor = 100,
1333 .deviceScaleFactor = 100 } },
1334 { .x = 1919,
1335 .y = 0,
1336 .width = 1920,
1337 .height = 1080,
1338 .is_primary = TRUE,
1339 .orig_screen = 0,
1340 .attributes = { .physicalWidth = 100,
1341 .physicalHeight = 100,
1342 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1343 .desktopScaleFactor = 100,
1344 .deviceScaleFactor = 100 } }
1345 };
1346
1347 const rdpMonitor multi_monitor_valid_2[] = {
1348 { .x = 0,
1349 .y = 0,
1350 .width = 1920,
1351 .height = 1080,
1352 .is_primary = TRUE,
1353 .orig_screen = 0,
1354 .attributes = { .physicalWidth = 100,
1355 .physicalHeight = 100,
1356 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1357 .desktopScaleFactor = 100,
1358 .deviceScaleFactor = 100 } },
1359 { .x = 3840,
1360 .y = 0,
1361 .width = 1920,
1362 .height = 1080,
1363 .is_primary = FALSE,
1364 .orig_screen = 0,
1365 .attributes = { .physicalWidth = 100,
1366 .physicalHeight = 100,
1367 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1368 .desktopScaleFactor = 100,
1369 .deviceScaleFactor = 100 } },
1370 { .x = 1920,
1371 .y = 0,
1372 .width = 1920,
1373 .height = 1080,
1374 .is_primary = FALSE,
1375 .orig_screen = 0,
1376 .attributes = { .physicalWidth = 100,
1377 .physicalHeight = 100,
1378 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1379 .desktopScaleFactor = 100,
1380 .deviceScaleFactor = 100 } }
1381 };
1382
1383 const rdpMonitor multi_monitor_valid_3[] = {
1384 { .x = 1920,
1385 .y = 0,
1386 .width = 1920,
1387 .height = 1080,
1388 .is_primary = TRUE,
1389 .orig_screen = 0,
1390 .attributes = { .physicalWidth = 100,
1391 .physicalHeight = 100,
1392 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1393 .desktopScaleFactor = 100,
1394 .deviceScaleFactor = 100 } },
1395 { .x = 3840,
1396 .y = 0,
1397 .width = 1920,
1398 .height = 1080,
1399 .is_primary = FALSE,
1400 .orig_screen = 0,
1401 .attributes = { .physicalWidth = 100,
1402 .physicalHeight = 100,
1403 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1404 .desktopScaleFactor = 100,
1405 .deviceScaleFactor = 100 } },
1406 { .x = 0,
1407 .y = 0,
1408 .width = 1920,
1409 .height = 1080,
1410 .is_primary = FALSE,
1411 .orig_screen = 0,
1412 .attributes = { .physicalWidth = 100,
1413 .physicalHeight = 100,
1414 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1415 .desktopScaleFactor = 100,
1416 .deviceScaleFactor = 100 } }
1417 };
1418
1419 const struct validity_test_case tests[] = {
1420 { TRUE, ARRAYSIZE(single_monitor_valid), single_monitor_valid },
1421 { FALSE, ARRAYSIZE(single_monitor_invalid_1), single_monitor_invalid_1 },
1422 { FALSE, ARRAYSIZE(single_monitor_invalid_2), single_monitor_invalid_2 },
1423 { FALSE, ARRAYSIZE(single_monitor_invalid_3), single_monitor_invalid_3 },
1424 { FALSE, ARRAYSIZE(single_monitor_invalid_4), single_monitor_invalid_4 },
1425 { TRUE, ARRAYSIZE(multi_monitor_valid), multi_monitor_valid },
1426 { TRUE, ARRAYSIZE(multi_monitor_invalid_1), multi_monitor_invalid_1 },
1427 { FALSE, ARRAYSIZE(multi_monitor_invalid_2), multi_monitor_invalid_2 },
1428 { FALSE, ARRAYSIZE(multi_monitor_invalid_3), multi_monitor_invalid_3 },
1429 { FALSE, ARRAYSIZE(multi_monitor_invalid_4), multi_monitor_invalid_4 },
1430 { TRUE, ARRAYSIZE(multi_monitor_valid_2), multi_monitor_valid_2 },
1431 { TRUE, ARRAYSIZE(multi_monitor_valid_3), multi_monitor_valid_3 }
1432 };
1433
1434 rc = TRUE;
1435 for (size_t x = 0; x < ARRAYSIZE(tests); x++)
1436 {
1437 const struct validity_test_case* cur = &tests[x];
1438
1439 if (!prepare_monitor_array(settings, cur))
1440 rc = log_result_case(FALSE, __func__, x);
1441 else
1442 {
1443#if defined(BUILD_TESTING_INTERNAL)
1444 const BOOL res = freerdp_settings_check_client_after_preconnect(settings);
1445#else
1446 const BOOL res = cur->expected;
1447#endif
1448
1449 if ((res != cur->expected) ||
1450 !check_primary_offset(settings, cur->monitors, cur->count))
1451 {
1452 rc = log_result_case(FALSE, __func__, x);
1453 }
1454 }
1455 }
1456
1457fail:
1458 freerdp_settings_free(settings);
1459 return log_result(rc);
1460}
1461
1462static BOOL test_string_null(rdpSettings* settings, FreeRDP_Settings_Keys_String id)
1463{
1464 if (!freerdp_settings_set_string(settings, id, nullptr))
1465 return FALSE;
1466
1467 const char* chk = freerdp_settings_get_string(settings, id);
1468 return (chk == nullptr);
1469}
1470
1471static BOOL test_string_check(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
1472 const char* string, size_t len)
1473{
1474 const char* chk = freerdp_settings_get_string(settings, id);
1475 if (!chk)
1476 return FALSE;
1477
1478 const size_t clen = strnlen(chk, len + 1);
1479
1480 /* set strings must always be '\0' terminated */
1481 if (clen != len)
1482 return FALSE;
1483
1484 /* Strings must match comparison */
1485 if (strncmp(string, chk, clen) != 0)
1486 return FALSE;
1487
1488 return TRUE;
1489}
1490
1491static BOOL test_string_check_reset(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
1492 const char* string, size_t len)
1493{
1494 return test_string_check(settings, id, string, len) && test_string_null(settings, id);
1495}
1496
1497static BOOL test_string_set_readback(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
1498 const char* string, size_t len)
1499{
1500 WINPR_ASSERT(len > 3);
1501
1502 BOOL rc = FALSE;
1503 WCHAR* wstr = nullptr;
1504
1505 const size_t slen = strnlen(string, len);
1506 if (!freerdp_settings_set_string_len(settings, id, string, slen - 1))
1507 goto fail;
1508
1509 if (!test_string_check_reset(settings, id, string, slen - 1))
1510 goto fail;
1511
1512 if (!freerdp_settings_set_string(settings, id, string))
1513 goto fail;
1514
1515 size_t wlen = 0;
1516 wstr = freerdp_settings_get_string_as_utf16(settings, id, &wlen);
1517 if (!wstr || (wlen != slen))
1518 goto fail;
1519
1520 if (!test_string_check_reset(settings, id, string, slen))
1521 goto fail;
1522
1523 if (!freerdp_settings_set_string_from_utf16N(settings, id, wstr, slen - 1))
1524 goto fail;
1525
1526 if (!test_string_check(settings, id, string, slen - 1))
1527 goto fail;
1528
1529 if (!freerdp_settings_set_string_from_utf16(settings, id, wstr))
1530 goto fail;
1531
1532 if (!test_string_check(settings, id, string, slen))
1533 goto fail;
1534
1535 rc = TRUE;
1536fail:
1537 free(wstr);
1538 return rc;
1539}
1540
1541static BOOL test_string_len(rdpSettings* settings)
1542{
1543 BOOL rc = FALSE;
1544
1545 const char user[] = "abcdefg";
1546 if (!test_string_set_readback(settings, FreeRDP_Username, user, sizeof(user)))
1547 goto fail;
1548
1549 const char pwd[] = "xyz";
1550 if (!test_string_set_readback(settings, FreeRDP_Password, pwd, sizeof(pwd)))
1551 goto fail;
1552
1553 const char domain[] = "foobar";
1554 if (!test_string_set_readback(settings, FreeRDP_Domain, domain, sizeof(domain)))
1555 goto fail;
1556
1557 rc = TRUE;
1558fail:
1559 return rc;
1560}
1561
1562static BOOL test_serialize_with(rdpSettings* src, const char* name)
1563{
1564 log_start();
1565 BOOL rc = FALSE;
1566 size_t slen = 0;
1567 rdpSettings* dst = nullptr;
1568 char* str = nullptr;
1569 if (!src)
1570 goto fail;
1571
1572 log_start_("%s-%s-%s", name, __func__, "freerdp_settings_serialize");
1573 str = freerdp_settings_serialize(src, TRUE, &slen);
1574 if (!str || (slen == 0))
1575 goto fail;
1576
1577 log_start_("%s-%s-%s", name, __func__, "freerdp_settings_deserialize");
1578 dst = freerdp_settings_deserialize(str, slen);
1579 if (!dst)
1580 goto fail;
1581
1582 log_start_("%s-%s-%s", name, __func__, "freerdp_settings_print_diff");
1583 rc = !freerdp_settings_print_diff(WLog_Get("TestSettings::serialize"), WLOG_WARN, src, dst);
1584
1585fail:
1588 free(str);
1589
1590 return log_result_(rc, "%s-%s", name, __func__);
1591}
1592
1593static BOOL test_serialize_strings(DWORD flags, const char* str)
1594{
1595 log_start();
1596 rdpSettings* src = freerdp_settings_new(flags);
1597 if (!src)
1598 return FALSE;
1599
1600 for (int x = 0; x < FreeRDP_Settings_StableAPI_MAX; x++)
1601 {
1602 union
1603 {
1604 int s;
1605 FreeRDP_Settings_Keys_Pointer ptr;
1606 } iter;
1607 iter.s = x;
1608
1609 SSIZE_T type = freerdp_settings_get_type_for_key(iter.s);
1610 switch (type)
1611 {
1612 case RDP_SETTINGS_TYPE_STRING:
1613 if (!freerdp_settings_set_string(src, iter.ptr, str))
1614 {
1616 return FALSE;
1617 }
1618 break;
1619 default:
1620 break;
1621 }
1622 }
1623
1624 char buffer[128] = WINPR_C_ARRAY_INIT;
1625 (void)_snprintf(buffer, sizeof(buffer), "%s flags 0x%08" PRIx32 " {%s}", __func__, flags, str);
1626 return test_serialize_with(src, buffer);
1627}
1628
1629static BOOL add_argv(rdpSettings* src, size_t argc, const char* argv[])
1630{
1631 ADDIN_ARGV* val = freerdp_addin_argv_new(argc, argv);
1632 if (!val)
1633 return FALSE;
1634 if (!freerdp_static_channel_collection_add(src, val))
1635 return FALSE;
1636 if (!freerdp_static_channel_collection_add(src, freerdp_addin_argv_clone(val)))
1637 return FALSE;
1638 if (!freerdp_dynamic_channel_collection_add(src, freerdp_addin_argv_clone(val)))
1639 return FALSE;
1640
1641 return TRUE;
1642}
1643
1644static BOOL add_dev_argv(rdpSettings* src, size_t argc, const char* argv[])
1645{
1646 FreeRDP_Settings_Keys_Pointer key = FreeRDP_DeviceArray;
1647 size_t count = 6;
1648 if (!freerdp_settings_set_pointer_len(src, key, nullptr, count))
1649 return FALSE;
1650
1651 const uint32_t types[] = { RDPDR_DTYP_SERIAL, RDPDR_DTYP_PARALLEL, RDPDR_DTYP_PRINT,
1652 RDPDR_DTYP_FILESYSTEM, RDPDR_DTYP_SMARTCARD };
1653
1654 for (size_t x = 0; x < count; x++)
1655 {
1656 const uint32_t type = types[x % ARRAYSIZE(types)];
1657 RDPDR_DEVICE* arg = freerdp_device_new(type, argc, argv);
1658 if (!arg)
1659 return FALSE;
1660 const BOOL rc = freerdp_settings_set_pointer_array(src, key, x, arg);
1661 freerdp_device_free(arg);
1662 if (!rc)
1663 return FALSE;
1664 }
1665 return TRUE;
1666}
1667
1668static BOOL fill_random(rdpSettings* src, FreeRDP_Settings_Keys_Pointer key, size_t elem,
1669 size_t len)
1670{
1671 if (!freerdp_settings_set_pointer_len(src, key, nullptr, len))
1672 return FALSE;
1673 uint8_t* data = freerdp_settings_get_pointer_writable(src, key);
1674 if (!data)
1675 return FALSE;
1676
1677 const size_t size = len * elem;
1678 char* random = calloc(len, elem);
1679 if (!random)
1680 return FALSE;
1681 char* b64 = crypto_base64_encode(random, size);
1682 free(random);
1683 memcpy(data, b64, size);
1684 free(b64);
1685 return TRUE;
1686}
1687
1688static BOOL fill_random_timezone(rdpSettings* src)
1689{
1690 FreeRDP_Settings_Keys_Pointer key = FreeRDP_ClientTimeZone;
1691 if (!fill_random(src, key, sizeof(TIME_ZONE_INFORMATION), 1))
1692 return FALSE;
1693
1695 if (!data)
1696 return FALSE;
1697 (void)ConvertUtf8ToWChar("testXXXXDaylight", data->DaylightName, ARRAYSIZE(data->DaylightName));
1698 (void)ConvertUtf8ToWChar("testXXXX", data->StandardName, ARRAYSIZE(data->StandardName));
1699
1700 return TRUE;
1701}
1702
1703static BOOL set_private_key(rdpSettings* src)
1704{
1705 if (!freerdp_settings_set_pointer_len(src, FreeRDP_RdpServerRsaKey, nullptr, 1))
1706 return FALSE;
1707
1708 rdpPrivateKey* key =
1709 freerdp_settings_get_pointer_array_writable(src, FreeRDP_RdpServerRsaKey, 0);
1710 if (!key)
1711 return FALSE;
1712
1713 return freerdp_key_generate(key, "RSA", 1, 4096);
1714}
1715
1716static BOOL set_cert(rdpSettings* src, FreeRDP_Settings_Keys_Pointer key)
1717{
1718 const char pem[] = "-----BEGIN CERTIFICATE-----\n"
1719 "MIICvTCCAaWgAwIBAgIEZrM9yjANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlt\n"
1720 "b3RvcmhlYWQwHhcNMjUwNDE1MTExMjE5WhcNMjYwNDE1MTExMjE5WjAUMRIwEAYD\n"
1721 "VQQDDAltb3RvcmhlYWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCw\n"
1722 "g0tADY3kh5Hi6YsTsQbuaPs50zlTpIv+rCCK3BNIblsIh4cSO1YGdWfB0gP9bUD1\n"
1723 "L7mPWRnIiAvwrRA/Mgyo+UgiYj/aE3xxN3adB9/QsUzNrI07o6L8MupV4237txMj\n"
1724 "uxVmarB4c7E4wFgSxwbMQPhQtoNNew3bY+EeqhQBMFfYy4z+rg60xl0QHGcMePY/\n"
1725 "xz0WMHrIz6FhZfBIr+BGViRtjIchbjcU0HfTSujX+MT0D5MBISe8aiFvrewFItfT\n"
1726 "vglriDLeNMiB9U/aRLV8OtW+heGNhi5qSC9JXEW70OFeGAoqtwyRHLnSh38Fo2xv\n"
1727 "fEc90zjkCan8usEDKuzBAgMBAAGjFzAVMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0G\n"
1728 "CSqGSIb3DQEBCwUAA4IBAQBY1wkJ6XWduNmTi+UNdcZ5e9GWV/3+SYLtFALwKVrU\n"
1729 "KQQbsYnGLfyUKXFc7e9JoZ+UCTJgY3EyL+6p79io+cFeTtpp1RVKljibbeRAP01W\n"
1730 "WbcxcHZFKgBlH1KNSeO7iOAPet3aCaVDKl1XSU7fhxtsfBBI9YTtaMZM5e9WhuHK\n"
1731 "lL11Un6ePThX+4NG1yYp0X+emqUHd/qaq8IShnU6ajvzoloWGf4vLlDSsuFHJJsK\n"
1732 "LnshNFOFGAjp1Se4DjhtUSr6Xofdse+kx9cSQazCZ5vFJNeHkxr0B7ojQ4bN37Tg\n"
1733 "2uyfSclCCLnmjcoRMlIGUiL2bevCPDRNRWiblDgx3tGG\n"
1734 "-----END CERTIFICATE-----\n";
1735
1736 rdpCertificate* cert = freerdp_certificate_new_from_pem(pem);
1737 if (!cert)
1738 return FALSE;
1739 return freerdp_settings_set_pointer_len(src, key, cert, 1);
1740}
1741
1742static BOOL set_string_array(rdpSettings* src, FreeRDP_Settings_Keys_Pointer key, uint32_t max)
1743{
1744 uint32_t count = 0;
1745 if (winpr_RAND(&count, sizeof(count)) < 0)
1746 return FALSE;
1747 count = count % max;
1748
1749 if (!freerdp_settings_set_pointer_len(src, key, nullptr, count))
1750 return FALSE;
1751
1752 for (uint32_t x = 0; x < count; x++)
1753 {
1754 char buffer[32] = WINPR_C_ARRAY_INIT;
1755 (void)_snprintf(buffer, sizeof(buffer), "foobar-0x%08" PRIu32, x);
1756 if (!freerdp_settings_set_pointer_array(src, key, x, buffer))
1757 return FALSE;
1758 }
1759 return TRUE;
1760}
1761
1762static BOOL test_serialize_pointer(DWORD flags)
1763{
1764 log_start();
1765 rdpSettings* src = freerdp_settings_new(flags);
1766 if (!src)
1767 goto fail;
1768
1769 const char* argv1[] = { "foobar", "lala", "haha" };
1770 const char* argv2[] = { "lala", "haha" };
1771 const char* argv3[] = { "haha" };
1772 if (!add_argv(src, ARRAYSIZE(argv1), argv1))
1773 goto fail;
1774 if (!add_argv(src, ARRAYSIZE(argv2), argv2))
1775 goto fail;
1776 if (!add_argv(src, ARRAYSIZE(argv3), argv3))
1777 goto fail;
1778 if (!add_dev_argv(src, ARRAYSIZE(argv3), argv3))
1779 goto fail;
1780
1781 struct key_len_pair
1782 {
1783 FreeRDP_Settings_Keys_Pointer key;
1784 size_t elem;
1785 size_t len;
1786 };
1787
1788 const struct key_len_pair keys[] = {
1789 { FreeRDP_ServerRandom, 1, 123 },
1790 { FreeRDP_RedirectionPassword, 1, 13 },
1791 { FreeRDP_ClientRandom, 1, 23 },
1792 { FreeRDP_RedirectionGuid, 1, 22 },
1793 { FreeRDP_LoadBalanceInfo, 1, 21 },
1794 { FreeRDP_ServerCertificate, 1, 512 },
1795 { FreeRDP_RedirectionTsvUrl, 1, 33 },
1796 { FreeRDP_GlyphCache, sizeof(GLYPH_CACHE_DEFINITION), 10 },
1797 { FreeRDP_FragCache, sizeof(GLYPH_CACHE_DEFINITION), 1 },
1798 { FreeRDP_BitmapCacheV2CellInfo, sizeof(BITMAP_CACHE_V2_CELL_INFO), 1 },
1799 { FreeRDP_OrderSupport, 1, 32 },
1800 { FreeRDP_ClientAutoReconnectCookie, sizeof(ARC_CS_PRIVATE_PACKET), 1 },
1801 { FreeRDP_ServerAutoReconnectCookie, sizeof(ARC_SC_PRIVATE_PACKET), 1 },
1802 { FreeRDP_Password51, 1, 54 },
1803 { FreeRDP_MonitorIds, 1, 111 },
1804 { FreeRDP_MonitorDefArray, 1, 7 },
1805 { FreeRDP_ChannelDefArray, 1, 31 },
1806 { FreeRDP_ReceivedCapabilities, sizeof(uint8_t), 33 },
1807 { FreeRDP_ReceivedCapabilityData, sizeof(uint8_t*), 33 },
1808 { FreeRDP_ReceivedCapabilityDataSizes, sizeof(UINT32), 33 }
1809 };
1810
1811 for (size_t x = 0; x < ARRAYSIZE(keys); x++)
1812 {
1813 const struct key_len_pair* cur = &keys[x];
1814 if (!fill_random(src, cur->key, cur->elem, cur->len))
1815 goto fail;
1816 }
1817
1818 if (!fill_random_timezone(src))
1819 goto fail;
1820
1821 void* ptr = nullptr;
1822 if (winpr_RAND((void*)&ptr, sizeof(void*)) < 0)
1823 goto fail;
1824 if (!freerdp_settings_set_pointer(src, FreeRDP_instance, ptr))
1825 goto fail;
1826
1827 if (!set_private_key(src))
1828 goto fail;
1829 if (!set_cert(src, FreeRDP_RedirectionTargetCertificate))
1830 goto fail;
1831 if (!set_cert(src, FreeRDP_RdpServerCertificate))
1832 goto fail;
1833
1834 if (!set_string_array(src, FreeRDP_ServerLicenseProductIssuers, 43))
1835 goto fail;
1836
1837 char addresses[12][43] = WINPR_C_ARRAY_INIT;
1838 char* strptr[12] = WINPR_C_ARRAY_INIT;
1839
1840 for (size_t x = 0; x < ARRAYSIZE(addresses); x++)
1841 {
1842 (void)_snprintf(addresses[x], 43, "foobar-0x%08" PRIx32, x);
1843 strptr[x] = addresses[x];
1844 }
1845
1846 if (!freerdp_target_net_addresses_copy(src, strptr, ARRAYSIZE(addresses)))
1847 goto fail;
1848
1849 for (size_t x = 0; x < ARRAYSIZE(addresses); x++)
1850 {
1851 uint32_t port = 0;
1852 if (winpr_RAND(&port, sizeof(port)) < 0)
1853 goto fail;
1854 if (!freerdp_settings_set_pointer_array(src, FreeRDP_TargetNetPorts, x, &port))
1855 goto fail;
1856 }
1857
1858 uint32_t count = freerdp_settings_get_uint32(src, FreeRDP_ReceivedCapabilitiesSize);
1859 if (count != 33)
1860 goto fail;
1861
1862 void* caps = freerdp_settings_get_pointer_writable(src, FreeRDP_ReceivedCapabilities);
1863 if (!caps)
1864 goto fail;
1865 if (winpr_RAND(caps, count) < 0)
1866 goto fail;
1867
1868 for (uint32_t x = 0; x < count; x++)
1869 {
1870 uint8_t* buffer = calloc(64, sizeof(uint8_t));
1871 if (!buffer)
1872 goto fail;
1873 if (winpr_RAND(buffer, sizeof(buffer)) < 0)
1874 goto fail;
1875 uint32_t blen = (buffer[0] % 52) + 13;
1876
1877 if (!freerdp_settings_set_pointer_array(src, FreeRDP_ReceivedCapabilityData, x, buffer))
1878 goto fail;
1879 if (!freerdp_settings_set_pointer_array(src, FreeRDP_ReceivedCapabilityDataSizes, x, &blen))
1880 goto fail;
1881 }
1882
1883 char buffer[128] = WINPR_C_ARRAY_INIT;
1884 (void)_snprintf(buffer, sizeof(buffer), "%s flags 0x%08" PRIx32, __func__, flags);
1885 return test_serialize_with(src, buffer);
1886fail:
1887 log_result(FALSE);
1889 return FALSE;
1890}
1891
1892static BOOL test_serialize(void)
1893{
1894 BOOL rc = FALSE;
1895 log_start();
1896 if (WINPR_JSON_version(nullptr, 0) < 0)
1897 {
1898 rc = TRUE;
1899 }
1900 else
1901 {
1902 for (uint32_t flags = 0;
1903 flags <= (FREERDP_SETTINGS_SERVER_MODE | FREERDP_SETTINGS_REMOTE_MODE); flags++)
1904 {
1905 char buffer[32] = WINPR_C_ARRAY_INIT;
1906 (void)_snprintf(buffer, sizeof(buffer), "default (flags 0x%08" PRIx32 ")", flags);
1907 if (!test_serialize_with(freerdp_settings_new(flags), buffer))
1908 return FALSE;
1909 if (!test_serialize_strings(flags, "foobar"))
1910 return FALSE;
1911 if (!test_serialize_strings(flags, ""))
1912 return FALSE;
1913 if (!test_serialize_strings(flags, nullptr))
1914 return FALSE;
1915 if (!test_serialize_pointer(flags))
1916 return FALSE;
1917 }
1918 rc = TRUE;
1919 }
1920
1921 log_result(rc);
1922 return TRUE;
1923}
1924
1925static BOOL test_bool_list(rdpSettings* settings, const rdpSettings* cloned)
1926{
1927 BOOL rc = FALSE;
1928 log_start();
1929
1930 WINPR_ASSERT(settings);
1931 WINPR_ASSERT(cloned);
1932
1933#if defined(have_bool_list_indices)
1934
1935 for (size_t x = 0; x < ARRAYSIZE(bool_list_indices); x++)
1936 {
1937 const size_t key = bool_list_indices[x];
1938 const char* name =
1939 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
1940 const BOOL val = freerdp_settings_get_bool(settings, key);
1941 const BOOL cval = freerdp_settings_get_bool(cloned, key);
1942 if (val != cval)
1943 {
1944 printf("mismatch for key %s: %u -> copy %u\n", name, val, cval);
1945 goto fail;
1946 }
1947 if (!freerdp_settings_set_bool(settings, key, val))
1948 goto fail;
1949 if (!check_key_helpers(key, "bool"))
1950 goto fail;
1951 }
1952
1953#endif
1954 rc = TRUE;
1955fail:
1956 return log_result(rc);
1957}
1958
1959static BOOL test_int16_list(const rdpSettings* settings, const rdpSettings* cloned)
1960{
1961 BOOL rc = FALSE;
1962 log_start();
1963
1964 WINPR_ASSERT(settings);
1965 WINPR_ASSERT(cloned);
1966
1967#if defined(have_int16_list_indices)
1968
1969 for (size_t x = 0; x < ARRAYSIZE(int16_list_indices); x++)
1970 {
1971 const size_t key = int16_list_indices[x];
1972 const char* name = freerdp_settings_get_name_for_key(key);
1973 const INT16 val = freerdp_settings_get_int16(settings, key);
1974 const INT16 cval = freerdp_settings_get_int16(cloned, key);
1975 if (val != cval)
1976 {
1977 printf("mismatch for key %s: %" PRId16 " -> copy %" PRId16 "\n", name, val, cval);
1978 goto fail;
1979 }
1980 if (!freerdp_settings_set_int16(settings, key, val))
1981 goto fail;
1982 if (!check_key_helpers(key, "int16"))
1983 goto fail;
1984 }
1985
1986#endif
1987 rc = TRUE;
1988fail:
1989 return log_result(rc);
1990}
1991
1992static BOOL test_uint16_list(rdpSettings* settings, const rdpSettings* cloned)
1993{
1994 BOOL rc = FALSE;
1995 log_start();
1996
1997 WINPR_ASSERT(settings);
1998 WINPR_ASSERT(cloned);
1999
2000#if defined(have_uint16_list_indices)
2001
2002 for (size_t x = 0; x < ARRAYSIZE(uint16_list_indices); x++)
2003 {
2004 const size_t key = uint16_list_indices[x];
2005 const char* name =
2006 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
2007 const UINT16 val = freerdp_settings_get_uint16(settings, key);
2008 const UINT16 cval = freerdp_settings_get_uint16(cloned, key);
2009 if (val != cval)
2010 {
2011 printf("mismatch for key %s: %" PRIu16 " -> copy %" PRIu16 "\n", name, val, cval);
2012 goto fail;
2013 }
2014 if (!freerdp_settings_set_uint16(settings, key, val))
2015 goto fail;
2016 if (!check_key_helpers(key, "uint16"))
2017 goto fail;
2018 }
2019
2020#endif
2021 rc = TRUE;
2022fail:
2023 return log_result(rc);
2024}
2025
2026static BOOL test_int32_list(rdpSettings* settings, const rdpSettings* cloned)
2027{
2028 BOOL rc = FALSE;
2029 log_start();
2030
2031 WINPR_ASSERT(settings);
2032 WINPR_ASSERT(cloned);
2033
2034#if defined(have_int32_list_indices)
2035
2036 for (size_t x = 0; x < ARRAYSIZE(int32_list_indices); x++)
2037 {
2038 const size_t key = int32_list_indices[x];
2039 const char* name =
2040 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
2041 const INT32 val = freerdp_settings_get_int32(settings, key);
2042 const INT32 cval = freerdp_settings_get_int32(cloned, key);
2043 if (val != cval)
2044 {
2045 printf("mismatch for key %s: %" PRId32 " -> copy %" PRId32 "\n", name, val, cval);
2046 goto fail;
2047 }
2048 if (!freerdp_settings_set_int32(settings, key, val))
2049 goto fail;
2050 if (!check_key_helpers(key, "int32"))
2051 goto fail;
2052 }
2053
2054#endif
2055
2056 rc = TRUE;
2057fail:
2058 return log_result(rc);
2059}
2060
2061static BOOL test_uint32_list(rdpSettings* settings, const rdpSettings* cloned)
2062{
2063 BOOL rc = FALSE;
2064 log_start();
2065
2066 WINPR_ASSERT(settings);
2067 WINPR_ASSERT(cloned);
2068
2069#if defined(have_uint32_list_indices)
2070
2071 for (size_t x = 0; x < ARRAYSIZE(uint32_list_indices); x++)
2072 {
2073 const size_t key = uint32_list_indices[x];
2074 const char* name =
2075 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
2076 const UINT32 val = freerdp_settings_get_uint32(settings, key);
2077 const UINT32 cval = freerdp_settings_get_uint32(cloned, key);
2078 if (val != cval)
2079 {
2080 printf("mismatch for key %s: %" PRIu32 " -> copy %" PRIu32 "\n", name, val, cval);
2081 goto fail;
2082 }
2083 if (!freerdp_settings_set_uint32(settings, key, val))
2084 goto fail;
2085 if (!check_key_helpers(key, "uint32"))
2086 goto fail;
2087 }
2088
2089#endif
2090
2091 rc = TRUE;
2092fail:
2093 return log_result(rc);
2094}
2095
2096static BOOL test_int64_list(const rdpSettings* settings, const rdpSettings* cloned)
2097{
2098 BOOL rc = FALSE;
2099 log_start();
2100
2101 WINPR_ASSERT(settings);
2102 WINPR_ASSERT(cloned);
2103
2104#if defined(have_int64_list_indices)
2105
2106 for (size_t x = 0; x < ARRAYSIZE(int64_list_indices); x++)
2107 {
2108 const size_t key = int64_list_indices[x];
2109 const char* name = freerdp_settings_get_name_for_key(key);
2110 const INT64 val = freerdp_settings_get_int64(settings, key);
2111 const INT64 cval = freerdp_settings_get_int64(cloned, key);
2112 if (val != cval)
2113 {
2114 printf("mismatch for key %s: %" PRId64 " -> copy %" PRId64 "\n", name, val, cval);
2115 goto fail;
2116 }
2117 if (!freerdp_settings_set_int64(settings, key, val))
2118 goto fail;
2119 if (!check_key_helpers(key, "int64"))
2120 goto fail;
2121 }
2122
2123#endif
2124
2125 rc = TRUE;
2126fail:
2127 return log_result(rc);
2128}
2129
2130static BOOL test_uint64_list(rdpSettings* settings, const rdpSettings* cloned)
2131{
2132 BOOL rc = FALSE;
2133 log_start();
2134
2135 WINPR_ASSERT(settings);
2136 WINPR_ASSERT(cloned);
2137
2138#if defined(have_uint64_list_indices)
2139
2140 for (size_t x = 0; x < ARRAYSIZE(uint64_list_indices); x++)
2141 {
2142 const size_t key = uint64_list_indices[x];
2143 const char* name =
2144 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
2145 const UINT64 val = freerdp_settings_get_uint64(settings, key);
2146 const UINT64 cval = freerdp_settings_get_uint64(cloned, key);
2147 if (val != cval)
2148 {
2149 printf("mismatch for key %s: %" PRIu64 " -> copy %" PRIu64 "\n", name, val, cval);
2150 goto fail;
2151 }
2152 if (!freerdp_settings_set_uint64(settings, key, val))
2153 goto fail;
2154 if (!check_key_helpers(key, "uint64"))
2155 goto fail;
2156 }
2157
2158#endif
2159
2160 rc = TRUE;
2161fail:
2162 return log_result(rc);
2163}
2164
2165static BOOL test_string_list(rdpSettings* settings, const rdpSettings* cloned)
2166{
2167 BOOL rc = FALSE;
2168 log_start();
2169
2170 WINPR_ASSERT(settings);
2171 WINPR_ASSERT(cloned);
2172
2173#if defined(have_string_list_indices)
2174
2175 for (size_t x = 0; x < ARRAYSIZE(string_list_indices); x++)
2176 {
2177 const size_t key = string_list_indices[x];
2178 const char val[] = "test-string";
2179 const char* res = nullptr;
2180 const char* name =
2181 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
2182 const char* oval = freerdp_settings_get_string(settings, key);
2183 const char* cval = freerdp_settings_get_string(cloned, key);
2184 if ((oval != cval) && (strcmp(oval, cval) != 0))
2185 {
2186 printf("mismatch for key %s: %s -> copy %s\n", name, oval, cval);
2187 goto fail;
2188 }
2189 if (!freerdp_settings_set_string(settings, key, val))
2190 goto fail;
2191
2192 res = freerdp_settings_get_string(settings, key);
2193
2194 if (strncmp(val, res, sizeof(val)) != 0)
2195 goto fail;
2196 }
2197
2198#endif
2199
2200 rc = TRUE;
2201fail:
2202 return log_result(rc);
2203}
2204
2205static BOOL test_pointer_list(const rdpSettings* settings, const rdpSettings* cloned)
2206{
2207 BOOL rc = FALSE;
2208 log_start();
2209
2210 WINPR_ASSERT(settings);
2211 WINPR_ASSERT(cloned);
2212
2213#if defined(have_pointer_list_indices)
2214
2215 for (size_t x = 0; x < ARRAYSIZE(pointer_list_indices); x++)
2216 {
2217 const size_t key = pointer_list_indices[x];
2218 const void* val = freerdp_settings_get_pointer(settings, key);
2219 WINPR_UNUSED(val);
2220 }
2221
2222#endif
2223
2224 rc = TRUE;
2225fail:
2226 return log_result(rc);
2227}
2228
2229static BOOL test_clone_copy(const rdpSettings* settings, const rdpSettings* cloned)
2230{
2231 BOOL rc = FALSE;
2232 log_start();
2233 WINPR_ASSERT(settings);
2234 WINPR_ASSERT(cloned);
2235
2236 rdpSettings* cloned2 = freerdp_settings_clone(settings);
2237 if (!cloned2)
2238 goto fail;
2239 if (!freerdp_settings_copy(cloned2, cloned))
2240 goto fail;
2241 rc = TRUE;
2242fail:
2243 freerdp_settings_free(cloned2);
2244 return log_result(rc);
2245}
2246
2247static BOOL test_all(void)
2248{
2249 BOOL rc = FALSE;
2250 log_start();
2251
2252 rdpSettings* settings = freerdp_settings_new(0);
2253 rdpSettings* cloned = nullptr;
2254
2255 if (!settings)
2256 {
2257 printf("Couldn't create settings\n");
2258 return -1;
2259 }
2260
2261 if (!test_string_len(settings))
2262 goto fail;
2263
2264 cloned = freerdp_settings_clone(settings);
2265
2266 if (!cloned)
2267 goto fail;
2268
2269 if (!test_bool_list(settings, cloned))
2270 goto fail;
2271 if (!test_int16_list(settings, cloned))
2272 goto fail;
2273 if (!test_uint16_list(settings, cloned))
2274 goto fail;
2275 if (!test_int32_list(settings, cloned))
2276 goto fail;
2277 if (!test_uint32_list(settings, cloned))
2278 goto fail;
2279 if (!test_int64_list(settings, cloned))
2280 goto fail;
2281 if (!test_uint64_list(settings, cloned))
2282 goto fail;
2283 if (!test_string_list(settings, cloned))
2284 goto fail;
2285 if (!test_pointer_list(settings, cloned))
2286 goto fail;
2287 if (!test_clone_copy(settings, cloned))
2288 goto fail;
2289
2290 rc = TRUE;
2291fail:
2292 freerdp_settings_free(cloned);
2293 freerdp_settings_free(settings);
2294 return log_result(rc);
2295}
2296
2297#if defined(BUILD_TESTING_INTERNAL)
2298static FreeRDP_Settings_Keys_UInt32 getLenForKey(FreeRDP_Settings_Keys_Pointer key)
2299{
2300 return FreeRDP_TargetNetAddressCount;
2301}
2302
2303static bool fillTargetBuffer(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer key)
2304{
2305 const size_t count = freerdp_settings_get_uint32(settings, getLenForKey(key));
2306 for (size_t x = 0; x < count; x++)
2307 {
2308 char test[128] = WINPR_C_ARRAY_INIT;
2309 (void)_snprintf(test, sizeof(test), "test_value_%" PRIuz, x);
2310 if (!freerdp_settings_set_pointer_array(settings, key, x, test))
2311 return false;
2312 }
2313 return true;
2314}
2315
2316static bool checkTargetBuffer(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer key,
2317 size_t count)
2318{
2319 for (size_t x = 0; x < count; x++)
2320 {
2321 char test[128] = WINPR_C_ARRAY_INIT;
2322 (void)_snprintf(test, sizeof(test), "test_value_%" PRIuz, x);
2323 const char* cmp = freerdp_settings_get_pointer_array(settings, key, x);
2324 if (!cmp)
2325 return false;
2326 if (strncmp(test, cmp, sizeof(test)) != 0)
2327 return false;
2328 }
2329 return true;
2330}
2331
2332static bool checkTargetBufferResized(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer key,
2333 size_t count, size_t newSize)
2334{
2335 if (count > newSize)
2336 count = newSize;
2337
2338 if (!checkTargetBuffer(settings, key, count))
2339 return false;
2340
2341 for (size_t x = count; x < newSize; x++)
2342 {
2343 const char* cmp = freerdp_settings_get_pointer_array(settings, key, x);
2344 if (cmp != nullptr)
2345 return false;
2346 }
2347 return true;
2348}
2349
2350static bool testSize(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer key, size_t newSize)
2351{
2352 if (!fillTargetBuffer(settings, key))
2353 return false;
2354 const size_t count = freerdp_settings_get_uint32(settings, getLenForKey(key));
2355 if (!checkTargetBuffer(settings, key, count))
2356 return false;
2357 if (key == FreeRDP_TargetNetAddresses)
2358 {
2359 if (!freerdp_target_net_addresses_resize(settings, newSize))
2360 return false;
2361 }
2362 else
2363 {
2364 return false;
2365 }
2366 if (!checkTargetBufferResized(settings, key, count, newSize))
2367 return false;
2368 return true;
2369}
2370
2371static bool testBufferResize(FreeRDP_Settings_Keys_Pointer key)
2372{
2373 bool rc = false;
2374 rdpSettings* settings = freerdp_settings_new(0);
2375 if (!settings)
2376 return false;
2377
2378 if (!testSize(settings, key, 10))
2379 goto fail;
2380 if (!testSize(settings, key, 23))
2381 goto fail;
2382 if (!testSize(settings, key, 13))
2383 goto fail;
2384 if (!testSize(settings, key, 0))
2385 goto fail;
2386
2387 rc = true;
2388fail:
2389 freerdp_settings_free(settings);
2390 return rc;
2391}
2392#endif
2393
2394int TestSettings(int argc, char* argv[])
2395{
2396 int rc = -1;
2397 WINPR_UNUSED(argc);
2398 WINPR_UNUSED(argv);
2399
2400 if (!test_serialize())
2401 goto fail;
2402 if (!test_dyn_channels())
2403 goto fail;
2404 if (!test_static_channels())
2405 goto fail;
2406 if (!test_copy())
2407 goto fail;
2408 if (!test_helpers())
2409 goto fail;
2410 if (!check_device_type())
2411 goto fail;
2412 if (!test_pointer_array())
2413 goto fail;
2414 if (!test_validity_check())
2415 goto fail;
2416 if (!test_all())
2417 goto fail;
2418#if defined(BUILD_TESTING_INTERNAL)
2419 // freerdp_target_net_addresses_resize
2420 if (!testBufferResize(FreeRDP_TargetNetAddresses))
2421 goto fail;
2422#endif
2423 rc = 0;
2424
2425fail:
2426 return rc;
2427}
WINPR_API int WINPR_JSON_version(char *buffer, size_t len)
Get the library version string.
Definition c-json.c:88
WINPR_ATTR_NODISCARD FREERDP_API const void * freerdp_settings_get_pointer(const rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a immutable pointer settings value.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
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 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 rdpSettings * freerdp_settings_clone(const rdpSettings *settings)
Creates a deep copy of settings.
FREERDP_API 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.
WINPR_ATTR_NODISCARD FREERDP_API SSIZE_T freerdp_settings_get_type_for_name(const char *value)
Get a key type for the name string of that key.
WINPR_ATTR_NODISCARD FREERDP_API INT32 freerdp_settings_get_int32(const rdpSettings *settings, FreeRDP_Settings_Keys_Int32 id)
Returns a INT32 settings value.
FREERDP_API BOOL freerdp_settings_set_int16(rdpSettings *settings, FreeRDP_Settings_Keys_Int16 id, INT16 val)
Sets a INT16 settings value.
FREERDP_API 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 void * freerdp_settings_get_pointer_writable(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a mutable pointer settings value.
WINPR_ATTR_NODISCARD FREERDP_API rdpSettings * freerdp_settings_deserialize(const char *jstr, size_t length)
A function that converts a JSON string to a rdpSettings struct.
WINPR_ATTR_NODISCARD FREERDP_API 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_copy(rdpSettings *dst, const rdpSettings *src)
Deep copies settings from src to dst.
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 BOOL freerdp_settings_set_uint64(rdpSettings *settings, FreeRDP_Settings_Keys_UInt64 id, UINT64 val)
Sets a UINT64 settings value.
FREERDP_API void freerdp_settings_free(rdpSettings *settings)
Free a settings struct with all data in it.
#define FREERDP_SETTINGS_SERVER_MODE
WINPR_ATTR_NODISCARD FREERDP_API INT16 freerdp_settings_get_int16(const rdpSettings *settings, FreeRDP_Settings_Keys_Int16 id)
Returns a INT16 settings value.
WINPR_ATTR_NODISCARD FREERDP_API SSIZE_T freerdp_settings_get_key_for_name(const char *value)
Get a key index for the name string of that key.
WINPR_ATTR_NODISCARD FREERDP_API rdpSettings * freerdp_settings_new(DWORD flags)
creates a new setting struct
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.
WINPR_ATTR_NODISCARD FREERDP_API char * freerdp_settings_serialize(const rdpSettings *settings, BOOL pretty, size_t *plength)
A function that converts a rdpSettings struct to a JSON serialized string.
FREERDP_API BOOL freerdp_settings_set_int32(rdpSettings *settings, FreeRDP_Settings_Keys_Int32 id, INT32 val)
Sets a INT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API WCHAR * freerdp_settings_get_string_as_utf16(const rdpSettings *settings, FreeRDP_Settings_Keys_String id, size_t *pCharLen)
Return an allocated UTF16 string.
FREERDP_API 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 BOOL freerdp_settings_set_monitor_def_array_sorted(rdpSettings *settings, const rdpMonitor *monitors, size_t count)
Sort monitor array according to:
FREERDP_API BOOL freerdp_settings_set_int64(rdpSettings *settings, FreeRDP_Settings_Keys_Int64 id, INT64 val)
Sets a INT64 settings value.
FREERDP_API BOOL freerdp_settings_set_uint16(rdpSettings *settings, FreeRDP_Settings_Keys_UInt16 id, UINT16 val)
Sets a UINT16 settings value.
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.
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.
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.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_print_diff(wLog *log, DWORD level, const rdpSettings *settings, const rdpSettings *other)
Dumps the difference between two settings structs to a WLog.
WINPR_ATTR_NODISCARD FREERDP_API SSIZE_T freerdp_settings_get_type_for_key(SSIZE_T key)
Get a key type for the key index.