summaryrefslogtreecommitdiffstats
path: root/libfreerdp/common/settings.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 01:24:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 01:24:41 +0000
commita9bcc81f821d7c66f623779fa5147e728eb3c388 (patch)
tree98676963bcdd537ae5908a067a8eb110b93486a6 /libfreerdp/common/settings.c
parentInitial commit. (diff)
downloadfreerdp3-a9bcc81f821d7c66f623779fa5147e728eb3c388.tar.xz
freerdp3-a9bcc81f821d7c66f623779fa5147e728eb3c388.zip
Adding upstream version 3.3.0+dfsg1.upstream/3.3.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'libfreerdp/common/settings.c')
-rw-r--r--libfreerdp/common/settings.c2185
1 files changed, 2185 insertions, 0 deletions
diff --git a/libfreerdp/common/settings.c b/libfreerdp/common/settings.c
new file mode 100644
index 0000000..34712c8
--- /dev/null
+++ b/libfreerdp/common/settings.c
@@ -0,0 +1,2185 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Settings Management
+ *
+ * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2016 Armin Novak <armin.novak@gmail.com>
+ * Copyright 2023 Armin Novak <anovak@thincast.com>
+ * Copyright 2023 Thincast Technologies GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <freerdp/config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <winpr/crt.h>
+#include <winpr/assert.h>
+
+#include "../core/settings.h"
+#include "../core/capabilities.h"
+
+#include <freerdp/crypto/certificate.h>
+#include <freerdp/settings.h>
+#include <freerdp/freerdp.h>
+#include <freerdp/log.h>
+
+#define TAG FREERDP_TAG("common")
+
+BOOL freerdp_addin_argv_add_argument_ex(ADDIN_ARGV* args, const char* argument, size_t len)
+{
+ char* str = NULL;
+ char** new_argv = NULL;
+
+ if (!args || !argument)
+ return FALSE;
+
+ if (len == 0)
+ len = strlen(argument);
+
+ new_argv = (char**)realloc(args->argv, sizeof(char*) * (args->argc + 1));
+
+ if (!new_argv)
+ return FALSE;
+
+ args->argv = new_argv;
+
+ str = calloc(len + 1, sizeof(char));
+ if (!str)
+ return FALSE;
+ memcpy(str, argument, len);
+ args->argv[args->argc++] = str;
+ return TRUE;
+}
+
+BOOL freerdp_addin_argv_add_argument(ADDIN_ARGV* args, const char* argument)
+{
+ return freerdp_addin_argv_add_argument_ex(args, argument, 0);
+}
+
+BOOL freerdp_addin_argv_del_argument(ADDIN_ARGV* args, const char* argument)
+{
+ if (!args || !argument)
+ return FALSE;
+ for (int x = 0; x < args->argc; x++)
+ {
+ char* arg = args->argv[x];
+ if (strcmp(argument, arg) == 0)
+ {
+ free(arg);
+ memmove_s(&args->argv[x], (args->argc - x) * sizeof(char*), &args->argv[x + 1],
+ (args->argc - x - 1) * sizeof(char*));
+ args->argv[args->argc - 1] = NULL;
+ args->argc--;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+int freerdp_addin_set_argument(ADDIN_ARGV* args, const char* argument)
+{
+ if (!args || !argument)
+ return -2;
+
+ for (int i = 0; i < args->argc; i++)
+ {
+ if (strcmp(args->argv[i], argument) == 0)
+ {
+ return 1;
+ }
+ }
+
+ if (!freerdp_addin_argv_add_argument(args, argument))
+ return -1;
+ return 0;
+}
+
+int freerdp_addin_replace_argument(ADDIN_ARGV* args, const char* previous, const char* argument)
+{
+ if (!args || !previous || !argument)
+ return -2;
+
+ for (int i = 0; i < args->argc; i++)
+ {
+ if (strcmp(args->argv[i], previous) == 0)
+ {
+ free(args->argv[i]);
+
+ if (!(args->argv[i] = _strdup(argument)))
+ return -1;
+
+ return 1;
+ }
+ }
+
+ if (!freerdp_addin_argv_add_argument(args, argument))
+ return -1;
+ return 0;
+}
+
+int freerdp_addin_set_argument_value(ADDIN_ARGV* args, const char* option, const char* value)
+{
+ BOOL rc = 0;
+ char* p = NULL;
+ char* str = NULL;
+ size_t length = 0;
+ if (!args || !option || !value)
+ return -2;
+ length = strlen(option) + strlen(value) + 1;
+ str = (char*)calloc(length + 1, sizeof(char));
+
+ if (!str)
+ return -1;
+
+ sprintf_s(str, length + 1, "%s:%s", option, value);
+
+ for (int i = 0; i < args->argc; i++)
+ {
+ p = strchr(args->argv[i], ':');
+
+ if (p)
+ {
+ if (strncmp(args->argv[i], option, p - args->argv[i]) == 0)
+ {
+ free(args->argv[i]);
+ args->argv[i] = str;
+ return 1;
+ }
+ }
+ }
+
+ rc = freerdp_addin_argv_add_argument(args, str);
+ free(str);
+ if (!rc)
+ return -1;
+ return 0;
+}
+
+int freerdp_addin_replace_argument_value(ADDIN_ARGV* args, const char* previous, const char* option,
+ const char* value)
+{
+ BOOL rc = 0;
+ char* str = NULL;
+ size_t length = 0;
+ if (!args || !previous || !option || !value)
+ return -2;
+ length = strlen(option) + strlen(value) + 1;
+ str = (char*)calloc(length + 1, sizeof(char));
+
+ if (!str)
+ return -1;
+
+ sprintf_s(str, length + 1, "%s:%s", option, value);
+
+ for (int i = 0; i < args->argc; i++)
+ {
+ if (strcmp(args->argv[i], previous) == 0)
+ {
+ free(args->argv[i]);
+ args->argv[i] = str;
+ return 1;
+ }
+ }
+
+ rc = freerdp_addin_argv_add_argument(args, str);
+ free(str);
+ if (!rc)
+ return -1;
+ return 0;
+}
+
+BOOL freerdp_device_collection_add(rdpSettings* settings, RDPDR_DEVICE* device)
+{
+ UINT32 count = 0;
+ UINT32 old = 0;
+ WINPR_ASSERT(settings);
+ WINPR_ASSERT(device);
+
+ count = freerdp_settings_get_uint32(settings, FreeRDP_DeviceCount) + 1;
+ old = freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize);
+ if (old < count)
+ {
+ UINT32 new_size = old * 2;
+ RDPDR_DEVICE** new_array = NULL;
+
+ if (new_size == 0)
+ new_size = count * 2;
+
+ new_array =
+ (RDPDR_DEVICE**)realloc(settings->DeviceArray, new_size * sizeof(RDPDR_DEVICE*));
+
+ if (!new_array)
+ return FALSE;
+
+ settings->DeviceArray = new_array;
+ memset(&settings->DeviceArray[old], 0, (new_size - old) * sizeof(RDPDR_DEVICE*));
+
+ if (!freerdp_settings_set_uint32(settings, FreeRDP_DeviceArraySize, new_size))
+ return FALSE;
+ }
+
+ settings->DeviceArray[settings->DeviceCount++] = device;
+ return TRUE;
+}
+
+RDPDR_DEVICE* freerdp_device_collection_find(rdpSettings* settings, const char* name)
+{
+ RDPDR_DEVICE* device = NULL;
+
+ WINPR_ASSERT(settings);
+ WINPR_ASSERT(name);
+ for (UINT32 index = 0; index < settings->DeviceCount; index++)
+ {
+ device = (RDPDR_DEVICE*)settings->DeviceArray[index];
+
+ if (!device->Name)
+ continue;
+
+ if (strcmp(device->Name, name) == 0)
+ return device;
+ }
+
+ return NULL;
+}
+
+RDPDR_DEVICE* freerdp_device_collection_find_type(rdpSettings* settings, UINT32 type)
+{
+ RDPDR_DEVICE* device = NULL;
+ WINPR_ASSERT(settings);
+
+ for (UINT32 index = 0; index < settings->DeviceCount; index++)
+ {
+ device = (RDPDR_DEVICE*)settings->DeviceArray[index];
+
+ if (device->Type == type)
+ return device;
+ }
+
+ return NULL;
+}
+
+RDPDR_DEVICE* freerdp_device_new(UINT32 Type, size_t count, const char* args[])
+{
+ size_t size = 0;
+ union
+ {
+ RDPDR_DEVICE* base;
+ RDPDR_DRIVE* drive;
+ RDPDR_SERIAL* serial;
+ RDPDR_PRINTER* printer;
+ RDPDR_PARALLEL* parallel;
+ RDPDR_SMARTCARD* smartcard;
+ } device;
+
+ device.base = NULL;
+ WINPR_ASSERT(args || (count == 0));
+
+ switch (Type)
+ {
+ case RDPDR_DTYP_PRINT:
+ size = sizeof(RDPDR_PRINTER);
+ break;
+ case RDPDR_DTYP_SERIAL:
+ size = sizeof(RDPDR_SERIAL);
+ break;
+ case RDPDR_DTYP_PARALLEL:
+ size = sizeof(RDPDR_PARALLEL);
+ break;
+ case RDPDR_DTYP_SMARTCARD:
+ size = sizeof(RDPDR_SMARTCARD);
+ break;
+ case RDPDR_DTYP_FILESYSTEM:
+ size = sizeof(RDPDR_DRIVE);
+ break;
+ default:
+ goto fail;
+ }
+
+ device.base = calloc(1, size);
+ if (!device.base)
+ goto fail;
+ device.base->Id = 0;
+ device.base->Type = Type;
+
+ if (count > 0)
+ {
+ device.base->Name = _strdup(args[0]);
+ if (!device.base->Name)
+ goto fail;
+
+ switch (Type)
+ {
+ case RDPDR_DTYP_PRINT:
+ if (count > 1)
+ {
+ device.printer->DriverName = _strdup(args[1]);
+ if (!device.printer->DriverName)
+ goto fail;
+ }
+
+ if (count > 2)
+ {
+ device.printer->IsDefault = _stricmp(args[2], "default") == 0;
+ }
+ break;
+ case RDPDR_DTYP_SERIAL:
+ if (count > 1)
+ {
+ device.serial->Path = _strdup(args[1]);
+ if (!device.serial->Path)
+ goto fail;
+ }
+
+ if (count > 2)
+ {
+ device.serial->Driver = _strdup(args[2]);
+ if (!device.serial->Driver)
+ goto fail;
+ }
+
+ if (count > 3)
+ {
+ device.serial->Permissive = _strdup(args[3]);
+ if (!device.serial->Permissive)
+ goto fail;
+ }
+ break;
+ case RDPDR_DTYP_PARALLEL:
+ if (count > 1)
+ {
+ device.parallel->Path = _strdup(args[1]);
+ if (!device.serial->Path)
+ goto fail;
+ }
+ break;
+ case RDPDR_DTYP_SMARTCARD:
+ break;
+ case RDPDR_DTYP_FILESYSTEM:
+ if (count > 1)
+ {
+ device.drive->Path = _strdup(args[1]);
+ if (!device.drive->Path)
+ goto fail;
+ }
+ if (count > 2)
+ device.drive->automount = (args[2] == NULL) ? TRUE : FALSE;
+ break;
+ default:
+ goto fail;
+ }
+ }
+ return device.base;
+
+fail:
+ freerdp_device_free(device.base);
+ return NULL;
+}
+
+void freerdp_device_free(RDPDR_DEVICE* device)
+{
+ union
+ {
+ RDPDR_DEVICE* dev;
+ RDPDR_DRIVE* drive;
+ RDPDR_SERIAL* serial;
+ RDPDR_PRINTER* printer;
+ RDPDR_PARALLEL* parallel;
+ RDPDR_SMARTCARD* smartcard;
+ } cnv;
+
+ cnv.dev = device;
+ if (!cnv.dev)
+ return;
+
+ switch (device->Type)
+ {
+ case RDPDR_DTYP_PRINT:
+ free(cnv.printer->DriverName);
+ break;
+ case RDPDR_DTYP_SERIAL:
+ free(cnv.serial->Path);
+ free(cnv.serial->Driver);
+ free(cnv.serial->Permissive);
+ break;
+ case RDPDR_DTYP_PARALLEL:
+ free(cnv.parallel->Path);
+ break;
+ case RDPDR_DTYP_SMARTCARD:
+ break;
+ case RDPDR_DTYP_FILESYSTEM:
+ free(cnv.drive->Path);
+ break;
+ default:
+ break;
+ }
+ free(cnv.dev->Name);
+ free(cnv.dev);
+}
+
+RDPDR_DEVICE* freerdp_device_clone(const RDPDR_DEVICE* device)
+{
+ union
+ {
+ const RDPDR_DEVICE* dev;
+ const RDPDR_DRIVE* drive;
+ const RDPDR_SERIAL* serial;
+ const RDPDR_PRINTER* printer;
+ const RDPDR_PARALLEL* parallel;
+ const RDPDR_SMARTCARD* smartcard;
+ } src;
+
+ union
+ {
+ RDPDR_DEVICE* dev;
+ RDPDR_DRIVE* drive;
+ RDPDR_SERIAL* serial;
+ RDPDR_PRINTER* printer;
+ RDPDR_PARALLEL* parallel;
+ RDPDR_SMARTCARD* smartcard;
+ } copy;
+ size_t count = 0;
+ const char* args[4] = { 0 };
+
+ copy.dev = NULL;
+ src.dev = device;
+
+ if (!device)
+ return NULL;
+
+ if (device->Name)
+ {
+ count = 1;
+ args[0] = device->Name;
+ }
+
+ switch (device->Type)
+ {
+ case RDPDR_DTYP_FILESYSTEM:
+ if (src.drive->Path)
+ {
+ args[1] = src.drive->Path;
+ count = 2;
+ }
+ break;
+
+ case RDPDR_DTYP_PRINT:
+ if (src.printer->DriverName)
+ {
+ args[1] = src.printer->DriverName;
+ count = 2;
+ }
+ break;
+
+ case RDPDR_DTYP_SMARTCARD:
+ break;
+
+ case RDPDR_DTYP_SERIAL:
+ if (src.serial->Path)
+ {
+ args[1] = src.serial->Path;
+ count = 2;
+ }
+
+ if (src.serial->Driver)
+ {
+ args[2] = src.serial->Driver;
+ count = 3;
+ }
+
+ if (src.serial->Permissive)
+ {
+ args[3] = src.serial->Permissive;
+ count = 4;
+ }
+ break;
+
+ case RDPDR_DTYP_PARALLEL:
+ if (src.parallel->Path)
+ {
+ args[1] = src.parallel->Path;
+ count = 2;
+ }
+ break;
+ default:
+ WLog_ERR(TAG, "unknown device type %" PRIu32 "", device->Type);
+ break;
+ }
+
+ copy.dev = freerdp_device_new(device->Type, count, args);
+ if (!copy.dev)
+ return NULL;
+
+ copy.dev->Id = device->Id;
+
+ return copy.dev;
+}
+
+void freerdp_device_collection_free(rdpSettings* settings)
+{
+ WINPR_ASSERT(settings);
+
+ if (settings->DeviceArray)
+ {
+ for (UINT32 index = 0; index < settings->DeviceArraySize; index++)
+ freerdp_settings_set_pointer_array(settings, FreeRDP_DeviceArray, index, NULL);
+ }
+
+ free(settings->DeviceArray);
+
+ freerdp_settings_set_pointer(settings, FreeRDP_DeviceArray, NULL);
+ freerdp_settings_set_uint32(settings, FreeRDP_DeviceArraySize, 0);
+ freerdp_settings_set_uint32(settings, FreeRDP_DeviceCount, 0);
+}
+
+BOOL freerdp_static_channel_collection_del(rdpSettings* settings, const char* name)
+{
+ const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
+ if (!settings || !settings->StaticChannelArray)
+ return FALSE;
+
+ for (UINT32 x = 0; x < count; x++)
+ {
+ ADDIN_ARGV* cur = settings->StaticChannelArray[x];
+ if (cur && (cur->argc > 0))
+ {
+ if (strcmp(name, cur->argv[0]) == 0)
+ {
+ const size_t rem = settings->StaticChannelArraySize - count + 1;
+ memmove_s(&settings->StaticChannelArray[x], (count - x) * sizeof(ADDIN_ARGV*),
+ &settings->StaticChannelArray[x + 1],
+ (count - x - 1) * sizeof(ADDIN_ARGV*));
+ memset(&settings->StaticChannelArray[count - 1], 0, sizeof(ADDIN_ARGV*) * rem);
+
+ freerdp_addin_argv_free(cur);
+ return freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelCount, count - 1);
+ }
+ }
+ }
+ {
+ const size_t rem = settings->StaticChannelArraySize - count;
+ memset(&settings->StaticChannelArray[count], 0, sizeof(ADDIN_ARGV*) * rem);
+ }
+ return FALSE;
+}
+
+BOOL freerdp_static_channel_collection_add(rdpSettings* settings, ADDIN_ARGV* channel)
+{
+ UINT32 count = 0;
+
+ WINPR_ASSERT(settings);
+ WINPR_ASSERT(channel);
+
+ count = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount) + 1;
+ if (freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize) < count)
+ {
+ const UINT32 oldSize =
+ freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
+ UINT32 new_size = oldSize * 2ul;
+ ADDIN_ARGV** new_array = NULL;
+ if (new_size == 0)
+ new_size = count * 2ul;
+
+ new_array =
+ (ADDIN_ARGV**)realloc(settings->StaticChannelArray, new_size * sizeof(ADDIN_ARGV*));
+
+ if (!new_array)
+ return FALSE;
+
+ settings->StaticChannelArray = new_array;
+ {
+ const size_t rem = new_size - oldSize;
+ memset(&settings->StaticChannelArray[oldSize], 0, sizeof(ADDIN_ARGV*) * rem);
+ }
+ if (!freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelArraySize, new_size))
+ return FALSE;
+ }
+
+ count = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount);
+
+ ADDIN_ARGV** cur = &settings->StaticChannelArray[count++];
+ freerdp_addin_argv_free(*cur);
+ *cur = channel;
+ return freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelCount, count);
+}
+
+ADDIN_ARGV* freerdp_static_channel_collection_find(rdpSettings* settings, const char* name)
+{
+ ADDIN_ARGV* channel = NULL;
+
+ WINPR_ASSERT(settings);
+ WINPR_ASSERT(name);
+
+ for (UINT32 index = 0;
+ index < freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelCount); index++)
+ {
+ channel = settings->StaticChannelArray[index];
+
+ if (strcmp(channel->argv[0], name) == 0)
+ return channel;
+ }
+
+ return NULL;
+}
+
+void freerdp_static_channel_collection_free(rdpSettings* settings)
+{
+ if (!settings)
+ return;
+
+ if (settings->StaticChannelArray)
+ {
+ for (UINT32 i = 0;
+ i < freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize); i++)
+ freerdp_addin_argv_free(settings->StaticChannelArray[i]);
+ }
+
+ free(settings->StaticChannelArray);
+ freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelArraySize, 0);
+ settings->StaticChannelArray = NULL;
+ freerdp_settings_set_uint32(settings, FreeRDP_StaticChannelCount, 0);
+}
+
+BOOL freerdp_dynamic_channel_collection_del(rdpSettings* settings, const char* name)
+{
+ const UINT32 count = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
+ if (!settings || !settings->DynamicChannelArray)
+ return FALSE;
+
+ for (UINT32 x = 0; x < count; x++)
+ {
+ ADDIN_ARGV* cur = settings->DynamicChannelArray[x];
+ if (cur && (cur->argc > 0))
+ {
+ if (strcmp(name, cur->argv[0]) == 0)
+ {
+ const size_t rem = settings->DynamicChannelArraySize - count + 1;
+ memmove_s(&settings->DynamicChannelArray[x], (count - x) * sizeof(ADDIN_ARGV*),
+ &settings->DynamicChannelArray[x + 1],
+ (count - x - 1) * sizeof(ADDIN_ARGV*));
+ memset(&settings->DynamicChannelArray[count - 1], 0, sizeof(ADDIN_ARGV*) * rem);
+
+ freerdp_addin_argv_free(cur);
+ return freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelCount,
+ count - 1);
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+BOOL freerdp_dynamic_channel_collection_add(rdpSettings* settings, ADDIN_ARGV* channel)
+{
+ UINT32 count = 0;
+ UINT32 oldSize = 0;
+
+ WINPR_ASSERT(settings);
+ WINPR_ASSERT(channel);
+
+ count = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount) + 1;
+ oldSize = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
+ if (oldSize < count)
+ {
+ ADDIN_ARGV** new_array = NULL;
+ UINT32 size = oldSize * 2;
+ if (size == 0)
+ size = count * 2;
+
+ new_array = realloc(settings->DynamicChannelArray, sizeof(ADDIN_ARGV*) * size);
+
+ if (!new_array)
+ return FALSE;
+
+ settings->DynamicChannelArray = new_array;
+ {
+ const size_t rem = size - oldSize;
+ memset(&settings->DynamicChannelArray[oldSize], 0, sizeof(ADDIN_ARGV*) * rem);
+ }
+ if (!freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelArraySize, size))
+ return FALSE;
+ }
+
+ count = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount);
+ settings->DynamicChannelArray[count++] = channel;
+ return freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelCount, count);
+}
+
+ADDIN_ARGV* freerdp_dynamic_channel_collection_find(const rdpSettings* settings, const char* name)
+{
+ WINPR_ASSERT(settings);
+ WINPR_ASSERT(name);
+
+ for (UINT32 index = 0;
+ index < freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelCount); index++)
+ {
+ ADDIN_ARGV* channel = settings->DynamicChannelArray[index];
+
+ if (strcmp(channel->argv[0], name) == 0)
+ return channel;
+ }
+
+ return NULL;
+}
+
+void freerdp_addin_argv_free(ADDIN_ARGV* args)
+{
+ if (!args)
+ return;
+
+ if (args->argv)
+ {
+ for (int index = 0; index < args->argc; index++)
+ free(args->argv[index]);
+ free(args->argv);
+ }
+
+ free(args);
+}
+
+ADDIN_ARGV* freerdp_addin_argv_new(size_t argc, const char* argv[])
+{
+ ADDIN_ARGV* args = calloc(1, sizeof(ADDIN_ARGV));
+ if (!args)
+ return NULL;
+ if (argc == 0)
+ return args;
+
+ args->argc = argc;
+ args->argv = calloc(argc, sizeof(char*));
+ if (!args->argv)
+ goto fail;
+
+ if (argv)
+ {
+ for (size_t x = 0; x < argc; x++)
+ {
+ args->argv[x] = _strdup(argv[x]);
+ if (!args->argv[x])
+ goto fail;
+ }
+ }
+ return args;
+
+fail:
+ freerdp_addin_argv_free(args);
+ return NULL;
+}
+
+ADDIN_ARGV* freerdp_addin_argv_clone(const ADDIN_ARGV* args)
+{
+ union
+ {
+ char** c;
+ const char** cc;
+ } cnv;
+ if (!args)
+ return NULL;
+ cnv.c = args->argv;
+ return freerdp_addin_argv_new(args->argc, cnv.cc);
+}
+
+void freerdp_dynamic_channel_collection_free(rdpSettings* settings)
+{
+ WINPR_ASSERT(settings);
+
+ if (settings->DynamicChannelArray)
+ {
+ for (UINT32 i = 0;
+ i < freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize); i++)
+ freerdp_addin_argv_free(settings->DynamicChannelArray[i]);
+ }
+
+ free(settings->DynamicChannelArray);
+ freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelArraySize, 0);
+ settings->DynamicChannelArray = NULL;
+ freerdp_settings_set_uint32(settings, FreeRDP_DynamicChannelCount, 0);
+}
+
+void freerdp_capability_buffer_free(rdpSettings* settings)
+{
+ WINPR_ASSERT(settings);
+
+ if (settings->ReceivedCapabilityData)
+ {
+ for (UINT32 x = 0; x < settings->ReceivedCapabilitiesSize; x++)
+ {
+ free(settings->ReceivedCapabilityData[x]);
+ settings->ReceivedCapabilityData[x] = NULL;
+ }
+ }
+ settings->ReceivedCapabilitiesSize = 0;
+
+ free(settings->ReceivedCapabilityDataSizes);
+ settings->ReceivedCapabilityDataSizes = NULL;
+
+ free(settings->ReceivedCapabilityData);
+ settings->ReceivedCapabilityData = NULL;
+ free(settings->ReceivedCapabilities);
+ settings->ReceivedCapabilities = NULL;
+}
+
+BOOL freerdp_capability_buffer_copy(rdpSettings* settings, const rdpSettings* src)
+{
+ WINPR_ASSERT(settings);
+ WINPR_ASSERT(src);
+
+ if (!freerdp_capability_buffer_allocate(settings, src->ReceivedCapabilitiesSize))
+ return FALSE;
+
+ for (UINT32 x = 0; x < src->ReceivedCapabilitiesSize; x++)
+ {
+ WINPR_ASSERT(settings->ReceivedCapabilities);
+ settings->ReceivedCapabilities[x] = src->ReceivedCapabilities[x];
+
+ WINPR_ASSERT(settings->ReceivedCapabilityDataSizes);
+ settings->ReceivedCapabilityDataSizes[x] = src->ReceivedCapabilityDataSizes[x];
+
+ WINPR_ASSERT(settings->ReceivedCapabilityData);
+ if (src->ReceivedCapabilityDataSizes[x] > 0)
+ {
+ void* tmp = realloc(settings->ReceivedCapabilityData[x],
+ settings->ReceivedCapabilityDataSizes[x]);
+ if (!tmp)
+ return FALSE;
+ memcpy(tmp, src->ReceivedCapabilityData[x], src->ReceivedCapabilityDataSizes[x]);
+ settings->ReceivedCapabilityData[x] = tmp;
+ }
+ else
+ {
+ free(settings->ReceivedCapabilityData[x]);
+ settings->ReceivedCapabilityData[x] = NULL;
+ }
+ }
+ return TRUE;
+}
+
+void freerdp_target_net_addresses_free(rdpSettings* settings)
+{
+ WINPR_ASSERT(settings);
+
+ if (settings->TargetNetAddresses)
+ {
+ for (UINT32 index = 0; index < settings->TargetNetAddressCount; index++)
+ free(settings->TargetNetAddresses[index]);
+ }
+
+ free(settings->TargetNetAddresses);
+ free(settings->TargetNetPorts);
+ settings->TargetNetAddressCount = 0;
+ settings->TargetNetAddresses = NULL;
+ settings->TargetNetPorts = NULL;
+}
+
+void freerdp_server_license_issuers_free(rdpSettings* settings)
+{
+ WINPR_ASSERT(settings);
+
+ if (settings->ServerLicenseProductIssuers)
+ {
+ for (UINT32 x = 0; x < settings->ServerLicenseProductIssuersCount; x++)
+ free(settings->ServerLicenseProductIssuers[x]);
+ }
+ free(settings->ServerLicenseProductIssuers);
+ settings->ServerLicenseProductIssuers = NULL;
+ settings->ServerLicenseProductIssuersCount = 0;
+}
+
+BOOL freerdp_server_license_issuers_copy(rdpSettings* settings, char** issuers, UINT32 count)
+{
+ WINPR_ASSERT(settings);
+ WINPR_ASSERT(issuers || (count == 0));
+
+ if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ServerLicenseProductIssuers, NULL,
+ count))
+ return FALSE;
+
+ for (UINT32 x = 0; x < count; x++)
+ {
+ char* issuer = _strdup(issuers[x]);
+ if (!issuer)
+ return FALSE;
+ settings->ServerLicenseProductIssuers[x] = issuer;
+ }
+
+ return TRUE;
+}
+
+void freerdp_performance_flags_make(rdpSettings* settings)
+{
+ UINT32 PerformanceFlags = PERF_FLAG_NONE;
+
+ if (freerdp_settings_get_bool(settings, FreeRDP_AllowFontSmoothing))
+ PerformanceFlags |= PERF_ENABLE_FONT_SMOOTHING;
+
+ if (freerdp_settings_get_bool(settings, FreeRDP_AllowDesktopComposition))
+ PerformanceFlags |= PERF_ENABLE_DESKTOP_COMPOSITION;
+
+ if (freerdp_settings_get_bool(settings, FreeRDP_DisableWallpaper))
+ PerformanceFlags |= PERF_DISABLE_WALLPAPER;
+
+ if (freerdp_settings_get_bool(settings, FreeRDP_DisableFullWindowDrag))
+ PerformanceFlags |= PERF_DISABLE_FULLWINDOWDRAG;
+
+ if (freerdp_settings_get_bool(settings, FreeRDP_DisableMenuAnims))
+ PerformanceFlags |= PERF_DISABLE_MENUANIMATIONS;
+
+ if (freerdp_settings_get_bool(settings, FreeRDP_DisableThemes))
+ PerformanceFlags |= PERF_DISABLE_THEMING;
+ freerdp_settings_set_uint32(settings, FreeRDP_PerformanceFlags, PerformanceFlags);
+}
+
+void freerdp_performance_flags_split(rdpSettings* settings)
+{
+ freerdp_settings_set_bool(settings, FreeRDP_AllowFontSmoothing,
+ (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) &
+ PERF_ENABLE_FONT_SMOOTHING)
+ ? TRUE
+ : FALSE);
+ freerdp_settings_set_bool(settings, FreeRDP_AllowDesktopComposition,
+ (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) &
+ PERF_ENABLE_DESKTOP_COMPOSITION)
+ ? TRUE
+ : FALSE);
+ freerdp_settings_set_bool(
+ settings, FreeRDP_DisableWallpaper,
+ (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) & PERF_DISABLE_WALLPAPER)
+ ? TRUE
+ : FALSE);
+ freerdp_settings_set_bool(settings, FreeRDP_DisableFullWindowDrag,
+ (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) &
+ PERF_DISABLE_FULLWINDOWDRAG)
+ ? TRUE
+ : FALSE);
+ freerdp_settings_set_bool(settings, FreeRDP_DisableMenuAnims,
+ (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) &
+ PERF_DISABLE_MENUANIMATIONS)
+ ? TRUE
+ : FALSE);
+ freerdp_settings_set_bool(
+ settings, FreeRDP_DisableThemes,
+ (freerdp_settings_get_uint32(settings, FreeRDP_PerformanceFlags) & PERF_DISABLE_THEMING)
+ ? TRUE
+ : FALSE);
+}
+
+BOOL freerdp_set_gateway_usage_method(rdpSettings* settings, UINT32 GatewayUsageMethod)
+{
+ if (!freerdp_settings_set_uint32(settings, FreeRDP_GatewayUsageMethod, GatewayUsageMethod))
+ return FALSE;
+
+ if (GatewayUsageMethod == TSC_PROXY_MODE_NONE_DIRECT)
+ {
+ if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, FALSE) ||
+ !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE))
+ return FALSE;
+ }
+ else if (GatewayUsageMethod == TSC_PROXY_MODE_DIRECT)
+ {
+ if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, TRUE) ||
+ !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE))
+ return FALSE;
+ }
+ else if (GatewayUsageMethod == TSC_PROXY_MODE_DETECT)
+ {
+ if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, TRUE) ||
+ !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, TRUE))
+ return FALSE;
+ }
+ else if (GatewayUsageMethod == TSC_PROXY_MODE_DEFAULT)
+ {
+ /**
+ * This corresponds to "Automatically detect RD Gateway server settings",
+ * which means the client attempts to use gateway group policy settings
+ * http://technet.microsoft.com/en-us/library/cc770601.aspx
+ */
+ if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, FALSE) ||
+ !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE))
+ return FALSE;
+ }
+ else if (GatewayUsageMethod == TSC_PROXY_MODE_NONE_DETECT)
+ {
+ if (!freerdp_settings_set_bool(settings, FreeRDP_GatewayEnabled, FALSE) ||
+ !freerdp_settings_set_bool(settings, FreeRDP_GatewayBypassLocal, FALSE))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void freerdp_update_gateway_usage_method(rdpSettings* settings, UINT32 GatewayEnabled,
+ UINT32 GatewayBypassLocal)
+{
+ UINT32 GatewayUsageMethod = 0;
+
+ if (!GatewayEnabled && !GatewayBypassLocal)
+ GatewayUsageMethod = TSC_PROXY_MODE_NONE_DIRECT;
+ else if (GatewayEnabled && !GatewayBypassLocal)
+ GatewayUsageMethod = TSC_PROXY_MODE_DIRECT;
+ else if (GatewayEnabled && GatewayBypassLocal)
+ GatewayUsageMethod = TSC_PROXY_MODE_DETECT;
+
+ freerdp_set_gateway_usage_method(settings, GatewayUsageMethod);
+}
+
+#if defined(WITH_FREERDP_DEPRECATED)
+BOOL freerdp_get_param_bool(const rdpSettings* settings, int id)
+{
+ return freerdp_settings_get_bool(settings, (FreeRDP_Settings_Keys_Bool)id);
+}
+
+int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param)
+{
+ return freerdp_settings_set_bool(settings, (FreeRDP_Settings_Keys_Bool)id, param) ? 0 : -1;
+}
+
+int freerdp_get_param_int(const rdpSettings* settings, int id)
+{
+ return freerdp_settings_get_int32(settings, (FreeRDP_Settings_Keys_Int32)id);
+}
+
+int freerdp_set_param_int(rdpSettings* settings, int id, int param)
+{
+ return freerdp_settings_set_int32(settings, (FreeRDP_Settings_Keys_Int32)id, param) ? 0 : -1;
+}
+
+UINT32 freerdp_get_param_uint32(const rdpSettings* settings, int id)
+{
+ return freerdp_settings_get_uint32(settings, (FreeRDP_Settings_Keys_UInt32)id);
+}
+
+int freerdp_set_param_uint32(rdpSettings* settings, int id, UINT32 param)
+{
+ return freerdp_settings_set_uint32(settings, (FreeRDP_Settings_Keys_UInt32)id, param) ? 0 : -1;
+}
+
+UINT64 freerdp_get_param_uint64(const rdpSettings* settings, int id)
+{
+ return freerdp_settings_get_uint64(settings, (FreeRDP_Settings_Keys_UInt64)id);
+}
+
+int freerdp_set_param_uint64(rdpSettings* settings, int id, UINT64 param)
+{
+ return freerdp_settings_set_uint64(settings, (FreeRDP_Settings_Keys_UInt64)id, param) ? 0 : -1;
+}
+
+char* freerdp_get_param_string(const rdpSettings* settings, int id)
+{
+ return (char*)freerdp_settings_get_string(settings, (FreeRDP_Settings_Keys_String)id);
+}
+
+int freerdp_set_param_string(rdpSettings* settings, int id, const char* param)
+{
+ return freerdp_settings_set_string(settings, (FreeRDP_Settings_Keys_String)id, param) ? 0 : -1;
+}
+#endif
+
+static BOOL value_to_uint(const char* value, ULONGLONG* result, ULONGLONG min, ULONGLONG max)
+{
+ char* endptr = NULL;
+ unsigned long long rc = 0;
+
+ if (!value || !result)
+ return FALSE;
+
+ errno = 0;
+ rc = _strtoui64(value, &endptr, 0);
+
+ if (errno != 0)
+ return FALSE;
+
+ if (endptr == value)
+ return FALSE;
+
+ if ((rc < min) || (rc > max))
+ return FALSE;
+
+ *result = rc;
+ return TRUE;
+}
+
+static BOOL value_to_int(const char* value, LONGLONG* result, LONGLONG min, LONGLONG max)
+{
+ char* endptr = NULL;
+ long long rc = 0;
+
+ if (!value || !result)
+ return FALSE;
+
+ errno = 0;
+ rc = _strtoi64(value, &endptr, 0);
+
+ if (errno != 0)
+ return FALSE;
+
+ if (endptr == value)
+ return FALSE;
+
+ if ((rc < min) || (rc > max))
+ return FALSE;
+
+ *result = rc;
+ return TRUE;
+}
+
+static BOOL parsing_fail(const char* key, const char* type, const char* value)
+{
+ WLog_ERR(TAG, "Failed to parse key [%s] of type [%s]: value [%s]", key, type, value);
+ return FALSE;
+}
+
+BOOL freerdp_settings_set_value_for_name(rdpSettings* settings, const char* name, const char* value)
+{
+ ULONGLONG uval = 0;
+ LONGLONG ival = 0;
+ SSIZE_T type = 0;
+
+ if (!settings || !name)
+ return FALSE;
+
+ const SSIZE_T i = freerdp_settings_get_key_for_name(name);
+ if (i < 0)
+ {
+ WLog_ERR(TAG, "Invalid settings key [%s]", name);
+ return FALSE;
+ }
+
+ const SSIZE_T index = i;
+
+ type = freerdp_settings_get_type_for_key(index);
+ switch (type)
+ {
+
+ case RDP_SETTINGS_TYPE_BOOL:
+ {
+ BOOL val = _strnicmp(value, "TRUE", 5) == 0;
+ if (!val && _strnicmp(value, "FALSE", 6) != 0)
+ return parsing_fail(name, "BOOL", value);
+ return freerdp_settings_set_bool(settings, (FreeRDP_Settings_Keys_Bool)index, val);
+ }
+ case RDP_SETTINGS_TYPE_UINT16:
+ if (!value_to_uint(value, &uval, 0, UINT16_MAX))
+ return parsing_fail(name, "UINT16", value);
+ if (!freerdp_settings_set_uint16(settings, (FreeRDP_Settings_Keys_UInt16)index, uval))
+ return parsing_fail(name, "UINT16", value);
+ return TRUE;
+
+ case RDP_SETTINGS_TYPE_INT16:
+ if (!value_to_int(value, &ival, INT16_MIN, INT16_MAX))
+ return parsing_fail(name, "INT16", value);
+ if (!freerdp_settings_set_int16(settings, (FreeRDP_Settings_Keys_Int16)index, ival))
+ return parsing_fail(name, "INT16", value);
+ return TRUE;
+ case RDP_SETTINGS_TYPE_UINT32:
+ if (!value_to_uint(value, &uval, 0, UINT32_MAX))
+ return parsing_fail(name, "UINT32", value);
+ if (!freerdp_settings_set_uint32(settings, (FreeRDP_Settings_Keys_UInt32)index, uval))
+ return parsing_fail(name, "UINT32", value);
+ return TRUE;
+ case RDP_SETTINGS_TYPE_INT32:
+ if (!value_to_int(value, &ival, INT32_MIN, INT32_MAX))
+ return parsing_fail(name, "INT32", value);
+ if (!freerdp_settings_set_int32(settings, (FreeRDP_Settings_Keys_Int32)index, ival))
+ return parsing_fail(name, "INT32", value);
+ return TRUE;
+ case RDP_SETTINGS_TYPE_UINT64:
+ if (!value_to_uint(value, &uval, 0, UINT64_MAX))
+ return parsing_fail(name, "UINT64", value);
+ if (!freerdp_settings_set_uint64(settings, (FreeRDP_Settings_Keys_UInt64)index, uval))
+ return parsing_fail(name, "UINT64", value);
+ return TRUE;
+ case RDP_SETTINGS_TYPE_INT64:
+ if (!value_to_int(value, &ival, INT64_MIN, INT64_MAX))
+ return parsing_fail(name, "INT64", value);
+ if (!freerdp_settings_set_int64(settings, (FreeRDP_Settings_Keys_Int64)index, ival))
+ return parsing_fail(name, "INT64", value);
+ return TRUE;
+
+ case RDP_SETTINGS_TYPE_STRING:
+ return freerdp_settings_set_string(settings, (FreeRDP_Settings_Keys_String)index,
+ value);
+ case RDP_SETTINGS_TYPE_POINTER:
+ return parsing_fail(name, "POINTER", value);
+ default:
+ return FALSE;
+ }
+ return FALSE;
+}
+
+BOOL freerdp_settings_set_pointer_len_(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
+ SSIZE_T lenId, const void* data, size_t len, size_t size)
+{
+ BOOL rc = FALSE;
+ void* copy = NULL;
+ void* old = freerdp_settings_get_pointer_writable(settings, id);
+ free(old);
+ if (!freerdp_settings_set_pointer(settings, id, NULL))
+ return FALSE;
+ if (lenId >= 0)
+ {
+ if (!freerdp_settings_set_uint32(settings, (FreeRDP_Settings_Keys_UInt32)lenId, 0))
+ return FALSE;
+ }
+
+ if (len == 0)
+ return TRUE;
+ copy = calloc(len, size);
+ if (!copy)
+ return FALSE;
+ if (data)
+ memcpy(copy, data, len * size);
+ rc = freerdp_settings_set_pointer(settings, id, copy);
+ if (!rc)
+ {
+ free(copy);
+ return FALSE;
+ }
+
+ // freerdp_settings_set_pointer takes ownership of copy
+ // NOLINTNEXTLINE(clang-analyzer-unix.Malloc)
+ if (lenId < 0)
+ return TRUE;
+ return freerdp_settings_set_uint32(settings, (FreeRDP_Settings_Keys_UInt32)lenId, len);
+}
+
+const void* freerdp_settings_get_pointer(const rdpSettings* settings,
+ FreeRDP_Settings_Keys_Pointer id)
+{
+ union
+ {
+ const rdpSettings* pc;
+ rdpSettings* p;
+ } cnv;
+ cnv.pc = settings;
+ return freerdp_settings_get_pointer_writable(cnv.p, id);
+}
+
+BOOL freerdp_settings_set_pointer_len(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
+ const void* data, size_t len)
+{
+ union
+ {
+ const void* cv;
+ void* v;
+ } cnv;
+
+ cnv.cv = data;
+ if (!settings)
+ return FALSE;
+
+ switch (id)
+ {
+ case FreeRDP_RdpServerCertificate:
+ freerdp_certificate_free(settings->RdpServerCertificate);
+
+ if (len > 1)
+ {
+ WLog_ERR(TAG, "FreeRDP_RdpServerCertificate::len must be 0 or 1");
+ return FALSE;
+ }
+ settings->RdpServerCertificate = cnv.v;
+ if (!settings->RdpServerCertificate && (len > 0))
+ {
+ settings->RdpServerCertificate = freerdp_certificate_new();
+ if (!settings->RdpServerCertificate)
+ return FALSE;
+ }
+ return TRUE;
+ case FreeRDP_RdpServerRsaKey:
+ freerdp_key_free(settings->RdpServerRsaKey);
+ if (len > 1)
+ {
+ WLog_ERR(TAG, "FreeRDP_RdpServerRsaKey::len must be 0 or 1");
+ return FALSE;
+ }
+ settings->RdpServerRsaKey = (rdpPrivateKey*)cnv.v;
+ if (!settings->RdpServerRsaKey && (len > 0))
+ {
+ settings->RdpServerRsaKey = freerdp_key_new();
+ if (!settings->RdpServerRsaKey)
+ return FALSE;
+ }
+ return TRUE;
+ case FreeRDP_RedirectionPassword:
+ return freerdp_settings_set_pointer_len_(
+ settings, id, FreeRDP_RedirectionPasswordLength, data, len, sizeof(char));
+ case FreeRDP_RedirectionTsvUrl:
+ return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_RedirectionTsvUrlLength,
+ data, len, sizeof(char));
+ case FreeRDP_RedirectionTargetCertificate:
+ freerdp_certificate_free(settings->RedirectionTargetCertificate);
+
+ if (len > 1)
+ {
+ WLog_ERR(TAG, "FreeRDP_RedirectionTargetCertificate::len must be 0 or 1");
+ return FALSE;
+ }
+ settings->RedirectionTargetCertificate = cnv.v;
+ if (!settings->RedirectionTargetCertificate && (len > 0))
+ {
+ settings->RedirectionTargetCertificate = freerdp_certificate_new();
+ if (!settings->RedirectionTargetCertificate)
+ return FALSE;
+ }
+ return TRUE;
+ case FreeRDP_RedirectionGuid:
+ return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_RedirectionGuidLength,
+ data, len, sizeof(BYTE));
+ case FreeRDP_LoadBalanceInfo:
+ return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_LoadBalanceInfoLength,
+ data, len, sizeof(char));
+ case FreeRDP_ServerRandom:
+ return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ServerRandomLength, data,
+ len, sizeof(char));
+ case FreeRDP_ClientRandom:
+ return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ClientRandomLength, data,
+ len, sizeof(char));
+ case FreeRDP_ServerCertificate:
+ return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ServerCertificateLength,
+ data, len, sizeof(char));
+ case FreeRDP_TargetNetAddresses:
+ if ((data == NULL) && (len == 0))
+ {
+ freerdp_target_net_addresses_free(settings);
+ return TRUE;
+ }
+ WLog_WARN(
+ TAG,
+ "[BUG] FreeRDP_TargetNetAddresses must not be resized from outside the library!");
+ return FALSE;
+ case FreeRDP_ServerLicenseProductIssuers:
+ if (data == NULL)
+ freerdp_server_license_issuers_free(settings);
+ return freerdp_settings_set_pointer_len_(settings, FreeRDP_ServerLicenseProductIssuers,
+ FreeRDP_ServerLicenseProductIssuersCount, data,
+ len, sizeof(char*));
+ case FreeRDP_TargetNetPorts:
+ if ((data == NULL) && (len == 0))
+ {
+ freerdp_target_net_addresses_free(settings);
+ return TRUE;
+ }
+ WLog_WARN(TAG,
+ "[BUG] FreeRDP_TargetNetPorts must not be resized from outside the library!");
+ return FALSE;
+ case FreeRDP_DeviceArray:
+ if (data == NULL)
+ freerdp_device_collection_free(settings);
+ return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_DeviceArraySize, data,
+ len, sizeof(ADDIN_ARGV*));
+ case FreeRDP_ChannelDefArray:
+ if ((len > 0) && (len < CHANNEL_MAX_COUNT))
+ WLog_WARN(TAG,
+ "FreeRDP_ChannelDefArray::len expected to be >= %" PRIu32
+ ", but have %" PRIu32,
+ CHANNEL_MAX_COUNT, len);
+ return freerdp_settings_set_pointer_len_(settings, FreeRDP_ChannelDefArray,
+ FreeRDP_ChannelDefArraySize, data, len,
+ sizeof(CHANNEL_DEF));
+ case FreeRDP_MonitorDefArray:
+ return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_MonitorDefArraySize,
+ data, len, sizeof(rdpMonitor));
+ case FreeRDP_ClientAutoReconnectCookie:
+ return freerdp_settings_set_pointer_len_(settings, id, -1, data, len,
+ sizeof(ARC_CS_PRIVATE_PACKET));
+ case FreeRDP_ServerAutoReconnectCookie:
+ return freerdp_settings_set_pointer_len_(settings, id, -1, data, len,
+ sizeof(ARC_SC_PRIVATE_PACKET));
+ case FreeRDP_ClientTimeZone:
+ if (len > 1)
+ {
+ WLog_ERR(TAG, "FreeRDP_ClientTimeZone::len must be 0 or 1");
+ return FALSE;
+ }
+ return freerdp_settings_set_pointer_len_(settings, id, -1, data, len,
+ sizeof(TIME_ZONE_INFORMATION));
+ case FreeRDP_BitmapCacheV2CellInfo:
+ return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_BitmapCacheV2NumCells,
+ data, len, sizeof(BITMAP_CACHE_V2_CELL_INFO));
+ case FreeRDP_GlyphCache:
+ if ((len != 0) && (len != 10))
+ {
+ WLog_ERR(TAG, "FreeRDP_GlyphCache::len must be 0 or 10");
+ return FALSE;
+ }
+ return freerdp_settings_set_pointer_len_(settings, id, -1, data, len,
+ sizeof(GLYPH_CACHE_DEFINITION));
+ case FreeRDP_FragCache:
+ if (len > 1)
+ {
+ WLog_ERR(TAG, "FreeRDP_FragCache::len must be 0 or 1");
+ return FALSE;
+ }
+ return freerdp_settings_set_pointer_len_(settings, id, -1, data, len,
+ sizeof(GLYPH_CACHE_DEFINITION));
+ case FreeRDP_StaticChannelArray:
+ if (data == NULL)
+ freerdp_static_channel_collection_free(settings);
+ return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_StaticChannelArraySize,
+ data, len, sizeof(ADDIN_ARGV*));
+ case FreeRDP_DynamicChannelArray:
+ if (data == NULL)
+ freerdp_dynamic_channel_collection_free(settings);
+ return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_DynamicChannelArraySize,
+ data, len, sizeof(ADDIN_ARGV*));
+ case FreeRDP_ReceivedCapabilityData:
+ if (data == NULL)
+ freerdp_capability_buffer_free(settings);
+ return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ReceivedCapabilitiesSize,
+ data, len, sizeof(BYTE*));
+ case FreeRDP_ReceivedCapabilities:
+ if (data == NULL)
+ freerdp_capability_buffer_free(settings);
+ return freerdp_settings_set_pointer_len_(settings, id, FreeRDP_ReceivedCapabilitiesSize,
+ data, len, sizeof(char));
+ case FreeRDP_OrderSupport:
+ return freerdp_settings_set_pointer_len_(settings, id, -1, data, len, sizeof(char));
+
+ case FreeRDP_MonitorIds:
+ return freerdp_settings_set_pointer_len_(
+ settings, FreeRDP_MonitorIds, FreeRDP_NumMonitorIds, data, len, sizeof(UINT32));
+
+ default:
+ if ((data == NULL) && (len == 0))
+ {
+ freerdp_settings_set_pointer(settings, id, NULL);
+ }
+ else
+ WLog_WARN(TAG, "Invalid id %" PRIuz, id);
+ return FALSE;
+ }
+}
+
+void* freerdp_settings_get_pointer_array_writable(const rdpSettings* settings,
+ FreeRDP_Settings_Keys_Pointer id, size_t offset)
+{
+ size_t max = 0;
+ if (!settings)
+ return NULL;
+ switch (id)
+ {
+ case FreeRDP_ClientAutoReconnectCookie:
+ max = 1;
+ if ((offset >= max) || !settings->ClientAutoReconnectCookie)
+ goto fail;
+ return &settings->ClientAutoReconnectCookie[offset];
+ case FreeRDP_ServerAutoReconnectCookie:
+ max = 1;
+ if ((offset >= max) || !settings->ServerAutoReconnectCookie)
+ goto fail;
+ return &settings->ServerAutoReconnectCookie[offset];
+ case FreeRDP_ServerCertificate:
+ max = freerdp_settings_get_uint32(settings, FreeRDP_ServerCertificateLength);
+ if (offset >= max)
+ goto fail;
+ return &settings->ServerCertificate[offset];
+ case FreeRDP_ServerRandom:
+ max = freerdp_settings_get_uint32(settings, FreeRDP_ServerRandomLength);
+ if (offset >= max)
+ goto fail;
+ return &settings->ServerRandom[offset];
+ case FreeRDP_ClientRandom:
+ max = freerdp_settings_get_uint32(settings, FreeRDP_ClientRandomLength);
+ if (offset >= max)
+ goto fail;
+ return &settings->ClientRandom[offset];
+ case FreeRDP_LoadBalanceInfo:
+ max = freerdp_settings_get_uint32(settings, FreeRDP_LoadBalanceInfoLength);
+ if (offset >= max)
+ goto fail;
+ return &settings->LoadBalanceInfo[offset];
+
+ case FreeRDP_RedirectionTsvUrl:
+ max = freerdp_settings_get_uint32(settings, FreeRDP_RedirectionTsvUrlLength);
+ if (offset >= max)
+ goto fail;
+ return &settings->RedirectionTsvUrl[offset];
+
+ case FreeRDP_RedirectionPassword:
+ max = freerdp_settings_get_uint32(settings, FreeRDP_RedirectionPasswordLength);
+ if (offset >= max)
+ goto fail;
+ return &settings->RedirectionPassword[offset];
+
+ case FreeRDP_OrderSupport:
+ max = 32;
+ if (offset >= max)
+ goto fail;
+ return &settings->OrderSupport[offset];
+ case FreeRDP_MonitorIds:
+ max = freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds);
+ if (offset >= max)
+ goto fail;
+ return &settings->MonitorIds[offset];
+ case FreeRDP_MonitorDefArray:
+ max = freerdp_settings_get_uint32(settings, FreeRDP_MonitorDefArraySize);
+ if (offset >= max)
+ goto fail;
+ return &settings->MonitorDefArray[offset];
+ case FreeRDP_ChannelDefArray:
+ max = freerdp_settings_get_uint32(settings, FreeRDP_ChannelDefArraySize);
+ if (offset >= max)
+ goto fail;
+ return &settings->ChannelDefArray[offset];
+ case FreeRDP_DeviceArray:
+ max = freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize);
+ if (offset >= max)
+ goto fail;
+ return settings->DeviceArray[offset];
+ case FreeRDP_StaticChannelArray:
+ max = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
+ if (offset >= max)
+ goto fail;
+ return settings->StaticChannelArray[offset];
+ case FreeRDP_DynamicChannelArray:
+ max = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
+ if (offset >= max)
+ goto fail;
+ return settings->DynamicChannelArray[offset];
+ case FreeRDP_FragCache:
+ max = 1;
+ if (offset >= max)
+ goto fail;
+ return &settings->FragCache[offset];
+ case FreeRDP_GlyphCache:
+ max = 10;
+ if (offset >= max)
+ goto fail;
+ return &settings->GlyphCache[offset];
+ case FreeRDP_BitmapCacheV2CellInfo:
+ max = freerdp_settings_get_uint32(settings, FreeRDP_BitmapCacheV2NumCells);
+ if (offset >= max)
+ goto fail;
+ return &settings->BitmapCacheV2CellInfo[offset];
+ case FreeRDP_ReceivedCapabilities:
+ max = freerdp_settings_get_uint32(settings, FreeRDP_ReceivedCapabilitiesSize);
+ if (offset >= max)
+ goto fail;
+ return &settings->ReceivedCapabilities[offset];
+ case FreeRDP_TargetNetAddresses:
+ max = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
+ if (offset >= max)
+ goto fail;
+ return settings->TargetNetAddresses[offset];
+ case FreeRDP_TargetNetPorts:
+ max = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
+ if (offset >= max)
+ goto fail;
+ return &settings->TargetNetPorts[offset];
+ case FreeRDP_ClientTimeZone:
+ max = 1;
+ if (offset >= max)
+ goto fail;
+ return settings->ClientTimeZone;
+ case FreeRDP_RdpServerCertificate:
+ max = 1;
+ if (offset >= max)
+ goto fail;
+ return settings->RdpServerCertificate;
+ case FreeRDP_RdpServerRsaKey:
+ max = 1;
+ if (offset >= max)
+ goto fail;
+ return settings->RdpServerRsaKey;
+ default:
+ WLog_WARN(TAG, "Invalid id %s [%" PRIuz "]", freerdp_settings_get_name_for_key(id), id);
+ return NULL;
+ }
+
+fail:
+ WLog_WARN(TAG, "Invalid offset for %s [%" PRIuz "]: size=%" PRIuz ", offset=%" PRIuz,
+ freerdp_settings_get_name_for_key(id), id, max, offset);
+ return NULL;
+}
+
+BOOL freerdp_settings_set_pointer_array(rdpSettings* settings, FreeRDP_Settings_Keys_Pointer id,
+ size_t offset, const void* data)
+{
+ size_t maxOffset = 0;
+ if (!settings)
+ return FALSE;
+ switch (id)
+ {
+ case FreeRDP_ClientAutoReconnectCookie:
+ maxOffset = 1;
+ if ((offset >= maxOffset) || !data || !settings->ClientAutoReconnectCookie)
+ goto fail;
+ settings->ClientAutoReconnectCookie[offset] = *(const ARC_CS_PRIVATE_PACKET*)data;
+ return TRUE;
+ case FreeRDP_ServerAutoReconnectCookie:
+ maxOffset = 1;
+ if ((offset >= maxOffset) || !data || !settings->ServerAutoReconnectCookie)
+ goto fail;
+ settings->ServerAutoReconnectCookie[offset] = *(const ARC_SC_PRIVATE_PACKET*)data;
+ return TRUE;
+ case FreeRDP_ServerCertificate:
+ maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ServerCertificateLength);
+ if ((offset >= maxOffset) || !data)
+ goto fail;
+ settings->ServerCertificate[offset] = *(const BYTE*)data;
+ return TRUE;
+ case FreeRDP_DeviceArray:
+ maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_DeviceArraySize);
+ if (offset >= maxOffset)
+ goto fail;
+ freerdp_device_free(settings->DeviceArray[offset]);
+ settings->DeviceArray[offset] = freerdp_device_clone(data);
+ return TRUE;
+ case FreeRDP_TargetNetAddresses:
+ maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
+ if ((offset >= maxOffset) || !data)
+ goto fail;
+ free(settings->TargetNetAddresses[offset]);
+ settings->TargetNetAddresses[offset] = _strdup((const char*)data);
+ return settings->TargetNetAddresses[offset] != NULL;
+ case FreeRDP_TargetNetPorts:
+ maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_TargetNetAddressCount);
+ if ((offset >= maxOffset) || !data)
+ goto fail;
+ settings->TargetNetPorts[offset] = *((const UINT32*)data);
+ return TRUE;
+ case FreeRDP_StaticChannelArray:
+ maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_StaticChannelArraySize);
+ if ((offset >= maxOffset) || !data)
+ goto fail;
+ freerdp_addin_argv_free(settings->StaticChannelArray[offset]);
+ settings->StaticChannelArray[offset] = freerdp_addin_argv_clone(data);
+ return TRUE;
+ case FreeRDP_DynamicChannelArray:
+ maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_DynamicChannelArraySize);
+ if ((offset >= maxOffset) || !data)
+ goto fail;
+ freerdp_addin_argv_free(settings->DynamicChannelArray[offset]);
+ settings->DynamicChannelArray[offset] = freerdp_addin_argv_clone(data);
+ return TRUE;
+ case FreeRDP_BitmapCacheV2CellInfo:
+ maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_BitmapCacheV2NumCells);
+ if ((offset >= maxOffset) || !data)
+ goto fail;
+ {
+ const BITMAP_CACHE_V2_CELL_INFO* cdata = (const BITMAP_CACHE_V2_CELL_INFO*)data;
+ settings->BitmapCacheV2CellInfo[offset] = *cdata;
+ }
+ return TRUE;
+ case FreeRDP_ServerRandom:
+ maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ServerRandomLength);
+ if ((offset >= maxOffset) || !data)
+ goto fail;
+ settings->ServerRandom[offset] = *(const BYTE*)data;
+ return TRUE;
+ case FreeRDP_ClientRandom:
+ maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ClientRandomLength);
+ if ((offset >= maxOffset) || !data)
+ goto fail;
+ settings->ClientRandom[offset] = *(const BYTE*)data;
+ return TRUE;
+ case FreeRDP_LoadBalanceInfo:
+ maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_LoadBalanceInfoLength);
+ if ((offset >= maxOffset) || !data)
+ goto fail;
+ settings->LoadBalanceInfo[offset] = *(const BYTE*)data;
+ return TRUE;
+ case FreeRDP_RedirectionTsvUrl:
+ maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_RedirectionTsvUrlLength);
+ if ((offset >= maxOffset) || !data)
+ goto fail;
+ settings->RedirectionTsvUrl[offset] = *(const BYTE*)data;
+ return TRUE;
+ case FreeRDP_RedirectionPassword:
+ maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_RedirectionPasswordLength);
+ if ((offset >= maxOffset) || !data)
+ goto fail;
+ settings->RedirectionPassword[offset] = *(const BYTE*)data;
+ return TRUE;
+ case FreeRDP_OrderSupport:
+ maxOffset = 32;
+ if (!settings->OrderSupport)
+ goto fail;
+ if ((offset >= maxOffset) || !data)
+ goto fail;
+ settings->OrderSupport[offset] = *(const BOOL*)data;
+ return TRUE;
+ case FreeRDP_GlyphCache:
+ maxOffset = 10;
+ if (!settings->GlyphCache)
+ goto fail;
+ if ((offset >= maxOffset) || !data)
+ goto fail;
+ settings->GlyphCache[offset] = *(const GLYPH_CACHE_DEFINITION*)data;
+ return TRUE;
+ case FreeRDP_FragCache:
+ maxOffset = 1;
+ if (!settings->FragCache)
+ goto fail;
+ if ((offset >= maxOffset) || !data)
+ goto fail;
+ settings->FragCache[offset] = *(const GLYPH_CACHE_DEFINITION*)data;
+ return TRUE;
+ case FreeRDP_MonitorIds:
+ maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_NumMonitorIds);
+ if ((offset >= maxOffset) || !data)
+ goto fail;
+ settings->MonitorIds[offset] = *(const UINT32*)data;
+ return TRUE;
+ case FreeRDP_ChannelDefArray:
+ maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_ChannelDefArraySize);
+ if ((offset >= maxOffset) || !data)
+ goto fail;
+ settings->ChannelDefArray[offset] = *(const CHANNEL_DEF*)data;
+ return TRUE;
+ case FreeRDP_MonitorDefArray:
+ maxOffset = freerdp_settings_get_uint32(settings, FreeRDP_MonitorDefArraySize);
+ if ((offset >= maxOffset) || !data)
+ goto fail;
+ settings->MonitorDefArray[offset] = *(const rdpMonitor*)data;
+ return TRUE;
+
+ case FreeRDP_ClientTimeZone:
+ maxOffset = 1;
+ if ((offset >= maxOffset) || !data || !settings->ClientTimeZone)
+ goto fail;
+ settings->ClientTimeZone[0] = *(const TIME_ZONE_INFORMATION*)data;
+ return TRUE;
+
+ default:
+ WLog_WARN(TAG, "Invalid id %s [%" PRIuz "]", freerdp_settings_get_name_for_key(id), id);
+ return FALSE;
+ }
+
+fail:
+ WLog_WARN(TAG, "[%s] Invalid offset=%" PRIuz " [%" PRIuz "] or NULL data=%p",
+ freerdp_settings_get_name_for_key(id), offset, maxOffset, data);
+ return FALSE;
+}
+
+const void* freerdp_settings_get_pointer_array(const rdpSettings* settings,
+ FreeRDP_Settings_Keys_Pointer id, size_t offset)
+{
+ return freerdp_settings_get_pointer_array_writable(settings, id, offset);
+}
+
+UINT32 freerdp_settings_get_codecs_flags(const rdpSettings* settings)
+{
+ UINT32 flags = FREERDP_CODEC_ALL;
+ if (settings->RemoteFxCodec == FALSE)
+ {
+ flags &= ~FREERDP_CODEC_REMOTEFX;
+ }
+ if (settings->NSCodec == FALSE)
+ {
+ flags &= ~FREERDP_CODEC_NSCODEC;
+ }
+ /*TODO: check other codecs flags */
+ return flags;
+}
+
+const char* freerdp_settings_get_server_name(const rdpSettings* settings)
+{
+ WINPR_ASSERT(settings);
+ const char* hostname = settings->ServerHostname;
+
+ if (settings->UserSpecifiedServerName)
+ hostname = settings->UserSpecifiedServerName;
+
+ return hostname;
+}
+
+#if defined(WITH_FREERDP_DEPRECATED)
+ADDIN_ARGV* freerdp_static_channel_clone(ADDIN_ARGV* channel)
+{
+ return freerdp_addin_argv_clone(channel);
+}
+
+ADDIN_ARGV* freerdp_dynamic_channel_clone(ADDIN_ARGV* channel)
+{
+ return freerdp_addin_argv_clone(channel);
+}
+#endif
+
+BOOL freerdp_target_net_addresses_copy(rdpSettings* settings, char** addresses, UINT32 count)
+{
+ WINPR_ASSERT(settings);
+ WINPR_ASSERT(addresses);
+
+ if (!freerdp_target_net_adresses_reset(settings, count))
+ return FALSE;
+
+ for (UINT32 i = 0; i < settings->TargetNetAddressCount; i++)
+ {
+ if (!freerdp_settings_set_pointer_array(settings, FreeRDP_TargetNetAddresses, i,
+ addresses[i]))
+ {
+ freerdp_target_net_addresses_free(settings);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+BOOL freerdp_device_equal(const RDPDR_DEVICE* what, const RDPDR_DEVICE* expect)
+{
+ if (!what && !expect)
+ return TRUE;
+ if (!what || !expect)
+ return FALSE;
+
+ if (what->Id != expect->Id)
+ return FALSE;
+ if (what->Type != expect->Type)
+ return FALSE;
+ if (what->Name && expect->Name)
+ {
+ if (strcmp(what->Name, expect->Name) != 0)
+ return FALSE;
+ }
+ else
+ {
+ if (what->Name != expect->Name)
+ return FALSE;
+ }
+
+ switch (what->Type)
+ {
+ case RDPDR_DTYP_PRINT:
+ {
+ const RDPDR_PRINTER* a = (const RDPDR_PRINTER*)what;
+ const RDPDR_PRINTER* b = (const RDPDR_PRINTER*)expect;
+ if (a->DriverName && b->DriverName)
+ return strcmp(a->DriverName, b->DriverName) == 0;
+ return a->DriverName == b->DriverName;
+ }
+
+ case RDPDR_DTYP_SERIAL:
+ {
+ const RDPDR_SERIAL* a = (const RDPDR_SERIAL*)what;
+ const RDPDR_SERIAL* b = (const RDPDR_SERIAL*)expect;
+
+ if (a->Path && b->Path)
+ {
+ if (strcmp(a->Path, b->Path) != 0)
+ return FALSE;
+ }
+ else if (a->Path != b->Path)
+ return FALSE;
+
+ if (a->Driver && b->Driver)
+ {
+ if (strcmp(a->Driver, b->Driver) != 0)
+ return FALSE;
+ }
+ else if (a->Driver != b->Driver)
+ return FALSE;
+ if (a->Permissive && b->Permissive)
+ return strcmp(a->Permissive, b->Permissive) == 0;
+ return a->Permissive == b->Permissive;
+ }
+
+ case RDPDR_DTYP_PARALLEL:
+ {
+ const RDPDR_PARALLEL* a = (const RDPDR_PARALLEL*)what;
+ const RDPDR_PARALLEL* b = (const RDPDR_PARALLEL*)expect;
+ if (a->Path && b->Path)
+ return strcmp(a->Path, b->Path) == 0;
+ return a->Path == b->Path;
+ }
+
+ case RDPDR_DTYP_SMARTCARD:
+ break;
+ case RDPDR_DTYP_FILESYSTEM:
+ {
+ const RDPDR_DRIVE* a = (const RDPDR_DRIVE*)what;
+ const RDPDR_DRIVE* b = (const RDPDR_DRIVE*)expect;
+ if (a->automount != b->automount)
+ return FALSE;
+ if (a->Path && b->Path)
+ return strcmp(a->Path, b->Path) == 0;
+ return a->Path == b->Path;
+ }
+
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+char* freerdp_rail_support_flags_to_string(UINT32 flags, char* buffer, size_t length)
+{
+ const UINT32 mask =
+ RAIL_LEVEL_SUPPORTED | RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED |
+ RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED | RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED |
+ RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED | RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED |
+ RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED | RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED;
+
+ if (flags & RAIL_LEVEL_SUPPORTED)
+ winpr_str_append("RAIL_LEVEL_SUPPORTED", buffer, length, "|");
+ if (flags & RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED)
+ winpr_str_append("RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED", buffer, length, "|");
+ if (flags & RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED)
+ winpr_str_append("RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED", buffer, length, "|");
+ if (flags & RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED)
+ winpr_str_append("RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED", buffer, length, "|");
+ if (flags & RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED)
+ winpr_str_append("RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED", buffer, length, "|");
+ if (flags & RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED)
+ winpr_str_append("RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED", buffer, length, "|");
+ if (flags & RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED)
+ winpr_str_append("RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED", buffer, length, "|");
+ if (flags & RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED)
+ winpr_str_append("RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED", buffer, length, "|");
+ if (flags & RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED)
+ winpr_str_append("RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED", buffer, length, "|");
+ if ((flags & ~mask) != 0)
+ {
+ char tbuffer[64] = { 0 };
+ _snprintf(tbuffer, sizeof(tbuffer), "RAIL_FLAG_UNKNOWN 0x%08" PRIx32, flags & mask);
+ winpr_str_append(tbuffer, buffer, length, "|");
+ }
+ return buffer;
+}
+
+BOOL freerdp_settings_update_from_caps(rdpSettings* settings, const BYTE* capsFlags,
+ const BYTE** capsData, const UINT32* capsSizes,
+ UINT32 capsCount, BOOL serverReceivedCaps)
+{
+ WINPR_ASSERT(settings);
+ WINPR_ASSERT(capsFlags || (capsCount == 0));
+ WINPR_ASSERT(capsData || (capsCount == 0));
+ WINPR_ASSERT(capsSizes || (capsCount == 0));
+ WINPR_ASSERT(capsCount <= UINT16_MAX);
+
+ for (UINT32 x = 0; x < capsCount; x++)
+ {
+ if (capsFlags[x])
+ {
+ wStream buffer;
+ wStream* sub = Stream_StaticConstInit(&buffer, capsData[x], capsSizes[x]);
+
+ if (!rdp_read_capability_set(sub, (UINT16)x, settings, serverReceivedCaps))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+const char* freerdp_rdp_version_string(UINT32 version)
+{
+ switch (version)
+ {
+ case RDP_VERSION_4:
+ return "RDP_VERSION_4";
+ case RDP_VERSION_5_PLUS:
+ return "RDP_VERSION_5_PLUS";
+ case RDP_VERSION_10_0:
+ return "RDP_VERSION_10_0";
+ case RDP_VERSION_10_1:
+ return "RDP_VERSION_10_1";
+ case RDP_VERSION_10_2:
+ return "RDP_VERSION_10_2";
+ case RDP_VERSION_10_3:
+ return "RDP_VERSION_10_3";
+ case RDP_VERSION_10_4:
+ return "RDP_VERSION_10_4";
+ case RDP_VERSION_10_5:
+ return "RDP_VERSION_10_5";
+ case RDP_VERSION_10_6:
+ return "RDP_VERSION_10_6";
+ case RDP_VERSION_10_7:
+ return "RDP_VERSION_10_7";
+ case RDP_VERSION_10_8:
+ return "RDP_VERSION_10_8";
+ case RDP_VERSION_10_9:
+ return "RDP_VERSION_10_9";
+ case RDP_VERSION_10_10:
+ return "RDP_VERSION_10_10";
+ case RDP_VERSION_10_11:
+ return "RDP_VERSION_10_11";
+ case RDP_VERSION_10_12:
+ return "RDP_VERSION_10_12";
+ default:
+ return "RDP_VERSION_UNKNOWN";
+ }
+}
+
+BOOL freerdp_settings_set_string_from_utf16(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
+ const WCHAR* param)
+{
+ WINPR_ASSERT(settings);
+
+ if (!param)
+ return freerdp_settings_set_string_copy_(settings, id, NULL, 0, TRUE);
+
+ size_t len = 0;
+
+ char* str = ConvertWCharToUtf8Alloc(param, &len);
+ if (!str && (len != 0))
+ return FALSE;
+
+ return freerdp_settings_set_string_(settings, id, str, len);
+}
+
+BOOL freerdp_settings_set_string_from_utf16N(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
+ const WCHAR* param, size_t length)
+{
+ size_t len = 0;
+
+ WINPR_ASSERT(settings);
+
+ if (!param)
+ return freerdp_settings_set_string_copy_(settings, id, NULL, length, TRUE);
+
+ char* str = ConvertWCharNToUtf8Alloc(param, length, &len);
+ if (!str && (length != 0))
+ {
+ /* If the input string is an empty string, but length > 0
+ * consider the conversion a success */
+ const size_t wlen = _wcsnlen(param, length);
+ if (wlen != 0)
+ return FALSE;
+ }
+
+ return freerdp_settings_set_string_(settings, id, str, len);
+}
+
+WCHAR* freerdp_settings_get_string_as_utf16(const rdpSettings* settings,
+ FreeRDP_Settings_Keys_String id, size_t* pCharLen)
+{
+ const char* str = freerdp_settings_get_string(settings, id);
+ if (pCharLen)
+ *pCharLen = 0;
+ if (!str)
+ return NULL;
+ return ConvertUtf8ToWCharAlloc(str, pCharLen);
+}
+
+const char* freerdp_rdpdr_dtyp_string(UINT32 type)
+{
+ switch (type)
+ {
+ case RDPDR_DTYP_FILESYSTEM:
+ return "RDPDR_DTYP_FILESYSTEM";
+ case RDPDR_DTYP_PARALLEL:
+ return "RDPDR_DTYP_PARALLEL";
+ case RDPDR_DTYP_PRINT:
+ return "RDPDR_DTYP_PRINT";
+ case RDPDR_DTYP_SERIAL:
+ return "RDPDR_DTYP_SERIAL";
+ case RDPDR_DTYP_SMARTCARD:
+ return "RDPDR_DTYP_SMARTCARD";
+ default:
+ return "RDPDR_DTYP_UNKNOWN";
+ }
+}
+
+const char* freerdp_encryption_level_string(UINT32 EncryptionLevel)
+{
+ switch (EncryptionLevel)
+ {
+ case ENCRYPTION_LEVEL_NONE:
+ return "ENCRYPTION_LEVEL_NONE";
+ case ENCRYPTION_LEVEL_LOW:
+ return "ENCRYPTION_LEVEL_LOW";
+ case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE:
+ return "ENCRYPTION_LEVEL_CLIENT_COMPATIBLE";
+ case ENCRYPTION_LEVEL_HIGH:
+ return "ENCRYPTION_LEVEL_HIGH";
+ case ENCRYPTION_LEVEL_FIPS:
+ return "ENCRYPTION_LEVEL_FIPS";
+ default:
+ return "ENCRYPTION_LEVEL_UNKNOWN";
+ }
+}
+
+const char* freerdp_encryption_methods_string(UINT32 EncryptionMethods, char* buffer, size_t size)
+{
+ if (EncryptionMethods == ENCRYPTION_METHOD_NONE)
+ {
+ winpr_str_append("ENCRYPTION_METHOD_NONE", buffer, size, "|");
+ return buffer;
+ }
+
+ if (EncryptionMethods & ENCRYPTION_METHOD_40BIT)
+ {
+ winpr_str_append("ENCRYPTION_METHOD_40BIT", buffer, size, "|");
+ }
+ if (EncryptionMethods & ENCRYPTION_METHOD_128BIT)
+ {
+ winpr_str_append("ENCRYPTION_METHOD_128BIT", buffer, size, "|");
+ }
+ if (EncryptionMethods & ENCRYPTION_METHOD_56BIT)
+ {
+ winpr_str_append("ENCRYPTION_METHOD_56BIT", buffer, size, "|");
+ }
+ if (EncryptionMethods & ENCRYPTION_METHOD_FIPS)
+ {
+ winpr_str_append("ENCRYPTION_METHOD_FIPS", buffer, size, "|");
+ }
+
+ return buffer;
+}
+
+const char* freerdp_supported_color_depths_string(UINT16 mask, char* buffer, size_t size)
+{
+ const UINT32 invalid = mask & ~(RNS_UD_32BPP_SUPPORT | RNS_UD_24BPP_SUPPORT |
+ RNS_UD_16BPP_SUPPORT | RNS_UD_15BPP_SUPPORT);
+
+ if (mask & RNS_UD_32BPP_SUPPORT)
+ winpr_str_append("RNS_UD_32BPP_SUPPORT", buffer, size, "|");
+ if (mask & RNS_UD_24BPP_SUPPORT)
+ winpr_str_append("RNS_UD_24BPP_SUPPORT", buffer, size, "|");
+ if (mask & RNS_UD_16BPP_SUPPORT)
+ winpr_str_append("RNS_UD_16BPP_SUPPORT", buffer, size, "|");
+ if (mask & RNS_UD_15BPP_SUPPORT)
+ winpr_str_append("RNS_UD_15BPP_SUPPORT", buffer, size, "|");
+
+ if (invalid != 0)
+ {
+ char str[32] = { 0 };
+ _snprintf(str, sizeof(str), "RNS_UD_INVALID[0x%04" PRIx32 "]", invalid);
+ winpr_str_append(str, buffer, size, "|");
+ }
+ char hex[32] = { 0 };
+ _snprintf(hex, sizeof(hex), "[0x%04" PRIx16 "]", mask);
+ return buffer;
+}
+
+BOOL freerdp_settings_append_string(rdpSettings* settings, FreeRDP_Settings_Keys_String id,
+ const char* separator, const char* param)
+{
+ const char* old = freerdp_settings_get_string(settings, id);
+
+ size_t len = 0;
+ char* str = NULL;
+
+ if (!old)
+ winpr_asprintf(&str, &len, "%s", param);
+ else if (!separator)
+ winpr_asprintf(&str, &len, "%s%s", old, param);
+ else
+ winpr_asprintf(&str, &len, "%s%s%s", old, separator, param);
+
+ const BOOL rc = freerdp_settings_set_string_len(settings, id, str, len);
+ free(str);
+ return rc;
+}
+
+BOOL freerdp_settings_are_valid(const rdpSettings* settings)
+{
+ return settings != NULL;
+}