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