FreeRDP
Loading...
Searching...
No Matches
TestSettings.c
1#include <stdio.h>
2
3#include <winpr/user.h>
4#include <winpr/crypto.h>
5
6#include <freerdp/settings.h>
7#include <freerdp/codecs.h>
8
9#include "settings_property_lists.h"
10#include "../settings.h"
11
12static BOOL log_result(BOOL value, const char* fkt)
13{
14 (void)fprintf(stderr, "TestSettings [%s] returned %s\n", fkt, value ? "TRUE" : "FALSE");
15 return value;
16}
17
18static BOOL log_result_case(BOOL value, const char* fkt, size_t testcase)
19{
20 (void)fprintf(stderr, "TestSettings [%s] testcase %" PRIuz " returned %s\n", fkt, testcase,
21 value ? "TRUE" : "FALSE");
22 return value;
23}
24
25static BOOL compare(const ADDIN_ARGV* got, const ADDIN_ARGV* expect)
26{
27 BOOL rc = TRUE;
28 if (!got && !expect)
29 return FALSE;
30 if (!got && expect)
31 return FALSE;
32 if (got && !expect)
33 return FALSE;
34 if (got->argc != expect->argc)
35 return FALSE;
36
37 for (int x = 0; x < expect->argc; x++)
38 {
39 if (strcmp(got->argv[x], expect->argv[x]) != 0)
40 rc = FALSE;
41 }
42 return log_result(rc, __func__);
43}
44
45static BOOL test_dyn_channels(void)
46{
47 BOOL rc = FALSE;
48 BOOL test = 0;
49 UINT32 u32 = 0;
50 rdpSettings* settings = freerdp_settings_new(0);
51 const char* argv1[] = { "foobar" };
52 ADDIN_ARGV* args1 = NULL;
53 const ADDIN_ARGV* cmp1 = NULL;
54 const char* argv2[] = { "gaga", "abba", "foo" };
55 ADDIN_ARGV* args2 = NULL;
56 const ADDIN_ARGV* cmp2 = NULL;
57 const ADDIN_ARGV* got = NULL;
58
59 if (!settings)
60 goto fail;
61
62 u32 = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
63 if (u32 != 0)
64 goto fail;
65
66 /* Test the function return an error for unknown channels */
67 test = freerdp_dynamic_channel_collection_del(settings, "foobar");
68 if (test)
69 goto fail;
70 got = freerdp_dynamic_channel_collection_find(settings, "foobar");
71 if (got)
72 goto fail;
73
74 /* Add the channel */
75 cmp1 = args1 = freerdp_addin_argv_new(ARRAYSIZE(argv1), argv1);
76 test = freerdp_dynamic_channel_collection_add(settings, args1);
77 if (!test)
78 goto fail;
79 args1 = NULL; /* settings have taken ownership */
80
81 u32 = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
82 if (u32 != 1)
83 goto fail;
84 u32 = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
85 if (u32 < 1)
86 goto fail;
87
88 cmp2 = args2 = freerdp_addin_argv_new(ARRAYSIZE(argv2), argv2);
89 test = freerdp_dynamic_channel_collection_add(settings, args2);
90 if (!test)
91 goto fail;
92 args2 = NULL; /* settings have taken ownership */
93
94 u32 = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
95 if (u32 != 2)
96 goto fail;
97 u32 = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
98 if (u32 < 2)
99 goto fail;
100
101 /* Test the function return success for known channels */
102 got = freerdp_dynamic_channel_collection_find(settings, "foobar");
103 if (!compare(got, cmp1))
104 goto fail;
105 got = freerdp_dynamic_channel_collection_find(settings, "gaga");
106 if (!compare(got, cmp2))
107 goto fail;
108 test = freerdp_dynamic_channel_collection_del(settings, "foobar");
109 if (!test)
110 goto fail;
111 u32 = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
112 if (u32 != 1)
113 goto fail;
114 u32 = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
115 if (u32 < 1)
116 goto fail;
117 got = freerdp_dynamic_channel_collection_find(settings, "foobar");
118 if (compare(got, cmp1))
119 goto fail;
120 got = freerdp_dynamic_channel_collection_find(settings, "gaga");
121 if (!compare(got, cmp2))
122 goto fail;
123 test = freerdp_dynamic_channel_collection_del(settings, "gaga");
124 if (!test)
125 goto fail;
126 u32 = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
127 if (u32 != 0)
128 goto fail;
129 got = freerdp_dynamic_channel_collection_find(settings, "foobar");
130 if (compare(got, cmp1))
131 goto fail;
132 got = freerdp_dynamic_channel_collection_find(settings, "gaga");
133 if (compare(got, cmp2))
134 goto fail;
135
136 rc = TRUE;
137
138fail:
139 freerdp_settings_free(settings);
140 freerdp_addin_argv_free(args1);
141 freerdp_addin_argv_free(args2);
142 return log_result(rc, __func__);
143}
144
145static BOOL test_static_channels(void)
146{
147 BOOL rc = FALSE;
148 BOOL test = 0;
149 UINT32 u32 = 0;
150 rdpSettings* settings = freerdp_settings_new(0);
151 const char* argv1[] = { "foobar" };
152 ADDIN_ARGV* args1 = NULL;
153 const ADDIN_ARGV* cmp1 = NULL;
154 const char* argv2[] = { "gaga", "abba", "foo" };
155 ADDIN_ARGV* args2 = NULL;
156 const ADDIN_ARGV* cmp2 = NULL;
157 const ADDIN_ARGV* got = NULL;
158
159 if (!settings)
160 goto fail;
161
162 u32 = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
163 if (u32 != 0)
164 goto fail;
165
166 /* Test the function return an error for unknown channels */
167 test = freerdp_static_channel_collection_del(settings, "foobar");
168 if (test)
169 goto fail;
170 got = freerdp_static_channel_collection_find(settings, "foobar");
171 if (got)
172 goto fail;
173
174 /* Add the channel */
175 cmp1 = args1 = freerdp_addin_argv_new(ARRAYSIZE(argv1), argv1);
176 test = freerdp_static_channel_collection_add(settings, args1);
177 if (!test)
178 goto fail;
179 args1 = NULL; /* settings have taken ownership */
180
181 u32 = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
182 if (u32 != 1)
183 goto fail;
184 u32 = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
185 if (u32 < 1)
186 goto fail;
187
188 cmp2 = args2 = freerdp_addin_argv_new(ARRAYSIZE(argv2), argv2);
189 test = freerdp_static_channel_collection_add(settings, args2);
190 if (!test)
191 goto fail;
192 args2 = NULL; /* settings have taken ownership */
193
194 u32 = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
195 if (u32 != 2)
196 goto fail;
197 u32 = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
198 if (u32 < 2)
199 goto fail;
200
201 /* Test the function return success for known channels */
202 got = freerdp_static_channel_collection_find(settings, "foobar");
203 if (!compare(got, cmp1))
204 goto fail;
205 got = freerdp_static_channel_collection_find(settings, "gaga");
206 if (!compare(got, cmp2))
207 goto fail;
208 test = freerdp_static_channel_collection_del(settings, "foobar");
209 if (!test)
210 goto fail;
211 u32 = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
212 if (u32 != 1)
213 goto fail;
214 u32 = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
215 if (u32 < 1)
216 goto fail;
217 got = freerdp_static_channel_collection_find(settings, "foobar");
218 if (compare(got, cmp1))
219 goto fail;
220 got = freerdp_static_channel_collection_find(settings, "gaga");
221 if (!compare(got, cmp2))
222 goto fail;
223 test = freerdp_static_channel_collection_del(settings, "gaga");
224 if (!test)
225 goto fail;
226 u32 = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
227 if (u32 != 0)
228 goto fail;
229 got = freerdp_static_channel_collection_find(settings, "foobar");
230 if (compare(got, cmp1))
231 goto fail;
232 got = freerdp_static_channel_collection_find(settings, "gaga");
233 if (compare(got, cmp2))
234 goto fail;
235
236 rc = TRUE;
237
238fail:
239 freerdp_settings_free(settings);
240 freerdp_addin_argv_free(args1);
241 freerdp_addin_argv_free(args2);
242 return log_result(rc, __func__);
243}
244
245static BOOL test_copy(void)
246{
247 BOOL rc = FALSE;
248 wLog* log = WLog_Get(__func__);
249 rdpSettings* settings = freerdp_settings_new(0);
250 rdpSettings* copy = freerdp_settings_clone(settings);
251 rdpSettings* modified = freerdp_settings_clone(settings);
252
253 if (!settings || !copy || !modified)
254 goto fail;
255 if (!freerdp_settings_set_string(modified, FreeRDP_ServerHostname, "somerandomname"))
256 goto fail;
257 if (freerdp_settings_print_diff(log, WLOG_WARN, settings, copy))
258 goto fail;
259 if (!freerdp_settings_print_diff(log, WLOG_WARN, settings, modified))
260 goto fail;
261
262 rc = TRUE;
263
264fail:
265 freerdp_settings_free(settings);
267 freerdp_settings_free(modified);
268 return log_result(rc, __func__);
269}
270
271static BOOL test_helpers(void)
272{
273 BOOL rc = FALSE;
274 UINT32 flags = 0;
275 rdpSettings* settings = freerdp_settings_new(0);
276 if (!settings)
277 goto fail;
278 if (!freerdp_settings_set_bool(settings, FreeRDP_RemoteFxCodec, TRUE))
279 goto fail;
280 if (!freerdp_settings_set_bool(settings, FreeRDP_NSCodec, TRUE))
281 goto fail;
282 flags = freerdp_settings_get_codecs_flags(settings);
283 if (flags != FREERDP_CODEC_ALL)
284 goto fail;
285
286 if (!freerdp_settings_set_bool(settings, FreeRDP_NSCodec, FALSE))
287 goto fail;
288 flags = freerdp_settings_get_codecs_flags(settings);
289 if (flags != (FREERDP_CODEC_ALL & ~FREERDP_CODEC_NSCODEC))
290 goto fail;
291
292 if (!freerdp_settings_set_bool(settings, FreeRDP_RemoteFxCodec, FALSE))
293 goto fail;
294 flags = freerdp_settings_get_codecs_flags(settings);
295 if (flags != (FREERDP_CODEC_ALL & ~(FREERDP_CODEC_NSCODEC | FREERDP_CODEC_REMOTEFX)))
296 goto fail;
297
298 if (!freerdp_settings_set_bool(settings, FreeRDP_NSCodec, TRUE))
299 goto fail;
300 flags = freerdp_settings_get_codecs_flags(settings);
301 if (flags != (FREERDP_CODEC_ALL & ~FREERDP_CODEC_REMOTEFX))
302 goto fail;
303
304 rc = TRUE;
305fail:
306 freerdp_settings_free(settings);
307 return log_result(rc, __func__);
308}
309
310static BOOL format_uint(char* buffer, size_t size, UINT64 value, UINT16 intType, UINT64 max)
311{
312 const UINT64 lvalue = value > max ? max : value;
313 intType = intType % 3;
314 switch (intType)
315 {
316 case 0:
317 (void)_snprintf(buffer, size, "%" PRIu64, lvalue);
318 return TRUE;
319 case 1:
320 (void)_snprintf(buffer, size, "0x%" PRIx64, lvalue);
321 return TRUE;
322 case 2:
323 if (max < UINT64_MAX)
324 (void)_snprintf(buffer, size, "%" PRIu64, max + 1);
325 else
326 (void)_snprintf(buffer, size, "too large a number");
327 return FALSE;
328 default:
329 (void)_snprintf(buffer, size, "not a number value");
330 return FALSE;
331 }
332}
333
334static BOOL print_negative(char* buffer, size_t size, INT64 value, INT64 min)
335{
336 switch (min)
337 {
338 case INT16_MIN:
339 (void)_snprintf(buffer, size, "%" PRId16, (INT16)value);
340 return FALSE;
341 case INT32_MIN:
342 (void)_snprintf(buffer, size, "%" PRId32, (INT32)value);
343 return FALSE;
344 case INT64_MIN:
345 (void)_snprintf(buffer, size, "%" PRId64, value);
346 return FALSE;
347 default:
348 (void)_snprintf(buffer, size, "too small a number");
349 return FALSE;
350 }
351}
352
353static BOOL print_xpositive(char* buffer, size_t size, INT64 value, INT64 max)
354{
355 if (value < 0)
356 {
357 (void)_snprintf(buffer, size, "%" PRId64, value);
358 return TRUE;
359 }
360
361 switch (max)
362 {
363 case INT16_MAX:
364 (void)_snprintf(buffer, size, "%" PRIx16, (INT16)value);
365 return FALSE;
366 case INT32_MAX:
367 (void)_snprintf(buffer, size, "%" PRIx32, (INT32)value);
368 return FALSE;
369 case INT64_MAX:
370 (void)_snprintf(buffer, size, "%" PRIx64, value);
371 return FALSE;
372 default:
373 (void)_snprintf(buffer, size, "too small a number");
374 return FALSE;
375 }
376}
377
378static BOOL format_int(char* buffer, size_t size, INT64 value, UINT16 intType, INT64 max, INT64 min)
379{
380 const INT64 lvalue = (value > max) ? max : ((value < min) ? min : value);
381 intType = intType % 4;
382
383 switch (intType)
384 {
385 case 0:
386 (void)_snprintf(buffer, size, "%" PRId64, lvalue);
387 return TRUE;
388 case 1:
389 print_xpositive(buffer, size, lvalue, max);
390 return TRUE;
391 case 2:
392 if (max < INT64_MAX)
393 (void)_snprintf(buffer, size, "%" PRId64, max + 1);
394 else
395 (void)_snprintf(buffer, size, "too large a number");
396 return FALSE;
397 case 3:
398 if (min < INT64_MIN)
399 print_negative(buffer, size, min - 1, INT64_MIN);
400 else
401 (void)_snprintf(buffer, size, "too small a number");
402 return FALSE;
403 default:
404 (void)_snprintf(buffer, size, "not a number value");
405 return FALSE;
406 }
407}
408
409static BOOL format_bool(char* buffer, size_t size, UINT16 intType)
410{
411 intType = intType % 10;
412 switch (intType)
413 {
414 case 0:
415 (void)_snprintf(buffer, size, "FALSE");
416 return TRUE;
417 case 1:
418 (void)_snprintf(buffer, size, "FaLsE");
419 return TRUE;
420 case 2:
421 (void)_snprintf(buffer, size, "False");
422 return TRUE;
423 case 3:
424 (void)_snprintf(buffer, size, "false");
425 return TRUE;
426 case 4:
427 (void)_snprintf(buffer, size, "falseentry");
428 return FALSE;
429 case 5:
430 (void)_snprintf(buffer, size, "TRUE");
431 return TRUE;
432 case 6:
433 (void)_snprintf(buffer, size, "TrUe");
434 return TRUE;
435 case 7:
436 (void)_snprintf(buffer, size, "True");
437 return TRUE;
438 case 8:
439 (void)_snprintf(buffer, size, "true");
440 return TRUE;
441 case 9:
442 (void)_snprintf(buffer, size, "someentry");
443 return FALSE;
444 default:
445 (void)_snprintf(buffer, size, "ok");
446 return FALSE;
447 }
448}
449
450static BOOL check_key_helpers(size_t key, const char* stype)
451{
452 int test_rounds = 100;
453 BOOL res = FALSE;
454 rdpSettings* settings = NULL;
455 SSIZE_T rc = 0;
456 SSIZE_T tkey = 0;
457 SSIZE_T type = 0;
458 const size_t clear_keys[] = { FreeRDP_RdpServerCertificate,
459 FreeRDP_RdpServerRsaKey,
460 FreeRDP_RedirectionPassword,
461 FreeRDP_RedirectionTsvUrl,
462 FreeRDP_LoadBalanceInfo,
463 FreeRDP_ServerRandom,
464 FreeRDP_ClientRandom,
465 FreeRDP_ServerCertificate,
466 FreeRDP_TargetNetAddresses,
467 FreeRDP_ReceivedCapabilities,
468 FreeRDP_ServerLicenseProductIssuers,
469 FreeRDP_TargetNetPorts,
470 FreeRDP_DeviceArray,
471 FreeRDP_ChannelDefArray,
472 FreeRDP_MonitorDefArray,
473 FreeRDP_ClientAutoReconnectCookie,
474 FreeRDP_ServerAutoReconnectCookie,
475 FreeRDP_ClientTimeZone,
476 FreeRDP_BitmapCacheV2CellInfo,
477 FreeRDP_GlyphCache,
478 FreeRDP_FragCache,
479 FreeRDP_StaticChannelArray,
480 FreeRDP_DynamicChannelArray,
481 FreeRDP_ReceivedCapabilities,
482 FreeRDP_OrderSupport,
483 FreeRDP_MonitorIds };
484 const char* name = freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
485 if (!name)
486 {
487 printf("[%s] missing name for key %" PRIuz "\n", stype, key);
488 return FALSE;
489 }
491 if (tkey < 0)
492 {
493 printf("[%s] missing reverse name for key %s [%" PRIuz "]\n", stype, name, key);
494 return FALSE;
495 }
496 if ((size_t)tkey != key)
497 {
498 printf("[%s] mismatch reverse name for key %s [%" PRIuz "]: %" PRIdz "\n", stype, name, key,
499 tkey);
500 return FALSE;
501 }
503 if (type < 0)
504 {
505 printf("[%s] missing reverse type for key %s [%" PRIuz "]\n", stype, name, key);
506 return FALSE;
507 }
508 rc = freerdp_settings_get_type_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
509 if (rc < 0)
510 {
511 printf("[%s] missing reverse name for key %s [%" PRIuz "]\n", stype, name, key);
512 return FALSE;
513 }
514
515 if (rc != type)
516 {
517 printf("[%s] mismatch reverse type for key %s [%" PRIuz "]: %" PRIdz " <--> %" PRIdz "\n",
518 stype, name, key, rc, type);
519 return FALSE;
520 }
521
522 settings = freerdp_settings_new(0);
523 if (!settings)
524 {
525 printf("[%s] freerdp_settings_new failed\n", stype);
526 goto fail;
527 }
528 for (size_t x = 0; x < ARRAYSIZE(clear_keys); x++)
529 {
530 const size_t id = clear_keys[x];
531 const char* foo = freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, id));
532 if (!freerdp_settings_set_pointer_len(settings, id, NULL, 0))
533 {
534 printf("[%s] freerdp_settings_set_pointer_len(%s, NULL, 0) failed\n", stype, foo);
535 goto fail;
536 }
537 }
538 do
539 {
540 UINT16 intEntryType = 0;
541 BOOL expect = 0;
542 BOOL have = 0;
543 char value[8192] = { 0 };
544 union
545 {
546 UINT64 u64;
547 INT64 i64;
548 UINT32 u32;
549 INT32 i32;
550 UINT16 u16;
551 INT16 i16;
552 void* pv;
553 } val;
554
555 winpr_RAND(&intEntryType, sizeof(intEntryType));
556 winpr_RAND(&val.u64, sizeof(val.u64));
557
558 switch (type)
559 {
560 case RDP_SETTINGS_TYPE_BOOL:
561 expect = format_bool(value, sizeof(value), intEntryType);
562 break;
563 case RDP_SETTINGS_TYPE_UINT16:
564 expect = format_uint(value, sizeof(value), val.u64, intEntryType, UINT16_MAX);
565 break;
566 case RDP_SETTINGS_TYPE_INT16:
567 expect =
568 format_int(value, sizeof(value), val.i64, intEntryType, INT16_MAX, INT16_MIN);
569 break;
570 case RDP_SETTINGS_TYPE_UINT32:
571 expect = format_uint(value, sizeof(value), val.u64, intEntryType, UINT32_MAX);
572 break;
573 case RDP_SETTINGS_TYPE_INT32:
574 expect =
575 format_int(value, sizeof(value), val.i64, intEntryType, INT32_MAX, INT32_MIN);
576 break;
577 case RDP_SETTINGS_TYPE_UINT64:
578 expect = format_uint(value, sizeof(value), val.u64, intEntryType, UINT64_MAX);
579 break;
580 case RDP_SETTINGS_TYPE_INT64:
581 expect =
582 format_int(value, sizeof(value), val.i64, intEntryType, INT64_MAX, INT64_MIN);
583 break;
584 case RDP_SETTINGS_TYPE_STRING:
585 expect = TRUE;
586 (void)_snprintf(value, sizeof(value), "somerandomstring");
587 break;
588 case RDP_SETTINGS_TYPE_POINTER:
589 expect = FALSE;
590 break;
591
592 default:
593 printf("[%s] invalid type for key %s [%" PRIuz "]: %" PRIdz " <--> %" PRIdz "\n",
594 stype, name, key, rc, type);
595 goto fail;
596 }
597
598 have = freerdp_settings_set_value_for_name(settings, name, value);
599 if (have != expect)
600 {
601 printf("[%s] have[%s] != expect[%s]\n", stype, have ? "TRUE" : "FALSE",
602 expect ? "TRUE" : "FALSE");
603 goto fail;
604 }
605
606 } while (test_rounds-- > 0);
607
608 res = TRUE;
609fail:
610 freerdp_settings_free(settings);
611 return log_result(res, __func__);
612}
613
614static BOOL check_args(const RDPDR_DEVICE* what, size_t count, const char* args[])
615{
616 WINPR_ASSERT(what);
617
618 if (count > 0)
619 {
620 if (strcmp(what->Name, args[0]) != 0)
621 return FALSE;
622 }
623
624 switch (what->Type)
625 {
626 case RDPDR_DTYP_PRINT:
627 {
628 const RDPDR_PRINTER* a = (const RDPDR_PRINTER*)what;
629 if (count <= 1)
630 return TRUE;
631 if (!a->DriverName)
632 return FALSE;
633 return strcmp(a->DriverName, args[1]) == 0;
634 }
635
636 case RDPDR_DTYP_SERIAL:
637 {
638 const RDPDR_SERIAL* a = (const RDPDR_SERIAL*)what;
639
640 if (count > 1)
641 {
642 if (!a->Path)
643 return FALSE;
644 if (strcmp(a->Path, args[1]) != 0)
645 return FALSE;
646 }
647
648 if (count > 2)
649 {
650 if (!a->Driver)
651 return FALSE;
652 if (strcmp(a->Driver, args[2]) != 0)
653 return FALSE;
654 }
655
656 if (count > 3)
657 {
658 if (!a->Permissive)
659 return FALSE;
660 if (strcmp(a->Permissive, args[3]) != 0)
661 return FALSE;
662 }
663 return TRUE;
664 }
665
666 case RDPDR_DTYP_PARALLEL:
667 {
668 const RDPDR_PARALLEL* a = (const RDPDR_PARALLEL*)what;
669 if (count <= 1)
670 return TRUE;
671 if (!a->Path)
672 return FALSE;
673 return strcmp(a->Path, args[1]) == 0;
674 }
675
676 case RDPDR_DTYP_SMARTCARD:
677 return TRUE;
678
679 case RDPDR_DTYP_FILESYSTEM:
680 {
681 const RDPDR_DRIVE* a = (const RDPDR_DRIVE*)what;
682 if (count > 1)
683 {
684 if (!a->Path)
685 return FALSE;
686 if (strcmp(a->Path, args[1]) != 0)
687 return FALSE;
688 }
689 if (count > 2)
690 {
691 return a->automount == (args[2] == NULL) ? TRUE : FALSE;
692 }
693 else
694 return !a->automount;
695 }
696
697 default:
698 return FALSE;
699 }
700}
701
702static int check_device_type_arg(UINT32 Type, size_t count, const char* args[])
703{
704 int rc = -3;
705 RDPDR_DEVICE* device = freerdp_device_new(Type, count, args);
706 RDPDR_DEVICE* clone = freerdp_device_clone(device);
707
708 if (!device)
709 goto fail;
710
711 rc++;
712 if (!clone)
713 goto fail;
714
715 rc++;
716 if (!check_args(device, count, args))
717 goto fail;
718
719 rc++;
720 if (!freerdp_device_equal(clone, device))
721 goto fail;
722 rc++;
723
724fail:
725 freerdp_device_free(device);
726 freerdp_device_free(clone);
727 return log_result(rc, __func__);
728}
729
730static BOOL check_device_type(void)
731{
732 struct test_entry
733 {
734 int expect;
735 UINT32 type;
736 size_t count;
737 const char** args;
738 };
739 const char* args[] = { "somename", "anothername", "3rdname", "4thname" };
740 const struct test_entry tests[] = {
741 { 1, RDPDR_DTYP_SERIAL, 0, NULL },
742 { 1, RDPDR_DTYP_SERIAL, 0, args },
743 { 1, RDPDR_DTYP_SERIAL, 1, args },
744 { 1, RDPDR_DTYP_SERIAL, 2, args },
745 { 1, RDPDR_DTYP_SERIAL, 3, args },
746 { 1, RDPDR_DTYP_SERIAL, 4, args },
747 { 1, RDPDR_DTYP_PARALLEL, 0, NULL },
748 { 1, RDPDR_DTYP_PARALLEL, 0, args },
749 { 1, RDPDR_DTYP_PARALLEL, 1, args },
750 { 1, RDPDR_DTYP_PARALLEL, 2, args },
751 { 1, RDPDR_DTYP_PARALLEL, 3, args },
752 { 1, RDPDR_DTYP_PARALLEL, 4, args },
753 { 1, RDPDR_DTYP_PRINT, 0, NULL },
754 { 1, RDPDR_DTYP_PRINT, 0, args },
755 { 1, RDPDR_DTYP_PRINT, 1, args },
756 { 1, RDPDR_DTYP_PRINT, 2, args },
757 { 1, RDPDR_DTYP_PRINT, 3, args },
758 { 1, RDPDR_DTYP_PRINT, 4, args },
759 { 1, RDPDR_DTYP_FILESYSTEM, 0, NULL },
760 { 1, RDPDR_DTYP_FILESYSTEM, 0, args },
761 { 1, RDPDR_DTYP_FILESYSTEM, 1, args },
762 { 1, RDPDR_DTYP_FILESYSTEM, 2, args },
763 { 1, RDPDR_DTYP_FILESYSTEM, 3, args },
764 { 1, RDPDR_DTYP_FILESYSTEM, 4, args },
765 { 1, RDPDR_DTYP_SMARTCARD, 0, NULL },
766 { 1, RDPDR_DTYP_SMARTCARD, 0, args },
767 { 1, RDPDR_DTYP_SMARTCARD, 1, args },
768 { 1, RDPDR_DTYP_SMARTCARD, 2, args },
769 { 1, RDPDR_DTYP_SMARTCARD, 3, args },
770 { 1, RDPDR_DTYP_SMARTCARD, 4, args },
771 { -3, 0x123, 0, NULL },
772 { -3, 0x123, 0, args },
773 { -3, 0x123, 1, args },
774 { -3, 0x123, 2, args },
775 { -3, 0x123, 3, args },
776 { -3, 0x123, 4, args },
777 };
778 BOOL rc = TRUE;
779 for (size_t x = 0; x < ARRAYSIZE(tests); x++)
780 {
781 const struct test_entry* cur = &tests[x];
782 int got = check_device_type_arg(cur->type, cur->count, cur->args);
783 if (got != cur->expect)
784 rc = FALSE;
785 }
786 return log_result(rc, __func__);
787}
788
789static BOOL check_offsets(rdpSettings* settings, size_t id, size_t min, size_t max, BOOL checkPtr)
790{
791 BOOL rc = TRUE;
792
793 WINPR_ASSERT(settings);
794
795 if (!freerdp_settings_get_pointer(settings, id))
796 return FALSE;
797
798 for (size_t x = min; x < max; x++)
799 {
800 const void* ptr = freerdp_settings_get_pointer_array(settings, id, x);
801 if (!ptr && checkPtr)
802 rc = FALSE;
803 }
804 return log_result(rc, __func__);
805}
806
807static BOOL test_write_offsets(rdpSettings* settings, size_t id, size_t elementSize, size_t min,
808 size_t max)
809{
810 WINPR_ASSERT(settings);
811
812 for (size_t x = min; x < max; x++)
813 {
814 const void* ptr = NULL;
815 char buffer[8192] = { 0 };
816
817 winpr_RAND(buffer, sizeof(buffer));
818 if (!freerdp_settings_set_pointer_array(settings, id, x, buffer))
819 return FALSE;
820 ptr = freerdp_settings_get_pointer_array(settings, id, x);
821 if (!ptr)
822 return FALSE;
823 if (memcmp(ptr, buffer, elementSize) != 0)
824 return FALSE;
825 }
826 return TRUE;
827}
828
829static BOOL test_pointer_array(void)
830{
831 struct pointer_test_case
832 {
833 BOOL checkPtr;
834 BOOL write;
835 size_t id;
836 SSIZE_T sizeId;
837 size_t size;
838 size_t elementSize;
839 };
840 const struct pointer_test_case tests[] = {
841 { FALSE, FALSE, FreeRDP_DeviceArray, FreeRDP_DeviceArraySize, 32, sizeof(RDPDR_DEVICE*) },
842 { FALSE, FALSE, FreeRDP_StaticChannelArray, FreeRDP_StaticChannelArraySize, 32,
843 sizeof(ADDIN_ARGV*) },
844 { FALSE, FALSE, FreeRDP_DynamicChannelArray, FreeRDP_DynamicChannelArraySize, 33,
845 sizeof(ADDIN_ARGV*) },
846 { TRUE, TRUE, FreeRDP_BitmapCacheV2CellInfo, FreeRDP_BitmapCacheV2NumCells, 5,
848 { FALSE, FALSE, FreeRDP_OrderSupport, -1, 32, sizeof(BYTE) },
849 { FALSE, FALSE, FreeRDP_ReceivedCapabilities, -1, 32, sizeof(BYTE) },
850 { TRUE, TRUE, FreeRDP_GlyphCache, -1, 10, sizeof(GLYPH_CACHE_DEFINITION) },
851 { TRUE, TRUE, FreeRDP_FragCache, -1, 1, sizeof(GLYPH_CACHE_DEFINITION) },
852 { TRUE, TRUE, FreeRDP_MonitorIds, FreeRDP_NumMonitorIds, 33, sizeof(UINT32) },
853 { TRUE, TRUE, FreeRDP_ChannelDefArray, FreeRDP_ChannelDefArraySize, 42,
854 sizeof(CHANNEL_DEF) },
855 { TRUE, TRUE, FreeRDP_MonitorDefArray, FreeRDP_MonitorDefArraySize, 33,
856 sizeof(rdpMonitor) },
857 { TRUE, TRUE, FreeRDP_ClientTimeZone, -1, 1, sizeof(TIME_ZONE_INFORMATION) },
858 { FALSE, FALSE, FreeRDP_RdpServerCertificate, -1, 1, sizeof(rdpCertificate*) },
859 //{ FALSE, FALSE, FreeRDP_RdpServerRsaKey, -1, 1, sizeof(rdpPrivateKey*) },
860 { TRUE, TRUE, FreeRDP_RedirectionPassword, FreeRDP_RedirectionPasswordLength, 42,
861 sizeof(char) },
862 { TRUE, TRUE, FreeRDP_RedirectionTsvUrl, FreeRDP_RedirectionTsvUrlLength, 42,
863 sizeof(char) },
864 { TRUE, TRUE, FreeRDP_LoadBalanceInfo, FreeRDP_LoadBalanceInfoLength, 42, sizeof(char) },
865 { TRUE, TRUE, FreeRDP_ServerRandom, FreeRDP_ServerRandomLength, 42, sizeof(char) },
866 { TRUE, TRUE, FreeRDP_ClientRandom, FreeRDP_ClientRandomLength, 42, sizeof(char) },
867 { TRUE, TRUE, FreeRDP_ServerCertificate, FreeRDP_ServerCertificateLength, 42,
868 sizeof(char) },
869 { TRUE, TRUE, FreeRDP_ClientAutoReconnectCookie, -1, 1, sizeof(ARC_CS_PRIVATE_PACKET) },
870 { TRUE, TRUE, FreeRDP_ServerAutoReconnectCookie, -1, 1, sizeof(ARC_SC_PRIVATE_PACKET) }
871 };
872 BOOL rc = FALSE;
873 rdpSettings* settings = freerdp_settings_new(0);
874 if (!settings)
875 goto fail;
876
877 for (size_t x = 0; x < ARRAYSIZE(tests); x++)
878 {
879 const struct pointer_test_case* cur = &tests[x];
880 if (!freerdp_settings_set_pointer_len(settings, cur->id, NULL, cur->size))
881 goto fail;
882 if (cur->sizeId >= 0)
883 {
884 const UINT32 s = freerdp_settings_get_uint32(settings, (size_t)cur->sizeId);
885 if (s != cur->size)
886 goto fail;
887 }
888 if (!check_offsets(settings, cur->id, 0, cur->size, cur->checkPtr))
889 goto fail;
890 if (check_offsets(settings, cur->id, cur->size, cur->size + 5, TRUE))
891 goto fail;
892 if (cur->write)
893 {
894 if (!test_write_offsets(settings, cur->id, cur->elementSize, 0, cur->size))
895 goto fail;
896 if (test_write_offsets(settings, cur->id, cur->elementSize, cur->size, cur->size + 5))
897 goto fail;
898 }
899 if (!freerdp_settings_set_pointer_len(settings, cur->id, NULL, 0))
900 goto fail;
901 if (cur->sizeId >= 0)
902 {
903 const UINT32 s = freerdp_settings_get_uint32(settings, (size_t)cur->sizeId);
904 if (s != 0)
905 goto fail;
906 }
907 if (check_offsets(settings, cur->id, 0, cur->size, cur->checkPtr))
908 goto fail;
909 if (cur->write)
910 {
911 if (test_write_offsets(settings, cur->id, cur->elementSize, 0, cur->size))
912 goto fail;
913 }
914 if (!freerdp_settings_set_pointer_len(settings, cur->id, NULL, cur->size))
915 goto fail;
916 if (cur->sizeId >= 0)
917 {
918 const UINT32 s = freerdp_settings_get_uint32(settings, (size_t)cur->sizeId);
919 if (s != cur->size)
920 goto fail;
921 }
922 if (!check_offsets(settings, cur->id, 0, cur->size, cur->checkPtr))
923 goto fail;
924 if (check_offsets(settings, cur->id, cur->size + 1, cur->size + 5, TRUE))
925 goto fail;
926 if (cur->write)
927 {
928 if (!test_write_offsets(settings, cur->id, cur->elementSize, 0, cur->size))
929 goto fail;
930 if (test_write_offsets(settings, cur->id, cur->elementSize, cur->size, cur->size + 5))
931 goto fail;
932 }
933 }
934
935 rc = TRUE;
936
937fail:
938 freerdp_settings_free(settings);
939 return log_result(rc, __func__);
940}
941
942struct validity_test_case
943{
944 BOOL expected;
945 size_t count;
946 const rdpMonitor* monitors;
947};
948
949static BOOL prepare_monitor_array(rdpSettings* settings, const struct validity_test_case* testcase)
950{
951 WINPR_ASSERT(settings);
952 WINPR_ASSERT(testcase);
953
954 return freerdp_settings_set_monitor_def_array_sorted(settings, testcase->monitors,
955 testcase->count);
956}
957
958static BOOL check_primary_offset(const rdpSettings* settings, const rdpMonitor* monitors,
959 size_t count)
960{
961 const rdpMonitor* cprimary = NULL;
962 for (size_t x = 0; x < count; x++)
963 {
964 const rdpMonitor* cur = &monitors[x];
965 if (cur->is_primary)
966 cprimary = cur;
967 }
968 if (!cprimary)
969 {
970 for (size_t x = 0; x < count; x++)
971 {
972 const rdpMonitor* cur = &monitors[x];
973 if ((cur->x == 0) && (cur->y == 0))
974 cprimary = cur;
975 }
976 }
977 const rdpMonitor* sprimary = NULL;
978 for (size_t x = 0; x < count; x++)
979 {
980 const rdpMonitor* cur =
981 freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorDefArray, x);
982 if (!cur)
983 return FALSE;
984 if (cur->is_primary)
985 sprimary = cur;
986 }
987
988 if (!sprimary || !cprimary)
989 return FALSE;
990
991 const INT32 xoff = cprimary->x;
992 const INT32 yoff = cprimary->y;
993 const INT32 sxoff = freerdp_settings_get_int32(settings, FreeRDP_MonitorLocalShiftX);
994 const INT32 syoff = freerdp_settings_get_int32(settings, FreeRDP_MonitorLocalShiftY);
995 if (xoff != sxoff)
996 return FALSE;
997 if (yoff != syoff)
998 return FALSE;
999 return TRUE;
1000}
1001
1002static BOOL test_validity_check(void)
1003{
1004 BOOL rc = FALSE;
1005 rdpSettings* settings = freerdp_settings_new(0);
1006 if (!settings)
1007 goto fail;
1008
1009 const rdpMonitor single_monitor_valid[] = {
1010 { .x = 0,
1011 .y = 0,
1012 .width = 1920,
1013 .height = 1080,
1014 .is_primary = TRUE,
1015 .orig_screen = 0,
1016 .attributes = { .physicalWidth = 100,
1017 .physicalHeight = 100,
1018 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1019 .desktopScaleFactor = 100,
1020 .deviceScaleFactor = 100 } }
1021 };
1022 const rdpMonitor single_monitor_invalid_1[] = {
1023 { .x = 0,
1024 .y = 0,
1025 .width = 192,
1026 .height = 1080,
1027 .is_primary = TRUE,
1028 .orig_screen = 0,
1029 .attributes = { .physicalWidth = 100,
1030 .physicalHeight = 100,
1031 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1032 .desktopScaleFactor = 100,
1033 .deviceScaleFactor = 100 } }
1034 };
1035 const rdpMonitor single_monitor_invalid_2[] = {
1036 { .x = 0,
1037 .y = 0,
1038 .width = 192,
1039 .height = 1080,
1040 .is_primary = TRUE,
1041 .orig_screen = 0,
1042 .attributes = { .physicalWidth = 100,
1043 .physicalHeight = 100,
1044 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1045 .desktopScaleFactor = 100,
1046 .deviceScaleFactor = 100 } }
1047 };
1048 const rdpMonitor single_monitor_invalid_3[] = {
1049 { .x = 0,
1050 .y = 0,
1051 .width = 192,
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_4[] = {
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 multi_monitor_valid[] = {
1075 { .x = 0,
1076 .y = 0,
1077 .width = 1920,
1078 .height = 1080,
1079 .is_primary = FALSE,
1080 .orig_screen = 0,
1081 .attributes = { .physicalWidth = 100,
1082 .physicalHeight = 100,
1083 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1084 .desktopScaleFactor = 100,
1085 .deviceScaleFactor = 100 } },
1086 { .x = 1920,
1087 .y = 0,
1088 .width = 1920,
1089 .height = 1080,
1090 .is_primary = FALSE,
1091 .orig_screen = 0,
1092 .attributes = { .physicalWidth = 100,
1093 .physicalHeight = 100,
1094 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1095 .desktopScaleFactor = 100,
1096 .deviceScaleFactor = 100 } },
1097 { .x = 0,
1098 .y = 1080,
1099 .width = 1920,
1100 .height = 1080,
1101 .is_primary = FALSE,
1102 .orig_screen = 0,
1103 .attributes = { .physicalWidth = 100,
1104 .physicalHeight = 100,
1105 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1106 .desktopScaleFactor = 100,
1107 .deviceScaleFactor = 100 } },
1108 { .x = -1920,
1109 .y = 0,
1110 .width = 1920,
1111 .height = 1080,
1112 .is_primary = FALSE,
1113 .orig_screen = 0,
1114 .attributes = { .physicalWidth = 100,
1115 .physicalHeight = 100,
1116 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1117 .desktopScaleFactor = 100,
1118 .deviceScaleFactor = 100 } },
1119 { .x = 0,
1120 .y = -1080,
1121 .width = 1920,
1122 .height = 1080,
1123 .is_primary = TRUE,
1124 .orig_screen = 0,
1125 .attributes = { .physicalWidth = 100,
1126 .physicalHeight = 100,
1127 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1128 .desktopScaleFactor = 100,
1129 .deviceScaleFactor = 100 } },
1130 { .x = 3840,
1131 .y = 0,
1132 .width = 1920,
1133 .height = 1080,
1134 .is_primary = FALSE,
1135 .orig_screen = 0,
1136 .attributes = { .physicalWidth = 100,
1137 .physicalHeight = 100,
1138 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1139 .desktopScaleFactor = 100,
1140 .deviceScaleFactor = 100 } },
1141 { .x = 5760,
1142 .y = -1079,
1143 .width = 1920,
1144 .height = 1080,
1145 .is_primary = FALSE,
1146 .orig_screen = 0,
1147 .attributes = { .physicalWidth = 100,
1148 .physicalHeight = 100,
1149 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1150 .desktopScaleFactor = 100,
1151 .deviceScaleFactor = 100 } },
1152 { .x = 7680,
1153 .y = 0,
1154 .width = 1920,
1155 .height = 1080,
1156 .is_primary = FALSE,
1157 .orig_screen = 0,
1158 .attributes = { .physicalWidth = 100,
1159 .physicalHeight = 100,
1160 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1161 .desktopScaleFactor = 100,
1162 .deviceScaleFactor = 100 } },
1163 { .x = 7680,
1164 .y = 1080,
1165 .width = 1920,
1166 .height = 1080,
1167 .is_primary = FALSE,
1168 .orig_screen = 0,
1169 .attributes = { .physicalWidth = 100,
1170 .physicalHeight = 100,
1171 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1172 .desktopScaleFactor = 100,
1173 .deviceScaleFactor = 100 } },
1174 { .x = 7680,
1175 .y = -1080,
1176 .width = 1920,
1177 .height = 1080,
1178 .is_primary = FALSE,
1179 .orig_screen = 0,
1180 .attributes = { .physicalWidth = 100,
1181 .physicalHeight = 100,
1182 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1183 .desktopScaleFactor = 100,
1184 .deviceScaleFactor = 100 } },
1185 { .x = 7680,
1186 .y = -2160,
1187 .width = 1920,
1188 .height = 1080,
1189 .is_primary = FALSE,
1190 .orig_screen = 0,
1191 .attributes = { .physicalWidth = 100,
1192 .physicalHeight = 100,
1193 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1194 .desktopScaleFactor = 100,
1195 .deviceScaleFactor = 100 } },
1196 { .x = 9599,
1197 .y = -3240,
1198 .width = 1920,
1199 .height = 1080,
1200 .is_primary = FALSE,
1201 .orig_screen = 0,
1202 .attributes = { .physicalWidth = 100,
1203 .physicalHeight = 100,
1204 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1205 .desktopScaleFactor = 100,
1206 .deviceScaleFactor = 100 } },
1207 };
1208 const rdpMonitor multi_monitor_invalid_1[] = {
1209 { .x = 0,
1210 .y = 0,
1211 .width = 1920,
1212 .height = 1080,
1213 .is_primary = FALSE,
1214 .orig_screen = 0,
1215 .attributes = { .physicalWidth = 100,
1216 .physicalHeight = 100,
1217 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1218 .desktopScaleFactor = 100,
1219 .deviceScaleFactor = 100 } },
1220 { .x = 1920,
1221 .y = 0,
1222 .width = 1920,
1223 .height = 1080,
1224 .is_primary = FALSE,
1225 .orig_screen = 0,
1226 .attributes = { .physicalWidth = 100,
1227 .physicalHeight = 100,
1228 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1229 .desktopScaleFactor = 100,
1230 .deviceScaleFactor = 100 } }
1231 };
1232 const rdpMonitor multi_monitor_invalid_2[] = {
1233 { .x = 1,
1234 .y = 0,
1235 .width = 1920,
1236 .height = 1080,
1237 .is_primary = FALSE,
1238 .orig_screen = 0,
1239 .attributes = { .physicalWidth = 100,
1240 .physicalHeight = 100,
1241 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1242 .desktopScaleFactor = 100,
1243 .deviceScaleFactor = 100 } },
1244 { .x = 1920,
1245 .y = 0,
1246 .width = 1920,
1247 .height = 1080,
1248 .is_primary = TRUE,
1249 .orig_screen = 0,
1250 .attributes = { .physicalWidth = 100,
1251 .physicalHeight = 100,
1252 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1253 .desktopScaleFactor = 100,
1254 .deviceScaleFactor = 100 } }
1255 };
1256 const rdpMonitor multi_monitor_invalid_3[] = {
1257 { .x = 0,
1258 .y = 0,
1259 .width = 1920,
1260 .height = 1080,
1261 .is_primary = FALSE,
1262 .orig_screen = 0,
1263 .attributes = { .physicalWidth = 100,
1264 .physicalHeight = 100,
1265 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1266 .desktopScaleFactor = 100,
1267 .deviceScaleFactor = 100 } },
1268 { .x = 1921,
1269 .y = 0,
1270 .width = 1920,
1271 .height = 1080,
1272 .is_primary = TRUE,
1273 .orig_screen = 0,
1274 .attributes = { .physicalWidth = 100,
1275 .physicalHeight = 100,
1276 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1277 .desktopScaleFactor = 100,
1278 .deviceScaleFactor = 100 } }
1279 };
1280 const rdpMonitor multi_monitor_invalid_4[] = {
1281 { .x = 0,
1282 .y = 0,
1283 .width = 1920,
1284 .height = 1080,
1285 .is_primary = FALSE,
1286 .orig_screen = 0,
1287 .attributes = { .physicalWidth = 100,
1288 .physicalHeight = 100,
1289 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1290 .desktopScaleFactor = 100,
1291 .deviceScaleFactor = 100 } },
1292 { .x = 1919,
1293 .y = 0,
1294 .width = 1920,
1295 .height = 1080,
1296 .is_primary = TRUE,
1297 .orig_screen = 0,
1298 .attributes = { .physicalWidth = 100,
1299 .physicalHeight = 100,
1300 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1301 .desktopScaleFactor = 100,
1302 .deviceScaleFactor = 100 } }
1303 };
1304
1305 const rdpMonitor multi_monitor_valid_2[] = {
1306 { .x = 0,
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 { .x = 3840,
1318 .y = 0,
1319 .width = 1920,
1320 .height = 1080,
1321 .is_primary = FALSE,
1322 .orig_screen = 0,
1323 .attributes = { .physicalWidth = 100,
1324 .physicalHeight = 100,
1325 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1326 .desktopScaleFactor = 100,
1327 .deviceScaleFactor = 100 } },
1328 { .x = 1920,
1329 .y = 0,
1330 .width = 1920,
1331 .height = 1080,
1332 .is_primary = FALSE,
1333 .orig_screen = 0,
1334 .attributes = { .physicalWidth = 100,
1335 .physicalHeight = 100,
1336 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1337 .desktopScaleFactor = 100,
1338 .deviceScaleFactor = 100 } }
1339 };
1340
1341 const rdpMonitor multi_monitor_valid_3[] = {
1342 { .x = 1920,
1343 .y = 0,
1344 .width = 1920,
1345 .height = 1080,
1346 .is_primary = TRUE,
1347 .orig_screen = 0,
1348 .attributes = { .physicalWidth = 100,
1349 .physicalHeight = 100,
1350 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1351 .desktopScaleFactor = 100,
1352 .deviceScaleFactor = 100 } },
1353 { .x = 3840,
1354 .y = 0,
1355 .width = 1920,
1356 .height = 1080,
1357 .is_primary = FALSE,
1358 .orig_screen = 0,
1359 .attributes = { .physicalWidth = 100,
1360 .physicalHeight = 100,
1361 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1362 .desktopScaleFactor = 100,
1363 .deviceScaleFactor = 100 } },
1364 { .x = 0,
1365 .y = 0,
1366 .width = 1920,
1367 .height = 1080,
1368 .is_primary = FALSE,
1369 .orig_screen = 0,
1370 .attributes = { .physicalWidth = 100,
1371 .physicalHeight = 100,
1372 .orientation = ORIENTATION_PREFERENCE_LANDSCAPE,
1373 .desktopScaleFactor = 100,
1374 .deviceScaleFactor = 100 } }
1375 };
1376
1377 const struct validity_test_case tests[] = {
1378 { TRUE, ARRAYSIZE(single_monitor_valid), single_monitor_valid },
1379 { FALSE, ARRAYSIZE(single_monitor_invalid_1), single_monitor_invalid_1 },
1380 { FALSE, ARRAYSIZE(single_monitor_invalid_2), single_monitor_invalid_2 },
1381 { FALSE, ARRAYSIZE(single_monitor_invalid_3), single_monitor_invalid_3 },
1382 { FALSE, ARRAYSIZE(single_monitor_invalid_4), single_monitor_invalid_4 },
1383 { TRUE, ARRAYSIZE(multi_monitor_valid), multi_monitor_valid },
1384 { TRUE, ARRAYSIZE(multi_monitor_invalid_1), multi_monitor_invalid_1 },
1385 { FALSE, ARRAYSIZE(multi_monitor_invalid_2), multi_monitor_invalid_2 },
1386 { FALSE, ARRAYSIZE(multi_monitor_invalid_3), multi_monitor_invalid_3 },
1387 { FALSE, ARRAYSIZE(multi_monitor_invalid_4), multi_monitor_invalid_4 },
1388 { TRUE, ARRAYSIZE(multi_monitor_valid_2), multi_monitor_valid_2 },
1389 { TRUE, ARRAYSIZE(multi_monitor_valid_3), multi_monitor_valid_3 }
1390 };
1391
1392 rc = TRUE;
1393 for (size_t x = 0; x < ARRAYSIZE(tests); x++)
1394 {
1395 const struct validity_test_case* cur = &tests[x];
1396
1397 if (!prepare_monitor_array(settings, cur))
1398 rc = log_result_case(FALSE, __func__, x);
1399 else
1400 {
1401#if defined(BUILD_TESTING_INTERNAL)
1402 const BOOL res = freerdp_settings_check_client_after_preconnect(settings);
1403#else
1404 const BOOL res = cur->expected;
1405#endif
1406
1407 if ((res != cur->expected) ||
1408 !check_primary_offset(settings, cur->monitors, cur->count))
1409 {
1410 rc = log_result_case(FALSE, __func__, x);
1411 }
1412 }
1413 }
1414
1415fail:
1416 freerdp_settings_free(settings);
1417 return log_result(rc, __func__);
1418}
1419
1420static BOOL test_string_null(rdpSettings* settings, FreeRDP_Settings_Keys_String id)
1421{
1422 if (!freerdp_settings_set_string(settings, id, NULL))
1423 return FALSE;
1424
1425 const char* chk = freerdp_settings_get_string(settings, id);
1426 return (chk == NULL);
1427}
1428
1429static BOOL test_string_check(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
1430 const char* string, size_t len)
1431{
1432 const char* chk = freerdp_settings_get_string(settings, id);
1433 if (!chk)
1434 return FALSE;
1435
1436 const size_t clen = strnlen(chk, len + 1);
1437
1438 /* set strings must always be '\0' terminated */
1439 if (clen != len)
1440 return FALSE;
1441
1442 /* Strings must match comparison */
1443 if (strncmp(string, chk, clen) != 0)
1444 return FALSE;
1445
1446 return TRUE;
1447}
1448
1449static BOOL test_string_check_reset(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
1450 const char* string, size_t len)
1451{
1452 return test_string_check(settings, id, string, len) && test_string_null(settings, id);
1453}
1454
1455static BOOL test_string_set_readback(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
1456 const char* string, size_t len)
1457{
1458 WINPR_ASSERT(len > 3);
1459
1460 BOOL rc = FALSE;
1461 WCHAR* wstr = NULL;
1462
1463 const size_t slen = strnlen(string, len);
1464 if (!freerdp_settings_set_string_len(settings, id, string, slen - 1))
1465 goto fail;
1466
1467 if (!test_string_check_reset(settings, id, string, slen - 1))
1468 goto fail;
1469
1470 if (!freerdp_settings_set_string(settings, id, string))
1471 goto fail;
1472
1473 size_t wlen = 0;
1474 wstr = freerdp_settings_get_string_as_utf16(settings, id, &wlen);
1475 if (!wstr || (wlen != slen))
1476 goto fail;
1477
1478 if (!test_string_check_reset(settings, id, string, slen))
1479 goto fail;
1480
1481 if (!freerdp_settings_set_string_from_utf16N(settings, id, wstr, slen - 1))
1482 goto fail;
1483
1484 if (!test_string_check(settings, id, string, slen - 1))
1485 goto fail;
1486
1487 if (!freerdp_settings_set_string_from_utf16(settings, id, wstr))
1488 goto fail;
1489
1490 if (!test_string_check(settings, id, string, slen))
1491 goto fail;
1492
1493 rc = TRUE;
1494fail:
1495 free(wstr);
1496 return rc;
1497}
1498
1499static BOOL test_string_len(rdpSettings* settings)
1500{
1501 BOOL rc = FALSE;
1502
1503 const char user[] = "abcdefg";
1504 if (!test_string_set_readback(settings, FreeRDP_Username, user, sizeof(user)))
1505 goto fail;
1506
1507 const char pwd[] = "xyz";
1508 if (!test_string_set_readback(settings, FreeRDP_Password, pwd, sizeof(pwd)))
1509 goto fail;
1510
1511 const char domain[] = "foobar";
1512 if (!test_string_set_readback(settings, FreeRDP_Domain, domain, sizeof(domain)))
1513 goto fail;
1514
1515 rc = TRUE;
1516fail:
1517 return rc;
1518}
1519
1520int TestSettings(int argc, char* argv[])
1521{
1522 int rc = -1;
1523 rdpSettings* settings = NULL;
1524 rdpSettings* cloned = NULL;
1525 rdpSettings* cloned2 = NULL;
1526 WINPR_UNUSED(argc);
1527 WINPR_UNUSED(argv);
1528
1529 if (!test_dyn_channels())
1530 goto fail;
1531 if (!test_static_channels())
1532 goto fail;
1533 if (!test_copy())
1534 goto fail;
1535 if (!test_helpers())
1536 goto fail;
1537 if (!check_device_type())
1538 goto fail;
1539 if (!test_pointer_array())
1540 goto fail;
1541 if (!test_validity_check())
1542 goto fail;
1543
1544 settings = freerdp_settings_new(0);
1545
1546 if (!settings)
1547 {
1548 printf("Couldn't create settings\n");
1549 return -1;
1550 }
1551
1552 if (!test_string_len(settings))
1553 goto fail;
1554
1555 cloned = freerdp_settings_clone(settings);
1556
1557 if (!cloned)
1558 goto fail;
1559
1560#if defined(have_bool_list_indices)
1561
1562 for (size_t x = 0; x < ARRAYSIZE(bool_list_indices); x++)
1563 {
1564 const size_t key = bool_list_indices[x];
1565 const char* name =
1566 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
1567 const BOOL val = freerdp_settings_get_bool(settings, key);
1568 const BOOL cval = freerdp_settings_get_bool(cloned, key);
1569 if (val != cval)
1570 {
1571 printf("mismatch for key %s: %u -> copy %u\n", name, val, cval);
1572 goto fail;
1573 }
1574 if (!freerdp_settings_set_bool(settings, key, val))
1575 goto fail;
1576 if (!check_key_helpers(key, "bool"))
1577 goto fail;
1578 }
1579
1580#endif
1581#if defined(have_int16_list_indices)
1582
1583 for (size_t x = 0; x < ARRAYSIZE(int16_list_indices); x++)
1584 {
1585 const size_t key = int16_list_indices[x];
1586 const char* name = freerdp_settings_get_name_for_key(key);
1587 const INT16 val = freerdp_settings_get_int16(settings, key);
1588 const INT16 cval = freerdp_settings_get_int16(cloned, key);
1589 if (val != cval)
1590 {
1591 printf("mismatch for key %s: %" PRId16 " -> copy %" PRId16 "\n", name, val, cval);
1592 goto fail;
1593 }
1594 if (!freerdp_settings_set_int16(settings, key, val))
1595 goto fail;
1596 if (!check_key_helpers(key, "int16"))
1597 goto fail;
1598 }
1599
1600#endif
1601#if defined(have_uint16_list_indices)
1602
1603 for (size_t x = 0; x < ARRAYSIZE(uint16_list_indices); x++)
1604 {
1605 const size_t key = uint16_list_indices[x];
1606 const char* name =
1607 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
1608 const UINT16 val = freerdp_settings_get_uint16(settings, key);
1609 const UINT16 cval = freerdp_settings_get_uint16(cloned, key);
1610 if (val != cval)
1611 {
1612 printf("mismatch for key %s: %" PRIu16 " -> copy %" PRIu16 "\n", name, val, cval);
1613 goto fail;
1614 }
1615 if (!freerdp_settings_set_uint16(settings, key, val))
1616 goto fail;
1617 if (!check_key_helpers(key, "uint16"))
1618 goto fail;
1619 }
1620
1621#endif
1622#if defined(have_uint32_list_indices)
1623
1624 for (size_t x = 0; x < ARRAYSIZE(uint32_list_indices); x++)
1625 {
1626 const size_t key = uint32_list_indices[x];
1627 const char* name =
1628 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
1629 const UINT32 val = freerdp_settings_get_uint32(settings, key);
1630 const UINT32 cval = freerdp_settings_get_uint32(cloned, key);
1631 if (val != cval)
1632 {
1633 printf("mismatch for key %s: %" PRIu32 " -> copy %" PRIu32 "\n", name, val, cval);
1634 goto fail;
1635 }
1636 if (!freerdp_settings_set_uint32(settings, key, val))
1637 goto fail;
1638 if (!check_key_helpers(key, "uint32"))
1639 goto fail;
1640 }
1641
1642#endif
1643#if defined(have_int32_list_indices)
1644
1645 for (size_t x = 0; x < ARRAYSIZE(int32_list_indices); x++)
1646 {
1647 const size_t key = int32_list_indices[x];
1648 const char* name =
1649 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
1650 const INT32 val = freerdp_settings_get_int32(settings, key);
1651 const INT32 cval = freerdp_settings_get_int32(cloned, key);
1652 if (val != cval)
1653 {
1654 printf("mismatch for key %s: %" PRId32 " -> copy %" PRId32 "\n", name, val, cval);
1655 goto fail;
1656 }
1657 if (!freerdp_settings_set_int32(settings, key, val))
1658 goto fail;
1659 if (!check_key_helpers(key, "int32"))
1660 goto fail;
1661 }
1662
1663#endif
1664#if defined(have_uint64_list_indices)
1665
1666 for (size_t x = 0; x < ARRAYSIZE(uint64_list_indices); x++)
1667 {
1668 const size_t key = uint64_list_indices[x];
1669 const char* name =
1670 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
1671 const UINT64 val = freerdp_settings_get_uint64(settings, key);
1672 const UINT64 cval = freerdp_settings_get_uint64(cloned, key);
1673 if (val != cval)
1674 {
1675 printf("mismatch for key %s: %" PRIu64 " -> copy %" PRIu64 "\n", name, val, cval);
1676 goto fail;
1677 }
1678 if (!freerdp_settings_set_uint64(settings, key, val))
1679 goto fail;
1680 if (!check_key_helpers(key, "uint64"))
1681 goto fail;
1682 }
1683
1684#endif
1685#if defined(have_int64_list_indices)
1686
1687 for (size_t x = 0; x < ARRAYSIZE(int64_list_indices); x++)
1688 {
1689 const size_t key = int64_list_indices[x];
1690 const char* name = freerdp_settings_get_name_for_key(key);
1691 const INT64 val = freerdp_settings_get_int64(settings, key);
1692 const INT64 cval = freerdp_settings_get_int64(cloned, key);
1693 if (val != cval)
1694 {
1695 printf("mismatch for key %s: %" PRId64 " -> copy %" PRId64 "\n", name, val, cval);
1696 goto fail;
1697 }
1698 if (!freerdp_settings_set_int64(settings, key, val))
1699 goto fail;
1700 if (!check_key_helpers(key, "int64"))
1701 goto fail;
1702 }
1703
1704#endif
1705#if defined(have_string_list_indices)
1706
1707 for (size_t x = 0; x < ARRAYSIZE(string_list_indices); x++)
1708 {
1709 const size_t key = string_list_indices[x];
1710 const char val[] = "test-string";
1711 const char* res = NULL;
1712 const char* name =
1713 freerdp_settings_get_name_for_key(WINPR_ASSERTING_INT_CAST(SSIZE_T, key));
1714 const char* oval = freerdp_settings_get_string(settings, key);
1715 const char* cval = freerdp_settings_get_string(cloned, key);
1716 if ((oval != cval) && (strcmp(oval, cval) != 0))
1717 {
1718 printf("mismatch for key %s: %s -> copy %s\n", name, oval, cval);
1719 goto fail;
1720 }
1721 if (!freerdp_settings_set_string(settings, key, val))
1722 goto fail;
1723
1724 res = freerdp_settings_get_string(settings, key);
1725
1726 if (strncmp(val, res, sizeof(val)) != 0)
1727 goto fail;
1728 }
1729
1730#endif
1731#if defined(have_pointer_list_indices)
1732
1733 for (size_t x = 0; x < ARRAYSIZE(pointer_list_indices); x++)
1734 {
1735 const size_t key = pointer_list_indices[x];
1736 const void* val = freerdp_settings_get_pointer(settings, key);
1737 WINPR_UNUSED(val);
1738 }
1739
1740#endif
1741 cloned2 = freerdp_settings_clone(settings);
1742 if (!cloned2)
1743 goto fail;
1744 if (!freerdp_settings_copy(cloned2, cloned))
1745 goto fail;
1746
1747 rc = 0;
1748fail:
1749 freerdp_settings_free(cloned);
1750 freerdp_settings_free(cloned2);
1751 freerdp_settings_free(settings);
1752 return rc;
1753}
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 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.
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 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 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.