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