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;
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;
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 = NULL;
76 const ADDIN_ARGV* cmp1 = NULL;
77 const char* argv2[] = { "gaga", "abba", "foo" };
78 ADDIN_ARGV* args2 = NULL;
79 const ADDIN_ARGV* cmp2 = NULL;
80 const ADDIN_ARGV* got = NULL;
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 = NULL; /* 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 = NULL; /* 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 = NULL;
177 const ADDIN_ARGV* cmp1 = NULL;
178 const char* argv2[] = { "gaga", "abba", "foo" };
179 ADDIN_ARGV* args2 = NULL;
180 const ADDIN_ARGV* cmp2 = NULL;
181 const ADDIN_ARGV* got = NULL;
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 = NULL; /* 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 = NULL; /* 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 = NULL;
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, NULL, 0))
560 {
561 printf("[%s] freerdp_settings_set_pointer_len(%s, NULL, 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] = { 0 };
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 winpr_RAND(&intEntryType, sizeof(intEntryType));
583 winpr_RAND(&val.u64, sizeof(val.u64));
584
585 switch (key)
586 {
587 case FreeRDP_ReceivedCapabilitiesSize:
588 case FreeRDP_TargetNetAddressCount:
589 val.u64 %= 512;
590 break;
591 default:
592 break;
593 }
594
595 switch (type)
596 {
597 case RDP_SETTINGS_TYPE_BOOL:
598 expect = format_bool(value, sizeof(value), intEntryType);
599 break;
600 case RDP_SETTINGS_TYPE_UINT16:
601 expect = format_uint(value, sizeof(value), val.u64, intEntryType, UINT16_MAX);
602 break;
603 case RDP_SETTINGS_TYPE_INT16:
604 expect =
605 format_int(value, sizeof(value), val.i64, intEntryType, INT16_MAX, INT16_MIN);
606 break;
607 case RDP_SETTINGS_TYPE_UINT32:
608 expect = format_uint(value, sizeof(value), val.u64, intEntryType, UINT32_MAX);
609 break;
610 case RDP_SETTINGS_TYPE_INT32:
611 expect =
612 format_int(value, sizeof(value), val.i64, intEntryType, INT32_MAX, INT32_MIN);
613 break;
614 case RDP_SETTINGS_TYPE_UINT64:
615 expect = format_uint(value, sizeof(value), val.u64, intEntryType, UINT64_MAX);
616 break;
617 case RDP_SETTINGS_TYPE_INT64:
618 expect =
619 format_int(value, sizeof(value), val.i64, intEntryType, INT64_MAX, INT64_MIN);
620 break;
621 case RDP_SETTINGS_TYPE_STRING:
622 expect = TRUE;
623 (void)_snprintf(value, sizeof(value), "somerandomstring");
624 break;
625 case RDP_SETTINGS_TYPE_POINTER:
626 expect = FALSE;
627 break;
628
629 default:
630 printf("[%s] invalid type for key %s [%" PRIuz "]: %" PRIdz " <--> %" PRIdz "\n",
631 stype, name, key, rc, type);
632 goto fail;
633 }
634
635 have = freerdp_settings_set_value_for_name(settings, name, value);
636 if (have != expect)
637 {
638 printf("[%s] %s=%s have [%s] != expect[%s]\n", stype, name, value,
639 have ? "TRUE" : "FALSE", expect ? "TRUE" : "FALSE");
640 goto fail;
641 }
642
643 } while (test_rounds-- > 0);
644
645 res = TRUE;
646fail:
647 freerdp_settings_free(settings);
648 return log_result(res);
649}
650
651static BOOL check_args(const RDPDR_DEVICE* what, size_t count, const char* args[])
652{
653 WINPR_ASSERT(what);
654
655 if (count > 0)
656 {
657 if (strcmp(what->Name, args[0]) != 0)
658 return FALSE;
659 }
660
661 switch (what->Type)
662 {
663 case RDPDR_DTYP_PRINT:
664 {
665 const RDPDR_PRINTER* a = (const RDPDR_PRINTER*)what;
666 if (count <= 1)
667 return TRUE;
668 if (!a->DriverName)
669 return FALSE;
670 return strcmp(a->DriverName, args[1]) == 0;
671 }
672
673 case RDPDR_DTYP_SERIAL:
674 {
675 const RDPDR_SERIAL* a = (const RDPDR_SERIAL*)what;
676
677 if (count > 1)
678 {
679 if (!a->Path)
680 return FALSE;
681 if (strcmp(a->Path, args[1]) != 0)
682 return FALSE;
683 }
684
685 if (count > 2)
686 {
687 if (!a->Driver)
688 return FALSE;
689 if (strcmp(a->Driver, args[2]) != 0)
690 return FALSE;
691 }
692
693 if (count > 3)
694 {
695 if (!a->Permissive)
696 return FALSE;
697 if (strcmp(a->Permissive, args[3]) != 0)
698 return FALSE;
699 }
700 return TRUE;
701 }
702
703 case RDPDR_DTYP_PARALLEL:
704 {
705 const RDPDR_PARALLEL* a = (const RDPDR_PARALLEL*)what;
706 if (count <= 1)
707 return TRUE;
708 if (!a->Path)
709 return FALSE;
710 return strcmp(a->Path, args[1]) == 0;
711 }
712
713 case RDPDR_DTYP_SMARTCARD:
714 return TRUE;
715
716 case RDPDR_DTYP_FILESYSTEM:
717 {
718 const RDPDR_DRIVE* a = (const RDPDR_DRIVE*)what;
719 if (count > 1)
720 {
721 if (!a->Path)
722 return FALSE;
723 if (strcmp(a->Path, args[1]) != 0)
724 return FALSE;
725 }
726 if (count > 2)
727 {
728 return a->automount == (args[2] == NULL) ? TRUE : FALSE;
729 }
730 else
731 return !a->automount;
732 }
733
734 default:
735 return FALSE;
736 }
737}
738
739static int check_device_type_arg(UINT32 Type, size_t count, const char* args[])
740{
741 int rc = -3;
742 RDPDR_DEVICE* device = freerdp_device_new(Type, count, args);
743 RDPDR_DEVICE* clone = freerdp_device_clone(device);
744
745 if (!device)
746 goto fail;
747
748 rc++;
749 if (!clone)
750 goto fail;
751
752 rc++;
753 if (!check_args(device, count, args))
754 goto fail;
755
756 rc++;
757 if (!freerdp_device_equal(clone, device))
758 goto fail;
759 rc++;
760
761fail:
762 freerdp_device_free(device);
763 freerdp_device_free(clone);
764 return log_result(rc);
765}
766
767static BOOL check_device_type(void)
768{
769 log_start();
770 struct test_entry
771 {
772 int expect;
773 UINT32 type;
774 size_t count;
775 const char** args;
776 };
777 const char* args[] = { "somename", "anothername", "3rdname", "4thname" };
778 const struct test_entry tests[] = {
779 { 1, RDPDR_DTYP_SERIAL, 0, NULL },
780 { 1, RDPDR_DTYP_SERIAL, 0, args },
781 { 1, RDPDR_DTYP_SERIAL, 1, args },
782 { 1, RDPDR_DTYP_SERIAL, 2, args },
783 { 1, RDPDR_DTYP_SERIAL, 3, args },
784 { 1, RDPDR_DTYP_SERIAL, 4, args },
785 { 1, RDPDR_DTYP_PARALLEL, 0, NULL },
786 { 1, RDPDR_DTYP_PARALLEL, 0, args },
787 { 1, RDPDR_DTYP_PARALLEL, 1, args },
788 { 1, RDPDR_DTYP_PARALLEL, 2, args },
789 { 1, RDPDR_DTYP_PARALLEL, 3, args },
790 { 1, RDPDR_DTYP_PARALLEL, 4, args },
791 { 1, RDPDR_DTYP_PRINT, 0, NULL },
792 { 1, RDPDR_DTYP_PRINT, 0, args },
793 { 1, RDPDR_DTYP_PRINT, 1, args },
794 { 1, RDPDR_DTYP_PRINT, 2, args },
795 { 1, RDPDR_DTYP_PRINT, 3, args },
796 { 1, RDPDR_DTYP_PRINT, 4, args },
797 { 1, RDPDR_DTYP_FILESYSTEM, 0, NULL },
798 { 1, RDPDR_DTYP_FILESYSTEM, 0, args },
799 { 1, RDPDR_DTYP_FILESYSTEM, 1, args },
800 { 1, RDPDR_DTYP_FILESYSTEM, 2, args },
801 { 1, RDPDR_DTYP_FILESYSTEM, 3, args },
802 { 1, RDPDR_DTYP_FILESYSTEM, 4, args },
803 { 1, RDPDR_DTYP_SMARTCARD, 0, NULL },
804 { 1, RDPDR_DTYP_SMARTCARD, 0, args },
805 { 1, RDPDR_DTYP_SMARTCARD, 1, args },
806 { 1, RDPDR_DTYP_SMARTCARD, 2, args },
807 { 1, RDPDR_DTYP_SMARTCARD, 3, args },
808 { 1, RDPDR_DTYP_SMARTCARD, 4, args },
809 { -3, 0x123, 0, NULL },
810 { -3, 0x123, 0, args },
811 { -3, 0x123, 1, args },
812 { -3, 0x123, 2, args },
813 { -3, 0x123, 3, args },
814 { -3, 0x123, 4, args },
815 };
816 BOOL rc = TRUE;
817 for (size_t x = 0; x < ARRAYSIZE(tests); x++)
818 {
819 const struct test_entry* cur = &tests[x];
820 int got = check_device_type_arg(cur->type, cur->count, cur->args);
821 if (got != cur->expect)
822 rc = FALSE;
823 }
824 return log_result(rc);
825}
826
827static BOOL check_offsets(rdpSettings* settings, size_t id, size_t min, size_t max, BOOL checkPtr)
828{
829 BOOL rc = TRUE;
830
831 WINPR_ASSERT(settings);
832
833 if (!freerdp_settings_get_pointer(settings, id))
834 return FALSE;
835
836 for (size_t x = min; x < max; x++)
837 {
838 const void* ptr = freerdp_settings_get_pointer_array(settings, id, x);
839 if (!ptr && checkPtr)
840 rc = FALSE;
841 }
842 return log_result(rc);
843}
844
845static BOOL test_write_offsets(rdpSettings* settings, size_t id, size_t elementSize, size_t min,
846 size_t max)
847{
848 WINPR_ASSERT(settings);
849
850 for (size_t x = min; x < max; x++)
851 {
852 const void* ptr = NULL;
853 char buffer[8192] = { 0 };
854
855 winpr_RAND(buffer, sizeof(buffer));
856 if (!freerdp_settings_set_pointer_array(settings, id, x, buffer))
857 return FALSE;
858 ptr = freerdp_settings_get_pointer_array(settings, id, x);
859 if (!ptr)
860 return FALSE;
861 if (memcmp(ptr, buffer, elementSize) != 0)
862 return FALSE;
863 }
864 return TRUE;
865}
866
867static BOOL test_pointer_array(void)
868{
869 struct pointer_test_case
870 {
871 BOOL checkPtr;
872 BOOL write;
873 size_t id;
874 SSIZE_T sizeId;
875 size_t size;
876 size_t elementSize;
877 };
878 const struct pointer_test_case tests[] = {
879 { FALSE, FALSE, FreeRDP_DeviceArray, FreeRDP_DeviceArraySize, 32, sizeof(RDPDR_DEVICE*) },
880 { FALSE, FALSE, FreeRDP_StaticChannelArray, FreeRDP_StaticChannelArraySize, 32,
881 sizeof(ADDIN_ARGV*) },
882 { FALSE, FALSE, FreeRDP_DynamicChannelArray, FreeRDP_DynamicChannelArraySize, 33,
883 sizeof(ADDIN_ARGV*) },
884 { TRUE, TRUE, FreeRDP_BitmapCacheV2CellInfo, FreeRDP_BitmapCacheV2NumCells, 5,
886 { FALSE, FALSE, FreeRDP_OrderSupport, -1, 32, sizeof(BYTE) },
887 { FALSE, FALSE, FreeRDP_ReceivedCapabilities, -1, 32, sizeof(BYTE) },
888 { TRUE, TRUE, FreeRDP_GlyphCache, -1, 10, sizeof(GLYPH_CACHE_DEFINITION) },
889 { TRUE, TRUE, FreeRDP_FragCache, -1, 1, sizeof(GLYPH_CACHE_DEFINITION) },
890 { TRUE, TRUE, FreeRDP_MonitorIds, FreeRDP_NumMonitorIds, 33, sizeof(UINT32) },
891 { TRUE, TRUE, FreeRDP_ChannelDefArray, FreeRDP_ChannelDefArraySize, 42,
892 sizeof(CHANNEL_DEF) },
893 { TRUE, TRUE, FreeRDP_MonitorDefArray, FreeRDP_MonitorDefArraySize, 33,
894 sizeof(rdpMonitor) },
895 { TRUE, TRUE, FreeRDP_ClientTimeZone, -1, 1, sizeof(TIME_ZONE_INFORMATION) },
896 { FALSE, FALSE, FreeRDP_RdpServerCertificate, -1, 1, sizeof(rdpCertificate*) },
897 //{ FALSE, FALSE, FreeRDP_RdpServerRsaKey, -1, 1, sizeof(rdpPrivateKey*) },
898 { TRUE, TRUE, FreeRDP_RedirectionPassword, FreeRDP_RedirectionPasswordLength, 42,
899 sizeof(char) },
900 { TRUE, TRUE, FreeRDP_RedirectionTsvUrl, FreeRDP_RedirectionTsvUrlLength, 42,
901 sizeof(char) },
902 { TRUE, TRUE, FreeRDP_LoadBalanceInfo, FreeRDP_LoadBalanceInfoLength, 42, sizeof(char) },
903 { TRUE, TRUE, FreeRDP_ServerRandom, FreeRDP_ServerRandomLength, 42, sizeof(char) },
904 { TRUE, TRUE, FreeRDP_ClientRandom, FreeRDP_ClientRandomLength, 42, sizeof(char) },
905 { TRUE, TRUE, FreeRDP_ServerCertificate, FreeRDP_ServerCertificateLength, 42,
906 sizeof(char) },
907 { TRUE, TRUE, FreeRDP_ClientAutoReconnectCookie, -1, 1, sizeof(ARC_CS_PRIVATE_PACKET) },
908 { TRUE, TRUE, FreeRDP_ServerAutoReconnectCookie, -1, 1, sizeof(ARC_SC_PRIVATE_PACKET) }
909 };
910 BOOL rc = FALSE;
911 rdpSettings* settings = freerdp_settings_new(0);
912 if (!settings)
913 goto fail;
914
915 for (size_t x = 0; x < ARRAYSIZE(tests); x++)
916 {
917 const struct pointer_test_case* cur = &tests[x];
918 if (!freerdp_settings_set_pointer_len(settings, cur->id, NULL, cur->size))
919 goto fail;
920 if (cur->sizeId >= 0)
921 {
922 const UINT32 s = freerdp_settings_get_uint32(settings, (size_t)cur->sizeId);
923 if (s != cur->size)
924 goto fail;
925 }
926 if (!check_offsets(settings, cur->id, 0, cur->size, cur->checkPtr))
927 goto fail;
928 if (check_offsets(settings, cur->id, cur->size, cur->size + 5, TRUE))
929 goto fail;
930 if (cur->write)
931 {
932 if (!test_write_offsets(settings, cur->id, cur->elementSize, 0, cur->size))
933 goto fail;
934 if (test_write_offsets(settings, cur->id, cur->elementSize, cur->size, cur->size + 5))
935 goto fail;
936 }
937 if (!freerdp_settings_set_pointer_len(settings, cur->id, NULL, 0))
938 goto fail;
939 if (cur->sizeId >= 0)
940 {
941 const UINT32 s = freerdp_settings_get_uint32(settings, (size_t)cur->sizeId);
942 if (s != 0)
943 goto fail;
944 }
945 if (check_offsets(settings, cur->id, 0, cur->size, cur->checkPtr))
946 goto fail;
947 if (cur->write)
948 {
949 if (test_write_offsets(settings, cur->id, cur->elementSize, 0, cur->size))
950 goto fail;
951 }
952 if (!freerdp_settings_set_pointer_len(settings, cur->id, NULL, cur->size))
953 goto fail;
954 if (cur->sizeId >= 0)
955 {
956 const UINT32 s = freerdp_settings_get_uint32(settings, (size_t)cur->sizeId);
957 if (s != cur->size)
958 goto fail;
959 }
960 if (!check_offsets(settings, cur->id, 0, cur->size, cur->checkPtr))
961 goto fail;
962 if (check_offsets(settings, cur->id, cur->size + 1, cur->size + 5, TRUE))
963 goto fail;
964 if (cur->write)
965 {
966 if (!test_write_offsets(settings, cur->id, cur->elementSize, 0, cur->size))
967 goto fail;
968 if (test_write_offsets(settings, cur->id, cur->elementSize, cur->size, cur->size + 5))
969 goto fail;
970 }
971 }
972
973 rc = TRUE;
974
975fail:
976 freerdp_settings_free(settings);
977 return log_result(rc);
978}
979
980struct validity_test_case
981{
982 BOOL expected;
983 size_t count;
984 const rdpMonitor* monitors;
985};
986
987static BOOL prepare_monitor_array(rdpSettings* settings, const struct validity_test_case* testcase)
988{
989 WINPR_ASSERT(settings);
990 WINPR_ASSERT(testcase);
991
992 return freerdp_settings_set_monitor_def_array_sorted(settings, testcase->monitors,
993 testcase->count);
994}
995
996static BOOL check_primary_offset(const rdpSettings* settings, const rdpMonitor* monitors,
997 size_t count)
998{
999 const rdpMonitor* cprimary = NULL;
1000 for (size_t x = 0; x < count; x++)
1001 {
1002 const rdpMonitor* cur = &monitors[x];
1003 if (cur->is_primary)
1004 cprimary = cur;
1005 }
1006 if (!cprimary)
1007 {
1008 for (size_t x = 0; x < count; x++)
1009 {
1010 const rdpMonitor* cur = &monitors[x];
1011 if ((cur->x == 0) && (cur->y == 0))
1012 cprimary = cur;
1013 }
1014 }
1015 const rdpMonitor* sprimary = NULL;
1016 for (size_t x = 0; x < count; x++)
1017 {
1018 const rdpMonitor* cur =
1019 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
1020 if (!cur)
1021 return FALSE;
1022 if (cur->is_primary)
1023 sprimary = cur;
1024 }
1025
1026 if (!sprimary || !cprimary)
1027 return FALSE;
1028
1029 const INT32 xoff = cprimary->x;
1030 const INT32 yoff = cprimary->y;
1031 const INT32 sxoff = freerdp_settings_get_int32(settings, FreeRDP_MonitorLocalShiftX);
1032 const INT32 syoff = freerdp_settings_get_int32(settings, FreeRDP_MonitorLocalShiftY);
1033 if (xoff != sxoff)
1034 return FALSE;
1035 if (yoff != syoff)
1036 return FALSE;
1037 return TRUE;
1038}
1039
1040static BOOL test_validity_check(void)
1041{
1042 log_start();
1043 BOOL rc = FALSE;
1044 rdpSettings* settings = freerdp_settings_new(0);
1045 if (!settings)
1046 goto fail;
1047
1048 const rdpMonitor single_monitor_valid[] = {
1049 { .x = 0,
1050 .y = 0,
1051 .width = 1920,
1052 .height = 1080,
1053 .is_primary = TRUE,
1054 .orig_screen = 0,
1055 .attributes = { .physicalWidth = 100,
1056 .physicalHeight = 100,
1057 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1058 .desktopScaleFactor = 100,
1059 .deviceScaleFactor = 100 } }
1060 };
1061 const rdpMonitor single_monitor_invalid_1[] = {
1062 { .x = 0,
1063 .y = 0,
1064 .width = 192,
1065 .height = 1080,
1066 .is_primary = TRUE,
1067 .orig_screen = 0,
1068 .attributes = { .physicalWidth = 100,
1069 .physicalHeight = 100,
1070 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1071 .desktopScaleFactor = 100,
1072 .deviceScaleFactor = 100 } }
1073 };
1074 const rdpMonitor single_monitor_invalid_2[] = {
1075 { .x = 0,
1076 .y = 0,
1077 .width = 192,
1078 .height = 1080,
1079 .is_primary = TRUE,
1080 .orig_screen = 0,
1081 .attributes = { .physicalWidth = 100,
1082 .physicalHeight = 100,
1083 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1084 .desktopScaleFactor = 100,
1085 .deviceScaleFactor = 100 } }
1086 };
1087 const rdpMonitor single_monitor_invalid_3[] = {
1088 { .x = 0,
1089 .y = 0,
1090 .width = 192,
1091 .height = 1080,
1092 .is_primary = TRUE,
1093 .orig_screen = 0,
1094 .attributes = { .physicalWidth = 100,
1095 .physicalHeight = 100,
1096 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1097 .desktopScaleFactor = 100,
1098 .deviceScaleFactor = 100 } }
1099 };
1100 const rdpMonitor single_monitor_invalid_4[] = {
1101 { .x = 0,
1102 .y = 0,
1103 .width = 192,
1104 .height = 1080,
1105 .is_primary = TRUE,
1106 .orig_screen = 0,
1107 .attributes = { .physicalWidth = 100,
1108 .physicalHeight = 100,
1109 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1110 .desktopScaleFactor = 100,
1111 .deviceScaleFactor = 100 } }
1112 };
1113 const rdpMonitor multi_monitor_valid[] = {
1114 { .x = 0,
1115 .y = 0,
1116 .width = 1920,
1117 .height = 1080,
1118 .is_primary = FALSE,
1119 .orig_screen = 0,
1120 .attributes = { .physicalWidth = 100,
1121 .physicalHeight = 100,
1122 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1123 .desktopScaleFactor = 100,
1124 .deviceScaleFactor = 100 } },
1125 { .x = 1920,
1126 .y = 0,
1127 .width = 1920,
1128 .height = 1080,
1129 .is_primary = FALSE,
1130 .orig_screen = 0,
1131 .attributes = { .physicalWidth = 100,
1132 .physicalHeight = 100,
1133 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1134 .desktopScaleFactor = 100,
1135 .deviceScaleFactor = 100 } },
1136 { .x = 0,
1137 .y = 1080,
1138 .width = 1920,
1139 .height = 1080,
1140 .is_primary = FALSE,
1141 .orig_screen = 0,
1142 .attributes = { .physicalWidth = 100,
1143 .physicalHeight = 100,
1144 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1145 .desktopScaleFactor = 100,
1146 .deviceScaleFactor = 100 } },
1147 { .x = -1920,
1148 .y = 0,
1149 .width = 1920,
1150 .height = 1080,
1151 .is_primary = FALSE,
1152 .orig_screen = 0,
1153 .attributes = { .physicalWidth = 100,
1154 .physicalHeight = 100,
1155 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1156 .desktopScaleFactor = 100,
1157 .deviceScaleFactor = 100 } },
1158 { .x = 0,
1159 .y = -1080,
1160 .width = 1920,
1161 .height = 1080,
1162 .is_primary = TRUE,
1163 .orig_screen = 0,
1164 .attributes = { .physicalWidth = 100,
1165 .physicalHeight = 100,
1166 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1167 .desktopScaleFactor = 100,
1168 .deviceScaleFactor = 100 } },
1169 { .x = 3840,
1170 .y = 0,
1171 .width = 1920,
1172 .height = 1080,
1173 .is_primary = FALSE,
1174 .orig_screen = 0,
1175 .attributes = { .physicalWidth = 100,
1176 .physicalHeight = 100,
1177 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1178 .desktopScaleFactor = 100,
1179 .deviceScaleFactor = 100 } },
1180 { .x = 5760,
1181 .y = -1079,
1182 .width = 1920,
1183 .height = 1080,
1184 .is_primary = FALSE,
1185 .orig_screen = 0,
1186 .attributes = { .physicalWidth = 100,
1187 .physicalHeight = 100,
1188 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1189 .desktopScaleFactor = 100,
1190 .deviceScaleFactor = 100 } },
1191 { .x = 7680,
1192 .y = 0,
1193 .width = 1920,
1194 .height = 1080,
1195 .is_primary = FALSE,
1196 .orig_screen = 0,
1197 .attributes = { .physicalWidth = 100,
1198 .physicalHeight = 100,
1199 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1200 .desktopScaleFactor = 100,
1201 .deviceScaleFactor = 100 } },
1202 { .x = 7680,
1203 .y = 1080,
1204 .width = 1920,
1205 .height = 1080,
1206 .is_primary = FALSE,
1207 .orig_screen = 0,
1208 .attributes = { .physicalWidth = 100,
1209 .physicalHeight = 100,
1210 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1211 .desktopScaleFactor = 100,
1212 .deviceScaleFactor = 100 } },
1213 { .x = 7680,
1214 .y = -1080,
1215 .width = 1920,
1216 .height = 1080,
1217 .is_primary = FALSE,
1218 .orig_screen = 0,
1219 .attributes = { .physicalWidth = 100,
1220 .physicalHeight = 100,
1221 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1222 .desktopScaleFactor = 100,
1223 .deviceScaleFactor = 100 } },
1224 { .x = 7680,
1225 .y = -2160,
1226 .width = 1920,
1227 .height = 1080,
1228 .is_primary = FALSE,
1229 .orig_screen = 0,
1230 .attributes = { .physicalWidth = 100,
1231 .physicalHeight = 100,
1232 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1233 .desktopScaleFactor = 100,
1234 .deviceScaleFactor = 100 } },
1235 { .x = 9599,
1236 .y = -3240,
1237 .width = 1920,
1238 .height = 1080,
1239 .is_primary = FALSE,
1240 .orig_screen = 0,
1241 .attributes = { .physicalWidth = 100,
1242 .physicalHeight = 100,
1243 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1244 .desktopScaleFactor = 100,
1245 .deviceScaleFactor = 100 } },
1246 };
1247 const rdpMonitor multi_monitor_invalid_1[] = {
1248 { .x = 0,
1249 .y = 0,
1250 .width = 1920,
1251 .height = 1080,
1252 .is_primary = FALSE,
1253 .orig_screen = 0,
1254 .attributes = { .physicalWidth = 100,
1255 .physicalHeight = 100,
1256 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1257 .desktopScaleFactor = 100,
1258 .deviceScaleFactor = 100 } },
1259 { .x = 1920,
1260 .y = 0,
1261 .width = 1920,
1262 .height = 1080,
1263 .is_primary = FALSE,
1264 .orig_screen = 0,
1265 .attributes = { .physicalWidth = 100,
1266 .physicalHeight = 100,
1267 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1268 .desktopScaleFactor = 100,
1269 .deviceScaleFactor = 100 } }
1270 };
1271 const rdpMonitor multi_monitor_invalid_2[] = {
1272 { .x = 1,
1273 .y = 0,
1274 .width = 1920,
1275 .height = 1080,
1276 .is_primary = FALSE,
1277 .orig_screen = 0,
1278 .attributes = { .physicalWidth = 100,
1279 .physicalHeight = 100,
1280 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1281 .desktopScaleFactor = 100,
1282 .deviceScaleFactor = 100 } },
1283 { .x = 1920,
1284 .y = 0,
1285 .width = 1920,
1286 .height = 1080,
1287 .is_primary = TRUE,
1288 .orig_screen = 0,
1289 .attributes = { .physicalWidth = 100,
1290 .physicalHeight = 100,
1291 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1292 .desktopScaleFactor = 100,
1293 .deviceScaleFactor = 100 } }
1294 };
1295 const rdpMonitor multi_monitor_invalid_3[] = {
1296 { .x = 0,
1297 .y = 0,
1298 .width = 1920,
1299 .height = 1080,
1300 .is_primary = FALSE,
1301 .orig_screen = 0,
1302 .attributes = { .physicalWidth = 100,
1303 .physicalHeight = 100,
1304 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1305 .desktopScaleFactor = 100,
1306 .deviceScaleFactor = 100 } },
1307 { .x = 1921,
1308 .y = 0,
1309 .width = 1920,
1310 .height = 1080,
1311 .is_primary = TRUE,
1312 .orig_screen = 0,
1313 .attributes = { .physicalWidth = 100,
1314 .physicalHeight = 100,
1315 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1316 .desktopScaleFactor = 100,
1317 .deviceScaleFactor = 100 } }
1318 };
1319 const rdpMonitor multi_monitor_invalid_4[] = {
1320 { .x = 0,
1321 .y = 0,
1322 .width = 1920,
1323 .height = 1080,
1324 .is_primary = FALSE,
1325 .orig_screen = 0,
1326 .attributes = { .physicalWidth = 100,
1327 .physicalHeight = 100,
1328 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1329 .desktopScaleFactor = 100,
1330 .deviceScaleFactor = 100 } },
1331 { .x = 1919,
1332 .y = 0,
1333 .width = 1920,
1334 .height = 1080,
1335 .is_primary = TRUE,
1336 .orig_screen = 0,
1337 .attributes = { .physicalWidth = 100,
1338 .physicalHeight = 100,
1339 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1340 .desktopScaleFactor = 100,
1341 .deviceScaleFactor = 100 } }
1342 };
1343
1344 const rdpMonitor multi_monitor_valid_2[] = {
1345 { .x = 0,
1346 .y = 0,
1347 .width = 1920,
1348 .height = 1080,
1349 .is_primary = TRUE,
1350 .orig_screen = 0,
1351 .attributes = { .physicalWidth = 100,
1352 .physicalHeight = 100,
1353 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1354 .desktopScaleFactor = 100,
1355 .deviceScaleFactor = 100 } },
1356 { .x = 3840,
1357 .y = 0,
1358 .width = 1920,
1359 .height = 1080,
1360 .is_primary = FALSE,
1361 .orig_screen = 0,
1362 .attributes = { .physicalWidth = 100,
1363 .physicalHeight = 100,
1364 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1365 .desktopScaleFactor = 100,
1366 .deviceScaleFactor = 100 } },
1367 { .x = 1920,
1368 .y = 0,
1369 .width = 1920,
1370 .height = 1080,
1371 .is_primary = FALSE,
1372 .orig_screen = 0,
1373 .attributes = { .physicalWidth = 100,
1374 .physicalHeight = 100,
1375 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1376 .desktopScaleFactor = 100,
1377 .deviceScaleFactor = 100 } }
1378 };
1379
1380 const rdpMonitor multi_monitor_valid_3[] = {
1381 { .x = 1920,
1382 .y = 0,
1383 .width = 1920,
1384 .height = 1080,
1385 .is_primary = TRUE,
1386 .orig_screen = 0,
1387 .attributes = { .physicalWidth = 100,
1388 .physicalHeight = 100,
1389 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1390 .desktopScaleFactor = 100,
1391 .deviceScaleFactor = 100 } },
1392 { .x = 3840,
1393 .y = 0,
1394 .width = 1920,
1395 .height = 1080,
1396 .is_primary = FALSE,
1397 .orig_screen = 0,
1398 .attributes = { .physicalWidth = 100,
1399 .physicalHeight = 100,
1400 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1401 .desktopScaleFactor = 100,
1402 .deviceScaleFactor = 100 } },
1403 { .x = 0,
1404 .y = 0,
1405 .width = 1920,
1406 .height = 1080,
1407 .is_primary = FALSE,
1408 .orig_screen = 0,
1409 .attributes = { .physicalWidth = 100,
1410 .physicalHeight = 100,
1411 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1412 .desktopScaleFactor = 100,
1413 .deviceScaleFactor = 100 } }
1414 };
1415
1416 const struct validity_test_case tests[] = {
1417 { TRUE, ARRAYSIZE(single_monitor_valid), single_monitor_valid },
1418 { FALSE, ARRAYSIZE(single_monitor_invalid_1), single_monitor_invalid_1 },
1419 { FALSE, ARRAYSIZE(single_monitor_invalid_2), single_monitor_invalid_2 },
1420 { FALSE, ARRAYSIZE(single_monitor_invalid_3), single_monitor_invalid_3 },
1421 { FALSE, ARRAYSIZE(single_monitor_invalid_4), single_monitor_invalid_4 },
1422 { TRUE, ARRAYSIZE(multi_monitor_valid), multi_monitor_valid },
1423 { TRUE, ARRAYSIZE(multi_monitor_invalid_1), multi_monitor_invalid_1 },
1424 { FALSE, ARRAYSIZE(multi_monitor_invalid_2), multi_monitor_invalid_2 },
1425 { FALSE, ARRAYSIZE(multi_monitor_invalid_3), multi_monitor_invalid_3 },
1426 { FALSE, ARRAYSIZE(multi_monitor_invalid_4), multi_monitor_invalid_4 },
1427 { TRUE, ARRAYSIZE(multi_monitor_valid_2), multi_monitor_valid_2 },
1428 { TRUE, ARRAYSIZE(multi_monitor_valid_3), multi_monitor_valid_3 }
1429 };
1430
1431 rc = TRUE;
1432 for (size_t x = 0; x < ARRAYSIZE(tests); x++)
1433 {
1434 const struct validity_test_case* cur = &tests[x];
1435
1436 if (!prepare_monitor_array(settings, cur))
1437 rc = log_result_case(FALSE, __func__, x);
1438 else
1439 {
1440#if defined(BUILD_TESTING_INTERNAL)
1441 const BOOL res = freerdp_settings_check_client_after_preconnect(settings);
1442#else
1443 const BOOL res = cur->expected;
1444#endif
1445
1446 if ((res != cur->expected) ||
1447 !check_primary_offset(settings, cur->monitors, cur->count))
1448 {
1449 rc = log_result_case(FALSE, __func__, x);
1450 }
1451 }
1452 }
1453
1454fail:
1455 freerdp_settings_free(settings);
1456 return log_result(rc);
1457}
1458
1459static BOOL test_string_null(rdpSettings* settings, FreeRDP_Settings_Keys_String id)
1460{
1461 if (!freerdp_settings_set_string(settings, id, NULL))
1462 return FALSE;
1463
1464 const char* chk = freerdp_settings_get_string(settings, id);
1465 return (chk == NULL);
1466}
1467
1468static BOOL test_string_check(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
1469 const char* string, size_t len)
1470{
1471 const char* chk = freerdp_settings_get_string(settings, id);
1472 if (!chk)
1473 return FALSE;
1474
1475 const size_t clen = strnlen(chk, len + 1);
1476
1477 /* set strings must always be '\0' terminated */
1478 if (clen != len)
1479 return FALSE;
1480
1481 /* Strings must match comparison */
1482 if (strncmp(string, chk, clen) != 0)
1483 return FALSE;
1484
1485 return TRUE;
1486}
1487
1488static BOOL test_string_check_reset(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
1489 const char* string, size_t len)
1490{
1491 return test_string_check(settings, id, string, len) && test_string_null(settings, id);
1492}
1493
1494static BOOL test_string_set_readback(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
1495 const char* string, size_t len)
1496{
1497 WINPR_ASSERT(len > 3);
1498
1499 BOOL rc = FALSE;
1500 WCHAR* wstr = NULL;
1501
1502 const size_t slen = strnlen(string, len);
1503 if (!freerdp_settings_set_string_len(settings, id, string, slen - 1))
1504 goto fail;
1505
1506 if (!test_string_check_reset(settings, id, string, slen - 1))
1507 goto fail;
1508
1509 if (!freerdp_settings_set_string(settings, id, string))
1510 goto fail;
1511
1512 size_t wlen = 0;
1513 wstr = freerdp_settings_get_string_as_utf16(settings, id, &wlen);
1514 if (!wstr || (wlen != slen))
1515 goto fail;
1516
1517 if (!test_string_check_reset(settings, id, string, slen))
1518 goto fail;
1519
1520 if (!freerdp_settings_set_string_from_utf16N(settings, id, wstr, slen - 1))
1521 goto fail;
1522
1523 if (!test_string_check(settings, id, string, slen - 1))
1524 goto fail;
1525
1526 if (!freerdp_settings_set_string_from_utf16(settings, id, wstr))
1527 goto fail;
1528
1529 if (!test_string_check(settings, id, string, slen))
1530 goto fail;
1531
1532 rc = TRUE;
1533fail:
1534 free(wstr);
1535 return rc;
1536}
1537
1538static BOOL test_string_len(rdpSettings* settings)
1539{
1540 BOOL rc = FALSE;
1541
1542 const char user[] = "abcdefg";
1543 if (!test_string_set_readback(settings, FreeRDP_Username, user, sizeof(user)))
1544 goto fail;
1545
1546 const char pwd[] = "xyz";
1547 if (!test_string_set_readback(settings, FreeRDP_Password, pwd, sizeof(pwd)))
1548 goto fail;
1549
1550 const char domain[] = "foobar";
1551 if (!test_string_set_readback(settings, FreeRDP_Domain, domain, sizeof(domain)))
1552 goto fail;
1553
1554 rc = TRUE;
1555fail:
1556 return rc;
1557}
1558
1559static BOOL test_serialize_with(rdpSettings* src, const char* name)
1560{
1561 log_start();
1562 BOOL rc = FALSE;
1563 size_t slen = 0;
1564 rdpSettings* dst = NULL;
1565 char* str = NULL;
1566 if (!src)
1567 goto fail;
1568
1569 log_start_("%s-%s-%s", name, __func__, "freerdp_settings_serialize");
1570 str = freerdp_settings_serialize(src, TRUE, &slen);
1571 if (!str || (slen == 0))
1572 goto fail;
1573
1574 log_start_("%s-%s-%s", name, __func__, "freerdp_settings_deserialize");
1575 dst = freerdp_settings_deserialize(str, slen);
1576 if (!dst)
1577 goto fail;
1578
1579 log_start_("%s-%s-%s", name, __func__, "freerdp_settings_print_diff");
1580 rc = !freerdp_settings_print_diff(WLog_Get("TestSettings::serialize"), WLOG_WARN, src, dst);
1581
1582fail:
1585 free(str);
1586
1587 return log_result_(rc, "%s-%s", name, __func__);
1588}
1589
1590static BOOL test_serialize_strings(DWORD flags, const char* str)
1591{
1592 log_start();
1593 rdpSettings* src = freerdp_settings_new(flags);
1594 if (!src)
1595 return FALSE;
1596
1597 for (int x = 0; x < FreeRDP_Settings_StableAPI_MAX; x++)
1598 {
1599 union
1600 {
1601 int s;
1602 FreeRDP_Settings_Keys_Pointer ptr;
1603 } iter;
1604 iter.s = x;
1605
1606 SSIZE_T type = freerdp_settings_get_type_for_key(iter.s);
1607 switch (type)
1608 {
1609 case RDP_SETTINGS_TYPE_STRING:
1610 if (!freerdp_settings_set_string(src, iter.ptr, str))
1611 {
1613 return FALSE;
1614 }
1615 break;
1616 default:
1617 break;
1618 }
1619 }
1620
1621 char buffer[128] = { 0 };
1622 (void)_snprintf(buffer, sizeof(buffer), "%s flags 0x%08" PRIx32 " {%s}", __func__, flags, str);
1623 return test_serialize_with(src, buffer);
1624}
1625
1626static BOOL add_argv(rdpSettings* src, size_t argc, const char* argv[])
1627{
1628 ADDIN_ARGV* val = freerdp_addin_argv_new(argc, argv);
1629 if (!val)
1630 return FALSE;
1631 if (!freerdp_static_channel_collection_add(src, val))
1632 return FALSE;
1633 if (!freerdp_static_channel_collection_add(src, freerdp_addin_argv_clone(val)))
1634 return FALSE;
1635 if (!freerdp_dynamic_channel_collection_add(src, freerdp_addin_argv_clone(val)))
1636 return FALSE;
1637
1638 return TRUE;
1639}
1640
1641static BOOL add_dev_argv(rdpSettings* src, size_t argc, const char* argv[])
1642{
1643 FreeRDP_Settings_Keys_Pointer key = FreeRDP_DeviceArray;
1644 size_t count = 6;
1645 if (!freerdp_settings_set_pointer_len(src, key, NULL, count))
1646 return FALSE;
1647
1648 const uint32_t types[] = { RDPDR_DTYP_SERIAL, RDPDR_DTYP_PARALLEL, RDPDR_DTYP_PRINT,
1649 RDPDR_DTYP_FILESYSTEM, RDPDR_DTYP_SMARTCARD };
1650
1651 for (size_t x = 0; x < count; x++)
1652 {
1653 const uint32_t type = types[x % ARRAYSIZE(types)];
1654 RDPDR_DEVICE* arg = freerdp_device_new(type, argc, argv);
1655 if (!arg)
1656 return FALSE;
1657 const BOOL rc = freerdp_settings_set_pointer_array(src, key, x, arg);
1658 freerdp_device_free(arg);
1659 if (!rc)
1660 return FALSE;
1661 }
1662 return TRUE;
1663}
1664
1665static BOOL fill_random(rdpSettings* src, FreeRDP_Settings_Keys_Pointer key, size_t elem,
1666 size_t len)
1667{
1668 if (!freerdp_settings_set_pointer_len(src, key, NULL, len))
1669 return FALSE;
1670 uint8_t* data = freerdp_settings_get_pointer_writable(src, key);
1671 if (!data)
1672 return FALSE;
1673
1674 const size_t size = len * elem;
1675 char* random = calloc(len, elem);
1676 if (!random)
1677 return FALSE;
1678 char* b64 = crypto_base64_encode(random, size);
1679 free(random);
1680 memcpy(data, b64, size);
1681 free(b64);
1682 return TRUE;
1683}
1684
1685static BOOL fill_random_timezone(rdpSettings* src)
1686{
1687 FreeRDP_Settings_Keys_Pointer key = FreeRDP_ClientTimeZone;
1688 if (!fill_random(src, key, sizeof(TIME_ZONE_INFORMATION), 1))
1689 return FALSE;
1690
1692 if (!data)
1693 return FALSE;
1694 (void)ConvertUtf8ToWChar("testXXXXDaylight", data->DaylightName, ARRAYSIZE(data->DaylightName));
1695 (void)ConvertUtf8ToWChar("testXXXX", data->StandardName, ARRAYSIZE(data->StandardName));
1696
1697 return TRUE;
1698}
1699
1700static BOOL set_private_key(rdpSettings* src)
1701{
1702 if (!freerdp_settings_set_pointer_len(src, FreeRDP_RdpServerRsaKey, NULL, 1))
1703 return FALSE;
1704
1705 rdpPrivateKey* key =
1706 freerdp_settings_get_pointer_array_writable(src, FreeRDP_RdpServerRsaKey, 0);
1707 if (!key)
1708 return FALSE;
1709
1710 return freerdp_key_generate(key, "RSA", 1, 4096);
1711}
1712
1713static BOOL set_cert(rdpSettings* src, FreeRDP_Settings_Keys_Pointer key)
1714{
1715 const char pem[] = "-----BEGIN CERTIFICATE-----\n"
1716 "MIICvTCCAaWgAwIBAgIEZrM9yjANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlt\n"
1717 "b3RvcmhlYWQwHhcNMjUwNDE1MTExMjE5WhcNMjYwNDE1MTExMjE5WjAUMRIwEAYD\n"
1718 "VQQDDAltb3RvcmhlYWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCw\n"
1719 "g0tADY3kh5Hi6YsTsQbuaPs50zlTpIv+rCCK3BNIblsIh4cSO1YGdWfB0gP9bUD1\n"
1720 "L7mPWRnIiAvwrRA/Mgyo+UgiYj/aE3xxN3adB9/QsUzNrI07o6L8MupV4237txMj\n"
1721 "uxVmarB4c7E4wFgSxwbMQPhQtoNNew3bY+EeqhQBMFfYy4z+rg60xl0QHGcMePY/\n"
1722 "xz0WMHrIz6FhZfBIr+BGViRtjIchbjcU0HfTSujX+MT0D5MBISe8aiFvrewFItfT\n"
1723 "vglriDLeNMiB9U/aRLV8OtW+heGNhi5qSC9JXEW70OFeGAoqtwyRHLnSh38Fo2xv\n"
1724 "fEc90zjkCan8usEDKuzBAgMBAAGjFzAVMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0G\n"
1725 "CSqGSIb3DQEBCwUAA4IBAQBY1wkJ6XWduNmTi+UNdcZ5e9GWV/3+SYLtFALwKVrU\n"
1726 "KQQbsYnGLfyUKXFc7e9JoZ+UCTJgY3EyL+6p79io+cFeTtpp1RVKljibbeRAP01W\n"
1727 "WbcxcHZFKgBlH1KNSeO7iOAPet3aCaVDKl1XSU7fhxtsfBBI9YTtaMZM5e9WhuHK\n"
1728 "lL11Un6ePThX+4NG1yYp0X+emqUHd/qaq8IShnU6ajvzoloWGf4vLlDSsuFHJJsK\n"
1729 "LnshNFOFGAjp1Se4DjhtUSr6Xofdse+kx9cSQazCZ5vFJNeHkxr0B7ojQ4bN37Tg\n"
1730 "2uyfSclCCLnmjcoRMlIGUiL2bevCPDRNRWiblDgx3tGG\n"
1731 "-----END CERTIFICATE-----\n";
1732
1733 rdpCertificate* cert = freerdp_certificate_new_from_pem(pem);
1734 if (!cert)
1735 return FALSE;
1736 return freerdp_settings_set_pointer_len(src, key, cert, 1);
1737}
1738
1739static BOOL set_string_array(rdpSettings* src, FreeRDP_Settings_Keys_Pointer key, uint32_t max)
1740{
1741 uint32_t count = 0;
1742 winpr_RAND(&count, sizeof(count));
1743 count = count % max;
1744
1745 if (!freerdp_settings_set_pointer_len(src, key, NULL, count))
1746 return FALSE;
1747
1748 for (uint32_t x = 0; x < count; x++)
1749 {
1750 char buffer[32] = { 0 };
1751 (void)_snprintf(buffer, sizeof(buffer), "foobar-0x%08" PRIu32, x);
1752 if (!freerdp_settings_set_pointer_array(src, key, x, buffer))
1753 return FALSE;
1754 }
1755 return TRUE;
1756}
1757
1758static BOOL test_serialize_pointer(DWORD flags)
1759{
1760 log_start();
1761 rdpSettings* src = freerdp_settings_new(flags);
1762 if (!src)
1763 goto fail;
1764
1765 const char* argv1[] = { "foobar", "lala", "haha" };
1766 const char* argv2[] = { "lala", "haha" };
1767 const char* argv3[] = { "haha" };
1768 if (!add_argv(src, ARRAYSIZE(argv1), argv1))
1769 goto fail;
1770 if (!add_argv(src, ARRAYSIZE(argv2), argv2))
1771 goto fail;
1772 if (!add_argv(src, ARRAYSIZE(argv3), argv3))
1773 goto fail;
1774 if (!add_dev_argv(src, ARRAYSIZE(argv3), argv3))
1775 goto fail;
1776
1777 struct key_len_pair
1778 {
1779 FreeRDP_Settings_Keys_Pointer key;
1780 size_t elem;
1781 size_t len;
1782 };
1783
1784 const struct key_len_pair keys[] = {
1785 { FreeRDP_ServerRandom, 1, 123 },
1786 { FreeRDP_RedirectionPassword, 1, 13 },
1787 { FreeRDP_ClientRandom, 1, 23 },
1788 { FreeRDP_RedirectionGuid, 1, 22 },
1789 { FreeRDP_LoadBalanceInfo, 1, 21 },
1790 { FreeRDP_ServerCertificate, 1, 512 },
1791 { FreeRDP_RedirectionTsvUrl, 1, 33 },
1792 { FreeRDP_GlyphCache, sizeof(GLYPH_CACHE_DEFINITION), 10 },
1793 { FreeRDP_FragCache, sizeof(GLYPH_CACHE_DEFINITION), 1 },
1794 { FreeRDP_BitmapCacheV2CellInfo, sizeof(BITMAP_CACHE_V2_CELL_INFO), 1 },
1795 { FreeRDP_OrderSupport, 1, 32 },
1796 { FreeRDP_ClientAutoReconnectCookie, sizeof(ARC_CS_PRIVATE_PACKET), 1 },
1797 { FreeRDP_ServerAutoReconnectCookie, sizeof(ARC_SC_PRIVATE_PACKET), 1 },
1798 { FreeRDP_Password51, 1, 54 },
1799 { FreeRDP_MonitorIds, 1, 111 },
1800 { FreeRDP_MonitorDefArray, 1, 7 },
1801 { FreeRDP_ChannelDefArray, 1, 31 },
1802 { FreeRDP_ReceivedCapabilities, sizeof(uint8_t), 33 },
1803 { FreeRDP_ReceivedCapabilityData, sizeof(uint8_t*), 33 },
1804 { FreeRDP_ReceivedCapabilityDataSizes, sizeof(UINT32), 33 }
1805 };
1806
1807 for (size_t x = 0; x < ARRAYSIZE(keys); x++)
1808 {
1809 const struct key_len_pair* cur = &keys[x];
1810 if (!fill_random(src, cur->key, cur->elem, cur->len))
1811 goto fail;
1812 }
1813
1814 if (!fill_random_timezone(src))
1815 goto fail;
1816
1817 void* ptr = NULL;
1818 winpr_RAND((void*)&ptr, sizeof(void*));
1819 if (!freerdp_settings_set_pointer(src, FreeRDP_instance, ptr))
1820 goto fail;
1821
1822 if (!set_private_key(src))
1823 goto fail;
1824 if (!set_cert(src, FreeRDP_RedirectionTargetCertificate))
1825 goto fail;
1826 if (!set_cert(src, FreeRDP_RdpServerCertificate))
1827 goto fail;
1828
1829 if (!set_string_array(src, FreeRDP_ServerLicenseProductIssuers, 43))
1830 goto fail;
1831
1832 char addresses[12][43] = { 0 };
1833 char* strptr[12] = { 0 };
1834
1835 for (size_t x = 0; x < ARRAYSIZE(addresses); x++)
1836 {
1837 (void)_snprintf(addresses[x], 43, "foobar-0x%08" PRIx32, x);
1838 strptr[x] = addresses[x];
1839 }
1840
1841 if (!freerdp_target_net_addresses_copy(src, strptr, ARRAYSIZE(addresses)))
1842 goto fail;
1843
1844 for (size_t x = 0; x < ARRAYSIZE(addresses); x++)
1845 {
1846 uint32_t port = 0;
1847 winpr_RAND(&port, sizeof(port));
1848 if (!freerdp_settings_set_pointer_array(src, FreeRDP_TargetNetPorts, x, &port))
1849 goto fail;
1850 }
1851
1852 uint32_t count = freerdp_settings_get_uint32(src, FreeRDP_ReceivedCapabilitiesSize);
1853 if (count != 33)
1854 goto fail;
1855
1856 void* caps = freerdp_settings_get_pointer_writable(src, FreeRDP_ReceivedCapabilities);
1857 if (!caps)
1858 goto fail;
1859 winpr_RAND(caps, count);
1860
1861 for (uint32_t x = 0; x < count; x++)
1862 {
1863 uint8_t* buffer = calloc(64, sizeof(uint8_t));
1864 if (!buffer)
1865 goto fail;
1866 winpr_RAND(buffer, sizeof(buffer));
1867 uint32_t blen = (buffer[0] % 52) + 13;
1868
1869 if (!freerdp_settings_set_pointer_array(src, FreeRDP_ReceivedCapabilityData, x, buffer))
1870 goto fail;
1871 if (!freerdp_settings_set_pointer_array(src, FreeRDP_ReceivedCapabilityDataSizes, x, &blen))
1872 goto fail;
1873 }
1874
1875 char buffer[128] = { 0 };
1876 (void)_snprintf(buffer, sizeof(buffer), "%s flags 0x%08" PRIx32, __func__, flags);
1877 return test_serialize_with(src, buffer);
1878fail:
1879 log_result(FALSE);
1881 return FALSE;
1882}
1883
1884static BOOL test_serialize(void)
1885{
1886 BOOL rc = FALSE;
1887 log_start();
1888 if (WINPR_JSON_version(NULL, 0) < 0)
1889 {
1890 rc = TRUE;
1891 }
1892 else
1893 {
1894 for (uint32_t flags = 0;
1895 flags <= (FREERDP_SETTINGS_SERVER_MODE | FREERDP_SETTINGS_REMOTE_MODE); flags++)
1896 {
1897 char buffer[32] = { 0 };
1898 (void)_snprintf(buffer, sizeof(buffer), "default (flags 0x%08" PRIx32 ")", flags);
1899 if (!test_serialize_with(freerdp_settings_new(flags), buffer))
1900 return FALSE;
1901 if (!test_serialize_strings(flags, "foobar"))
1902 return FALSE;
1903 if (!test_serialize_strings(flags, ""))
1904 return FALSE;
1905 if (!test_serialize_strings(flags, NULL))
1906 return FALSE;
1907 if (!test_serialize_pointer(flags))
1908 return FALSE;
1909 }
1910 rc = TRUE;
1911 }
1912
1913 log_result(rc);
1914 return TRUE;
1915}
1916
1917static BOOL test_bool_list(rdpSettings* settings, const rdpSettings* cloned)
1918{
1919 BOOL rc = FALSE;
1920 log_start();
1921
1922 WINPR_ASSERT(settings);
1923 WINPR_ASSERT(cloned);
1924
1925#if defined(have_bool_list_indices)
1926
1927 for (size_t x = 0; x < ARRAYSIZE(bool_list_indices); x++)
1928 {
1929 const size_t key = bool_list_indices[x];
1930 const char* name =
1931 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
1932 const BOOL val = freerdp_settings_get_bool(settings, key);
1933 const BOOL cval = freerdp_settings_get_bool(cloned, key);
1934 if (val != cval)
1935 {
1936 printf("mismatch for key %s: %u -> copy %u\n", name, val, cval);
1937 goto fail;
1938 }
1939 if (!freerdp_settings_set_bool(settings, key, val))
1940 goto fail;
1941 if (!check_key_helpers(key, "bool"))
1942 goto fail;
1943 }
1944
1945#endif
1946 rc = TRUE;
1947fail:
1948 return log_result(rc);
1949}
1950
1951static BOOL test_int16_list(const rdpSettings* settings, const rdpSettings* cloned)
1952{
1953 BOOL rc = FALSE;
1954 log_start();
1955
1956 WINPR_ASSERT(settings);
1957 WINPR_ASSERT(cloned);
1958
1959#if defined(have_int16_list_indices)
1960
1961 for (size_t x = 0; x < ARRAYSIZE(int16_list_indices); x++)
1962 {
1963 const size_t key = int16_list_indices[x];
1964 const char* name = freerdp_settings_get_name_for_key(key);
1965 const INT16 val = freerdp_settings_get_int16(settings, key);
1966 const INT16 cval = freerdp_settings_get_int16(cloned, key);
1967 if (val != cval)
1968 {
1969 printf("mismatch for key %s: %" PRId16 " -> copy %" PRId16 "\n", name, val, cval);
1970 goto fail;
1971 }
1972 if (!freerdp_settings_set_int16(settings, key, val))
1973 goto fail;
1974 if (!check_key_helpers(key, "int16"))
1975 goto fail;
1976 }
1977
1978#endif
1979 rc = TRUE;
1980fail:
1981 return log_result(rc);
1982}
1983
1984static BOOL test_uint16_list(rdpSettings* settings, const rdpSettings* cloned)
1985{
1986 BOOL rc = FALSE;
1987 log_start();
1988
1989 WINPR_ASSERT(settings);
1990 WINPR_ASSERT(cloned);
1991
1992#if defined(have_uint16_list_indices)
1993
1994 for (size_t x = 0; x < ARRAYSIZE(uint16_list_indices); x++)
1995 {
1996 const size_t key = uint16_list_indices[x];
1997 const char* name =
1998 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
1999 const UINT16 val = freerdp_settings_get_uint16(settings, key);
2000 const UINT16 cval = freerdp_settings_get_uint16(cloned, key);
2001 if (val != cval)
2002 {
2003 printf("mismatch for key %s: %" PRIu16 " -> copy %" PRIu16 "\n", name, val, cval);
2004 goto fail;
2005 }
2006 if (!freerdp_settings_set_uint16(settings, key, val))
2007 goto fail;
2008 if (!check_key_helpers(key, "uint16"))
2009 goto fail;
2010 }
2011
2012#endif
2013 rc = TRUE;
2014fail:
2015 return log_result(rc);
2016}
2017
2018static BOOL test_int32_list(rdpSettings* settings, const rdpSettings* cloned)
2019{
2020 BOOL rc = FALSE;
2021 log_start();
2022
2023 WINPR_ASSERT(settings);
2024 WINPR_ASSERT(cloned);
2025
2026#if defined(have_int32_list_indices)
2027
2028 for (size_t x = 0; x < ARRAYSIZE(int32_list_indices); x++)
2029 {
2030 const size_t key = int32_list_indices[x];
2031 const char* name =
2032 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
2033 const INT32 val = freerdp_settings_get_int32(settings, key);
2034 const INT32 cval = freerdp_settings_get_int32(cloned, key);
2035 if (val != cval)
2036 {
2037 printf("mismatch for key %s: %" PRId32 " -> copy %" PRId32 "\n", name, val, cval);
2038 goto fail;
2039 }
2040 if (!freerdp_settings_set_int32(settings, key, val))
2041 goto fail;
2042 if (!check_key_helpers(key, "int32"))
2043 goto fail;
2044 }
2045
2046#endif
2047
2048 rc = TRUE;
2049fail:
2050 return log_result(rc);
2051}
2052
2053static BOOL test_uint32_list(rdpSettings* settings, const rdpSettings* cloned)
2054{
2055 BOOL rc = FALSE;
2056 log_start();
2057
2058 WINPR_ASSERT(settings);
2059 WINPR_ASSERT(cloned);
2060
2061#if defined(have_uint32_list_indices)
2062
2063 for (size_t x = 0; x < ARRAYSIZE(uint32_list_indices); x++)
2064 {
2065 const size_t key = uint32_list_indices[x];
2066 const char* name =
2067 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
2068 const UINT32 val = freerdp_settings_get_uint32(settings, key);
2069 const UINT32 cval = freerdp_settings_get_uint32(cloned, key);
2070 if (val != cval)
2071 {
2072 printf("mismatch for key %s: %" PRIu32 " -> copy %" PRIu32 "\n", name, val, cval);
2073 goto fail;
2074 }
2075 if (!freerdp_settings_set_uint32(settings, key, val))
2076 goto fail;
2077 if (!check_key_helpers(key, "uint32"))
2078 goto fail;
2079 }
2080
2081#endif
2082
2083 rc = TRUE;
2084fail:
2085 return log_result(rc);
2086}
2087
2088static BOOL test_int64_list(const rdpSettings* settings, const rdpSettings* cloned)
2089{
2090 BOOL rc = FALSE;
2091 log_start();
2092
2093 WINPR_ASSERT(settings);
2094 WINPR_ASSERT(cloned);
2095
2096#if defined(have_int64_list_indices)
2097
2098 for (size_t x = 0; x < ARRAYSIZE(int64_list_indices); x++)
2099 {
2100 const size_t key = int64_list_indices[x];
2101 const char* name = freerdp_settings_get_name_for_key(key);
2102 const INT64 val = freerdp_settings_get_int64(settings, key);
2103 const INT64 cval = freerdp_settings_get_int64(cloned, key);
2104 if (val != cval)
2105 {
2106 printf("mismatch for key %s: %" PRId64 " -> copy %" PRId64 "\n", name, val, cval);
2107 goto fail;
2108 }
2109 if (!freerdp_settings_set_int64(settings, key, val))
2110 goto fail;
2111 if (!check_key_helpers(key, "int64"))
2112 goto fail;
2113 }
2114
2115#endif
2116
2117 rc = TRUE;
2118fail:
2119 return log_result(rc);
2120}
2121
2122static BOOL test_uint64_list(rdpSettings* settings, const rdpSettings* cloned)
2123{
2124 BOOL rc = FALSE;
2125 log_start();
2126
2127 WINPR_ASSERT(settings);
2128 WINPR_ASSERT(cloned);
2129
2130#if defined(have_uint64_list_indices)
2131
2132 for (size_t x = 0; x < ARRAYSIZE(uint64_list_indices); x++)
2133 {
2134 const size_t key = uint64_list_indices[x];
2135 const char* name =
2136 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
2137 const UINT64 val = freerdp_settings_get_uint64(settings, key);
2138 const UINT64 cval = freerdp_settings_get_uint64(cloned, key);
2139 if (val != cval)
2140 {
2141 printf("mismatch for key %s: %" PRIu64 " -> copy %" PRIu64 "\n", name, val, cval);
2142 goto fail;
2143 }
2144 if (!freerdp_settings_set_uint64(settings, key, val))
2145 goto fail;
2146 if (!check_key_helpers(key, "uint64"))
2147 goto fail;
2148 }
2149
2150#endif
2151
2152 rc = TRUE;
2153fail:
2154 return log_result(rc);
2155}
2156
2157static BOOL test_string_list(rdpSettings* settings, const rdpSettings* cloned)
2158{
2159 BOOL rc = FALSE;
2160 log_start();
2161
2162 WINPR_ASSERT(settings);
2163 WINPR_ASSERT(cloned);
2164
2165#if defined(have_string_list_indices)
2166
2167 for (size_t x = 0; x < ARRAYSIZE(string_list_indices); x++)
2168 {
2169 const size_t key = string_list_indices[x];
2170 const char val[] = "test-string";
2171 const char* res = NULL;
2172 const char* name =
2173 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
2174 const char* oval = freerdp_settings_get_string(settings, key);
2175 const char* cval = freerdp_settings_get_string(cloned, key);
2176 if ((oval != cval) && (strcmp(oval, cval) != 0))
2177 {
2178 printf("mismatch for key %s: %s -> copy %s\n", name, oval, cval);
2179 goto fail;
2180 }
2181 if (!freerdp_settings_set_string(settings, key, val))
2182 goto fail;
2183
2184 res = freerdp_settings_get_string(settings, key);
2185
2186 if (strncmp(val, res, sizeof(val)) != 0)
2187 goto fail;
2188 }
2189
2190#endif
2191
2192 rc = TRUE;
2193fail:
2194 return log_result(rc);
2195}
2196
2197static BOOL test_pointer_list(const rdpSettings* settings, const rdpSettings* cloned)
2198{
2199 BOOL rc = FALSE;
2200 log_start();
2201
2202 WINPR_ASSERT(settings);
2203 WINPR_ASSERT(cloned);
2204
2205#if defined(have_pointer_list_indices)
2206
2207 for (size_t x = 0; x < ARRAYSIZE(pointer_list_indices); x++)
2208 {
2209 const size_t key = pointer_list_indices[x];
2210 const void* val = freerdp_settings_get_pointer(settings, key);
2211 WINPR_UNUSED(val);
2212 }
2213
2214#endif
2215
2216 rc = TRUE;
2217fail:
2218 return log_result(rc);
2219}
2220
2221static BOOL test_clone_copy(const rdpSettings* settings, const rdpSettings* cloned)
2222{
2223 BOOL rc = FALSE;
2224 log_start();
2225 WINPR_ASSERT(settings);
2226 WINPR_ASSERT(cloned);
2227
2228 rdpSettings* cloned2 = freerdp_settings_clone(settings);
2229 if (!cloned2)
2230 goto fail;
2231 if (!freerdp_settings_copy(cloned2, cloned))
2232 goto fail;
2233 rc = TRUE;
2234fail:
2235 freerdp_settings_free(cloned2);
2236 return log_result(rc);
2237}
2238
2239static BOOL test_all(void)
2240{
2241 BOOL rc = FALSE;
2242 log_start();
2243
2244 rdpSettings* settings = freerdp_settings_new(0);
2245 rdpSettings* cloned = NULL;
2246
2247 if (!settings)
2248 {
2249 printf("Couldn't create settings\n");
2250 return -1;
2251 }
2252
2253 if (!test_string_len(settings))
2254 goto fail;
2255
2256 cloned = freerdp_settings_clone(settings);
2257
2258 if (!cloned)
2259 goto fail;
2260
2261 if (!test_bool_list(settings, cloned))
2262 goto fail;
2263 if (!test_int16_list(settings, cloned))
2264 goto fail;
2265 if (!test_uint16_list(settings, cloned))
2266 goto fail;
2267 if (!test_int32_list(settings, cloned))
2268 goto fail;
2269 if (!test_uint32_list(settings, cloned))
2270 goto fail;
2271 if (!test_int64_list(settings, cloned))
2272 goto fail;
2273 if (!test_uint64_list(settings, cloned))
2274 goto fail;
2275 if (!test_string_list(settings, cloned))
2276 goto fail;
2277 if (!test_pointer_list(settings, cloned))
2278 goto fail;
2279 if (!test_clone_copy(settings, cloned))
2280 goto fail;
2281
2282 rc = TRUE;
2283fail:
2284 freerdp_settings_free(cloned);
2285 freerdp_settings_free(settings);
2286 return log_result(rc);
2287}
2288
2289#if defined(BUILD_TESTING_INTERNAL)
2290static FreeRDP_Settings_Keys_UInt32 getLenForKey(FreeRDP_Settings_Keys_Pointer key)
2291{
2292 return FreeRDP_TargetNetAddressCount;
2293}
2294
2295static bool fillTargetBuffer(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer key)
2296{
2297 const size_t count = freerdp_settings_get_uint32(settings, getLenForKey(key));
2298 for (size_t x = 0; x < count; x++)
2299 {
2300 char test[128] = { 0 };
2301 (void)_snprintf(test, sizeof(test), "test_value_%" PRIuz, x);
2302 if (!freerdp_settings_set_pointer_array(settings, key, x, test))
2303 return false;
2304 }
2305 return true;
2306}
2307
2308static bool checkTargetBuffer(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer key,
2309 size_t count)
2310{
2311 for (size_t x = 0; x < count; x++)
2312 {
2313 char test[128] = { 0 };
2314 (void)_snprintf(test, sizeof(test), "test_value_%" PRIuz, x);
2315 const char* cmp = freerdp_settings_get_pointer_array(settings, key, x);
2316 if (!cmp)
2317 return false;
2318 if (strncmp(test, cmp, sizeof(test)) != 0)
2319 return false;
2320 }
2321 return true;
2322}
2323
2324static bool checkTargetBufferResized(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer key,
2325 size_t count, size_t newSize)
2326{
2327 if (count > newSize)
2328 count = newSize;
2329
2330 if (!checkTargetBuffer(settings, key, count))
2331 return false;
2332
2333 for (size_t x = count; x < newSize; x++)
2334 {
2335 const char* cmp = freerdp_settings_get_pointer_array(settings, key, x);
2336 if (cmp != NULL)
2337 return false;
2338 }
2339 return true;
2340}
2341
2342static bool testSize(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer key, size_t newSize)
2343{
2344 if (!fillTargetBuffer(settings, key))
2345 return false;
2346 const size_t count = freerdp_settings_get_uint32(settings, getLenForKey(key));
2347 if (!checkTargetBuffer(settings, key, count))
2348 return false;
2349 if (key == FreeRDP_TargetNetAddresses)
2350 {
2351 if (!freerdp_target_net_addresses_resize(settings, newSize))
2352 return false;
2353 }
2354 else
2355 {
2356 return false;
2357 }
2358 if (!checkTargetBufferResized(settings, key, count, newSize))
2359 return false;
2360 return true;
2361}
2362
2363static bool testBufferResize(FreeRDP_Settings_Keys_Pointer key)
2364{
2365 bool rc = false;
2366 rdpSettings* settings = freerdp_settings_new(0);
2367 if (!settings)
2368 return false;
2369
2370 if (!testSize(settings, key, 10))
2371 goto fail;
2372 if (!testSize(settings, key, 23))
2373 goto fail;
2374 if (!testSize(settings, key, 13))
2375 goto fail;
2376 if (!testSize(settings, key, 0))
2377 goto fail;
2378
2379 rc = true;
2380fail:
2381 freerdp_settings_free(settings);
2382 return rc;
2383}
2384#endif
2385
2386int TestSettings(int argc, char* argv[])
2387{
2388 int rc = -1;
2389 WINPR_UNUSED(argc);
2390 WINPR_UNUSED(argv);
2391
2392 if (!test_serialize())
2393 goto fail;
2394 if (!test_dyn_channels())
2395 goto fail;
2396 if (!test_static_channels())
2397 goto fail;
2398 if (!test_copy())
2399 goto fail;
2400 if (!test_helpers())
2401 goto fail;
2402 if (!check_device_type())
2403 goto fail;
2404 if (!test_pointer_array())
2405 goto fail;
2406 if (!test_validity_check())
2407 goto fail;
2408 if (!test_all())
2409 goto fail;
2410#if defined(BUILD_TESTING_INTERNAL)
2411 // freerdp_target_net_addresses_resize
2412 if (!testBufferResize(FreeRDP_TargetNetAddresses))
2413 goto fail;
2414#endif
2415 rc = 0;
2416
2417fail:
2418 return rc;
2419}
WINPR_API int WINPR_JSON_version(char *buffer, size_t len)
Get the library version string.
Definition c-json.c:88
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *param)
Sets a string settings value. The param is copied.
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API rdpSettings * freerdp_settings_new(DWORD flags)
creates a new setting struct
FREERDP_API INT64 freerdp_settings_get_int64(const rdpSettings *settings, FreeRDP_Settings_Keys_Int64 id)
Returns a INT64 settings value.
FREERDP_API rdpSettings * freerdp_settings_clone(const rdpSettings *settings)
Creates a deep copy of settings.
FREERDP_API BOOL freerdp_settings_print_diff(wLog *log, DWORD level, const rdpSettings *src, const rdpSettings *other)
Dumps the difference between two settings structs to a WLog.
FREERDP_API SSIZE_T freerdp_settings_get_type_for_name(const char *value)
Get a key type for the name string of that key.
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.
FREERDP_API SSIZE_T freerdp_settings_get_type_for_key(SSIZE_T key)
Get a key type for the key index.
FREERDP_API UINT64 freerdp_settings_get_uint64(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt64 id)
Returns a UINT64 settings value.
FREERDP_API SSIZE_T freerdp_settings_get_key_for_name(const char *value)
Get a key index for the name string of that key.
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.
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 param)
Sets a INT32 settings value.
FREERDP_API void freerdp_settings_free(rdpSettings *settings)
Free a settings struct with all data in it.
#define FREERDP_SETTINGS_SERVER_MODE
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 UINT16 freerdp_settings_get_uint16(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt16 id)
Returns a UINT16 settings value.
FREERDP_API void * freerdp_settings_get_pointer_writable(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a mutable pointer settings value.
FREERDP_API BOOL freerdp_settings_copy(rdpSettings *dst, const rdpSettings *src)
Deep copies settings from src to dst.
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_uint64(rdpSettings *settings, FreeRDP_Settings_Keys_UInt64 id, UINT64 param)
Sets a UINT64 settings value.
FREERDP_API BOOL freerdp_settings_set_int16(rdpSettings *settings, FreeRDP_Settings_Keys_Int16 id, INT16 param)
Sets a INT16 settings value.
FREERDP_API BOOL freerdp_settings_set_int64(rdpSettings *settings, FreeRDP_Settings_Keys_Int64 id, INT64 param)
Sets a INT64 settings value.
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.
FREERDP_API BOOL freerdp_settings_set_pointer(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id, const void *data)
Set a pointer to value data.
FREERDP_API INT32 freerdp_settings_get_int32(const rdpSettings *settings, FreeRDP_Settings_Keys_Int32 id)
Returns a INT32 settings value.
FREERDP_API const void * freerdp_settings_get_pointer(const rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a immutable pointer settings value.
FREERDP_API UINT32 freerdp_settings_get_codecs_flags(const rdpSettings *settings)
helper function to get a mask of supported codec flags.
FREERDP_API BOOL freerdp_settings_set_string_len(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *param, size_t len)
Sets a string settings value. The param is copied.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.
FREERDP_API const char * freerdp_settings_get_name_for_key(SSIZE_T key)
Returns the type name for a key.
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
FREERDP_API BOOL freerdp_settings_set_uint16(rdpSettings *settings, FreeRDP_Settings_Keys_UInt16 id, UINT16 param)
Sets a UINT16 settings value.
FREERDP_API INT16 freerdp_settings_get_int16(const rdpSettings *settings, FreeRDP_Settings_Keys_Int16 id)
Returns a INT16 settings value.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL param)
Sets a BOOL settings value.
FREERDP_API rdpSettings * freerdp_settings_deserialize(const char *json, size_t length)
A function that converts a JSON string to a rdpSettings struct.