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