Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FreeRDP/FreeRDP.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Fleisz <martin.fleisz@thincast.com>2020-05-20 17:45:43 +0300
committerGitHub <noreply@github.com>2020-05-20 17:45:43 +0300
commit1923e63516c1182bd5e917aeac563431e8c5381a (patch)
tree5997d6fcac797e2c836c84ac4a7c04aef39cc147
parent11b9b1ca6be433f1da5bbf5e152d554d3eb67ac6 (diff)
parent3c33c6e1a20601da2f47ac8546f5ab6223a66049 (diff)
Merge pull request #6212 from akallabeth/stable_backport_cve2.1.1
Stable backport cve
-rw-r--r--CMakeLists.txt6
-rw-r--r--ChangeLog18
-rw-r--r--channels/audin/client/audin_main.c11
-rw-r--r--channels/cliprdr/client/cliprdr_main.c12
-rw-r--r--channels/cliprdr/cliprdr_common.c1
-rw-r--r--channels/cliprdr/server/cliprdr_main.c12
-rw-r--r--channels/disp/client/disp_main.c11
-rw-r--r--channels/drdynvc/client/drdynvc_main.c478
-rw-r--r--channels/drdynvc/client/drdynvc_main.h11
-rw-r--r--channels/echo/client/echo_main.c12
-rw-r--r--channels/geometry/client/geometry_main.c13
-rw-r--r--channels/printer/client/cups/printer_cups.c26
-rw-r--r--channels/rail/client/rail_orders.c6
-rw-r--r--channels/rail/rail_common.c51
-rw-r--r--channels/rail/rail_common.h2
-rw-r--r--channels/rail/server/rail_main.c8
-rw-r--r--channels/rdpei/client/rdpei_main.c9
-rw-r--r--channels/rdpei/rdpei_common.c32
-rw-r--r--channels/rdpgfx/client/rdpgfx_main.c17
-rw-r--r--channels/rdpsnd/client/mac/CMakeLists.txt2
-rw-r--r--channels/rdpsnd/client/rdpsnd_main.c9
-rw-r--r--channels/urbdrc/client/urbdrc_main.c14
-rw-r--r--channels/urbdrc/client/urbdrc_main.h1
-rw-r--r--channels/video/client/video_main.c17
-rw-r--r--client/Android/Studio/build.gradle2
-rw-r--r--client/Android/android_freerdp.c2
-rw-r--r--client/Sample/tf_freerdp.c5
-rw-r--r--client/Windows/wf_client.c2
-rw-r--r--client/X11/xf_client.c9
-rw-r--r--client/X11/xf_event.c6
-rw-r--r--client/X11/xf_keyboard.c6
-rw-r--r--client/X11/xfreerdp.h6
-rw-r--r--client/common/cmdline.c5
-rw-r--r--client/common/file.c20
-rw-r--r--config.h.in1
-rw-r--r--libfreerdp/codec/clear.c7
-rw-r--r--libfreerdp/codec/interleaved.c4
-rw-r--r--libfreerdp/codec/mppc.c6
-rw-r--r--libfreerdp/codec/ncrush.c6
-rw-r--r--libfreerdp/codec/nsc.c14
-rw-r--r--libfreerdp/codec/planar.c5
-rw-r--r--libfreerdp/codec/progressive.c4
-rw-r--r--libfreerdp/codec/rfx_dwt.c35
-rw-r--r--libfreerdp/codec/rfx_rlgr.c15
-rw-r--r--libfreerdp/common/settings_getters.c323
-rw-r--r--libfreerdp/common/settings_str.c96
-rw-r--r--libfreerdp/core/capabilities.c6
-rw-r--r--libfreerdp/core/gateway/http.c5
-rw-r--r--libfreerdp/core/gateway/tsg.c2
-rw-r--r--libfreerdp/core/info.c398
-rw-r--r--libfreerdp/core/nla.c10
-rw-r--r--libfreerdp/core/orders.c2
-rw-r--r--libfreerdp/core/proxy.c5
-rw-r--r--libfreerdp/core/rdp.c58
-rw-r--r--libfreerdp/core/rdp.h1
-rw-r--r--libfreerdp/core/security.c25
-rw-r--r--libfreerdp/core/settings.c221
-rw-r--r--libfreerdp/core/settings.h5
-rw-r--r--libfreerdp/core/test/TestConnect.c3
-rw-r--r--libfreerdp/core/test/TestSettings.c89
-rw-r--r--libfreerdp/core/transport.c2
-rw-r--r--libfreerdp/crypto/crypto.c79
-rw-r--r--libfreerdp/crypto/tls.c3
-rw-r--r--libfreerdp/primitives/prim_colors.c38
-rw-r--r--libfreerdp/primitives/prim_shift.c12
-rw-r--r--libfreerdp/primitives/prim_shift_opt.c4
-rw-r--r--libfreerdp/primitives/prim_templates.h4
-rw-r--r--libfreerdp/primitives/test/TestPrimitivesShift.c85
-rwxr-xr-xscripts/update-settings-tests135
-rw-r--r--server/proxy/freerdp_proxy.c10
-rw-r--r--server/proxy/pf_client.c98
-rw-r--r--server/shadow/freerdp-shadow-cli.1.in2
-rw-r--r--winpr/CMakeLists.txt2
-rw-r--r--winpr/include/winpr/bitstream.h32
-rw-r--r--winpr/include/winpr/sam.h7
-rw-r--r--winpr/include/winpr/stream.h88
-rw-r--r--winpr/libwinpr/crt/test/TestAlignment.c2
-rw-r--r--winpr/libwinpr/crt/utf.c104
-rw-r--r--winpr/libwinpr/smartcard/smartcard_pcsc.c5
-rw-r--r--winpr/libwinpr/sspi/NTLM/ntlm_message.c96
-rw-r--r--winpr/libwinpr/sspi/sspi_winpr.c9
-rw-r--r--winpr/libwinpr/sspi/test/TestNTLM.c36
-rw-r--r--winpr/libwinpr/timezone/timezone.c6
-rw-r--r--winpr/libwinpr/utils/collections/PubSub.c9
-rw-r--r--winpr/libwinpr/utils/ini.c25
-rw-r--r--winpr/libwinpr/utils/lodepng/lodepng.c3
-rw-r--r--winpr/libwinpr/utils/sam.c16
-rw-r--r--winpr/libwinpr/utils/test/TestIni.c57
-rw-r--r--winpr/tools/makecert-cli/winpr-makecert.1.in2
89 files changed, 1873 insertions, 1286 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a4d22b31e..1d685b921 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -81,7 +81,7 @@ if ($ENV{BUILD_NUMBER})
endif()
set(WITH_LIBRARY_VERSIONING "ON")
-set(RAW_VERSION_STRING "2.1.0")
+set(RAW_VERSION_STRING "2.1.1")
if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag")
file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING)
elseif(USE_VERSION_FROM_GIT_TAG)
@@ -936,10 +936,6 @@ if(MBEDTLS_FOUND)
add_definitions("-DWITH_MBEDTLS")
endif()
-if (TARGET_ARCH MATCHES "sparc")
- set(HAVE_ALIGNED_REQUIRED 1)
-endif()
-
if (WITH_X264 OR WITH_OPENH264 OR WITH_MEDIA_FOUNDATION OR WITH_FFMPEG)
set(WITH_GFX_H264 ON)
else()
diff --git a/ChangeLog b/ChangeLog
index a61d04822..593cb89a6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+# 2020-05-20 Version 2.1.1
+
+Important notes:
+* CVE: GHSL-2020-100 OOB Read in ntlm_read_ChallengeMessage
+* CVE: GHSL-2020-101 OOB Read in security_fips_decrypt due to uninitialized value
+* CVE: GHSL-2020-102 OOB Write in crypto_rsa_common
+* Enforce synchronous legacy RDP encryption count (#6156)
+* Fixed some leaks and crashes missed in 2.1.0
+* Removed dynamic channel listener limits
+* Lots of resource cleanup fixes (clang sanitizers)
+* A couple of performance improvements
+* Various small annoyances eliminated (typos, prefilled username for windows client, ...)
+
+
+For a complete and detailed change log since the last release candidate run:
+git log 2.1.0..2.1.1
+
+
# 2020-05-05 Version 2.1.0
Important notes:
diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c
index 1b14fd3b7..26ac48390 100644
--- a/channels/audin/client/audin_main.c
+++ b/channels/audin/client/audin_main.c
@@ -100,6 +100,8 @@ struct _AUDIN_PLUGIN
FREERDP_DSP_CONTEXT* dsp_context;
wLog* log;
+
+ IWTSListener* listener;
};
static BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args);
@@ -687,7 +689,7 @@ static UINT audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag
audin->listener_callback->plugin = pPlugin;
audin->listener_callback->channel_mgr = pChannelMgr;
return pChannelMgr->CreateListener(pChannelMgr, "AUDIO_INPUT", 0,
- (IWTSListenerCallback*)audin->listener_callback, NULL);
+ &audin->listener_callback->iface, &audin->listener);
}
/**
@@ -704,6 +706,13 @@ static UINT audin_plugin_terminated(IWTSPlugin* pPlugin)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
WLog_Print(audin->log, WLOG_TRACE, "...");
+
+ if (audin->listener_callback)
+ {
+ IWTSVirtualChannelManager* mgr = audin->listener_callback->channel_mgr;
+ if (mgr)
+ IFCALL(mgr->DestroyListener, mgr, audin->listener);
+ }
audio_formats_free(audin->fixed_format, 1);
if (audin->device)
diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c
index 8541cabcc..b5d119a20 100644
--- a/channels/cliprdr/client/cliprdr_main.c
+++ b/channels/cliprdr/client/cliprdr_main.c
@@ -594,7 +594,7 @@ static UINT cliprdr_temp_directory(CliprdrClientContext* context,
wStream* s;
WCHAR* wszTempDir = NULL;
cliprdrPlugin* cliprdr = (cliprdrPlugin*)context->handle;
- s = cliprdr_packet_new(CB_TEMP_DIRECTORY, 0, 520 * 2);
+ s = cliprdr_packet_new(CB_TEMP_DIRECTORY, 0, 260 * sizeof(WCHAR));
if (!s)
{
@@ -607,11 +607,13 @@ static UINT cliprdr_temp_directory(CliprdrClientContext* context,
if (length < 0)
return ERROR_INTERNAL_ERROR;
- if (length > 520)
- length = 520;
+ /* Path must be 260 UTF16 characters with '\0' termination.
+ * ensure this here */
+ if (length >= 260)
+ length = 259;
- Stream_Write(s, wszTempDir, (size_t)length * 2);
- Stream_Zero(s, (520 - (size_t)length) * 2);
+ Stream_Write_UTF16_String(s, wszTempDir, length);
+ Stream_Zero(s, 520 - (length * sizeof(WCHAR)));
free(wszTempDir);
WLog_Print(cliprdr->log, WLOG_DEBUG, "TempDirectory: %s", tempDirectory->szTempDir);
return cliprdr_packet_send(cliprdr, s);
diff --git a/channels/cliprdr/cliprdr_common.c b/channels/cliprdr/cliprdr_common.c
index a699852b6..c0fae6e89 100644
--- a/channels/cliprdr/cliprdr_common.c
+++ b/channels/cliprdr/cliprdr_common.c
@@ -395,7 +395,6 @@ UINT cliprdr_read_file_contents_response(wStream* s, CLIPRDR_FILE_CONTENTS_RESPO
UINT cliprdr_read_format_list(wStream* s, CLIPRDR_FORMAT_LIST* formatList, BOOL useLongFormatNames)
{
UINT32 index;
- size_t position;
BOOL asciiNames;
int formatNameLength;
char* szFormatName;
diff --git a/channels/cliprdr/server/cliprdr_main.c b/channels/cliprdr/server/cliprdr_main.c
index 8854a0fb7..da4ab0b9b 100644
--- a/channels/cliprdr/server/cliprdr_main.c
+++ b/channels/cliprdr/server/cliprdr_main.c
@@ -553,7 +553,7 @@ static UINT cliprdr_server_receive_temporary_directory(CliprdrServerContext* con
UINT error = CHANNEL_RC_OK;
WINPR_UNUSED(header);
- if ((slength = Stream_GetRemainingLength(s)) < 520)
+ if ((slength = Stream_GetRemainingLength(s)) < 260 * sizeof(WCHAR))
{
WLog_ERR(TAG, "Stream_GetRemainingLength returned %" PRIuz " but should at least be 520",
slength);
@@ -562,9 +562,9 @@ static UINT cliprdr_server_receive_temporary_directory(CliprdrServerContext* con
wszTempDir = (WCHAR*)Stream_Pointer(s);
- if (wszTempDir[260] != 0)
+ if (wszTempDir[259] != 0)
{
- WLog_ERR(TAG, "wszTempDir[260] was not 0");
+ WLog_ERR(TAG, "wszTempDir[259] was not 0");
return ERROR_INVALID_DATA;
}
@@ -578,10 +578,10 @@ static UINT cliprdr_server_receive_temporary_directory(CliprdrServerContext* con
return ERROR_INVALID_DATA;
}
- length = strnlen(cliprdr->temporaryDirectory, 520);
+ length = strnlen(cliprdr->temporaryDirectory, 260);
- if (length > 519)
- length = 519;
+ if (length >= 260)
+ length = 259;
CopyMemory(tempDirectory.szTempDir, cliprdr->temporaryDirectory, length);
tempDirectory.szTempDir[length] = '\0';
diff --git a/channels/disp/client/disp_main.c b/channels/disp/client/disp_main.c
index d3e9a22cf..fa92c252a 100644
--- a/channels/disp/client/disp_main.c
+++ b/channels/disp/client/disp_main.c
@@ -308,8 +308,7 @@ static UINT disp_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage
disp->listener_callback->plugin = pPlugin;
disp->listener_callback->channel_mgr = pChannelMgr;
status = pChannelMgr->CreateListener(pChannelMgr, DISP_DVC_CHANNEL_NAME, 0,
- (IWTSListenerCallback*)disp->listener_callback,
- &(disp->listener));
+ &disp->listener_callback->iface, &(disp->listener));
disp->listener->pInterface = disp->iface.pInterface;
return status;
}
@@ -322,6 +321,14 @@ static UINT disp_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage
static UINT disp_plugin_terminated(IWTSPlugin* pPlugin)
{
DISP_PLUGIN* disp = (DISP_PLUGIN*)pPlugin;
+
+ if (disp && disp->listener_callback)
+ {
+ IWTSVirtualChannelManager* mgr = disp->listener_callback->channel_mgr;
+ if (mgr)
+ IFCALL(mgr->DestroyListener, mgr, disp->listener);
+ }
+
free(disp->listener_callback);
free(disp->iface.pInterface);
free(pPlugin);
diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c
index fa09cd08f..eb5b418e1 100644
--- a/channels/drdynvc/client/drdynvc_main.c
+++ b/channels/drdynvc/client/drdynvc_main.c
@@ -30,6 +30,7 @@
#define TAG CHANNELS_TAG("drdynvc.client")
+static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr);
static void dvcman_channel_free(void* channel);
static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const BYTE* data,
UINT32 dataSize);
@@ -39,6 +40,7 @@ static void dvcman_wtslistener_free(DVCMAN_LISTENER* listener)
{
if (listener)
free(listener->channel_name);
+
free(listener);
}
@@ -67,64 +69,50 @@ static UINT dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr,
DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
DVCMAN_LISTENER* listener;
- if (dvcman->num_listeners < MAX_PLUGINS)
- {
- WLog_DBG(TAG, "create_listener: %d.%s.", dvcman->num_listeners, pszChannelName);
- listener = (DVCMAN_LISTENER*)calloc(1, sizeof(DVCMAN_LISTENER));
+ WLog_DBG(TAG, "create_listener: %d.%s.", ArrayList_Count(dvcman->listeners) + 1,
+ pszChannelName);
+ listener = (DVCMAN_LISTENER*)calloc(1, sizeof(DVCMAN_LISTENER));
- if (!listener)
- {
- WLog_ERR(TAG, "calloc failed!");
- return CHANNEL_RC_NO_MEMORY;
- }
+ if (!listener)
+ {
+ WLog_ERR(TAG, "calloc failed!");
+ return CHANNEL_RC_NO_MEMORY;
+ }
- listener->iface.GetConfiguration = dvcman_get_configuration;
- listener->iface.pInterface = NULL;
- listener->dvcman = dvcman;
- listener->channel_name = _strdup(pszChannelName);
+ listener->iface.GetConfiguration = dvcman_get_configuration;
+ listener->iface.pInterface = NULL;
+ listener->dvcman = dvcman;
+ listener->channel_name = _strdup(pszChannelName);
- if (!listener->channel_name)
- {
- WLog_ERR(TAG, "_strdup failed!");
- dvcman_wtslistener_free(listener);
- return CHANNEL_RC_NO_MEMORY;
- }
+ if (!listener->channel_name)
+ {
+ WLog_ERR(TAG, "_strdup failed!");
+ dvcman_wtslistener_free(listener);
+ return CHANNEL_RC_NO_MEMORY;
+ }
- listener->flags = ulFlags;
- listener->listener_callback = pListenerCallback;
+ listener->flags = ulFlags;
+ listener->listener_callback = pListenerCallback;
- if (ppListener)
- *ppListener = (IWTSListener*)listener;
+ if (ppListener)
+ *ppListener = (IWTSListener*)listener;
- dvcman->listeners[dvcman->num_listeners++] = (IWTSListener*)listener;
- return CHANNEL_RC_OK;
- }
- else
- {
- WLog_ERR(TAG, "create_listener: Maximum DVC listener number reached.");
+ if (ArrayList_Add(dvcman->listeners, listener) < 0)
return ERROR_INTERNAL_ERROR;
- }
+ return CHANNEL_RC_OK;
}
static UINT dvcman_destroy_listener(IWTSVirtualChannelManager* pChannelMgr, IWTSListener* pListener)
{
- size_t x;
DVCMAN_LISTENER* listener = (DVCMAN_LISTENER*)pListener;
+ WINPR_UNUSED(pChannelMgr);
+
if (listener)
{
DVCMAN* dvcman = listener->dvcman;
- for (x = 0; x < dvcman->num_listeners; x++)
- {
- if (dvcman->listeners[x] == pListener)
- {
- size_t rest = (dvcman->num_listeners - x - 1) * sizeof(IWTSListener*);
- MoveMemory(&dvcman->listeners[x], &dvcman->listeners[x + 1], rest);
- dvcman->num_listeners--;
- dvcman_wtslistener_free(listener);
- break;
- }
- }
+ if (dvcman)
+ ArrayList_Remove(dvcman->listeners, listener);
}
return CHANNEL_RC_OK;
@@ -140,34 +128,42 @@ static UINT dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const ch
{
DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*)pEntryPoints)->dvcman;
- if (dvcman->num_plugins < MAX_PLUGINS)
- {
- dvcman->plugin_names[dvcman->num_plugins] = name;
- dvcman->plugins[dvcman->num_plugins++] = pPlugin;
- WLog_DBG(TAG, "register_plugin: num_plugins %d", dvcman->num_plugins);
- return CHANNEL_RC_OK;
- }
- else
- {
- WLog_ERR(TAG, "register_plugin: Maximum DVC plugin number %u reached.", MAX_PLUGINS);
+ if (ArrayList_Add(dvcman->plugin_names, _strdup(name)) < 0)
return ERROR_INTERNAL_ERROR;
- }
+ if (ArrayList_Add(dvcman->plugins, pPlugin) < 0)
+ return ERROR_INTERNAL_ERROR;
+
+ WLog_DBG(TAG, "register_plugin: num_plugins %d", ArrayList_Count(dvcman->plugins));
+ return CHANNEL_RC_OK;
}
static IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name)
{
- size_t i;
+ IWTSPlugin* plugin = NULL;
+ size_t i, nc, pc;
DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*)pEntryPoints)->dvcman;
+ if (!dvcman || !pEntryPoints || !name)
+ return NULL;
+
+ nc = ArrayList_Count(dvcman->plugin_names);
+ pc = ArrayList_Count(dvcman->plugins);
+ if (nc != pc)
+ return NULL;
- for (i = 0; i < dvcman->num_plugins; i++)
+ ArrayList_Lock(dvcman->plugin_names);
+ ArrayList_Lock(dvcman->plugins);
+ for (i = 0; i < pc; i++)
{
- if (dvcman->plugin_names[i] == name || strcmp(dvcman->plugin_names[i], name) == 0)
+ const char* cur = ArrayList_GetItem(dvcman->plugin_names, i);
+ if (strcmp(cur, name) == 0)
{
- return dvcman->plugins[i];
+ plugin = ArrayList_GetItem(dvcman->plugins, i);
+ break;
}
}
-
- return NULL;
+ ArrayList_Unlock(dvcman->plugin_names);
+ ArrayList_Unlock(dvcman->plugins);
+ return plugin;
}
static ADDIN_ARGV* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
@@ -196,38 +192,45 @@ static IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager*
UINT32 ChannelId)
{
int index;
- BOOL found = FALSE;
- DVCMAN_CHANNEL* channel;
+ IWTSVirtualChannel* channel = NULL;
DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
ArrayList_Lock(dvcman->channels);
- index = 0;
- channel = (DVCMAN_CHANNEL*)ArrayList_GetItem(dvcman->channels, index++);
-
- while (channel)
+ for (index = 0; index < ArrayList_Count(dvcman->channels); index++)
{
- if (channel->channel_id == ChannelId)
+ DVCMAN_CHANNEL* cur = (DVCMAN_CHANNEL*)ArrayList_GetItem(dvcman->channels, index);
+ if (cur->channel_id == ChannelId)
{
- found = TRUE;
+ channel = &cur->iface;
break;
}
-
- channel = (DVCMAN_CHANNEL*)ArrayList_GetItem(dvcman->channels, index++);
}
ArrayList_Unlock(dvcman->channels);
- return (found) ? ((IWTSVirtualChannel*)channel) : NULL;
+ return channel;
+}
+
+static void dvcman_plugin_terminate(void* plugin)
+{
+ IWTSPlugin* pPlugin = plugin;
+
+ UINT error = IFCALLRESULT(CHANNEL_RC_OK, pPlugin->Terminated, pPlugin);
+ if (error != CHANNEL_RC_OK)
+ WLog_ERR(TAG, "Terminated failed with error %" PRIu32 "!", error);
}
+static void wts_listener_free(void* arg)
+{
+ DVCMAN_LISTENER* listener = (DVCMAN_LISTENER*)arg;
+ dvcman_wtslistener_free(listener);
+}
static IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
{
+ wObject* obj;
DVCMAN* dvcman;
dvcman = (DVCMAN*)calloc(1, sizeof(DVCMAN));
if (!dvcman)
- {
- WLog_Print(plugin->log, WLOG_ERROR, "calloc failed!");
return NULL;
- }
dvcman->iface.CreateListener = dvcman_create_listener;
dvcman->iface.DestroyListener = dvcman_destroy_listener;
@@ -238,24 +241,36 @@ static IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
dvcman->channels = ArrayList_New(TRUE);
if (!dvcman->channels)
- {
- WLog_Print(plugin->log, WLOG_ERROR, "ArrayList_New failed!");
- free(dvcman);
- return NULL;
- }
+ goto fail;
- dvcman->channels->object.fnObjectFree = dvcman_channel_free;
- dvcman->pool = StreamPool_New(TRUE, 10);
+ obj = ArrayList_Object(dvcman->channels);
+ obj->fnObjectFree = dvcman_channel_free;
+ dvcman->pool = StreamPool_New(TRUE, 10);
if (!dvcman->pool)
- {
- WLog_Print(plugin->log, WLOG_ERROR, "StreamPool_New failed!");
- ArrayList_Free(dvcman->channels);
- free(dvcman);
- return NULL;
- }
-
- return (IWTSVirtualChannelManager*)dvcman;
+ goto fail;
+
+ dvcman->listeners = ArrayList_New(TRUE);
+ if (!dvcman->listeners)
+ goto fail;
+ obj = ArrayList_Object(dvcman->listeners);
+ obj->fnObjectFree = wts_listener_free;
+
+ dvcman->plugin_names = ArrayList_New(TRUE);
+ if (!dvcman->plugin_names)
+ goto fail;
+ obj = ArrayList_Object(dvcman->plugin_names);
+ obj->fnObjectFree = free;
+
+ dvcman->plugins = ArrayList_New(TRUE);
+ if (!dvcman->plugins)
+ goto fail;
+ obj = ArrayList_Object(dvcman->plugins);
+ obj->fnObjectFree = dvcman_plugin_terminate;
+ return &dvcman->iface;
+fail:
+ dvcman_free(plugin, &dvcman->iface);
+ return NULL;
}
/**
@@ -304,31 +319,22 @@ static DVCMAN_CHANNEL* dvcman_channel_new(drdynvcPlugin* drdynvc,
channel = (DVCMAN_CHANNEL*)calloc(1, sizeof(DVCMAN_CHANNEL));
if (!channel)
- {
- WLog_Print(drdynvc->log, WLOG_ERROR, "calloc failed!");
- return NULL;
- }
+ goto fail;
channel->dvcman = (DVCMAN*)pChannelMgr;
channel->channel_id = ChannelId;
channel->channel_name = _strdup(ChannelName);
if (!channel->channel_name)
- {
- WLog_Print(drdynvc->log, WLOG_ERROR, "_strdup failed!");
- free(channel);
- return NULL;
- }
+ goto fail;
if (!InitializeCriticalSectionEx(&(channel->lock), 0, 0))
- {
- WLog_Print(drdynvc->log, WLOG_ERROR, "InitializeCriticalSectionEx failed!");
- free(channel->channel_name);
- free(channel);
- return NULL;
- }
+ goto fail;
return channel;
+fail:
+ dvcman_channel_free(channel);
+ return NULL;
}
static void dvcman_channel_free(void* arg)
@@ -341,6 +347,7 @@ static void dvcman_channel_free(void* arg)
if (channel->channel_callback)
{
IFCALL(channel->channel_callback->OnClose, channel->channel_callback);
+ channel->channel_callback = NULL;
}
if (channel->status == CHANNEL_RC_OK)
@@ -374,33 +381,29 @@ static void dvcman_channel_free(void* arg)
free(channel);
}
-static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr)
+static void dvcman_clear(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr)
{
- size_t i;
- IWTSPlugin* pPlugin;
DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
- UINT error;
- ArrayList_Free(dvcman->channels);
- for (i = 0; i < dvcman->num_listeners; i++)
- {
- DVCMAN_LISTENER* listener = (DVCMAN_LISTENER*)dvcman->listeners[i];
- dvcman_wtslistener_free(listener);
- }
+ WINPR_UNUSED(drdynvc);
- dvcman->num_listeners = 0;
+ ArrayList_Clear(dvcman->plugins);
+ ArrayList_Clear(dvcman->channels);
+ ArrayList_Clear(dvcman->plugin_names);
+ ArrayList_Clear(dvcman->listeners);
+}
- for (i = 0; i < dvcman->num_plugins; i++)
- {
- pPlugin = dvcman->plugins[i];
+static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr)
+{
+ DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
- if (pPlugin->Terminated)
- if ((error = pPlugin->Terminated(pPlugin)))
- WLog_Print(drdynvc->log, WLOG_ERROR, "Terminated failed with error %" PRIu32 "!",
- error);
- }
+ WINPR_UNUSED(drdynvc);
+
+ ArrayList_Free(dvcman->plugins);
+ ArrayList_Free(dvcman->channels);
+ ArrayList_Free(dvcman->plugin_names);
+ ArrayList_Free(dvcman->listeners);
- dvcman->num_plugins = 0;
StreamPool_Free(dvcman->pool);
free(dvcman);
}
@@ -413,24 +416,26 @@ static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChan
static UINT dvcman_init(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr)
{
size_t i;
- IWTSPlugin* pPlugin;
DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
- UINT error;
+ UINT error = CHANNEL_RC_OK;
- for (i = 0; i < dvcman->num_plugins; i++)
+ ArrayList_Lock(dvcman->plugins);
+ for (i = 0; i < ArrayList_Count(dvcman->plugins); i++)
{
- pPlugin = dvcman->plugins[i];
+ IWTSPlugin* pPlugin = ArrayList_GetItem(dvcman->plugins, i);
- if (pPlugin->Initialize)
- if ((error = pPlugin->Initialize(pPlugin, pChannelMgr)))
- {
- WLog_Print(drdynvc->log, WLOG_ERROR, "Initialize failed with error %" PRIu32 "!",
- error);
- return error;
- }
+ error = IFCALLRESULT(CHANNEL_RC_OK, pPlugin->Initialize, pPlugin, pChannelMgr);
+ if (error != CHANNEL_RC_OK)
+ {
+ WLog_Print(drdynvc->log, WLOG_ERROR, "Initialize failed with error %" PRIu32 "!",
+ error);
+ goto fail;
+ }
}
- return CHANNEL_RC_OK;
+fail:
+ ArrayList_Unlock(dvcman->plugins);
+ return error;
}
/**
@@ -482,7 +487,6 @@ static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelMana
BOOL bAccept;
DVCMAN_CHANNEL* channel;
DrdynvcClientContext* context;
- IWTSVirtualChannelCallback* pCallback;
DVCMAN* dvcman = (DVCMAN*)pChannelMgr;
UINT error;
@@ -493,18 +497,20 @@ static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelMana
}
channel->status = ERROR_NOT_CONNECTED;
- ArrayList_Add(dvcman->channels, channel);
+ if (ArrayList_Add(dvcman->channels, channel) < 0)
+ return ERROR_INTERNAL_ERROR;
- for (i = 0; i < dvcman->num_listeners; i++)
+ ArrayList_Lock(dvcman->listeners);
+ for (i = 0; i < ArrayList_Count(dvcman->listeners); i++)
{
- DVCMAN_LISTENER* listener = (DVCMAN_LISTENER*)dvcman->listeners[i];
+ DVCMAN_LISTENER* listener = (DVCMAN_LISTENER*)ArrayList_GetItem(dvcman->listeners, i);
if (strcmp(listener->channel_name, ChannelName) == 0)
{
+ IWTSVirtualChannelCallback* pCallback = NULL;
channel->iface.Write = dvcman_write_channel;
channel->iface.Close = dvcman_close_channel_iface;
bAccept = TRUE;
- pCallback = NULL;
if ((error = listener->listener_callback->OnNewChannelConnection(
listener->listener_callback, &channel->iface, NULL, &bAccept, &pCallback)) ==
@@ -524,7 +530,7 @@ static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelMana
WLog_Print(drdynvc->log, WLOG_ERROR,
"context.OnChannelConnected failed with error %" PRIu32 "", error);
- return error;
+ goto fail;
}
else
{
@@ -532,19 +538,23 @@ static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelMana
{
WLog_Print(drdynvc->log, WLOG_ERROR,
"OnNewChannelConnection failed with error %" PRIu32 "!", error);
- return error;
+ goto fail;
}
else
{
WLog_Print(drdynvc->log, WLOG_ERROR,
"OnNewChannelConnection returned with bAccept FALSE!");
- return ERROR_INTERNAL_ERROR;
+ error = ERROR_INTERNAL_ERROR;
+ goto fail;
}
}
}
}
+ error = ERROR_INTERNAL_ERROR;
+fail:
+ ArrayList_Unlock(dvcman->listeners);
- return ERROR_INTERNAL_ERROR;
+ return error;
}
/**
@@ -608,10 +618,10 @@ static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32
if (drdynvc && bSendClosePDU)
{
- wStream* s = Stream_New(NULL, 5);
+ wStream* s = StreamPool_Take(dvcman->pool, 5);
if (!s)
{
- WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!");
+ WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!");
error = CHANNEL_RC_NO_MEMORY;
}
else
@@ -689,7 +699,7 @@ static UINT dvcman_receive_channel_data(drdynvcPlugin* drdynvc,
if (channel->dvc_data)
{
/* Fragmented data */
- if (Stream_GetPosition(channel->dvc_data) + dataSize > Stream_Capacity(channel->dvc_data))
+ if (Stream_GetPosition(channel->dvc_data) + dataSize > channel->dvc_data_length)
{
WLog_Print(drdynvc->log, WLOG_ERROR, "data exceeding declared length!");
Stream_Release(channel->dvc_data);
@@ -764,16 +774,16 @@ static UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s)
return CHANNEL_RC_OK;
case CHANNEL_RC_NOT_CONNECTED:
- Stream_Free(s, TRUE);
+ Stream_Release(s);
return CHANNEL_RC_OK;
case CHANNEL_RC_BAD_CHANNEL_HANDLE:
- Stream_Free(s, TRUE);
+ Stream_Release(s);
WLog_ERR(TAG, "VirtualChannelWriteEx failed with CHANNEL_RC_BAD_CHANNEL_HANDLE");
return status;
default:
- Stream_Free(s, TRUE);
+ Stream_Release(s);
WLog_Print(drdynvc->log, WLOG_ERROR,
"VirtualChannelWriteEx failed with %s [%08" PRIX32 "]",
WTSErrorToString(status), status);
@@ -795,17 +805,20 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const B
UINT8 cbLen;
unsigned long chunkLength;
UINT status = CHANNEL_RC_BAD_INIT_HANDLE;
+ DVCMAN* dvcman;
if (!drdynvc)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
+ dvcman = (DVCMAN*)drdynvc->channel_mgr;
+
WLog_Print(drdynvc->log, WLOG_DEBUG, "write_data: ChannelId=%" PRIu32 " size=%" PRIu32 "",
ChannelId, dataSize);
- data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH);
+ data_out = StreamPool_Take(dvcman->pool, CHANNEL_CHUNK_LENGTH);
if (!data_out)
{
- WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!");
+ WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!");
return CHANNEL_RC_NO_MEMORY;
}
@@ -815,7 +828,8 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const B
if (dataSize == 0)
{
- status = dvcman_close_channel(drdynvc->channel_mgr, ChannelId, TRUE);
+ dvcman_close_channel(drdynvc->channel_mgr, ChannelId, TRUE);
+ Stream_Release(data_out);
}
else if (dataSize <= CHANNEL_CHUNK_LENGTH - pos)
{
@@ -841,11 +855,11 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const B
while (status == CHANNEL_RC_OK && dataSize > 0)
{
- data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH);
+ data_out = StreamPool_Take(dvcman->pool, CHANNEL_CHUNK_LENGTH);
if (!data_out)
{
- WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!");
+ WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!");
return CHANNEL_RC_NO_MEMORY;
}
@@ -886,12 +900,14 @@ static UINT drdynvc_send_capability_response(drdynvcPlugin* drdynvc)
{
UINT status;
wStream* s;
+ DVCMAN* dvcman;
if (!drdynvc)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
+ dvcman = (DVCMAN*)drdynvc->channel_mgr;
WLog_Print(drdynvc->log, WLOG_TRACE, "capability_response");
- s = Stream_New(NULL, 4);
+ s = StreamPool_Take(dvcman->pool, 4);
if (!s)
{
@@ -1002,11 +1018,13 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int c
UINT channel_status;
char* name;
size_t length;
+ DVCMAN* dvcman;
WINPR_UNUSED(Sp);
if (!drdynvc)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
+ dvcman = (DVCMAN*)drdynvc->channel_mgr;
if (drdynvc->state == DRDYNVC_STATE_CAPABILITIES)
{
/**
@@ -1039,11 +1057,11 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int c
WLog_Print(drdynvc->log, WLOG_DEBUG,
"process_create_request: ChannelId=%" PRIu32 " ChannelName=%s", ChannelId, name);
channel_status = dvcman_create_channel(drdynvc, drdynvc->channel_mgr, ChannelId, name);
- data_out = Stream_New(NULL, pos + 4);
+ data_out = StreamPool_Take(dvcman->pool, pos + 4);
if (!data_out)
{
- WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!");
+ WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!");
return CHANNEL_RC_NO_MEMORY;
}
@@ -1231,22 +1249,23 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc,
if (dataFlags & CHANNEL_FLAG_FIRST)
{
+ DVCMAN* mgr = (DVCMAN*)drdynvc->channel_mgr;
if (drdynvc->data_in)
- Stream_Free(drdynvc->data_in, TRUE);
+ Stream_Release(drdynvc->data_in);
- drdynvc->data_in = Stream_New(NULL, totalLength);
+ drdynvc->data_in = StreamPool_Take(mgr->pool, totalLength);
}
if (!(data_in = drdynvc->data_in))
{
- WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!");
+ WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!");
return CHANNEL_RC_NO_MEMORY;
}
if (!Stream_EnsureRemainingCapacity(data_in, dataLength))
{
WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
- Stream_Free(drdynvc->data_in, TRUE);
+ Stream_Release(drdynvc->data_in);
drdynvc->data_in = NULL;
return ERROR_INTERNAL_ERROR;
}
@@ -1255,7 +1274,9 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc,
if (dataFlags & CHANNEL_FLAG_LAST)
{
- if (Stream_Capacity(data_in) != Stream_GetPosition(data_in))
+ const size_t cap = Stream_Capacity(data_in);
+ const size_t pos = Stream_GetPosition(data_in);
+ if (cap < pos)
{
WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_plugin_process_received: read error");
return ERROR_INVALID_DATA;
@@ -1304,7 +1325,7 @@ static void VCAPITYPE drdynvc_virtual_channel_open_event_ex(LPVOID lpUserParam,
case CHANNEL_EVENT_WRITE_COMPLETE:
{
wStream* s = (wStream*)pData;
- Stream_Free(s, TRUE);
+ Stream_Release(s);
}
break;
@@ -1359,7 +1380,7 @@ static DWORD WINAPI drdynvc_virtual_channel_client_thread(LPVOID arg)
"drdynvc_order_recv failed with error %" PRIu32 "!", error);
}
- Stream_Free(data, TRUE);
+ Stream_Release(data);
}
}
@@ -1397,7 +1418,41 @@ static void drdynvc_queue_object_free(void* obj)
s = (wStream*)msg->wParam;
if (s)
- Stream_Free(s, TRUE);
+ Stream_Release(s);
+}
+
+static UINT drdynvc_virtual_channel_event_initialized(drdynvcPlugin* drdynvc, LPVOID pData,
+ UINT32 dataLength)
+{
+ UINT error = CHANNEL_RC_OK;
+ WINPR_UNUSED(pData);
+ WINPR_UNUSED(dataLength);
+
+ if (!drdynvc)
+ goto error;
+
+ drdynvc->queue = MessageQueue_New(NULL);
+
+ if (!drdynvc->queue)
+ {
+ error = CHANNEL_RC_NO_MEMORY;
+ WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_New failed!");
+ goto error;
+ }
+
+ drdynvc->queue->object.fnObjectFree = drdynvc_queue_object_free;
+ drdynvc->channel_mgr = dvcman_new(drdynvc);
+
+ if (!drdynvc->channel_mgr)
+ {
+ error = CHANNEL_RC_NO_MEMORY;
+ WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_new failed!");
+ goto error;
+ }
+
+ return CHANNEL_RC_OK;
+error:
+ return ERROR_INTERNAL_ERROR;
}
/**
@@ -1431,25 +1486,6 @@ static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVO
return status;
}
- drdynvc->queue = MessageQueue_New(NULL);
-
- if (!drdynvc->queue)
- {
- error = CHANNEL_RC_NO_MEMORY;
- WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_New failed!");
- goto error;
- }
-
- drdynvc->queue->object.fnObjectFree = drdynvc_queue_object_free;
- drdynvc->channel_mgr = dvcman_new(drdynvc);
-
- if (!drdynvc->channel_mgr)
- {
- error = CHANNEL_RC_NO_MEMORY;
- WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_new failed!");
- goto error;
- }
-
settings = (rdpSettings*)drdynvc->channelEntryPoints.pExtendedData;
for (index = 0; index < settings->DynamicChannelCount; index++)
@@ -1512,10 +1548,9 @@ static UINT drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc)
return status;
}
- MessageQueue_Free(drdynvc->queue);
CloseHandle(drdynvc->thread);
- drdynvc->queue = NULL;
drdynvc->thread = NULL;
+
status = drdynvc->channelEntryPoints.pVirtualChannelCloseEx(drdynvc->InitHandle,
drdynvc->OpenHandle);
@@ -1525,20 +1560,16 @@ static UINT drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc)
WTSErrorToString(status), status);
}
+ dvcman_clear(drdynvc, drdynvc->channel_mgr);
+ MessageQueue_Clear(drdynvc->queue);
drdynvc->OpenHandle = 0;
if (drdynvc->data_in)
{
- Stream_Free(drdynvc->data_in, TRUE);
+ Stream_Release(drdynvc->data_in);
drdynvc->data_in = NULL;
}
- if (drdynvc->channel_mgr)
- {
- dvcman_free(drdynvc, drdynvc->channel_mgr);
- drdynvc->channel_mgr = NULL;
- }
-
return status;
}
@@ -1552,6 +1583,13 @@ static UINT drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc)
if (!drdynvc)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
+ if (drdynvc->channel_mgr)
+ {
+ dvcman_free(drdynvc, drdynvc->channel_mgr);
+ drdynvc->channel_mgr = NULL;
+ }
+ MessageQueue_Free(drdynvc->queue);
+ drdynvc->queue = NULL;
drdynvc->InitHandle = 0;
free(drdynvc->context);
free(drdynvc);
@@ -1560,6 +1598,7 @@ static UINT drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc)
static UINT drdynvc_virtual_channel_event_attached(drdynvcPlugin* drdynvc)
{
+ UINT error = CHANNEL_RC_OK;
size_t i;
DVCMAN* dvcman;
@@ -1571,25 +1610,27 @@ static UINT drdynvc_virtual_channel_event_attached(drdynvcPlugin* drdynvc)
if (!dvcman)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
- for (i = 0; i < dvcman->num_plugins; i++)
+ ArrayList_Lock(dvcman->plugins);
+ for (i = 0; i < ArrayList_Count(dvcman->plugins); i++)
{
- UINT error;
- IWTSPlugin* pPlugin = dvcman->plugins[i];
+ IWTSPlugin* pPlugin = ArrayList_GetItem(dvcman->plugins, i);
- if (pPlugin->Attached)
- if ((error = pPlugin->Attached(pPlugin)))
- {
- WLog_Print(drdynvc->log, WLOG_ERROR, "Attach failed with error %" PRIu32 "!",
- error);
- return error;
- }
+ error = IFCALLRESULT(CHANNEL_RC_OK, pPlugin->Attached, pPlugin);
+ if (error != CHANNEL_RC_OK)
+ {
+ WLog_Print(drdynvc->log, WLOG_ERROR, "Attach failed with error %" PRIu32 "!", error);
+ goto fail;
+ }
}
- return CHANNEL_RC_OK;
+fail:
+ ArrayList_Unlock(dvcman->plugins);
+ return error;
}
static UINT drdynvc_virtual_channel_event_detached(drdynvcPlugin* drdynvc)
{
+ UINT error = CHANNEL_RC_OK;
size_t i;
DVCMAN* dvcman;
@@ -1601,21 +1642,23 @@ static UINT drdynvc_virtual_channel_event_detached(drdynvcPlugin* drdynvc)
if (!dvcman)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
- for (i = 0; i < dvcman->num_plugins; i++)
+ ArrayList_Lock(dvcman->plugins);
+ for (i = 0; i < ArrayList_Count(dvcman->plugins); i++)
{
- UINT error;
- IWTSPlugin* pPlugin = dvcman->plugins[i];
+ IWTSPlugin* pPlugin = ArrayList_GetItem(dvcman->plugins, i);
- if (pPlugin->Detached)
- if ((error = pPlugin->Detached(pPlugin)))
- {
- WLog_Print(drdynvc->log, WLOG_ERROR, "Detach failed with error %" PRIu32 "!",
- error);
- return error;
- }
+ error = IFCALLRESULT(CHANNEL_RC_OK, pPlugin->Detached, pPlugin);
+ if (error != CHANNEL_RC_OK)
+ {
+ WLog_Print(drdynvc->log, WLOG_ERROR, "Detach failed with error %" PRIu32 "!", error);
+ goto fail;
+ }
}
- return CHANNEL_RC_OK;
+fail:
+ ArrayList_Unlock(dvcman->plugins);
+
+ return error;
}
static VOID VCAPITYPE drdynvc_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle,
@@ -1633,6 +1676,9 @@ static VOID VCAPITYPE drdynvc_virtual_channel_init_event_ex(LPVOID lpUserParam,
switch (event)
{
+ case CHANNEL_EVENT_INITIALIZED:
+ error = drdynvc_virtual_channel_event_initialized(drdynvc, pData, dataLength);
+ break;
case CHANNEL_EVENT_CONNECTED:
if ((error = drdynvc_virtual_channel_event_connected(drdynvc, pData, dataLength)))
WLog_Print(drdynvc->log, WLOG_ERROR,
diff --git a/channels/drdynvc/client/drdynvc_main.h b/channels/drdynvc/client/drdynvc_main.h
index f91059988..646c8fdfb 100644
--- a/channels/drdynvc/client/drdynvc_main.h
+++ b/channels/drdynvc/client/drdynvc_main.h
@@ -37,21 +37,16 @@
typedef struct drdynvc_plugin drdynvcPlugin;
-#define MAX_PLUGINS 32
-
struct _DVCMAN
{
IWTSVirtualChannelManager iface;
drdynvcPlugin* drdynvc;
- size_t num_plugins;
- const char* plugin_names[MAX_PLUGINS];
- IWTSPlugin* plugins[MAX_PLUGINS];
-
- size_t num_listeners;
- IWTSListener* listeners[MAX_PLUGINS];
+ wArrayList* plugin_names;
+ wArrayList* plugins;
+ wArrayList* listeners;
wArrayList* channels;
wStreamPool* pool;
};
diff --git a/channels/echo/client/echo_main.c b/channels/echo/client/echo_main.c
index e830122a7..c8dc4d8a5 100644
--- a/channels/echo/client/echo_main.c
+++ b/channels/echo/client/echo_main.c
@@ -59,6 +59,7 @@ struct _ECHO_PLUGIN
IWTSPlugin iface;
ECHO_LISTENER_CALLBACK* listener_callback;
+ IWTSListener* listener;
};
/**
@@ -142,8 +143,8 @@ static UINT echo_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage
echo->listener_callback->plugin = pPlugin;
echo->listener_callback->channel_mgr = pChannelMgr;
- return pChannelMgr->CreateListener(pChannelMgr, "ECHO", 0,
- (IWTSListenerCallback*)echo->listener_callback, NULL);
+ return pChannelMgr->CreateListener(pChannelMgr, "ECHO", 0, &echo->listener_callback->iface,
+ &echo->listener);
}
/**
@@ -154,7 +155,12 @@ static UINT echo_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage
static UINT echo_plugin_terminated(IWTSPlugin* pPlugin)
{
ECHO_PLUGIN* echo = (ECHO_PLUGIN*)pPlugin;
-
+ if (echo && echo->listener_callback)
+ {
+ IWTSVirtualChannelManager* mgr = echo->listener_callback->channel_mgr;
+ if (mgr)
+ IFCALL(mgr->DestroyListener, mgr, echo->listener);
+ }
free(echo);
return CHANNEL_RC_OK;
diff --git a/channels/geometry/client/geometry_main.c b/channels/geometry/client/geometry_main.c
index f08b76cf1..eb65b2ca2 100644
--- a/channels/geometry/client/geometry_main.c
+++ b/channels/geometry/client/geometry_main.c
@@ -410,9 +410,9 @@ static UINT geometry_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMa
geometry->listener_callback->iface.OnNewChannelConnection = geometry_on_new_channel_connection;
geometry->listener_callback->plugin = pPlugin;
geometry->listener_callback->channel_mgr = pChannelMgr;
- status = pChannelMgr->CreateListener(pChannelMgr, GEOMETRY_DVC_CHANNEL_NAME, 0,
- (IWTSListenerCallback*)geometry->listener_callback,
- &(geometry->listener));
+ status =
+ pChannelMgr->CreateListener(pChannelMgr, GEOMETRY_DVC_CHANNEL_NAME, 0,
+ &geometry->listener_callback->iface, &(geometry->listener));
geometry->listener->pInterface = geometry->iface.pInterface;
return status;
}
@@ -427,6 +427,13 @@ static UINT geometry_plugin_terminated(IWTSPlugin* pPlugin)
GEOMETRY_PLUGIN* geometry = (GEOMETRY_PLUGIN*)pPlugin;
GeometryClientContext* context = (GeometryClientContext*)geometry->iface.pInterface;
+ if (geometry && geometry->listener_callback)
+ {
+ IWTSVirtualChannelManager* mgr = geometry->listener_callback->channel_mgr;
+ if (mgr)
+ IFCALL(mgr->DestroyListener, mgr, geometry->listener);
+ }
+
if (context)
HashTable_Free(context->geometries);
diff --git a/channels/printer/client/cups/printer_cups.c b/channels/printer/client/cups/printer_cups.c
index 8e462c1b1..1f9f07b24 100644
--- a/channels/printer/client/cups/printer_cups.c
+++ b/channels/printer/client/cups/printer_cups.c
@@ -364,13 +364,15 @@ static void printer_cups_add_ref_driver(rdpPrinterDriver* driver)
}
/* Singleton */
-static rdpCupsPrinterDriver* cups_driver = NULL;
+static rdpCupsPrinterDriver* uniq_cups_driver = NULL;
static void printer_cups_release_ref_driver(rdpPrinterDriver* driver)
{
rdpCupsPrinterDriver* cups_driver = (rdpCupsPrinterDriver*)driver;
if (cups_driver->references <= 1)
{
+ if (uniq_cups_driver == cups_driver)
+ uniq_cups_driver = NULL;
free(cups_driver);
cups_driver = NULL;
}
@@ -384,23 +386,23 @@ rdpPrinterDriver* cups_freerdp_printer_client_subsystem_entry(void)
FREERDP_API rdpPrinterDriver* freerdp_printer_client_subsystem_entry(void)
#endif
{
- if (!cups_driver)
+ if (!uniq_cups_driver)
{
- cups_driver = (rdpCupsPrinterDriver*)calloc(1, sizeof(rdpCupsPrinterDriver));
+ uniq_cups_driver = (rdpCupsPrinterDriver*)calloc(1, sizeof(rdpCupsPrinterDriver));
- if (!cups_driver)
+ if (!uniq_cups_driver)
return NULL;
- cups_driver->driver.EnumPrinters = printer_cups_enum_printers;
- cups_driver->driver.ReleaseEnumPrinters = printer_cups_release_enum_printers;
- cups_driver->driver.GetPrinter = printer_cups_get_printer;
+ uniq_cups_driver->driver.EnumPrinters = printer_cups_enum_printers;
+ uniq_cups_driver->driver.ReleaseEnumPrinters = printer_cups_release_enum_printers;
+ uniq_cups_driver->driver.GetPrinter = printer_cups_get_printer;
- cups_driver->driver.AddRef = printer_cups_add_ref_driver;
- cups_driver->driver.ReleaseRef = printer_cups_release_ref_driver;
+ uniq_cups_driver->driver.AddRef = printer_cups_add_ref_driver;
+ uniq_cups_driver->driver.ReleaseRef = printer_cups_release_ref_driver;
- cups_driver->id_sequence = 1;
- cups_driver->driver.AddRef(&cups_driver->driver);
+ uniq_cups_driver->id_sequence = 1;
+ uniq_cups_driver->driver.AddRef(&uniq_cups_driver->driver);
}
- return &cups_driver->driver;
+ return &uniq_cups_driver->driver;
}
diff --git a/channels/rail/client/rail_orders.c b/channels/rail/client/rail_orders.c
index 86a345622..c394a5925 100644
--- a/channels/rail/client/rail_orders.c
+++ b/channels/rail/client/rail_orders.c
@@ -49,8 +49,7 @@ UINT rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType)
rail_write_pdu_header(s, orderType, orderLength);
Stream_SetPosition(s, orderLength);
WLog_Print(rail->log, WLOG_DEBUG, "Sending %s PDU, length: %" PRIu16 "",
- RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)],
- orderLength);
+ rail_get_order_type_string(orderType), orderLength);
return rail_send_channel_data(rail, s);
}
@@ -926,8 +925,7 @@ UINT rail_order_recv(railPlugin* rail, wStream* s)
}
WLog_Print(rail->log, WLOG_DEBUG, "Received %s PDU, length:%" PRIu16 "",
- RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)],
- orderLength);
+ rail_get_order_type_string(orderType), orderLength);
switch (orderType)
{
diff --git a/channels/rail/rail_common.c b/channels/rail/rail_common.c
index 4e1a81df7..902a738c5 100644
--- a/channels/rail/rail_common.c
+++ b/channels/rail/rail_common.c
@@ -27,29 +27,34 @@
#define TAG CHANNELS_TAG("rail.common")
-const char* const RAIL_ORDER_TYPE_STRINGS[] = { "",
- "Execute",
- "Activate",
- "System Parameters Update",
- "System Command",
- "Handshake",
- "Notify Event",
- "",
- "Window Move",
- "Local Move/Size",
- "Min Max Info",
- "Client Status",
- "System Menu",
- "Language Bar Info",
- "Get Application ID Request",
- "Get Application ID Response",
- "Execute Result",
- "",
- "",
- "",
- "",
- "",
- "" };
+static const char* const RAIL_ORDER_TYPE_STRINGS[] = { "",
+ "Execute",
+ "Activate",
+ "System Parameters Update",
+ "System Command",
+ "Handshake",
+ "Notify Event",
+ "",
+ "Window Move",
+ "Local Move/Size",
+ "Min Max Info",
+ "Client Status",
+ "System Menu",
+ "Language Bar Info",
+ "Get Application ID Request",
+ "Get Application ID Response",
+ "Execute Result",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "" };
+
+const char* rail_get_order_type_string(BYTE orderType)
+{
+ return RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)];
+}
/**
* Function description
diff --git a/channels/rail/rail_common.h b/channels/rail/rail_common.h
index aa83b8ac4..6d411ebb1 100644
--- a/channels/rail/rail_common.h
+++ b/channels/rail/rail_common.h
@@ -26,7 +26,7 @@
#include <freerdp/rail.h>
-extern const char* const RAIL_ORDER_TYPE_STRINGS[];
+const char* rail_get_order_type_string(BYTE orderType);
#define RAIL_PDU_HEADER_LENGTH 4
diff --git a/channels/rail/server/rail_main.c b/channels/rail/server/rail_main.c
index 385b0dd9c..18a707242 100644
--- a/channels/rail/server/rail_main.c
+++ b/channels/rail/server/rail_main.c
@@ -71,8 +71,8 @@ UINT rail_send_pdu(RailServerContext* context, wStream* s, UINT16 orderType)
Stream_SetPosition(s, 0);
rail_write_pdu_header(s, orderType, orderLength);
Stream_SetPosition(s, orderLength);
- WLog_DBG(TAG, "Sending %s PDU, length: %" PRIu16 "",
- RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], orderLength);
+ WLog_DBG(TAG, "Sending %s PDU, length: %" PRIu16 "", rail_get_order_type_string(orderType),
+ orderLength);
return rail_send(context, s, orderLength);
}
@@ -1573,8 +1573,8 @@ UINT rail_server_handle_messages(RailServerContext* context)
return ERROR_INTERNAL_ERROR;
}
- WLog_DBG(TAG, "Received %s PDU, length:%" PRIu16 "",
- RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], orderLength);
+ WLog_DBG(TAG, "Received %s PDU, length:%" PRIu16 "", rail_get_order_type_string(orderType),
+ orderLength);
switch (orderType)
{
diff --git a/channels/rdpei/client/rdpei_main.c b/channels/rdpei/client/rdpei_main.c
index 7dd65211d..0a0cfefb2 100644
--- a/channels/rdpei/client/rdpei_main.c
+++ b/channels/rdpei/client/rdpei_main.c
@@ -571,8 +571,7 @@ static UINT rdpei_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag
rdpei->listener_callback->channel_mgr = pChannelMgr;
if ((error = pChannelMgr->CreateListener(pChannelMgr, RDPEI_DVC_CHANNEL_NAME, 0,
- (IWTSListenerCallback*)rdpei->listener_callback,
- &(rdpei->listener))))
+ &rdpei->listener_callback->iface, &(rdpei->listener))))
{
WLog_ERR(TAG, "ChannelMgr->CreateListener failed with error %" PRIu32 "!", error);
goto error_out;
@@ -598,6 +597,12 @@ static UINT rdpei_plugin_terminated(IWTSPlugin* pPlugin)
if (!pPlugin)
return ERROR_INVALID_PARAMETER;
+ if (rdpei && rdpei->listener_callback)
+ {
+ IWTSVirtualChannelManager* mgr = rdpei->listener_callback->channel_mgr;
+ if (mgr)
+ IFCALL(mgr->DestroyListener, mgr, rdpei->listener);
+ }
free(rdpei->listener_callback);
free(rdpei->context);
free(rdpei);
diff --git a/channels/rdpei/rdpei_common.c b/channels/rdpei/rdpei_common.c
index adf9710d1..f01d4dd78 100644
--- a/channels/rdpei/rdpei_common.c
+++ b/channels/rdpei/rdpei_common.c
@@ -199,18 +199,18 @@ BOOL rdpei_write_4byte_unsigned(wStream* s, UINT32 value)
{
BYTE byte;
- if (value <= 0x3F)
+ if (value <= 0x3FUL)
{
Stream_Write_UINT8(s, value);
}
- else if (value <= 0x3FFF)
+ else if (value <= 0x3FFFUL)
{
byte = (value >> 8) & 0x3F;
Stream_Write_UINT8(s, byte | 0x40);
byte = (value & 0xFF);
Stream_Write_UINT8(s, byte);
}
- else if (value <= 0x3FFFFF)
+ else if (value <= 0x3FFFFFUL)
{
byte = (value >> 16) & 0x3F;
Stream_Write_UINT8(s, byte | 0x80);
@@ -219,7 +219,7 @@ BOOL rdpei_write_4byte_unsigned(wStream* s, UINT32 value)
byte = (value & 0xFF);
Stream_Write_UINT8(s, byte);
}
- else if (value <= 0x3FFFFF)
+ else if (value <= 0x3FFFFFFFUL)
{
byte = (value >> 24) & 0x3F;
Stream_Write_UINT8(s, byte | 0xC0);
@@ -306,7 +306,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value)
value *= -1;
}
- if (value <= 0x1F)
+ if (value <= 0x1FUL)
{
byte = value & 0x1F;
@@ -315,7 +315,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value)
Stream_Write_UINT8(s, byte);
}
- else if (value <= 0x1FFF)
+ else if (value <= 0x1FFFUL)
{
byte = (value >> 8) & 0x1F;
@@ -326,7 +326,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value)
byte = (value & 0xFF);
Stream_Write_UINT8(s, byte);
}
- else if (value <= 0x1FFFFF)
+ else if (value <= 0x1FFFFFUL)
{
byte = (value >> 16) & 0x1F;
@@ -339,7 +339,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value)
byte = (value & 0xFF);
Stream_Write_UINT8(s, byte);
}
- else if (value <= 0x1FFFFF)
+ else if (value <= 0x1FFFFFFFUL)
{
byte = (value >> 24) & 0x1F;
@@ -478,12 +478,12 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value)
{
BYTE byte;
- if (value <= 0x1F)
+ if (value <= 0x1FULL)
{
byte = value & 0x1F;
Stream_Write_UINT8(s, byte);
}
- else if (value <= 0x1FFF)
+ else if (value <= 0x1FFFULL)
{
byte = (value >> 8) & 0x1F;
byte |= (1 << 5);
@@ -491,7 +491,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value)
byte = (value & 0xFF);
Stream_Write_UINT8(s, byte);
}
- else if (value <= 0x1FFFFF)
+ else if (value <= 0x1FFFFFULL)
{
byte = (value >> 16) & 0x1F;
byte |= (2 << 5);
@@ -501,7 +501,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value)
byte = (value & 0xFF);
Stream_Write_UINT8(s, byte);
}
- else if (value <= 0x1FFFFF)
+ else if (value <= 0x1FFFFFULL)
{
byte = (value >> 24) & 0x1F;
byte |= (3 << 5);
@@ -513,7 +513,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value)
byte = (value & 0xFF);
Stream_Write_UINT8(s, byte);
}
- else if (value <= 0x1FFFFFFF)
+ else if (value <= 0x1FFFFFFFULL)
{
byte = (value >> 32) & 0x1F;
byte |= (4 << 5);
@@ -527,7 +527,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value)
byte = (value & 0xFF);
Stream_Write_UINT8(s, byte);
}
- else if (value <= 0x1FFFFFFFFF)
+ else if (value <= 0x1FFFFFFFFFULL)
{
byte = (value >> 40) & 0x1F;
byte |= (5 << 5);
@@ -543,7 +543,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value)
byte = (value & 0xFF);
Stream_Write_UINT8(s, byte);
}
- else if (value <= 0x1FFFFFFFFFFF)
+ else if (value <= 0x1FFFFFFFFFFFULL)
{
byte = (value >> 48) & 0x1F;
byte |= (6 << 5);
@@ -561,7 +561,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value)
byte = (value & 0xFF);
Stream_Write_UINT8(s, byte);
}
- else if (value <= 0x1FFFFFFFFFFFFF)
+ else if (value <= 0x1FFFFFFFFFFFFFFFULL)
{
byte = (value >> 56) & 0x1F;
byte |= (7 << 5);
diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c
index 7bc25dba9..6ca75bd1d 100644
--- a/channels/rdpgfx/client/rdpgfx_main.c
+++ b/channels/rdpgfx/client/rdpgfx_main.c
@@ -605,7 +605,7 @@ static UINT rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wS
monitor = &(pdu.monitorDefArray[index]);
DEBUG_RDPGFX(gfx->log,
"RecvResetGraphicsPdu: monitor left:%" PRIi32 " top:%" PRIi32 " right:%" PRIi32
- " left:%" PRIi32 " flags:0x%" PRIx32 "",
+ " bottom:%" PRIi32 " flags:0x%" PRIx32 "",
monitor->left, monitor->top, monitor->right, monitor->bottom, monitor->flags);
}
@@ -1826,12 +1826,6 @@ static UINT rdpgfx_on_close(IWTSVirtualChannelCallback* pChannelCallback)
free_surfaces(context, gfx->SurfaceTable);
evict_cache_slots(context, gfx->MaxCacheSlots, gfx->CacheSlots);
- if (gfx->listener_callback)
- {
- free(gfx->listener_callback);
- gfx->listener_callback = NULL;
- }
-
free(callback);
gfx->UnacknowledgedFrames = 0;
gfx->TotalDecodedFrames = 0;
@@ -1896,8 +1890,7 @@ static UINT rdpgfx_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMana
gfx->listener_callback->plugin = pPlugin;
gfx->listener_callback->channel_mgr = pChannelMgr;
error = pChannelMgr->CreateListener(pChannelMgr, RDPGFX_DVC_CHANNEL_NAME, 0,
- (IWTSListenerCallback*)gfx->listener_callback,
- &(gfx->listener));
+ &gfx->listener_callback->iface, &(gfx->listener));
gfx->listener->pInterface = gfx->iface.pInterface;
DEBUG_RDPGFX(gfx->log, "Initialize");
return error;
@@ -1913,6 +1906,12 @@ static UINT rdpgfx_plugin_terminated(IWTSPlugin* pPlugin)
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)pPlugin;
RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface;
DEBUG_RDPGFX(gfx->log, "Terminated");
+ if (gfx && gfx->listener_callback)
+ {
+ IWTSVirtualChannelManager* mgr = gfx->listener_callback->channel_mgr;
+ if (mgr)
+ IFCALL(mgr->DestroyListener, mgr, gfx->listener);
+ }
rdpgfx_client_context_free(context);
return CHANNEL_RC_OK;
}
diff --git a/channels/rdpsnd/client/mac/CMakeLists.txt b/channels/rdpsnd/client/mac/CMakeLists.txt
index 19f77e404..8b846561a 100644
--- a/channels/rdpsnd/client/mac/CMakeLists.txt
+++ b/channels/rdpsnd/client/mac/CMakeLists.txt
@@ -19,6 +19,7 @@
define_channel_client_subsystem("rdpsnd" "mac" "")
+find_library(COCOA_LIBRARY Cocoa REQUIRED)
FIND_LIBRARY(CORE_FOUNDATION CoreFoundation)
FIND_LIBRARY(CORE_AUDIO CoreAudio REQUIRED)
FIND_LIBRARY(AUDIO_TOOL AudioToolbox REQUIRED)
@@ -38,6 +39,7 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
${AUDIO_TOOL}
${AV_FOUNDATION}
${CORE_AUDIO}
+ ${COCOA_LIBRARY}
${CORE_FOUNDATION})
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp winpr)
diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c
index 2526ec55d..9318c95c6 100644
--- a/channels/rdpsnd/client/rdpsnd_main.c
+++ b/channels/rdpsnd/client/rdpsnd_main.c
@@ -1541,8 +1541,7 @@ static UINT rdpsnd_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMana
rdpsnd->listener_callback->plugin = pPlugin;
rdpsnd->listener_callback->channel_mgr = pChannelMgr;
status = pChannelMgr->CreateListener(pChannelMgr, RDPSND_DVC_CHANNEL_NAME, 0,
- (IWTSListenerCallback*)rdpsnd->listener_callback,
- &(rdpsnd->listener));
+ &rdpsnd->listener_callback->iface, &(rdpsnd->listener));
rdpsnd->listener->pInterface = rdpsnd->iface.pInterface;
return rdpsnd_virtual_channel_event_initialized(rdpsnd);
}
@@ -1557,6 +1556,12 @@ static UINT rdpsnd_plugin_terminated(IWTSPlugin* pPlugin)
rdpsndPlugin* rdpsnd = (rdpsndPlugin*)pPlugin;
if (rdpsnd)
{
+ if (rdpsnd->listener_callback)
+ {
+ IWTSVirtualChannelManager* mgr = rdpsnd->listener_callback->channel_mgr;
+ if (mgr)
+ IFCALL(mgr->DestroyListener, mgr, rdpsnd->listener);
+ }
free(rdpsnd->listener_callback);
free(rdpsnd->iface.pInterface);
}
diff --git a/channels/urbdrc/client/urbdrc_main.c b/channels/urbdrc/client/urbdrc_main.c
index 6dbdc5a41..6f383ecb7 100644
--- a/channels/urbdrc/client/urbdrc_main.c
+++ b/channels/urbdrc/client/urbdrc_main.c
@@ -668,12 +668,13 @@ static UINT urbdrc_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMana
{
UINT status;
URBDRC_PLUGIN* urbdrc = (URBDRC_PLUGIN*)pPlugin;
- IUDEVMAN* udevman = urbdrc->udevman;
+ IUDEVMAN* udevman;
char channelName[sizeof(URBDRC_CHANNEL_NAME)] = { URBDRC_CHANNEL_NAME };
- if (!urbdrc)
+ if (!urbdrc || !urbdrc->udevman)
return ERROR_INVALID_PARAMETER;
+ udevman = urbdrc->udevman;
urbdrc->listener_callback =
(URBDRC_LISTENER_CALLBACK*)calloc(1, sizeof(URBDRC_LISTENER_CALLBACK));
@@ -687,7 +688,7 @@ static UINT urbdrc_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMana
/* [MS-RDPEUSB] 2.1 Transport defines the channel name in uppercase letters */
CharUpperA(channelName);
status = pChannelMgr->CreateListener(pChannelMgr, channelName, 0,
- &urbdrc->listener_callback->iface, NULL);
+ &urbdrc->listener_callback->iface, &urbdrc->listener);
if (status != CHANNEL_RC_OK)
return status;
@@ -709,7 +710,12 @@ static UINT urbdrc_plugin_terminated(IWTSPlugin* pPlugin)
if (!urbdrc)
return ERROR_INVALID_DATA;
-
+ if (urbdrc->listener_callback)
+ {
+ IWTSVirtualChannelManager* mgr = urbdrc->listener_callback->channel_mgr;
+ if (mgr)
+ IFCALL(mgr->DestroyListener, mgr, urbdrc->listener);
+ }
udevman = urbdrc->udevman;
if (udevman)
diff --git a/channels/urbdrc/client/urbdrc_main.h b/channels/urbdrc/client/urbdrc_main.h
index 2a750d64d..2b643f7cb 100644
--- a/channels/urbdrc/client/urbdrc_main.h
+++ b/channels/urbdrc/client/urbdrc_main.h
@@ -84,6 +84,7 @@ struct _URBDRC_PLUGIN
char* subsystem;
wLog* log;
+ IWTSListener* listener;
};
typedef BOOL (*PREGISTERURBDRCSERVICE)(IWTSPlugin* plugin, IUDEVMAN* udevman);
diff --git a/channels/video/client/video_main.c b/channels/video/client/video_main.c
index 1efadb399..9a68d92d3 100644
--- a/channels/video/client/video_main.c
+++ b/channels/video/client/video_main.c
@@ -1048,7 +1048,7 @@ static UINT video_plugin_initialize(IWTSPlugin* plugin, IWTSVirtualChannelManage
callback->channel_mgr = channelMgr;
status = channelMgr->CreateListener(channelMgr, VIDEO_CONTROL_DVC_CHANNEL_NAME, 0,
- (IWTSListenerCallback*)callback, &(video->controlListener));
+ &callback->iface, &(video->controlListener));
if (status != CHANNEL_RC_OK)
return status;
@@ -1067,7 +1067,7 @@ static UINT video_plugin_initialize(IWTSPlugin* plugin, IWTSVirtualChannelManage
callback->channel_mgr = channelMgr;
status = channelMgr->CreateListener(channelMgr, VIDEO_DATA_DVC_CHANNEL_NAME, 0,
- (IWTSListenerCallback*)callback, &(video->dataListener));
+ &callback->iface, &(video->dataListener));
if (status == CHANNEL_RC_OK)
video->dataListener->pInterface = video->wtsPlugin.pInterface;
@@ -1084,6 +1084,19 @@ static UINT video_plugin_terminated(IWTSPlugin* pPlugin)
{
VIDEO_PLUGIN* video = (VIDEO_PLUGIN*)pPlugin;
+ if (video->control_callback)
+ {
+ IWTSVirtualChannelManager* mgr = video->control_callback->channel_mgr;
+ if (mgr)
+ IFCALL(mgr->DestroyListener, mgr, video->controlListener);
+ }
+ if (video->data_callback)
+ {
+ IWTSVirtualChannelManager* mgr = video->data_callback->channel_mgr;
+ if (mgr)
+ IFCALL(mgr->DestroyListener, mgr, video->dataListener);
+ }
+
if (video->context)
VideoClientContextPriv_free(video->context->priv);
diff --git a/client/Android/Studio/build.gradle b/client/Android/Studio/build.gradle
index e944b11d3..319280d5e 100644
--- a/client/Android/Studio/build.gradle
+++ b/client/Android/Studio/build.gradle
@@ -29,7 +29,7 @@ def getVersionName = { ->
ext {
versionName = properties.get('VERSION_NAME', getVersionName())
- versionCode = properties.get('VERSION_CODE', 16)
+ versionCode = properties.get('VERSION_CODE', 17)
println '----------------- Project configuration -------------------'
println 'VERSION_NAME: ' + versionName
diff --git a/client/Android/android_freerdp.c b/client/Android/android_freerdp.c
index 7d332c731..0b0f27b09 100644
--- a/client/Android/android_freerdp.c
+++ b/client/Android/android_freerdp.c
@@ -56,7 +56,7 @@
#define TAG CLIENT_TAG("android")
/* Defines the JNI version supported by this library. */
-#define FREERDP_JNI_VERSION "2.1.0"
+#define FREERDP_JNI_VERSION "2.1.1"
static void android_OnChannelConnectedEventHandler(void* context, ChannelConnectedEventArgs* e)
{
diff --git a/client/Sample/tf_freerdp.c b/client/Sample/tf_freerdp.c
index 4340f1d30..3ba82c783 100644
--- a/client/Sample/tf_freerdp.c
+++ b/client/Sample/tf_freerdp.c
@@ -342,7 +342,10 @@ int main(int argc, char* argv[])
freerdp_client_settings_command_line_status_print(context->settings, status, argc, argv);
if (status)
- return 0;
+ {
+ rc = 0;
+ goto fail;
+ }
if (freerdp_client_start(context) != 0)
goto fail;
diff --git a/client/Windows/wf_client.c b/client/Windows/wf_client.c
index 19bca36c9..11667258a 100644
--- a/client/Windows/wf_client.c
+++ b/client/Windows/wf_client.c
@@ -438,6 +438,8 @@ static BOOL wf_authenticate_raw(freerdp* instance, const char* title, char** use
fSave = FALSE;
dwFlags = CREDUI_FLAGS_DO_NOT_PERSIST | CREDUI_FLAGS_EXCLUDE_CERTIFICATES;
+ if (username && *username)
+ strncpy(UserName, *username, CREDUI_MAX_USERNAME_LENGTH);
if (wfc->isConsole)
status = CredUICmdLinePromptForCredentialsA(
title, NULL, 0, UserName, CREDUI_MAX_USERNAME_LENGTH + 1, Password,
diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c
index 84cd60341..146c7feea 100644
--- a/client/X11/xf_client.c
+++ b/client/X11/xf_client.c
@@ -223,8 +223,15 @@ BOOL xf_picture_transform_required(xfContext* xfc)
}
#endif /* WITH_XRENDER defined */
-void xf_draw_screen(xfContext* xfc, int x, int y, int w, int h)
+void xf_draw_screen_(xfContext* xfc, int x, int y, int w, int h, const char* fkt, const char* file,
+ int line)
{
+ if (!xfc)
+ {
+ WLog_DBG(TAG, "[%s] called from [%s] xfc=%p", __FUNCTION__, fkt, xfc);
+ return;
+ }
+
if (w == 0 || h == 0)
{
WLog_WARN(TAG, "invalid width and/or height specified: w=%d h=%d", w, h);
diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c
index 5f4f8297d..e7a889efc 100644
--- a/client/X11/xf_event.c
+++ b/client/X11/xf_event.c
@@ -185,7 +185,8 @@ BOOL xf_event_action_script_init(xfContext* xfc)
while (fgets(buffer, sizeof(buffer), actionScript))
{
- strtok(buffer, "\n");
+ char* context = NULL;
+ strtok_s(buffer, "\n", &context);
xevent = _strdup(buffer);
if (!xevent || ArrayList_Add(xfc->xevents, xevent) < 0)
@@ -253,7 +254,8 @@ static BOOL xf_event_execute_action_script(xfContext* xfc, const XEvent* event)
while (fgets(buffer, sizeof(buffer), actionScript))
{
- strtok(buffer, "\n");
+ char* context = NULL;
+ strtok_s(buffer, "\n", &context);
}
pclose(actionScript);
diff --git a/client/X11/xf_keyboard.c b/client/X11/xf_keyboard.c
index 50b259308..794acea0c 100644
--- a/client/X11/xf_keyboard.c
+++ b/client/X11/xf_keyboard.c
@@ -74,7 +74,8 @@ static BOOL xf_keyboard_action_script_init(xfContext* xfc)
while (fgets(buffer, sizeof(buffer), keyScript) != NULL)
{
- strtok(buffer, "\n");
+ char* context = NULL;
+ strtok_s(buffer, "\n", &context);
keyCombination = _strdup(buffer);
if (!keyCombination || ArrayList_Add(xfc->keyCombinations, keyCombination) < 0)
@@ -433,7 +434,8 @@ static int xf_keyboard_execute_action_script(xfContext* xfc, XF_MODIFIER_KEYS* m
while (fgets(buffer, sizeof(buffer), keyScript) != NULL)
{
- strtok(buffer, "\n");
+ char* context = NULL;
+ strtok_s(buffer, "\n", &context);
if (strcmp(buffer, "key-local") == 0)
status = 0;
diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h
index 3ad3ddc6a..8599d56ec 100644
--- a/client/X11/xfreerdp.h
+++ b/client/X11/xfreerdp.h
@@ -307,7 +307,11 @@ void xf_lock_x11_(xfContext* xfc, const char* fkt);
void xf_unlock_x11_(xfContext* xfc, const char* fkt);
BOOL xf_picture_transform_required(xfContext* xfc);
-void xf_draw_screen(xfContext* xfc, int x, int y, int w, int h);
+
+#define xf_draw_screen(_xfc, _x, _y, _w, _h) \
+ xf_draw_screen_((_xfc), (_x), (_y), (_w), (_h), __FUNCTION__, __FILE__, __LINE__)
+void xf_draw_screen_(xfContext* xfc, int x, int y, int w, int h, const char* fkt, const char* file,
+ int line);
FREERDP_API DWORD xf_exit_code_from_disconnect_reason(DWORD reason);
diff --git a/client/common/cmdline.c b/client/common/cmdline.c
index cdea23de0..bad661987 100644
--- a/client/common/cmdline.c
+++ b/client/common/cmdline.c
@@ -3500,8 +3500,9 @@ BOOL freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings)
BOOL success;
const char* name = NULL;
const char* drive = tok;
- char* start = strtok(tok, "(");
- char* end = strtok(NULL, ")");
+ char* subcontext = NULL;
+ char* start = strtok_s(tok, "(", &subcontext);
+ char* end = strtok_s(NULL, ")", &subcontext);
if (start && end)
name = end;
diff --git a/client/common/file.c b/client/common/file.c
index 7cac1acab..b9ded2631 100644
--- a/client/common/file.c
+++ b/client/common/file.c
@@ -203,6 +203,7 @@ struct rdp_file
DWORD flags;
};
+static void freerdp_client_file_string_check_free(LPSTR str);
/*
* Set an integer in a rdpFile
*
@@ -841,15 +842,16 @@ BOOL freerdp_client_parse_rdp_file_ex(rdpFile* file, const char* name, rdp_file_
return status;
}
-#define FILE_POPULATE_STRING(_target, _setting) \
- do \
- { \
- if (_setting) \
- { \
- _target = _strdup(_setting); \
- if (!_target) \
- return FALSE; \
- } \
+#define FILE_POPULATE_STRING(_target, _setting) \
+ do \
+ { \
+ if (_setting) \
+ { \
+ freerdp_client_file_string_check_free(_target); \
+ _target = _strdup(_setting); \
+ if (!_target) \
+ return FALSE; \
+ } \
} while (0)
BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, const rdpSettings* settings)
diff --git a/config.h.in b/config.h.in
index c2e20d356..cf8f3f601 100644
--- a/config.h.in
+++ b/config.h.in
@@ -26,7 +26,6 @@
#cmakedefine HAVE_EXECINFO_H
/* Features */
-#cmakedefine HAVE_ALIGNED_REQUIRED
#cmakedefine SWRESAMPLE_FOUND
#cmakedefine AVRESAMPLE_FOUND
diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c
index 118e09b35..083f1aa97 100644
--- a/libfreerdp/codec/clear.c
+++ b/libfreerdp/codec/clear.c
@@ -783,7 +783,7 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32
if (vBarUpdate)
{
UINT32 x;
- BYTE* pSrcPixel;
+ BYTE* pSrcPixel = NULL;
BYTE* dstBuffer;
if (clear->VBarStorageCursor >= CLEARCODEC_VBAR_SIZE)
@@ -826,8 +826,9 @@ static BOOL clear_decompress_bands_data(CLEAR_CONTEXT* clear, wStream* s, UINT32
if ((y + count) > vBarPixelCount)
count = (vBarPixelCount > y) ? (vBarPixelCount - y) : 0;
- pSrcPixel =
- &vBarShortEntry->pixels[(y - vBarYOn) * GetBytesPerPixel(clear->format)];
+ if (count > 0)
+ pSrcPixel =
+ &vBarShortEntry->pixels[(y - vBarYOn) * GetBytesPerPixel(clear->format)];
for (x = 0; x < count; x++)
{
diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c
index 784937a49..e9f92c700 100644
--- a/libfreerdp/codec/interleaved.c
+++ b/libfreerdp/codec/interleaved.c
@@ -272,11 +272,7 @@ static INLINE void write_pixel_16(BYTE* _buf, UINT16 _pix)
#define WHITE_PIXEL 0xFFFF
#define DESTWRITEPIXEL(_buf, _pix) write_pixel_16(_buf, _pix)
#define DESTREADPIXEL(_pix, _buf) _pix = ((UINT16*)(_buf))[0]
-#ifdef HAVE_ALIGNED_REQUIRED
#define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8)
-#else
-#define SRCREADPIXEL(_pix, _buf) _pix = ((UINT16*)(_buf))[0]
-#endif
#define DESTNEXTPIXEL(_buf) _buf += 2
#define SRCNEXTPIXEL(_buf) _buf += 2
#define WRITEFGBGIMAGE WriteFgBgImage16to16
diff --git a/libfreerdp/codec/mppc.c b/libfreerdp/codec/mppc.c
index cdad24863..217fae41d 100644
--- a/libfreerdp/codec/mppc.c
+++ b/libfreerdp/codec/mppc.c
@@ -772,11 +772,15 @@ void mppc_context_reset(MPPC_CONTEXT* mppc, BOOL flush)
ZeroMemory(&(mppc->MatchBuffer), sizeof(mppc->MatchBuffer));
if (flush)
+ {
mppc->HistoryOffset = mppc->HistoryBufferSize + 1;
+ mppc->HistoryPtr = mppc->HistoryBuffer;
+ }
else
+ {
mppc->HistoryOffset = 0;
-
mppc->HistoryPtr = &(mppc->HistoryBuffer[mppc->HistoryOffset]);
+ }
}
MPPC_CONTEXT* mppc_context_new(DWORD CompressionLevel, BOOL Compressor)
diff --git a/libfreerdp/codec/ncrush.c b/libfreerdp/codec/ncrush.c
index af503fc7c..3d6a216d3 100644
--- a/libfreerdp/codec/ncrush.c
+++ b/libfreerdp/codec/ncrush.c
@@ -1926,9 +1926,9 @@ static INLINE UINT16 get_word(const BYTE* data)
static INLINE UINT32 get_dword(const BYTE* data)
{
UINT32 tmp = *data++;
- tmp |= *data++ << 8U;
- tmp |= *data++ << 16U;
- tmp |= *data++ << 24U;
+ tmp |= (UINT32)*data++ << 8U;
+ tmp |= (UINT32)*data++ << 16U;
+ tmp |= (UINT32)*data++ << 24U;
return tmp;
}
diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c
index 6c0755217..6627e0b63 100644
--- a/libfreerdp/codec/nsc.c
+++ b/libfreerdp/codec/nsc.c
@@ -113,14 +113,12 @@ static BOOL nsc_decode(NSC_CONTEXT* context)
static BOOL nsc_rle_decode(BYTE* in, BYTE* out, UINT32 outSize, UINT32 originalSize)
{
- UINT32 len;
- UINT32 left;
- BYTE value;
- left = originalSize;
+ UINT32 left = originalSize;
while (left > 4)
{
- value = *in++;
+ const BYTE value = *in++;
+ UINT32 len = 0;
if (left == 5)
{
@@ -143,8 +141,10 @@ static BOOL nsc_rle_decode(BYTE* in, BYTE* out, UINT32 outSize, UINT32 originalS
else
{
in++;
- len = *((UINT32*)in);
- in += 4;
+ len = ((UINT32)(*in++));
+ len |= ((UINT32)(*in++)) << 8U;
+ len |= ((UINT32)(*in++)) << 16U;
+ len |= ((UINT32)(*in++)) << 24U;
}
if (outSize < len)
diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c
index b4b1a4cd2..2a0861678 100644
--- a/libfreerdp/codec/planar.c
+++ b/libfreerdp/codec/planar.c
@@ -1170,7 +1170,6 @@ BYTE* freerdp_bitmap_planar_delta_encode_plane(const BYTE* inPlane, UINT32 width
BYTE* outPlane)
{
char s2c;
- INT32 delta;
UINT32 y, x;
BYTE* outPtr;
const BYTE *srcPtr, *prevLinePtr;
@@ -1194,9 +1193,9 @@ BYTE* freerdp_bitmap_planar_delta_encode_plane(const BYTE* inPlane, UINT32 width
{
for (x = 0; x < width; x++, outPtr++, srcPtr++, prevLinePtr++)
{
- delta = *srcPtr - *prevLinePtr;
+ INT32 delta = *srcPtr - *prevLinePtr;
s2c = (delta >= 0) ? (char)delta : (char)(~((BYTE)(-delta)) + 1);
- s2c = (s2c >= 0) ? (s2c << 1) : (char)(((~((BYTE)s2c) + 1) << 1) - 1);
+ s2c = (s2c >= 0) ? ((UINT32)s2c << 1) : (char)(((UINT32)(~((BYTE)s2c) + 1) << 1) - 1);
*outPtr = (BYTE)s2c;
}
}
diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c
index bfa2dc5da..e2660b19f 100644
--- a/libfreerdp/codec/progressive.c
+++ b/libfreerdp/codec/progressive.c
@@ -1183,7 +1183,7 @@ static INLINE int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* s
sign[index] = input;
}
- buffer[index] += (input << shift);
+ buffer[index] += (INT16)((UINT32)input << shift);
}
return 1;
@@ -1995,7 +1995,7 @@ static INLINE INT32 progressive_wb_read_region_header(PROGRESSIVE_CONTEXT* progr
len -= region->tileDataSize;
if (len > 0)
WLog_Print(progressive->log, WLOG_DEBUG,
- "Unused byes detected, %" PRIuz " bytes not processed", len);
+ "Unused bytes detected, %" PRIuz " bytes not processed", len);
return 0;
}
diff --git a/libfreerdp/codec/rfx_dwt.c b/libfreerdp/codec/rfx_dwt.c
index a72d63f4c..4c727cda7 100644
--- a/libfreerdp/codec/rfx_dwt.c
+++ b/libfreerdp/codec/rfx_dwt.c
@@ -87,26 +87,27 @@ void rfx_dwt_2d_decode_block(INT16* buffer, INT16* idwt, int subband_width)
/* Inverse DWT in vertical direction, results are stored in original buffer. */
for (x = 0; x < total_width; x++)
{
- /* Even coefficients */
- for (n = 0; n < subband_width; n++)
- {
- y = n << 1;
- dst = buffer + y * total_width + x;
- l = idwt + n * total_width + x;
- h = l + subband_width * total_width;
- dst[0] = *l - (((n > 0 ? *(h - total_width) : *h) + (*h) + 1) >> 1);
- }
+ l = idwt + x;
+ h = idwt + x + subband_width * total_width;
+ dst = buffer + x;
- /* Odd coefficients */
- for (n = 0; n < subband_width; n++)
+ *dst = *l - ((*h * 2 + 1) >> 1);
+
+ for (n = 1; n < subband_width; n++)
{
- y = n << 1;
- dst = buffer + y * total_width + x;
- l = idwt + n * total_width + x;
- h = l + subband_width * total_width;
- dst[total_width] =
- (*h << 1) + ((dst[0] + dst[n < subband_width - 1 ? 2 * total_width : 0]) >> 1);
+ l += total_width;
+ h += total_width;
+
+ /* Even coefficients */
+ dst[2 * total_width] = *l - ((*(h - total_width) + *h + 1) >> 1);
+
+ /* Odd coefficients */
+ dst[total_width] = (*(h - total_width) << 1) + ((*dst + dst[2 * total_width]) >> 1);
+
+ dst += 2 * total_width;
}
+
+ dst[total_width] = (*h << 1) + ((*dst * 2) >> 1);
}
}
diff --git a/libfreerdp/codec/rfx_rlgr.c b/libfreerdp/codec/rfx_rlgr.c
index 655739244..a0d2c95a7 100644
--- a/libfreerdp/codec/rfx_rlgr.c
+++ b/libfreerdp/codec/rfx_rlgr.c
@@ -282,7 +282,10 @@ int rfx_rlgr_decode(RLGR_MODE mode, const BYTE* pSrcData, UINT32 SrcSize, INT16*
break;
bs->mask = ((1 << kr) - 1);
- code = (UINT16)((bs->accumulator >> (32 - kr)) & bs->mask);
+ if (kr > 0)
+ code = (UINT16)((bs->accumulator >> (32 - kr)) & bs->mask);
+ else
+ code = 0;
BitStream_Shift(bs, kr);
/* add (vk << kr) to code */
@@ -390,7 +393,10 @@ int rfx_rlgr_decode(RLGR_MODE mode, const BYTE* pSrcData, UINT32 SrcSize, INT16*
break;
bs->mask = ((1 << kr) - 1);
- code = (UINT16)((bs->accumulator >> (32 - kr)) & bs->mask);
+ if (kr > 0)
+ code = (UINT16)((bs->accumulator >> (32 - kr)) & bs->mask);
+ else
+ code = 0;
BitStream_Shift(bs, kr);
/* add (vk << kr) to code */
@@ -477,7 +483,10 @@ int rfx_rlgr_decode(RLGR_MODE mode, const BYTE* pSrcData, UINT32 SrcSize, INT16*
break;
bs->mask = ((1 << nIdx) - 1);
- val1 = ((bs->accumulator >> (32 - nIdx)) & bs->mask);
+ if (nIdx > 0)
+ val1 = ((bs->accumulator >> (32 - nIdx)) & bs->mask);
+ else
+ val1 = 0;
BitStream_Shift(bs, nIdx);
val2 = code - val1;
diff --git a/libfreerdp/common/settings_getters.c b/libfreerdp/common/settings_getters.c
index 9ea65070b..2e49b8923 100644
--- a/libfreerdp/common/settings_getters.c
+++ b/libfreerdp/common/settings_getters.c
@@ -2358,7 +2358,7 @@ const char* freerdp_settings_get_string(const rdpSettings* settings, size_t id)
}
}
-BOOL freerdp_settings_set_string(rdpSettings* settings, size_t id, const char* val)
+BOOL freerdp_settings_set_string_(rdpSettings* settings, size_t id, const char* val, BOOL cleanup)
{
if (!settings)
return FALSE;
@@ -2366,332 +2366,398 @@ BOOL freerdp_settings_set_string(rdpSettings* settings, size_t id, const char* v
switch (id)
{
case FreeRDP_AcceptedCert:
- free(settings->AcceptedCert);
+ if (cleanup)
+ free(settings->AcceptedCert);
settings->AcceptedCert = (val ? _strdup(val) : NULL);
return (!val || settings->AcceptedCert != NULL);
case FreeRDP_AllowedTlsCiphers:
- free(settings->AllowedTlsCiphers);
+ if (cleanup)
+ free(settings->AllowedTlsCiphers);
settings->AllowedTlsCiphers = (val ? _strdup(val) : NULL);
return (!val || settings->AllowedTlsCiphers != NULL);
case FreeRDP_AlternateShell:
- free(settings->AlternateShell);
+ if (cleanup)
+ free(settings->AlternateShell);
settings->AlternateShell = (val ? _strdup(val) : NULL);
return (!val || settings->AlternateShell != NULL);
case FreeRDP_AssistanceFile:
- free(settings->AssistanceFile);
+ if (cleanup)
+ free(settings->AssistanceFile);
settings->AssistanceFile = (val ? _strdup(val) : NULL);
return (!val || settings->AssistanceFile != NULL);
case FreeRDP_AuthenticationServiceClass:
- free(settings->AuthenticationServiceClass);
+ if (cleanup)
+ free(settings->AuthenticationServiceClass);
settings->AuthenticationServiceClass = (val ? _strdup(val) : NULL);
return (!val || settings->AuthenticationServiceClass != NULL);
case FreeRDP_CertificateAcceptedFingerprints:
- free(settings->CertificateAcceptedFingerprints);
+ if (cleanup)
+ free(settings->CertificateAcceptedFingerprints);
settings->CertificateAcceptedFingerprints = (val ? _strdup(val) : NULL);
return (!val || settings->CertificateAcceptedFingerprints != NULL);
case FreeRDP_CertificateContent:
- free(settings->CertificateContent);
+ if (cleanup)
+ free(settings->CertificateContent);
settings->CertificateContent = (val ? _strdup(val) : NULL);
return (!val || settings->CertificateContent != NULL);
case FreeRDP_CertificateFile:
- free(settings->CertificateFile);
+ if (cleanup)
+ free(settings->CertificateFile);
settings->CertificateFile = (val ? _strdup(val) : NULL);
return (!val || settings->CertificateFile != NULL);
case FreeRDP_CertificateName:
- free(settings->CertificateName);
+ if (cleanup)
+ free(settings->CertificateName);
settings->CertificateName = (val ? _strdup(val) : NULL);
return (!val || settings->CertificateName != NULL);
case FreeRDP_ClientAddress:
- free(settings->ClientAddress);
+ if (cleanup)
+ free(settings->ClientAddress);
settings->ClientAddress = (val ? _strdup(val) : NULL);
return (!val || settings->ClientAddress != NULL);
case FreeRDP_ClientDir:
- free(settings->ClientDir);
+ if (cleanup)
+ free(settings->ClientDir);
settings->ClientDir = (val ? _strdup(val) : NULL);
return (!val || settings->ClientDir != NULL);
case FreeRDP_ClientHostname:
- free(settings->ClientHostname);
+ if (cleanup)
+ free(settings->ClientHostname);
settings->ClientHostname = (val ? _strdup(val) : NULL);
return (!val || settings->ClientHostname != NULL);
case FreeRDP_ClientProductId:
- free(settings->ClientProductId);
+ if (cleanup)
+ free(settings->ClientProductId);
settings->ClientProductId = (val ? _strdup(val) : NULL);
return (!val || settings->ClientProductId != NULL);
case FreeRDP_ComputerName:
- free(settings->ComputerName);
+ if (cleanup)
+ free(settings->ComputerName);
settings->ComputerName = (val ? _strdup(val) : NULL);
return (!val || settings->ComputerName != NULL);
case FreeRDP_ConfigPath:
- free(settings->ConfigPath);
+ if (cleanup)
+ free(settings->ConfigPath);
settings->ConfigPath = (val ? _strdup(val) : NULL);
return (!val || settings->ConfigPath != NULL);
case FreeRDP_ConnectionFile:
- free(settings->ConnectionFile);
+ if (cleanup)
+ free(settings->ConnectionFile);
settings->ConnectionFile = (val ? _strdup(val) : NULL);
return (!val || settings->ConnectionFile != NULL);
case FreeRDP_CurrentPath:
- free(settings->CurrentPath);
+ if (cleanup)
+ free(settings->CurrentPath);
settings->CurrentPath = (val ? _strdup(val) : NULL);
return (!val || settings->CurrentPath != NULL);
case FreeRDP_Domain:
- free(settings->Domain);
+ if (cleanup)
+ free(settings->Domain);
settings->Domain = (val ? _strdup(val) : NULL);
return (!val || settings->Domain != NULL);
case FreeRDP_DrivesToRedirect:
- free(settings->DrivesToRedirect);
+ if (cleanup)
+ free(settings->DrivesToRedirect);
settings->DrivesToRedirect = (val ? _strdup(val) : NULL);
return (!val || settings->DrivesToRedirect != NULL);
case FreeRDP_DumpRemoteFxFile:
- free(settings->DumpRemoteFxFile);
+ if (cleanup)
+ free(settings->DumpRemoteFxFile);
settings->DumpRemoteFxFile = (val ? _strdup(val) : NULL);
return (!val || settings->DumpRemoteFxFile != NULL);
case FreeRDP_DynamicDSTTimeZoneKeyName:
- free(settings->DynamicDSTTimeZoneKeyName);
+ if (cleanup)
+ free(settings->DynamicDSTTimeZoneKeyName);
settings->DynamicDSTTimeZoneKeyName = (val ? _strdup(val) : NULL);
return (!val || settings->DynamicDSTTimeZoneKeyName != NULL);
case FreeRDP_GatewayAcceptedCert:
- free(settings->GatewayAcceptedCert);
+ if (cleanup)
+ free(settings->GatewayAcceptedCert);
settings->GatewayAcceptedCert = (val ? _strdup(val) : NULL);
return (!val || settings->GatewayAcceptedCert != NULL);
case FreeRDP_GatewayAccessToken:
- free(settings->GatewayAccessToken);
+ if (cleanup)
+ free(settings->GatewayAccessToken);
settings->GatewayAccessToken = (val ? _strdup(val) : NULL);
return (!val || settings->GatewayAccessToken != NULL);
case FreeRDP_GatewayDomain:
- free(settings->GatewayDomain);
+ if (cleanup)
+ free(settings->GatewayDomain);
settings->GatewayDomain = (val ? _strdup(val) : NULL);
return (!val || settings->GatewayDomain != NULL);
case FreeRDP_GatewayHostname:
- free(settings->GatewayHostname);
+ if (cleanup)
+ free(settings->GatewayHostname);
settings->GatewayHostname = (val ? _strdup(val) : NULL);
return (!val || settings->GatewayHostname != NULL);
case FreeRDP_GatewayPassword:
- free(settings->GatewayPassword);
+ if (cleanup)
+ free(settings->GatewayPassword);
settings->GatewayPassword = (val ? _strdup(val) : NULL);
return (!val || settings->GatewayPassword != NULL);
case FreeRDP_GatewayUsername:
- free(settings->GatewayUsername);
+ if (cleanup)
+ free(settings->GatewayUsername);
settings->GatewayUsername = (val ? _strdup(val) : NULL);
return (!val || settings->GatewayUsername != NULL);
case FreeRDP_HomePath:
- free(settings->HomePath);
+ if (cleanup)
+ free(settings->HomePath);
settings->HomePath = (val ? _strdup(val) : NULL);
return (!val || settings->HomePath != NULL);
case FreeRDP_ImeFileName:
- free(settings->ImeFileName);
+ if (cleanup)
+ free(settings->ImeFileName);
settings->ImeFileName = (val ? _strdup(val) : NULL);
return (!val || settings->ImeFileName != NULL);
case FreeRDP_KerberosKdc:
- free(settings->KerberosKdc);
+ if (cleanup)
+ free(settings->KerberosKdc);
settings->KerberosKdc = (val ? _strdup(val) : NULL);
return (!val || settings->KerberosKdc != NULL);
case FreeRDP_KerberosRealm:
- free(settings->KerberosRealm);
+ if (cleanup)
+ free(settings->KerberosRealm);
settings->KerberosRealm = (val ? _strdup(val) : NULL);
return (!val || settings->KerberosRealm != NULL);
case FreeRDP_NtlmSamFile:
- free(settings->NtlmSamFile);
+ if (cleanup)
+ free(settings->NtlmSamFile);
settings->NtlmSamFile = (val ? _strdup(val) : NULL);
return (!val || settings->NtlmSamFile != NULL);
case FreeRDP_Password:
- free(settings->Password);
+ if (cleanup)
+ free(settings->Password);
settings->Password = (val ? _strdup(val) : NULL);
return (!val || settings->Password != NULL);
case FreeRDP_PasswordHash:
- free(settings->PasswordHash);
+ if (cleanup)
+ free(settings->PasswordHash);
settings->PasswordHash = (val ? _strdup(val) : NULL);
return (!val || settings->PasswordHash != NULL);
case FreeRDP_PlayRemoteFxFile:
- free(settings->PlayRemoteFxFile);
+ if (cleanup)
+ free(settings->PlayRemoteFxFile);
settings->PlayRemoteFxFile = (val ? _strdup(val) : NULL);
return (!val || settings->PlayRemoteFxFile != NULL);
case FreeRDP_PreconnectionBlob:
- free(settings->PreconnectionBlob);
+ if (cleanup)
+ free(settings->PreconnectionBlob);
settings->PreconnectionBlob = (val ? _strdup(val) : NULL);
return (!val || settings->PreconnectionBlob != NULL);
case FreeRDP_PrivateKeyContent:
- free(settings->PrivateKeyContent);
+ if (cleanup)
+ free(settings->PrivateKeyContent);
settings->PrivateKeyContent = (val ? _strdup(val) : NULL);
return (!val || settings->PrivateKeyContent != NULL);
case FreeRDP_PrivateKeyFile:
- free(settings->PrivateKeyFile);
+ if (cleanup)
+ free(settings->PrivateKeyFile);
settings->PrivateKeyFile = (val ? _strdup(val) : NULL);
return (!val || settings->PrivateKeyFile != NULL);
case FreeRDP_ProxyHostname:
- free(settings->ProxyHostname);
+ if (cleanup)
+ free(settings->ProxyHostname);
settings->ProxyHostname = (val ? _strdup(val) : NULL);
return (!val || settings->ProxyHostname != NULL);
case FreeRDP_ProxyPassword:
- free(settings->ProxyPassword);
+ if (cleanup)
+ free(settings->ProxyPassword);
settings->ProxyPassword = (val ? _strdup(val) : NULL);
return (!val || settings->ProxyPassword != NULL);
case FreeRDP_ProxyUsername:
- free(settings->ProxyUsername);
+ if (cleanup)
+ free(settings->ProxyUsername);
settings->ProxyUsername = (val ? _strdup(val) : NULL);
return (!val || settings->ProxyUsername != NULL);
case FreeRDP_RDP2TCPArgs:
- free(settings->RDP2TCPArgs);
+ if (cleanup)
+ free(settings->RDP2TCPArgs);
settings->RDP2TCPArgs = (val ? _strdup(val) : NULL);
return (!val || settings->RDP2TCPArgs != NULL);
case FreeRDP_RdpKeyContent:
- free(settings->RdpKeyContent);
+ if (cleanup)
+ free(settings->RdpKeyContent);
settings->RdpKeyContent = (val ? _strdup(val) : NULL);
return (!val || settings->RdpKeyContent != NULL);
case FreeRDP_RdpKeyFile:
- free(settings->RdpKeyFile);
+ if (cleanup)
+ free(settings->RdpKeyFile);
settings->RdpKeyFile = (val ? _strdup(val) : NULL);
return (!val || settings->RdpKeyFile != NULL);
case FreeRDP_RedirectionAcceptedCert:
- free(settings->RedirectionAcceptedCert);
+ if (cleanup)
+ free(settings->RedirectionAcceptedCert);
settings->RedirectionAcceptedCert = (val ? _strdup(val) : NULL);
return (!val || settings->RedirectionAcceptedCert != NULL);
case FreeRDP_RedirectionDomain:
- free(settings->RedirectionDomain);
+ if (cleanup)
+ free(settings->RedirectionDomain);
settings->RedirectionDomain = (val ? _strdup(val) : NULL);
return (!val || settings->RedirectionDomain != NULL);
case FreeRDP_RedirectionTargetFQDN:
- free(settings->RedirectionTargetFQDN);
+ if (cleanup)
+ free(settings->RedirectionTargetFQDN);
settings->RedirectionTargetFQDN = (val ? _strdup(val) : NULL);
return (!val || settings->RedirectionTargetFQDN != NULL);
case FreeRDP_RedirectionTargetNetBiosName:
- free(settings->RedirectionTargetNetBiosName);
+ if (cleanup)
+ free(settings->RedirectionTargetNetBiosName);
settings->RedirectionTargetNetBiosName = (val ? _strdup(val) : NULL);
return (!val || settings->RedirectionTargetNetBiosName != NULL);
case FreeRDP_RedirectionUsername:
- free(settings->RedirectionUsername);
+ if (cleanup)
+ free(settings->RedirectionUsername);
settings->RedirectionUsername = (val ? _strdup(val) : NULL);
return (!val || settings->RedirectionUsername != NULL);
case FreeRDP_RemoteApplicationCmdLine:
- free(settings->RemoteApplicationCmdLine);
+ if (cleanup)
+ free(settings->RemoteApplicationCmdLine);
settings->RemoteApplicationCmdLine = (val ? _strdup(val) : NULL);
return (!val || settings->RemoteApplicationCmdLine != NULL);
case FreeRDP_RemoteApplicationFile:
- free(settings->RemoteApplicationFile);
+ if (cleanup)
+ free(settings->RemoteApplicationFile);
settings->RemoteApplicationFile = (val ? _strdup(val) : NULL);
return (!val || settings->RemoteApplicationFile != NULL);
case FreeRDP_RemoteApplicationGuid:
- free(settings->RemoteApplicationGuid);
+ if (cleanup)
+ free(settings->RemoteApplicationGuid);
settings->RemoteApplicationGuid = (val ? _strdup(val) : NULL);
return (!val || settings->RemoteApplicationGuid != NULL);
case FreeRDP_RemoteApplicationIcon:
- free(settings->RemoteApplicationIcon);
+ if (cleanup)
+ free(settings->RemoteApplicationIcon);
settings->RemoteApplicationIcon = (val ? _strdup(val) : NULL);
return (!val || settings->RemoteApplicationIcon != NULL);
case FreeRDP_RemoteApplicationName:
- free(settings->RemoteApplicationName);
+ if (cleanup)
+ free(settings->RemoteApplicationName);
settings->RemoteApplicationName = (val ? _strdup(val) : NULL);
return (!val || settings->RemoteApplicationName != NULL);
case FreeRDP_RemoteApplicationProgram:
- free(settings->RemoteApplicationProgram);
+ if (cleanup)
+ free(settings->RemoteApplicationProgram);
settings->RemoteApplicationProgram = (val ? _strdup(val) : NULL);
return (!val || settings->RemoteApplicationProgram != NULL);
case FreeRDP_RemoteApplicationWorkingDir:
- free(settings->RemoteApplicationWorkingDir);
+ if (cleanup)
+ free(settings->RemoteApplicationWorkingDir);
settings->RemoteApplicationWorkingDir = (val ? _strdup(val) : NULL);
return (!val || settings->RemoteApplicationWorkingDir != NULL);
case FreeRDP_RemoteAssistancePassStub:
- free(settings->RemoteAssistancePassStub);
+ if (cleanup)
+ free(settings->RemoteAssistancePassStub);
settings->RemoteAssistancePassStub = (val ? _strdup(val) : NULL);
return (!val || settings->RemoteAssistancePassStub != NULL);
case FreeRDP_RemoteAssistancePassword:
- free(settings->RemoteAssistancePassword);
+ if (cleanup)
+ free(settings->RemoteAssistancePassword);
settings->RemoteAssistancePassword = (val ? _strdup(val) : NULL);
return (!val || settings->RemoteAssistancePassword != NULL);
case FreeRDP_RemoteAssistanceRCTicket:
- free(settings->RemoteAssistanceRCTicket);
+ if (cleanup)
+ free(settings->RemoteAssistanceRCTicket);
settings->RemoteAssistanceRCTicket = (val ? _strdup(val) : NULL);
return (!val || settings->RemoteAssistanceRCTicket != NULL);
case FreeRDP_RemoteAssistanceSessionId:
- free(settings->RemoteAssistanceSessionId);
+ if (cleanup)
+ free(settings->RemoteAssistanceSessionId);
settings->RemoteAssistanceSessionId = (val ? _strdup(val) : NULL);
return (!val || settings->RemoteAssistanceSessionId != NULL);
case FreeRDP_ServerHostname:
- free(settings->ServerHostname);
+ if (cleanup)
+ free(settings->ServerHostname);
settings->ServerHostname = (val ? _strdup(val) : NULL);
return (!val || settings->ServerHostname != NULL);
case FreeRDP_ShellWorkingDirectory:
- free(settings->ShellWorkingDirectory);
+ if (cleanup)
+ free(settings->ShellWorkingDirectory);
settings->ShellWorkingDirectory = (val ? _strdup(val) : NULL);
return (!val || settings->ShellWorkingDirectory != NULL);
case FreeRDP_TargetNetAddress:
- free(settings->TargetNetAddress);
+ if (cleanup)
+ free(settings->TargetNetAddress);
settings->TargetNetAddress = (val ? _strdup(val) : NULL);
return (!val || settings->TargetNetAddress != NULL);
case FreeRDP_Username:
- free(settings->Username);
+ if (cleanup)
+ free(settings->Username);
settings->Username = (val ? _strdup(val) : NULL);
return (!val || settings->Username != NULL);
case FreeRDP_WindowTitle:
- free(settings->WindowTitle);
+ if (cleanup)
+ free(settings->WindowTitle);
settings->WindowTitle = (val ? _strdup(val) : NULL);
return (!val || settings->WindowTitle != NULL);
case FreeRDP_WmClass:
- free(settings->WmClass);
+ if (cleanup)
+ free(settings->WmClass);
settings->WmClass = (val ? _strdup(val) : NULL);
return (!val || settings->WmClass != NULL);
@@ -2702,6 +2768,11 @@ BOOL freerdp_settings_set_string(rdpSettings* settings, size_t id, const char* v
return TRUE;
}
+BOOL freerdp_settings_set_string(rdpSettings* settings, size_t id, const char* val)
+{
+ return freerdp_settings_set_string_(settings, id, val, TRUE);
+}
+
const void* freerdp_settings_get_pointer(const rdpSettings* settings, size_t id)
{
if (!settings)
@@ -2792,3 +2863,121 @@ const void* freerdp_settings_get_pointer(const rdpSettings* settings, size_t id)
return FALSE;
}
}
+
+BOOL freerdp_settings_set_pointer(rdpSettings* settings, size_t id, const void* val)
+{
+ if (!settings)
+ return FALSE;
+
+ switch (id)
+ {
+ case FreeRDP_BitmapCacheV2CellInfo:
+ settings->BitmapCacheV2CellInfo = (void*)val;
+ break;
+
+ case FreeRDP_ChannelDefArray:
+ settings->ChannelDefArray = (void*)val;
+ break;
+
+ case FreeRDP_ClientAutoReconnectCookie:
+ settings->ClientAutoReconnectCookie = (void*)val;
+ break;
+
+ case FreeRDP_ClientRandom:
+ settings->ClientRandom = (void*)val;
+ break;
+
+ case FreeRDP_ClientTimeZone:
+ settings->ClientTimeZone = (void*)val;
+ break;
+
+ case FreeRDP_DeviceArray:
+ settings->DeviceArray = (void*)val;
+ break;
+
+ case FreeRDP_DynamicChannelArray:
+ settings->DynamicChannelArray = (void*)val;
+ break;
+
+ case FreeRDP_FragCache:
+ settings->FragCache = (void*)val;
+ break;
+
+ case FreeRDP_GlyphCache:
+ settings->GlyphCache = (void*)val;
+ break;
+
+ case FreeRDP_LoadBalanceInfo:
+ settings->LoadBalanceInfo = (void*)val;
+ break;
+
+ case FreeRDP_MonitorDefArray:
+ settings->MonitorDefArray = (void*)val;
+ break;
+
+ case FreeRDP_MonitorIds:
+ settings->MonitorIds = (void*)val;
+ break;
+
+ case FreeRDP_OrderSupport:
+ settings->OrderSupport = (void*)val;
+ break;
+
+ case FreeRDP_Password51:
+ settings->Password51 = (void*)val;
+ break;
+
+ case FreeRDP_RdpServerCertificate:
+ settings->RdpServerCertificate = (void*)val;
+ break;
+
+ case FreeRDP_RdpServerRsaKey:
+ settings->RdpServerRsaKey = (void*)val;
+ break;
+
+ case FreeRDP_ReceivedCapabilities:
+ settings->ReceivedCapabilities = (void*)val;
+ break;
+
+ case FreeRDP_RedirectionPassword:
+ settings->RedirectionPassword = (void*)val;
+ break;
+
+ case FreeRDP_RedirectionTsvUrl:
+ settings->RedirectionTsvUrl = (void*)val;
+ break;
+
+ case FreeRDP_ServerAutoReconnectCookie:
+ settings->ServerAutoReconnectCookie = (void*)val;
+ break;
+
+ case FreeRDP_ServerCertificate:
+ settings->ServerCertificate = (void*)val;
+ break;
+
+ case FreeRDP_ServerRandom:
+ settings->ServerRandom = (void*)val;
+ break;
+
+ case FreeRDP_StaticChannelArray:
+ settings->StaticChannelArray = (void*)val;
+ break;
+
+ case FreeRDP_TargetNetAddresses:
+ settings->TargetNetAddresses = (void*)val;
+ break;
+
+ case FreeRDP_TargetNetPorts:
+ settings->TargetNetPorts = (void*)val;
+ break;
+
+ case FreeRDP_instance:
+ settings->instance = (void*)val;
+ break;
+
+ default:
+ WLog_ERR(TAG, "[%s] Invalid key index %" PRIuz, __FUNCTION__, id);
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/libfreerdp/common/settings_str.c b/libfreerdp/common/settings_str.c
index 8ba0b38ae..699c94b2d 100644
--- a/libfreerdp/common/settings_str.c
+++ b/libfreerdp/common/settings_str.c
@@ -3,6 +3,8 @@
#include <freerdp/settings.h>
#include <freerdp/log.h>
+#include "../core/settings.h"
+
#define TAG FREERDP_TAG("common.settings")
struct settings_str_entry
@@ -385,6 +387,100 @@ static const struct settings_str_entry settings_map[] = {
{ FreeRDP_instance, 8, "FreeRDP_instance" },
};
+BOOL freerdp_settings_clone_keys(rdpSettings* dst, const rdpSettings* src)
+{
+ size_t x;
+ for (x = 0; x < ARRAYSIZE(settings_map); x++)
+ {
+ const struct settings_str_entry* cur = &settings_map[x];
+ switch (cur->type)
+ {
+ case 0: /* bool */
+ {
+ BOOL sval = freerdp_settings_get_bool(src, cur->id);
+ if (!freerdp_settings_set_bool(dst, cur->id, sval))
+ return FALSE;
+ }
+ break;
+ case 1: /* UINT16 */
+ {
+ UINT16 sval = freerdp_settings_get_uint16(src, cur->id);
+ if (!freerdp_settings_set_uint16(dst, cur->id, sval))
+ return FALSE;
+ }
+ break;
+ case 2: /* INT16 */
+ {
+ INT16 sval = freerdp_settings_get_int16(src, cur->id);
+ if (!freerdp_settings_set_int16(dst, cur->id, sval))
+ return FALSE;
+ }
+ break;
+ case 3: /* UINT32 */
+ {
+ UINT32 sval = freerdp_settings_get_uint32(src, cur->id);
+ if (!freerdp_settings_set_uint32(dst, cur->id, sval))
+ return FALSE;
+ }
+ break;
+ case 4: /* INT32 */
+ {
+ INT32 sval = freerdp_settings_get_int32(src, cur->id);
+ if (!freerdp_settings_set_int32(dst, cur->id, sval))
+ return FALSE;
+ }
+ break;
+ case 5: /* UINT64 */
+ {
+ UINT64 sval = freerdp_settings_get_uint64(src, cur->id);
+ if (!freerdp_settings_set_uint64(dst, cur->id, sval))
+ return FALSE;
+ }
+ break;
+ case 6: /* INT64 */
+ {
+ INT64 sval = freerdp_settings_get_int64(src, cur->id);
+ if (!freerdp_settings_set_int64(dst, cur->id, sval))
+ return FALSE;
+ }
+ break;
+ case 7: /* strings */
+ {
+ const char* sval = freerdp_settings_get_string(src, cur->id);
+ if (!freerdp_settings_set_string_(dst, cur->id, sval, FALSE))
+ return FALSE;
+ }
+ break;
+ case 8: /* pointer */
+ {
+ const void* sval = freerdp_settings_get_pointer(src, cur->id);
+ if (!freerdp_settings_set_pointer(dst, cur->id, sval))
+ return FALSE;
+ }
+ break;
+ }
+ }
+ return TRUE;
+}
+
+void freerdp_settings_free_keys(rdpSettings* dst, BOOL cleanup)
+{
+ size_t x;
+ for (x = 0; x < ARRAYSIZE(settings_map); x++)
+ {
+ const struct settings_str_entry* cur = &settings_map[x];
+ switch (cur->type)
+ {
+ case 7: /* strings */
+ freerdp_settings_set_string_(dst, cur->id, NULL, cleanup);
+ break;
+ case 8: /* pointer */
+ freerdp_settings_set_pointer(dst, cur->id, NULL);
+ break;
+ }
+ }
+}
+
SSIZE_T freerdp_settings_get_key_for_name(const char* value)
{
size_t x;
diff --git a/libfreerdp/core/capabilities.c b/libfreerdp/core/capabilities.c
index 31a1f9af3..d91f9078f 100644
--- a/libfreerdp/core/capabilities.c
+++ b/libfreerdp/core/capabilities.c
@@ -2702,9 +2702,9 @@ static BOOL rdp_read_bitmap_codec_guid(wStream* s, GUID* guid)
if (Stream_GetRemainingLength(s) < 16)
return FALSE;
Stream_Read(s, g, 16);
- guid->Data1 = (g[3] << 24) | (g[2] << 16) | (g[1] << 8) | g[0];
- guid->Data2 = (g[5] << 8) | g[4];
- guid->Data3 = (g[7] << 8) | g[6];
+ guid->Data1 = ((UINT32)g[3] << 24U) | ((UINT32)g[2] << 16U) | (g[1] << 8U) | g[0];
+ guid->Data2 = (g[5] << 8U) | g[4];
+ guid->Data3 = (g[7] << 8U) | g[6];
guid->Data4[0] = g[8];
guid->Data4[1] = g[9];
guid->Data4[2] = g[10];
diff --git a/libfreerdp/core/gateway/http.c b/libfreerdp/core/gateway/http.c
index 8d13e8907..848101099 100644
--- a/libfreerdp/core/gateway/http.c
+++ b/libfreerdp/core/gateway/http.c
@@ -814,6 +814,7 @@ HttpResponse* http_response_recv(rdpTls* tls, BOOL readContentLength)
size_t count = 0;
char* buffer = (char*)Stream_Buffer(response->data);
char* line = (char*)Stream_Buffer(response->data);
+ char* context = NULL;
while ((line = string_strnstr(line, "\r\n", payloadOffset - (line - buffer) - 2UL)))
{
@@ -834,12 +835,12 @@ HttpResponse* http_response_recv(rdpTls* tls, BOOL readContentLength)
buffer[payloadOffset - 1] = '\0';
buffer[payloadOffset - 2] = '\0';
count = 0;
- line = strtok(buffer, "\r\n");
+ line = strtok_s(buffer, "\r\n", &context);
while (line && (response->count > count))
{
response->lines[count] = line;
- line = strtok(NULL, "\r\n");
+ line = strtok_s(NULL, "\r\n", &context);
count++;
}
diff --git a/libfreerdp/core/gateway/tsg.c b/libfreerdp/core/gateway/tsg.c
index 91f851f15..7537f18dd 100644
--- a/libfreerdp/core/gateway/tsg.c
+++ b/libfreerdp/core/gateway/tsg.c
@@ -781,7 +781,7 @@ static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu,
Stream_Read_UINT32(pdu->s, Pointer); /* TsgCapsPtr (4 bytes) */
Stream_Read_UINT32(pdu->s, versionCaps->numCapabilities); /* NumCapabilities (4 bytes) */
Stream_Read_UINT16(pdu->s, versionCaps->majorVersion); /* MajorVersion (2 bytes) */
- Stream_Read_UINT16(pdu->s, versionCaps->majorVersion); /* MinorVersion (2 bytes) */
+ Stream_Read_UINT16(pdu->s, versionCaps->minorVersion); /* MinorVersion (2 bytes) */
Stream_Read_UINT16(
pdu->s, versionCaps->quarantineCapabilities); /* QuarantineCapabilities (2 bytes) */
diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c
index 843693e01..7fd96b934 100644
--- a/libfreerdp/core/info.c
+++ b/libfreerdp/core/info.c
@@ -67,6 +67,54 @@ static struct
{ INFO_HIDEF_RAIL_SUPPORTED, "INFO_HIDEF_RAIL_SUPPORTED" },
};
+static BOOL rdp_read_info_null_string(UINT32 flags, wStream* s, size_t cbLen, CHAR** dst,
+ size_t max)
+{
+ CHAR* ret = NULL;
+
+ const BOOL unicode = flags & INFO_UNICODE;
+ const size_t nullSize = unicode ? sizeof(WCHAR) : sizeof(CHAR);
+
+ if (Stream_GetRemainingLength(s) < (size_t)(cbLen))
+ return FALSE;
+
+ if (cbLen > 0)
+ {
+ WCHAR domain[512 / sizeof(WCHAR) + sizeof(WCHAR)] = { 0 };
+ /* cbDomain is the size in bytes of the character data in the Domain field.
+ * This size excludes (!) the length of the mandatory null terminator.
+ * Maximum value including the mandatory null terminator: 512
+ */
+ if ((cbLen % 2) || (cbLen > (max - nullSize)))
+ {
+ WLog_ERR(TAG, "protocol error: invalid value: %" PRIuz "", cbLen);
+ return FALSE;
+ }
+
+ Stream_Read(s, domain, cbLen);
+
+ if (unicode)
+ {
+ if (ConvertFromUnicode(CP_UTF8, 0, domain, cbLen, &ret, 0, NULL, NULL) < 1)
+ {
+ WLog_ERR(TAG, "failed to convert Domain string");
+ return FALSE;
+ }
+ }
+ else
+ {
+ ret = calloc(cbLen + 1, nullSize);
+ if (!ret)
+ return FALSE;
+ memcpy(ret, domain, cbLen);
+ }
+ }
+
+ free(*dst);
+ *dst = ret;
+ return TRUE;
+}
+
static char* rdp_info_package_flags_description(UINT32 flags)
{
char* result;
@@ -245,10 +293,6 @@ static BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s)
UINT16 cbClientDir;
UINT16 cbAutoReconnectLen;
rdpSettings* settings = rdp->settings;
- union {
- BYTE* bp;
- WCHAR* wp;
- } ptrconv;
if (Stream_GetRemainingLength(s) < 4)
return FALSE;
@@ -275,32 +319,9 @@ static BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s)
if (Stream_GetRemainingLength(s) < cbClientAddress)
return FALSE;
- if (settings->ClientAddress)
- {
- free(settings->ClientAddress);
- settings->ClientAddress = NULL;
- }
-
- if (cbClientAddress)
- {
- ptrconv.bp = Stream_Pointer(s);
-
- if (ptrconv.wp[cbClientAddress / 2 - 1])
- {
- WLog_ERR(TAG, "protocol error: clientAddress must be null terminated");
- return FALSE;
- }
-
- if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &settings->ClientAddress, 0, NULL,
- NULL) < 1)
- {
- WLog_ERR(TAG, "failed to convert client address");
- return FALSE;
- }
-
- Stream_Seek(s, cbClientAddress);
- WLog_DBG(TAG, "rdp client address: [%s]", settings->ClientAddress);
- }
+ if (!rdp_read_info_null_string(INFO_UNICODE, s, cbClientAddress, &settings->ClientAddress,
+ (settings->RdpVersion < RDP_VERSION_10_0) ? 64 : 80))
+ return FALSE;
if (Stream_GetRemainingLength(s) < 2)
return FALSE;
@@ -315,41 +336,9 @@ static BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s)
* sets cbClientDir to 0.
*/
- if ((cbClientDir % 2) || cbClientDir > 512)
- {
- WLog_ERR(TAG, "protocol error: invalid cbClientDir value: %" PRIu16 "", cbClientDir);
- return FALSE;
- }
-
- if (Stream_GetRemainingLength(s) < cbClientDir)
+ if (!rdp_read_info_null_string(INFO_UNICODE, s, cbClientDir, &settings->ClientDir, 512))
return FALSE;
- if (settings->ClientDir)
- {
- free(settings->ClientDir);
- settings->ClientDir = NULL;
- }
-
- if (cbClientDir)
- {
- ptrconv.bp = Stream_Pointer(s);
-
- if (ptrconv.wp[cbClientDir / 2 - 1])
- {
- WLog_ERR(TAG, "protocol error: clientDir must be null terminated");
- return FALSE;
- }
-
- if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &settings->ClientDir, 0, NULL, NULL) < 1)
- {
- WLog_ERR(TAG, "failed to convert client directory");
- return FALSE;
- }
-
- Stream_Seek(s, cbClientDir);
- WLog_DBG(TAG, "rdp client dir: [%s]", settings->ClientDir);
- }
-
/**
* down below all fields are optional but if one field is not present,
* then all of the subsequent fields also MUST NOT be present.
@@ -474,6 +463,68 @@ fail:
return ret;
}
+static BOOL rdp_read_info_string(UINT32 flags, wStream* s, size_t cbLenNonNull, CHAR** dst,
+ size_t max)
+{
+ union {
+ char c;
+ WCHAR w;
+ BYTE b[2];
+ } terminator;
+ CHAR* ret = NULL;
+
+ const BOOL unicode = flags & INFO_UNICODE;
+ const size_t nullSize = unicode ? sizeof(WCHAR) : sizeof(CHAR);
+
+ if (Stream_GetRemainingLength(s) < (size_t)(cbLenNonNull + nullSize))
+ return FALSE;
+
+ if (cbLenNonNull > 0)
+ {
+ WCHAR domain[512 / sizeof(WCHAR) + sizeof(WCHAR)] = { 0 };
+ /* cbDomain is the size in bytes of the character data in the Domain field.
+ * This size excludes (!) the length of the mandatory null terminator.
+ * Maximum value including the mandatory null terminator: 512
+ */
+ if ((cbLenNonNull % 2) || (cbLenNonNull > (max - nullSize)))
+ {
+ WLog_ERR(TAG, "protocol error: invalid value: %" PRIuz "", cbLenNonNull);
+ return FALSE;
+ }
+
+ Stream_Read(s, domain, cbLenNonNull);
+
+ if (unicode)
+ {
+ if (ConvertFromUnicode(CP_UTF8, 0, domain, cbLenNonNull, &ret, 0, NULL, NULL) < 1)
+ {
+ WLog_ERR(TAG, "failed to convert Domain string");
+ return FALSE;
+ }
+ }
+ else
+ {
+ ret = calloc(cbLenNonNull + 1, nullSize);
+ if (!ret)
+ return FALSE;
+ memcpy(ret, domain, cbLenNonNull);
+ }
+ }
+
+ terminator.w = L'\0';
+ Stream_Read(s, terminator.b, nullSize);
+
+ if (terminator.w != L'\0')
+ {
+ WLog_ERR(TAG, "protocol error: Domain must be null terminated");
+ free(ret);
+ return FALSE;
+ }
+
+ *dst = ret;
+ return TRUE;
+}
+
/**
* Read Info Packet (TS_INFO_PACKET).\n
* @msdn{cc240475}
@@ -483,6 +534,7 @@ fail:
static BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s, UINT16 tpktlength)
{
+ BOOL smallsize = FALSE;
UINT32 flags;
UINT16 cbDomain;
UINT16 cbUserName;
@@ -491,16 +543,12 @@ static BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s, UINT16 tpktlength)
UINT16 cbWorkingDir;
UINT32 CompressionLevel;
rdpSettings* settings = rdp->settings;
- union {
- BYTE* bp;
- WCHAR* wp;
- } ptrconv;
if (Stream_GetRemainingLength(s) < 18)
return FALSE;
Stream_Read_UINT32(s, settings->KeyboardCodePage); /* CodePage (4 bytes ) */
- Stream_Read_UINT32(s, flags); /* flags (4 bytes) */
+ Stream_Read_UINT32(s, flags); /* flags (4 bytes) */
settings->AudioCapture = ((flags & INFO_AUDIOCAPTURE) ? TRUE : FALSE);
settings->AudioPlayback = ((flags & INFO_NOAUDIOPLAYBACK) ? FALSE : TRUE);
settings->AutoLogonEnabled = ((flags & INFO_AUTOLOGON) ? TRUE : FALSE);
@@ -520,11 +568,9 @@ static BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s, UINT16 tpktlength)
settings->CompressionLevel = CompressionLevel;
}
- if (!(flags & INFO_UNICODE))
- {
- WLog_ERR(TAG, "Client without INFO_UNICODE flag: this is currently not supported");
- return FALSE;
- }
+ /* RDP 4 and 5 have smaller credential limits */
+ if (settings->RdpVersion < RDP_VERSION_5_PLUS)
+ smallsize = TRUE;
Stream_Read_UINT16(s, cbDomain); /* cbDomain (2 bytes) */
Stream_Read_UINT16(s, cbUserName); /* cbUserName (2 bytes) */
@@ -532,179 +578,21 @@ static BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s, UINT16 tpktlength)
Stream_Read_UINT16(s, cbAlternateShell); /* cbAlternateShell (2 bytes) */
Stream_Read_UINT16(s, cbWorkingDir); /* cbWorkingDir (2 bytes) */
- if (Stream_GetRemainingLength(s) < (size_t)(cbDomain + 2))
+ if (!rdp_read_info_string(flags, s, cbDomain, &settings->Domain, smallsize ? 52 : 512))
return FALSE;
- if (cbDomain > 0)
- {
- /* cbDomain is the size in bytes of the character data in the Domain field.
- * This size excludes (!) the length of the mandatory null terminator.
- * Maximum value including the mandatory null terminator: 512
- */
- if ((cbDomain % 2) || cbDomain > 512)
- {
- WLog_ERR(TAG, "protocol error: invalid cbDomain value: %" PRIu16 "", cbDomain);
- return FALSE;
- }
-
- ptrconv.bp = Stream_Pointer(s);
-
- if (ptrconv.wp[cbDomain / 2])
- {
- WLog_ERR(TAG, "protocol error: Domain must be null terminated");
- return FALSE;
- }
-
- if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &settings->Domain, 0, NULL, NULL) < 1)
- {
- WLog_ERR(TAG, "failed to convert Domain string");
- return FALSE;
- }
-
- Stream_Seek(s, cbDomain);
- }
-
- Stream_Seek(s, 2);
-
- if (Stream_GetRemainingLength(s) < (size_t)(cbUserName + 2))
+ if (!rdp_read_info_string(flags, s, cbUserName, &settings->Username, smallsize ? 44 : 512))
return FALSE;
- if (cbUserName > 0)
- {
- /* cbUserName is the size in bytes of the character data in the UserName field.
- * This size excludes (!) the length of the mandatory null terminator.
- * Maximum value including the mandatory null terminator: 512
- */
- if ((cbUserName % 2) || cbUserName > 512)
- {
- WLog_ERR(TAG, "protocol error: invalid cbUserName value: %" PRIu16 "", cbUserName);
- return FALSE;
- }
-
- ptrconv.bp = Stream_Pointer(s);
-
- if (ptrconv.wp[cbUserName / 2])
- {
- WLog_ERR(TAG, "protocol error: UserName must be null terminated");
- return FALSE;
- }
-
- if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &settings->Username, 0, NULL, NULL) < 1)
- {
- WLog_ERR(TAG, "failed to convert UserName string");
- return FALSE;
- }
-
- Stream_Seek(s, cbUserName);
- }
-
- Stream_Seek(s, 2);
-
- if (Stream_GetRemainingLength(s) < (size_t)(cbPassword + 2))
+ if (!rdp_read_info_string(flags, s, cbPassword, &settings->Password, smallsize ? 32 : 512))
return FALSE;
- if (cbPassword > 0)
- {
- /* cbPassword is the size in bytes of the character data in the Password field.
- * This size excludes (!) the length of the mandatory null terminator.
- * Maximum value including the mandatory null terminator: 512
- */
- if ((cbPassword % 2) || cbPassword > LB_PASSWORD_MAX_LENGTH)
- {
- WLog_ERR(TAG, "protocol error: invalid cbPassword value: %" PRIu16 "", cbPassword);
- return FALSE;
- }
-
- ptrconv.bp = Stream_Pointer(s);
-
- if (ptrconv.wp[cbPassword / 2])
- {
- WLog_ERR(TAG, "protocol error: Password must be null terminated");
- return FALSE;
- }
-
- if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &settings->Password, 0, NULL, NULL) < 1)
- {
- WLog_ERR(TAG, "failed to convert Password string");
- return FALSE;
- }
-
- Stream_Seek(s, cbPassword);
- }
-
- Stream_Seek(s, 2);
-
- if (Stream_GetRemainingLength(s) < (size_t)(cbAlternateShell + 2))
+ if (!rdp_read_info_string(flags, s, cbAlternateShell, &settings->AlternateShell, 512))
return FALSE;
- if (cbAlternateShell > 0)
- {
- /* cbAlternateShell is the size in bytes of the character data in the AlternateShell field.
- * This size excludes (!) the length of the mandatory null terminator.
- * Maximum value including the mandatory null terminator: 512
- */
- if ((cbAlternateShell % 2) || cbAlternateShell > 512)
- {
- WLog_ERR(TAG, "protocol error: invalid cbAlternateShell value: %" PRIu16 "",
- cbAlternateShell);
- return FALSE;
- }
-
- ptrconv.bp = Stream_Pointer(s);
-
- if (ptrconv.wp[cbAlternateShell / 2])
- {
- WLog_ERR(TAG, "protocol error: AlternateShell must be null terminated");
- return FALSE;
- }
-
- if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &settings->AlternateShell, 0, NULL,
- NULL) < 1)
- {
- WLog_ERR(TAG, "failed to convert AlternateShell string");
- return FALSE;
- }
-
- Stream_Seek(s, cbAlternateShell);
- }
-
- Stream_Seek(s, 2);
-
- if (Stream_GetRemainingLength(s) < (size_t)(cbWorkingDir + 2))
+ if (!rdp_read_info_string(flags, s, cbWorkingDir, &settings->ShellWorkingDirectory, 512))
return FALSE;
- if (cbWorkingDir > 0)
- {
- /* cbWorkingDir is the size in bytes of the character data in the WorkingDir field.
- * This size excludes (!) the length of the mandatory null terminator.
- * Maximum value including the mandatory null terminator: 512
- */
- if ((cbWorkingDir % 2) || cbWorkingDir > 512)
- {
- WLog_ERR(TAG, "protocol error: invalid cbWorkingDir value: %" PRIu16 "", cbWorkingDir);
- return FALSE;
- }
-
- ptrconv.bp = Stream_Pointer(s);
-
- if (ptrconv.wp[cbWorkingDir / 2])
- {
- WLog_ERR(TAG, "protocol error: WorkingDir must be null terminated");
- return FALSE;
- }
-
- if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &settings->ShellWorkingDirectory, 0,
- NULL, NULL) < 1)
- {
- WLog_ERR(TAG, "failed to convert AlternateShell string");
- return FALSE;
- }
-
- Stream_Seek(s, cbWorkingDir);
- }
-
- Stream_Seek(s, 2);
-
if (settings->RdpVersion >= RDP_VERSION_5_PLUS)
return rdp_read_extended_info_packet(rdp, s); /* extraInfo */
@@ -909,12 +797,12 @@ static BOOL rdp_write_info_packet(rdpRdp* rdp, wStream* s)
/* excludes (!) the length of the mandatory null terminator */
cbWorkingDir = cbWorkingDir >= 2 ? cbWorkingDir - 2 : cbWorkingDir;
Stream_Write_UINT32(s, settings->KeyboardCodePage); /* CodePage (4 bytes) */
- Stream_Write_UINT32(s, flags); /* flags (4 bytes) */
- Stream_Write_UINT16(s, cbDomain); /* cbDomain (2 bytes) */
- Stream_Write_UINT16(s, cbUserName); /* cbUserName (2 bytes) */
- Stream_Write_UINT16(s, cbPassword); /* cbPassword (2 bytes) */
- Stream_Write_UINT16(s, cbAlternateShell); /* cbAlternateShell (2 bytes) */
- Stream_Write_UINT16(s, cbWorkingDir); /* cbWorkingDir (2 bytes) */
+ Stream_Write_UINT32(s, flags); /* flags (4 bytes) */
+ Stream_Write_UINT16(s, cbDomain); /* cbDomain (2 bytes) */
+ Stream_Write_UINT16(s, cbUserName); /* cbUserName (2 bytes) */
+ Stream_Write_UINT16(s, cbPassword); /* cbPassword (2 bytes) */
+ Stream_Write_UINT16(s, cbAlternateShell); /* cbAlternateShell (2 bytes) */
+ Stream_Write_UINT16(s, cbWorkingDir); /* cbWorkingDir (2 bytes) */
Stream_Write(s, domainW, cbDomain);
@@ -1115,10 +1003,6 @@ static BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info* info)
UINT32 Size;
UINT32 cbDomain;
UINT32 cbUserName;
- union {
- BYTE* bp;
- WCHAR* wp;
- } ptrconv;
WINPR_UNUSED(rdp);
ZeroMemory(info, sizeof(*info));
@@ -1141,7 +1025,8 @@ static BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info* info)
*/
if (cbDomain)
{
- if ((cbDomain % 2) || cbDomain > 52)
+ WCHAR domain[26] = { 0 };
+ if ((cbDomain % 2) || (cbDomain > 52))
{
WLog_ERR(TAG, "protocol error: invalid cbDomain value: %" PRIu32 "", cbDomain);
goto fail;
@@ -1153,23 +1038,22 @@ static BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info* info)
goto fail;
}
- ptrconv.bp = Stream_Pointer(s);
+ memcpy(domain, Stream_Pointer(s), cbDomain);
+ Stream_Seek(s, cbDomain); /* domain */
- if (ptrconv.wp[cbDomain / 2 - 1])
+ if (domain[cbDomain / sizeof(WCHAR) - 1])
{
WLog_ERR(TAG, "protocol error: Domain field must be null terminated");
goto fail;
}
- if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &info->domain, 0, NULL, FALSE) < 1)
+ if (ConvertFromUnicode(CP_UTF8, 0, domain, -1, &info->domain, 0, NULL, FALSE) < 1)
{
WLog_ERR(TAG, "failed to convert the Domain string");
goto fail;
}
}
- Stream_Seek(s, cbDomain); /* domain */
-
/* cbUserName is the size in bytes of the Unicode character data in the UserName field.
* The size of the mandatory null terminator is include in this value.
* Note: Since MS-RDPBCGR 2.2.10.1.1.2 does not mention any size limits we assume
@@ -1178,6 +1062,8 @@ static BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info* info)
*/
if (cbUserName)
{
+ WCHAR user[256] = { 0 };
+
if ((cbUserName % 2) || cbUserName < 2 || cbUserName > 512)
{
WLog_ERR(TAG, "protocol error: invalid cbUserName value: %" PRIu32 "", cbUserName);
@@ -1190,22 +1076,22 @@ static BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info* info)
goto fail;
}
- ptrconv.bp = Stream_Pointer(s);
+ memcpy(user, Stream_Pointer(s), cbUserName);
+ Stream_Seek(s, cbUserName); /* userName */
- if (ptrconv.wp[cbUserName / 2 - 1])
+ if (user[cbUserName / sizeof(WCHAR) - 1])
{
WLog_ERR(TAG, "protocol error: UserName field must be null terminated");
goto fail;
}
- if (ConvertFromUnicode(CP_UTF8, 0, ptrconv.wp, -1, &info->username, 0, NULL, FALSE) < 1)
+ if (ConvertFromUnicode(CP_UTF8, 0, user, -1, &info->username, 0, NULL, FALSE) < 1)
{
WLog_ERR(TAG, "failed to convert the Domain string");
goto fail;
}
}
- Stream_Seek(s, cbUserName); /* userName */
WLog_DBG(TAG, "LogonInfoV2: SessionId: 0x%08" PRIX32 " UserName: [%s] Domain: [%s]",
info->sessionId, info->username, info->domain);
return TRUE;
diff --git a/libfreerdp/core/nla.c b/libfreerdp/core/nla.c
index 03efc839a..63d77abf9 100644
--- a/libfreerdp/core/nla.c
+++ b/libfreerdp/core/nla.c
@@ -1144,6 +1144,7 @@ SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla)
const BOOL ntlm = (_tcsncmp(nla->packageName, NTLM_SSP_NAME, ARRAYSIZE(NTLM_SSP_NAME)) == 0);
public_key_length = nla->PublicKey.cbBuffer;
+ sspi_SecBufferFree(&nla->pubKeyAuth);
if (!sspi_SecBufferAlloc(&nla->pubKeyAuth,
public_key_length + nla->ContextSizes.cbSecurityTrailer))
return SEC_E_INSUFFICIENT_MEMORY;
@@ -1212,6 +1213,7 @@ SECURITY_STATUS nla_encrypt_public_key_hash(rdpNla* nla)
const size_t hashSize =
nla->server ? sizeof(ServerClientHashMagic) : sizeof(ClientServerHashMagic);
+ sspi_SecBufferFree(&nla->pubKeyAuth);
if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, auth_data_length))
{
status = SEC_E_INSUFFICIENT_MEMORY;
@@ -2069,6 +2071,7 @@ static int nla_decode_ts_request(rdpNla* nla, wStream* s)
return -1;
}
+ sspi_SecBufferFree(&nla->negoToken);
if (!sspi_SecBufferAlloc(&nla->negoToken, length))
return -1;
@@ -2097,6 +2100,7 @@ static int nla_decode_ts_request(rdpNla* nla, wStream* s)
Stream_GetRemainingLength(s) < length)
return -1;
+ sspi_SecBufferFree(&nla->pubKeyAuth);
if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, length))
return -1;
@@ -2121,6 +2125,7 @@ static int nla_decode_ts_request(rdpNla* nla, wStream* s)
Stream_GetRemainingLength(s) < length)
return -1;
+ sspi_SecBufferFree(&nla->ClientNonce);
if (!sspi_SecBufferAlloc(&nla->ClientNonce, length))
return -1;
@@ -2357,10 +2362,6 @@ rdpNla* nla_new(freerdp* instance, rdpTransport* transport, rdpSettings* setting
nla->sendSeqNum = 0;
nla->recvSeqNum = 0;
nla->version = 6;
- ZeroMemory(&nla->ClientNonce, sizeof(SecBuffer));
- ZeroMemory(&nla->negoToken, sizeof(SecBuffer));
- ZeroMemory(&nla->pubKeyAuth, sizeof(SecBuffer));
- ZeroMemory(&nla->authInfo, sizeof(SecBuffer));
SecInvalidateHandle(&nla->context);
if (settings->NtlmSamFile)
@@ -2465,6 +2466,7 @@ void nla_free(rdpNla* nla)
sspi_SecBufferFree(&nla->tsCredentials);
free(nla->ServicePrincipalName);
nla_identity_free(nla->identity);
+ nla_buffer_free(nla);
free(nla);
}
diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c
index bac9dc113..e053bd480 100644
--- a/libfreerdp/core/orders.c
+++ b/libfreerdp/core/orders.c
@@ -2548,7 +2548,7 @@ static CACHE_BRUSH_ORDER* update_read_cache_brush_order(rdpUpdate* update, wStre
Stream_Read_UINT8(s, cache_brush->index); /* cacheEntry (1 byte) */
Stream_Read_UINT8(s, iBitmapFormat); /* iBitmapFormat (1 byte) */
- if (iBitmapFormat > ARRAYSIZE(BMF_BPP))
+ if (iBitmapFormat >= ARRAYSIZE(BMF_BPP))
goto fail;
cache_brush->bpp = BMF_BPP[iBitmapFormat];
diff --git a/libfreerdp/core/proxy.c b/libfreerdp/core/proxy.c
index 634dfaabd..a50b7ed47 100644
--- a/libfreerdp/core/proxy.c
+++ b/libfreerdp/core/proxy.c
@@ -144,6 +144,7 @@ static BOOL check_no_proxy(rdpSettings* settings, const char* no_proxy)
BOOL result = FALSE;
char* current;
char* copy;
+ char* context = NULL;
size_t host_len;
struct sockaddr_in sa4;
struct sockaddr_in6 sa6;
@@ -164,7 +165,7 @@ static BOOL check_no_proxy(rdpSettings* settings, const char* no_proxy)
if (!copy)
return FALSE;
- current = strtok(copy, delimiter);
+ current = strtok_s(copy, delimiter, &context);
while (current && !result)
{
@@ -243,7 +244,7 @@ static BOOL check_no_proxy(rdpSettings* settings, const char* no_proxy)
}
}
- current = strtok(NULL, delimiter);
+ current = strtok_s(NULL, delimiter, &context);
}
free(copy);
diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c
index b9c60c74e..fd771ae3e 100644
--- a/libfreerdp/core/rdp.c
+++ b/libfreerdp/core/rdp.c
@@ -1751,6 +1751,7 @@ rdpRdp* rdp_new(rdpContext* context)
if (!rdp)
return NULL;
+ InitializeCriticalSection(&rdp->critical);
rdp->context = context;
rdp->instance = context->instance;
flags = 0;
@@ -1763,7 +1764,7 @@ rdpRdp* rdp_new(rdpContext* context)
context->settings = freerdp_settings_new(flags);
if (!context->settings)
- goto out_free;
+ goto fail;
newSettings = TRUE;
}
@@ -1784,93 +1785,67 @@ rdpRdp* rdp_new(rdpContext* context)
rdp->transport = transport_new(context);
if (!rdp->transport)
- goto out_free_settings;
+ goto fail;
rdp->license = license_new(rdp);
if (!rdp->license)
- goto out_free_transport;
+ goto fail;
rdp->input = input_new(rdp);
if (!rdp->input)
- goto out_free_license;
+ goto fail;
rdp->update = update_new(rdp);
if (!rdp->update)
- goto out_free_input;
+ goto fail;
rdp->fastpath = fastpath_new(rdp);
if (!rdp->fastpath)
- goto out_free_update;
+ goto fail;
rdp->nego = nego_new(rdp->transport);
if (!rdp->nego)
- goto out_free_fastpath;
+ goto fail;
rdp->mcs = mcs_new(rdp->transport);
if (!rdp->mcs)
- goto out_free_nego;
+ goto fail;
rdp->redirection = redirection_new();
if (!rdp->redirection)
- goto out_free_mcs;
+ goto fail;
rdp->autodetect = autodetect_new();
if (!rdp->autodetect)
- goto out_free_redirection;
+ goto fail;
rdp->heartbeat = heartbeat_new();
if (!rdp->heartbeat)
- goto out_free_autodetect;
+ goto fail;
rdp->multitransport = multitransport_new();
if (!rdp->multitransport)
- goto out_free_heartbeat;
+ goto fail;
rdp->bulk = bulk_new(context);
if (!rdp->bulk)
- goto out_free_multitransport;
+ goto fail;
return rdp;
-out_free_multitransport:
- multitransport_free(rdp->multitransport);
-out_free_heartbeat:
- heartbeat_free(rdp->heartbeat);
-out_free_autodetect:
- autodetect_free(rdp->autodetect);
-out_free_redirection:
- redirection_free(rdp->redirection);
-out_free_mcs:
- mcs_free(rdp->mcs);
-out_free_nego:
- nego_free(rdp->nego);
-out_free_fastpath:
- fastpath_free(rdp->fastpath);
-out_free_update:
- update_free(rdp->update);
-out_free_input:
- input_free(rdp->input);
-out_free_license:
- license_free(rdp->license);
-out_free_transport:
- transport_free(rdp->transport);
-out_free_settings:
- if (newSettings)
- freerdp_settings_free(rdp->settings);
-
-out_free:
- free(rdp);
+fail:
+ rdp_free(rdp);
return NULL;
}
@@ -1950,6 +1925,7 @@ void rdp_free(rdpRdp* rdp)
{
if (rdp)
{
+ DeleteCriticalSection(&rdp->critical);
winpr_RC4_Free(rdp->rc4_decrypt_key);
winpr_RC4_Free(rdp->rc4_encrypt_key);
winpr_Cipher_Free(rdp->fips_encrypt);
diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h
index e728ea357..47281d611 100644
--- a/libfreerdp/core/rdp.h
+++ b/libfreerdp/core/rdp.h
@@ -179,6 +179,7 @@ struct rdp_rdp
UINT64 inPackets;
UINT64 outBytes;
UINT64 outPackets;
+ CRITICAL_SECTION critical;
};
FREERDP_LOCAL BOOL rdp_read_security_header(wStream* s, UINT16* flags, UINT16* length);
diff --git a/libfreerdp/core/security.c b/libfreerdp/core/security.c
index 9ef9b1afd..e6571c36d 100644
--- a/libfreerdp/core/security.c
+++ b/libfreerdp/core/security.c
@@ -712,26 +712,31 @@ out:
BOOL security_encrypt(BYTE* data, size_t length, rdpRdp* rdp)
{
+ BOOL rc = FALSE;
+ EnterCriticalSection(&rdp->critical);
if (rdp->encrypt_use_count >= 4096)
{
if (!security_key_update(rdp->encrypt_key, rdp->encrypt_update_key, rdp->rc4_key_len, rdp))
- return FALSE;
+ goto fail;
winpr_RC4_Free(rdp->rc4_encrypt_key);
rdp->rc4_encrypt_key = winpr_RC4_New(rdp->encrypt_key, rdp->rc4_key_len);
if (!rdp->rc4_encrypt_key)
- return FALSE;
+ goto fail;
rdp->encrypt_use_count = 0;
}
if (!winpr_RC4_Update(rdp->rc4_encrypt_key, length, data, data))
- return FALSE;
+ goto fail;
rdp->encrypt_use_count++;
rdp->encrypt_checksum_use_count++;
- return TRUE;
+ rc = TRUE;
+fail:
+ LeaveCriticalSection(&rdp->critical);
+ return rc;
}
BOOL security_decrypt(BYTE* data, size_t length, rdpRdp* rdp)
@@ -793,19 +798,27 @@ out:
BOOL security_fips_encrypt(BYTE* data, size_t length, rdpRdp* rdp)
{
+ BOOL rc = FALSE;
size_t olen;
+ EnterCriticalSection(&rdp->critical);
if (!winpr_Cipher_Update(rdp->fips_encrypt, data, length, data, &olen))
- return FALSE;
+ goto fail;
rdp->encrypt_use_count++;
- return TRUE;
+ rc = TRUE;
+fail:
+ LeaveCriticalSection(&rdp->critical);
+ return rc;
}
BOOL security_fips_decrypt(BYTE* data, size_t length, rdpRdp* rdp)
{
size_t olen;
+ if (!rdp || !rdp->fips_decrypt)
+ return FALSE;
+
if (!winpr_Cipher_Update(rdp->fips_decrypt, data, length, data, &olen))
return FALSE;
diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c
index 15481641b..25d2390c0 100644
--- a/libfreerdp/core/settings.c
+++ b/libfreerdp/core/settings.c
@@ -40,6 +40,8 @@
#include <freerdp/build-config.h>
#include <ctype.h>
+#include "settings.h"
+
#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable : 4244)
@@ -626,39 +628,15 @@ out_fail:
static void freerdp_settings_free_internal(rdpSettings* settings)
{
- free(settings->ServerHostname);
- free(settings->Username);
- free(settings->Password);
- free(settings->Domain);
- free(settings->PasswordHash);
- free(settings->AcceptedCert);
- free(settings->AlternateShell);
- free(settings->ShellWorkingDirectory);
- free(settings->ComputerName);
free(settings->ChannelDefArray);
free(settings->MonitorDefArray);
free(settings->MonitorIds);
- free(settings->ClientAddress);
- free(settings->ClientDir);
- free(settings->AllowedTlsCiphers);
- free(settings->NtlmSamFile);
- free(settings->CertificateFile);
- free(settings->PrivateKeyFile);
- free(settings->ConnectionFile);
- free(settings->AssistanceFile);
free(settings->ReceivedCapabilities);
free(settings->OrderSupport);
- free(settings->ClientHostname);
- free(settings->ClientProductId);
free(settings->ServerRandom);
free(settings->ClientRandom);
free(settings->ServerCertificate);
- free(settings->RdpKeyFile);
certificate_free(settings->RdpServerCertificate);
- free(settings->CertificateContent);
- free(settings->PrivateKeyContent);
- free(settings->RdpKeyContent);
- free(settings->CertificateAcceptedFingerprints);
free(settings->ClientAutoReconnectCookie);
free(settings->ServerAutoReconnectCookie);
free(settings->ClientTimeZone);
@@ -666,52 +644,21 @@ static void freerdp_settings_free_internal(rdpSettings* settings)
free(settings->GlyphCache);
free(settings->FragCache);
key_free(settings->RdpServerRsaKey);
- free(settings->ConfigPath);
- free(settings->CurrentPath);
- free(settings->HomePath);
free(settings->LoadBalanceInfo);
- free(settings->TargetNetAddress);
- free(settings->RedirectionTargetFQDN);
- free(settings->RedirectionTargetNetBiosName);
- free(settings->RedirectionUsername);
- free(settings->RedirectionDomain);
free(settings->RedirectionPassword);
free(settings->RedirectionTsvUrl);
- free(settings->RedirectionAcceptedCert);
- free(settings->RemoteAssistanceSessionId);
- free(settings->RemoteAssistancePassword);
- free(settings->RemoteAssistancePassStub);
- free(settings->RemoteAssistanceRCTicket);
- free(settings->AuthenticationServiceClass);
- free(settings->GatewayHostname);
- free(settings->GatewayUsername);
- free(settings->GatewayPassword);
- free(settings->GatewayDomain);
- free(settings->GatewayAccessToken);
- free(settings->GatewayAcceptedCert);
- free(settings->CertificateName);
- free(settings->DynamicDSTTimeZoneKeyName);
- free(settings->PreconnectionBlob);
- free(settings->KerberosKdc);
- free(settings->KerberosRealm);
- free(settings->DumpRemoteFxFile);
- free(settings->PlayRemoteFxFile);
- free(settings->RemoteApplicationName);
- free(settings->RemoteApplicationIcon);
- free(settings->RemoteApplicationProgram);
- free(settings->RemoteApplicationFile);
- free(settings->RemoteApplicationGuid);
- free(settings->RemoteApplicationCmdLine);
- free(settings->ImeFileName);
- free(settings->DrivesToRedirect);
- free(settings->WindowTitle);
- free(settings->WmClass);
- free(settings->ActionScript);
+
freerdp_target_net_addresses_free(settings);
freerdp_device_collection_free(settings);
freerdp_static_channel_collection_free(settings);
freerdp_dynamic_channel_collection_free(settings);
- memset(settings, 0, sizeof(rdpSettings));
+
+ /* Extensions */
+ free(settings->ActionScript);
+ settings->ActionScript = NULL;
+
+ /* Free all strings, set other pointers NULL */
+ freerdp_settings_free_keys(settings, TRUE);
}
void freerdp_settings_free(rdpSettings* settings)
@@ -723,79 +670,13 @@ void freerdp_settings_free(rdpSettings* settings)
free(settings);
}
-BOOL freerdp_settings_copy(rdpSettings* _settings, const rdpSettings* settings)
+static BOOL freerdp_settings_int_buffer_copy(rdpSettings* _settings, const rdpSettings* settings)
{
+ BOOL rc = FALSE;
UINT32 index;
- if (!settings || !_settings)
+ if (!_settings || !settings)
return FALSE;
- freerdp_settings_free_internal(_settings);
- *_settings = *settings;
-
- /* char* values */
-#define CHECKED_STRDUP(name) \
- if (settings->name && !(_settings->name = _strdup(settings->name))) \
- goto out_fail
- CHECKED_STRDUP(ServerHostname); /* 20 */
- CHECKED_STRDUP(Username); /* 21 */
- CHECKED_STRDUP(Password); /* 22 */
- CHECKED_STRDUP(Domain); /* 23 */
- CHECKED_STRDUP(PasswordHash); /* 24 */
- CHECKED_STRDUP(AcceptedCert); /* 27 */
- CHECKED_STRDUP(AlternateShell); /* 640 */
- CHECKED_STRDUP(ShellWorkingDirectory); /* 641 */
- CHECKED_STRDUP(ClientAddress); /* 769 */
- CHECKED_STRDUP(ClientDir); /* 770 */
- CHECKED_STRDUP(DynamicDSTTimeZoneKeyName); /* 897 */
- CHECKED_STRDUP(RemoteAssistanceSessionId); /* 1025 */
- CHECKED_STRDUP(RemoteAssistancePassStub); /* 1026 */
- CHECKED_STRDUP(RemoteAssistancePassword); /* 1027 */
- CHECKED_STRDUP(RemoteAssistanceRCTicket); /* 1028 */
- CHECKED_STRDUP(AuthenticationServiceClass); /* 1098 */
- CHECKED_STRDUP(AllowedTlsCiphers); /* 1101 */
- CHECKED_STRDUP(NtlmSamFile); /* 1103 */
- CHECKED_STRDUP(PreconnectionBlob); /* 1155 */
- CHECKED_STRDUP(TargetNetAddress); /* 1217 */
- CHECKED_STRDUP(RedirectionUsername); /* 1220 */
- CHECKED_STRDUP(RedirectionDomain); /* 1221 */
- CHECKED_STRDUP(RedirectionTargetFQDN); /* 1224 */
- CHECKED_STRDUP(RedirectionTargetNetBiosName); /* 1225 */
- CHECKED_STRDUP(RedirectionAcceptedCert); /* 1231 */
- CHECKED_STRDUP(KerberosKdc); /* 1344 */
- CHECKED_STRDUP(KerberosRealm); /* 1345 */
- CHECKED_STRDUP(CertificateName); /* 1409 */
- CHECKED_STRDUP(CertificateFile); /* 1410 */
- CHECKED_STRDUP(PrivateKeyFile); /* 1411 */
- CHECKED_STRDUP(RdpKeyFile); /* 1412 */
- CHECKED_STRDUP(CertificateContent); /* 1416 */
- CHECKED_STRDUP(PrivateKeyContent); /* 1417 */
- CHECKED_STRDUP(RdpKeyContent); /* 1418 */
- CHECKED_STRDUP(WindowTitle); /* 1542 */
- CHECKED_STRDUP(WmClass); /* 1549 */
- CHECKED_STRDUP(ComputerName); /* 1664 */
- CHECKED_STRDUP(ConnectionFile); /* 1728 */
- CHECKED_STRDUP(AssistanceFile); /* 1729 */
- CHECKED_STRDUP(HomePath); /* 1792 */
- CHECKED_STRDUP(ConfigPath); /* 1793 */
- CHECKED_STRDUP(CurrentPath); /* 1794 */
- CHECKED_STRDUP(DumpRemoteFxFile); /* 1858 */
- CHECKED_STRDUP(PlayRemoteFxFile); /* 1859 */
- CHECKED_STRDUP(GatewayHostname); /* 1986 */
- CHECKED_STRDUP(GatewayUsername); /* 1987 */
- CHECKED_STRDUP(GatewayPassword); /* 1988 */
- CHECKED_STRDUP(GatewayDomain); /* 1989 */
- CHECKED_STRDUP(GatewayAccessToken); /* 1997 */
- CHECKED_STRDUP(GatewayAcceptedCert); /* 1998 */
- CHECKED_STRDUP(ProxyHostname); /* 2016 */
- CHECKED_STRDUP(RemoteApplicationName); /* 2113 */
- CHECKED_STRDUP(RemoteApplicationIcon); /* 2114 */
- CHECKED_STRDUP(RemoteApplicationProgram); /* 2115 */
- CHECKED_STRDUP(RemoteApplicationFile); /* 2116 */
- CHECKED_STRDUP(RemoteApplicationGuid); /* 2117 */
- CHECKED_STRDUP(RemoteApplicationCmdLine); /* 2118 */
- CHECKED_STRDUP(ImeFileName); /* 2628 */
- CHECKED_STRDUP(DrivesToRedirect); /* 4290 */
- CHECKED_STRDUP(ActionScript);
if (settings->LoadBalanceInfo && settings->LoadBalanceInfoLength)
{
@@ -902,15 +783,6 @@ BOOL freerdp_settings_copy(rdpSettings* _settings, const rdpSettings* settings)
CopyMemory(_settings->ReceivedCapabilities, settings->ReceivedCapabilities, 32);
CopyMemory(_settings->OrderSupport, settings->OrderSupport, 32);
- _settings->ClientHostname = _strdup(settings->ClientHostname);
-
- if (!_settings->ClientHostname)
- goto out_fail;
-
- _settings->ClientProductId = _strdup(settings->ClientProductId);
-
- if (!_settings->ClientProductId)
- goto out_fail;
_settings->BitmapCacheV2CellInfo =
(BITMAP_CACHE_V2_CELL_INFO*)malloc(sizeof(BITMAP_CACHE_V2_CELL_INFO) * 6);
@@ -933,16 +805,6 @@ BOOL freerdp_settings_copy(rdpSettings* _settings, const rdpSettings* settings)
CopyMemory(_settings->GlyphCache, settings->GlyphCache, sizeof(GLYPH_CACHE_DEFINITION) * 10);
CopyMemory(_settings->FragCache, settings->FragCache, sizeof(GLYPH_CACHE_DEFINITION));
- if (settings->CertificateContent)
- _settings->CertificateContent = _strdup(settings->CertificateContent);
- if (settings->PrivateKeyContent)
- _settings->PrivateKeyContent = _strdup(settings->PrivateKeyContent);
- if (settings->RdpKeyContent)
- _settings->RdpKeyContent = _strdup(settings->RdpKeyContent);
- if (settings->CertificateAcceptedFingerprints)
- _settings->CertificateAcceptedFingerprints =
- _strdup(settings->CertificateAcceptedFingerprints);
-
_settings->ClientAutoReconnectCookie =
(ARC_CS_PRIVATE_PACKET*)malloc(sizeof(ARC_CS_PRIVATE_PACKET));
@@ -1119,6 +981,55 @@ BOOL freerdp_settings_copy(rdpSettings* _settings, const rdpSettings* settings)
goto out_fail;
}
+ if (settings->ActionScript)
+ _settings->ActionScript = _strdup(settings->ActionScript);
+ rc = TRUE;
+out_fail:
+ return rc;
+}
+
+BOOL freerdp_settings_copy(rdpSettings* _settings, const rdpSettings* settings)
+{
+ BOOL rc;
+
+ if (!settings || !_settings)
+ return FALSE;
+
+ /* This is required to free all non string buffers */
+ freerdp_settings_free_internal(_settings);
+ /* This copies everything except allocated non string buffers. reset all allocated buffers to
+ * NULL to fix issues during cleanup */
+ rc = freerdp_settings_clone_keys(_settings, settings);
+
+ _settings->LoadBalanceInfo = NULL;
+ _settings->ServerRandom = NULL;
+ _settings->ClientRandom = NULL;
+ _settings->RdpServerCertificate = NULL;
+ _settings->RdpServerRsaKey = NULL;
+ _settings->ChannelDefArray = NULL;
+ _settings->MonitorDefArray = NULL;
+ _settings->MonitorIds = NULL;
+ _settings->ReceivedCapabilities = NULL;
+ _settings->OrderSupport = NULL;
+ _settings->BitmapCacheV2CellInfo = NULL;
+ _settings->GlyphCache = NULL;
+ _settings->FragCache = NULL;
+ _settings->ClientAutoReconnectCookie = NULL;
+ _settings->ServerAutoReconnectCookie = NULL;
+ _settings->ClientTimeZone = NULL;
+ _settings->RedirectionPassword = NULL;
+ _settings->RedirectionTsvUrl = NULL;
+ _settings->TargetNetAddresses = NULL;
+ _settings->DeviceArray = NULL;
+ _settings->StaticChannelArray = NULL;
+ _settings->DynamicChannelArray = NULL;
+ _settings->ActionScript = NULL;
+ if (!rc)
+ goto out_fail;
+
+ /* Begin copying */
+ if (!freerdp_settings_int_buffer_copy(_settings, settings))
+ goto out_fail;
return TRUE;
out_fail:
freerdp_settings_free_internal(_settings);
@@ -1134,13 +1045,7 @@ rdpSettings* freerdp_settings_clone(const rdpSettings* settings)
return _settings;
out_fail:
- /* In case any memory allocation failed during clone, some bytes might leak.
- *
- * freerdp_settings_free can't be reliable used at this point since it could
- * free memory of pointers copied by CopyMemory and detecting and freeing
- * each allocation separately is quite painful.
- */
- free(_settings);
+ freerdp_settings_free(_settings);
return NULL;
}
#ifdef _WIN32
diff --git a/libfreerdp/core/settings.h b/libfreerdp/core/settings.h
index 513cfb66a..d03369fd8 100644
--- a/libfreerdp/core/settings.h
+++ b/libfreerdp/core/settings.h
@@ -26,5 +26,10 @@
#include <freerdp/api.h>
FREERDP_LOCAL BOOL freerdp_settings_set_default_order_support(rdpSettings* settings);
+FREERDP_LOCAL BOOL freerdp_settings_set_pointer(rdpSettings* dst, size_t index, const void* ptr);
+FREERDP_LOCAL BOOL freerdp_settings_clone_keys(rdpSettings* dst, const rdpSettings* src);
+FREERDP_LOCAL void freerdp_settings_free_keys(rdpSettings* dst, BOOL cleanup);
+FREERDP_LOCAL BOOL freerdp_settings_set_string_(rdpSettings* settings, size_t id, const char* val,
+ BOOL cleanup);
#endif /* FREERDP_LIB_CORE_SETTINGS_H */
diff --git a/libfreerdp/core/test/TestConnect.c b/libfreerdp/core/test/TestConnect.c
index 3f79fa03e..7bf196951 100644
--- a/libfreerdp/core/test/TestConnect.c
+++ b/libfreerdp/core/test/TestConnect.c
@@ -180,6 +180,8 @@ static int testSuccess(int port)
path = GetCombinedPath(exe, "Sample");
wpath = GetCombinedPath(wexe, "Sample");
+ free(exe);
+ exe = NULL;
if (!path || !wpath)
goto fail;
@@ -226,6 +228,7 @@ static int testSuccess(int port)
fail:
free(exe);
+ free(wexe);
free(path);
free(wpath);
free(commandLine);
diff --git a/libfreerdp/core/test/TestSettings.c b/libfreerdp/core/test/TestSettings.c
index 6ae9219a3..c9373bd0b 100644
--- a/libfreerdp/core/test/TestSettings.c
+++ b/libfreerdp/core/test/TestSettings.c
@@ -6,7 +6,8 @@ int TestSettings(int argc, char* argv[])
int rc = -1;
size_t x;
rdpSettings* settings = NULL;
- rdpSettings* cloned;
+ rdpSettings* cloned = NULL;
+ rdpSettings* cloned2 = NULL;
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
settings = freerdp_settings_new(0);
@@ -17,24 +18,29 @@ int TestSettings(int argc, char* argv[])
return -1;
}
- settings->Username = _strdup("abcdefg");
- settings->Password = _strdup("xyz");
+ if (!freerdp_settings_set_string(settings, FreeRDP_Username, "abcdefg"))
+ goto fail;
+ if (!freerdp_settings_set_string(settings, FreeRDP_Password, "xyz"))
+ goto fail;
+
cloned = freerdp_settings_clone(settings);
if (!cloned)
- {
- printf("Problem cloning settings\n");
- freerdp_settings_free(settings);
- return -1;
- }
+ goto fail;
#if defined(have_bool_list_indices)
for (x = 0; x < ARRAYSIZE(bool_list_indices); x++)
{
const size_t key = bool_list_indices[x];
+ const char* name = freerdp_settings_get_name_for_key(key);
const BOOL val = freerdp_settings_get_bool(settings, key);
-
+ const BOOL cval = freerdp_settings_get_bool(cloned, key);
+ if (val != cval)
+ {
+ printf("mismatch for key %s: %u -> copy %u\n", name, val, cval);
+ goto fail;
+ }
if (!freerdp_settings_set_bool(settings, key, val))
goto fail;
}
@@ -45,8 +51,14 @@ int TestSettings(int argc, char* argv[])
for (x = 0; x < ARRAYSIZE(int16_list_indices); x++)
{
const size_t key = int16_list_indices[x];
+ const char* name = freerdp_settings_get_name_for_key(key);
const INT16 val = freerdp_settings_get_int16(settings, key);
-
+ const INT16 cval = freerdp_settings_get_int16(cloned, key);
+ if (val != cval)
+ {
+ printf("mismatch for key %s: %" PRId16 " -> copy %" PRId16 "\n", name, val, cval);
+ goto fail;
+ }
if (!freerdp_settings_set_int16(settings, key, val))
goto fail;
}
@@ -57,8 +69,14 @@ int TestSettings(int argc, char* argv[])
for (x = 0; x < ARRAYSIZE(uint16_list_indices); x++)
{
const size_t key = uint16_list_indices[x];
+ const char* name = freerdp_settings_get_name_for_key(key);
const UINT16 val = freerdp_settings_get_uint16(settings, key);
-
+ const UINT16 cval = freerdp_settings_get_uint16(cloned, key);
+ if (val != cval)
+ {
+ printf("mismatch for key %s: %" PRIu16 " -> copy %" PRIu16 "\n", name, val, cval);
+ goto fail;
+ }
if (!freerdp_settings_set_uint16(settings, key, val))
goto fail;
}
@@ -69,8 +87,14 @@ int TestSettings(int argc, char* argv[])
for (x = 0; x < ARRAYSIZE(uint32_list_indices); x++)
{
const size_t key = uint32_list_indices[x];
+ const char* name = freerdp_settings_get_name_for_key(key);
const UINT32 val = freerdp_settings_get_uint32(settings, key);
-
+ const UINT32 cval = freerdp_settings_get_uint32(cloned, key);
+ if (val != cval)
+ {
+ printf("mismatch for key %s: %" PRIu32 " -> copy %" PRIu32 "\n", name, val, cval);
+ goto fail;
+ }
if (!freerdp_settings_set_uint32(settings, key, val))
goto fail;
}
@@ -81,8 +105,14 @@ int TestSettings(int argc, char* argv[])
for (x = 0; x < ARRAYSIZE(int32_list_indices); x++)
{
const size_t key = int32_list_indices[x];
+ const char* name = freerdp_settings_get_name_for_key(key);
const INT32 val = freerdp_settings_get_int32(settings, key);
-
+ const INT32 cval = freerdp_settings_get_int32(cloned, key);
+ if (val != cval)
+ {
+ printf("mismatch for key %s: %" PRId32 " -> copy %" PRId32 "\n", name, val, cval);
+ goto fail;
+ }
if (!freerdp_settings_set_int32(settings, key, val))
goto fail;
}
@@ -93,8 +123,14 @@ int TestSettings(int argc, char* argv[])
for (x = 0; x < ARRAYSIZE(uint64_list_indices); x++)
{
const size_t key = uint64_list_indices[x];
+ const char* name = freerdp_settings_get_name_for_key(key);
const UINT64 val = freerdp_settings_get_uint64(settings, key);
-
+ const UINT64 cval = freerdp_settings_get_uint64(cloned, key);
+ if (val != cval)
+ {
+ printf("mismatch for key %s: %" PRIu64 " -> copy %" PRIu64 "\n", name, val, cval);
+ goto fail;
+ }
if (!freerdp_settings_set_uint64(settings, key, val))
goto fail;
}
@@ -105,8 +141,14 @@ int TestSettings(int argc, char* argv[])
for (x = 0; x < ARRAYSIZE(int64_list_indices); x++)
{
const size_t key = int64_list_indices[x];
+ const char* name = freerdp_settings_get_name_for_key(key);
const INT64 val = freerdp_settings_get_int64(settings, key);
-
+ const INT64 cval = freerdp_settings_get_int64(cloned, key);
+ if (val != cval)
+ {
+ printf("mismatch for key %s: %" PRId64 " -> copy %" PRId64 "\n", name, val, cval);
+ goto fail;
+ }
if (!freerdp_settings_set_int64(settings, key, val))
goto fail;
}
@@ -119,7 +161,14 @@ int TestSettings(int argc, char* argv[])
const size_t key = string_list_indices[x];
const char val[] = "test-string";
const char* res;
-
+ const char* name = freerdp_settings_get_name_for_key(key);
+ const char* oval = freerdp_settings_get_string(settings, key);
+ const char* cval = freerdp_settings_get_string(cloned, key);
+ if ((oval != cval) && (strcmp(oval, cval) != 0))
+ {
+ printf("mismatch for key %s: %s -> copy %s\n", name, oval, cval);
+ goto fail;
+ }
if (!freerdp_settings_set_string(settings, key, val))
goto fail;
@@ -136,12 +185,20 @@ int TestSettings(int argc, char* argv[])
{
const size_t key = pointer_list_indices[x];
const void* val = freerdp_settings_get_pointer(settings, key);
+ WINPR_UNUSED(val);
}
#endif
+ cloned2 = freerdp_settings_clone(settings);
+ if (!cloned2)
+ goto fail;
+ if (!freerdp_settings_copy(cloned2, cloned))
+ goto fail;
+
rc = 0;
fail:
freerdp_settings_free(cloned);
+ freerdp_settings_free(cloned2);
freerdp_settings_free(settings);
return rc;
}
diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c
index 534cc6b8c..b20d4a2fe 100644
--- a/libfreerdp/core/transport.c
+++ b/libfreerdp/core/transport.c
@@ -325,6 +325,7 @@ BOOL transport_connect_nla(rdpTransport* transport)
if (!settings->Authentication)
return TRUE;
+ nla_free(rdp->nla);
rdp->nla = nla_new(instance, transport, settings);
if (!rdp->nla)
@@ -1214,6 +1215,7 @@ void transport_free(rdpTransport* transport)
if (transport->ReceiveBuffer)
Stream_Release(transport->ReceiveBuffer);
+ nla_free(transport->nla);
StreamPool_Free(transport->ReceivePool);
CloseHandle(transport->connectedEvent);
CloseHandle(transport->rereadEvent);
diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c
index 0920e356e..841468339 100644
--- a/libfreerdp/crypto/crypto.c
+++ b/libfreerdp/crypto/crypto.c
@@ -96,13 +96,24 @@ exit:
static int crypto_rsa_common(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus,
const BYTE* exponent, int exponent_size, BYTE* output)
{
- BN_CTX* ctx;
+ BN_CTX* ctx = NULL;
int output_length = -1;
- BYTE* input_reverse;
- BYTE* modulus_reverse;
- BYTE* exponent_reverse;
- BIGNUM *mod, *exp, *x, *y;
- input_reverse = (BYTE*)malloc(2 * key_length + exponent_size);
+ BYTE* input_reverse = NULL;
+ BYTE* modulus_reverse = NULL;
+ BYTE* exponent_reverse = NULL;
+ BIGNUM* mod = NULL;
+ BIGNUM* exp = NULL;
+ BIGNUM* x = NULL;
+ BIGNUM* y = NULL;
+ size_t bufferSize = 2 * key_length + exponent_size;
+
+ if (!input || (length < 0) || (exponent_size < 0) || !modulus || !exponent || !output)
+ return -1;
+
+ if (length > bufferSize)
+ bufferSize = length;
+
+ input_reverse = (BYTE*)calloc(bufferSize, 1);
if (!input_reverse)
return -1;
@@ -131,16 +142,24 @@ static int crypto_rsa_common(const BYTE* input, int length, UINT32 key_length, c
if (!(y = BN_new()))
goto fail_bn_y;
- BN_bin2bn(modulus_reverse, key_length, mod);
- BN_bin2bn(exponent_reverse, exponent_size, exp);
- BN_bin2bn(input_reverse, length, x);
- BN_mod_exp(y, x, exp, mod, ctx);
+ if (!BN_bin2bn(modulus_reverse, key_length, mod))
+ goto fail;
+
+ if (!BN_bin2bn(exponent_reverse, exponent_size, exp))
+ goto fail;
+ if (!BN_bin2bn(input_reverse, length, x))
+ goto fail;
+ if (BN_mod_exp(y, x, exp, mod, ctx) != 1)
+ goto fail;
output_length = BN_bn2bin(y, output);
+ if (output_length < 0)
+ goto fail;
crypto_reverse(output, output_length);
- if (output_length < (int)key_length)
+ if (output_length < key_length)
memset(output + output_length, 0, key_length - output_length);
+fail:
BN_free(y);
fail_bn_y:
BN_clear_free(x);
@@ -797,6 +816,8 @@ static int verify_cb(int ok, X509_STORE_CTX* csc)
BOOL x509_verify_certificate(CryptoCert cert, const char* certificate_store_path)
{
+ size_t i;
+ const int purposes[3] = { X509_PURPOSE_SSL_SERVER, X509_PURPOSE_SSL_CLIENT, X509_PURPOSE_ANY };
X509_STORE_CTX* csc;
BOOL status = FALSE;
X509_STORE* cert_ctx = NULL;
@@ -831,23 +852,35 @@ BOOL x509_verify_certificate(CryptoCert cert, const char* certificate_store_path
X509_LOOKUP_add_dir(lookup, certificate_store_path, X509_FILETYPE_PEM);
}
- csc = X509_STORE_CTX_new();
-
- if (csc == NULL)
- goto end;
-
X509_STORE_set_flags(cert_ctx, 0);
- if (!X509_STORE_CTX_init(csc, cert_ctx, cert->px509, cert->px509chain))
- goto end;
+ for (i = 0; i < ARRAYSIZE(purposes); i++)
+ {
+ int err = -1, rc = -1;
+ int purpose = purposes[i];
+ csc = X509_STORE_CTX_new();
+
+ if (csc == NULL)
+ goto skip;
+ if (!X509_STORE_CTX_init(csc, cert_ctx, cert->px509, cert->px509chain))
+ goto skip;
- X509_STORE_CTX_set_purpose(csc, X509_PURPOSE_ANY);
- X509_STORE_CTX_set_verify_cb(csc, verify_cb);
+ X509_STORE_CTX_set_purpose(csc, purpose);
+ X509_STORE_CTX_set_verify_cb(csc, verify_cb);
- if (X509_verify_cert(csc) == 1)
- status = TRUE;
+ rc = X509_verify_cert(csc);
+ err = X509_STORE_CTX_get_error(csc);
+ skip:
+ X509_STORE_CTX_free(csc);
+ if (rc == 1)
+ {
+ status = TRUE;
+ break;
+ }
+ else if (err != X509_V_ERR_INVALID_PURPOSE)
+ break;
+ }
- X509_STORE_CTX_free(csc);
X509_STORE_free(cert_ctx);
end:
return status;
diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c
index d7743994e..c94c55534 100644
--- a/libfreerdp/crypto/tls.c
+++ b/libfreerdp/crypto/tls.c
@@ -1198,9 +1198,10 @@ static BOOL is_accepted_fingerprint(CryptoCert cert, const char* CertificateAcce
char* cur = strtok_s(copy, ",", &context);
while (cur)
{
+ char* subcontext = NULL;
BOOL equal;
char* strhash;
- const char* h = strtok(cur, ":");
+ const char* h = strtok_s(cur, ":", &subcontext);
const char* fp;
if (!h)
diff --git a/libfreerdp/primitives/prim_colors.c b/libfreerdp/primitives/prim_colors.c
index a9d36e39a..54c7ecbc9 100644
--- a/libfreerdp/primitives/prim_colors.c
+++ b/libfreerdp/primitives/prim_colors.c
@@ -50,13 +50,13 @@ static pstatus_t general_yCbCrToRGB_16s8u_P3AC4R_BGRX(const INT16* const pSrc[3]
{
INT16 R, G, B;
const INT32 divisor = 16;
- const INT32 Y = ((*pY++) + 4096) << divisor;
+ const INT32 Y = (INT32)((UINT32)((*pY++) + 4096) << divisor);
const INT32 Cb = (*pCb++);
const INT32 Cr = (*pCr++);
- const INT32 CrR = Cr * (INT32)(1.402525f * (1 << divisor));
- const INT32 CrG = Cr * (INT32)(0.714401f * (1 << divisor));
- const INT32 CbG = Cb * (INT32)(0.343730f * (1 << divisor));
- const INT32 CbB = Cb * (INT32)(1.769905f * (1 << divisor));
+ const INT64 CrR = Cr * (INT64)(1.402525f * (1 << divisor)) * 1LL;
+ const INT64 CrG = Cr * (INT64)(0.714401f * (1 << divisor)) * 1LL;
+ const INT64 CbG = Cb * (INT64)(0.343730f * (1 << divisor)) * 1LL;
+ const INT64 CbB = Cb * (INT64)(1.769905f * (1 << divisor)) * 1LL;
R = ((INT16)((CrR + Y) >> divisor) >> 5);
G = ((INT16)((Y - CbG - CrG) >> divisor) >> 5);
B = ((INT16)((CbB + Y) >> divisor) >> 5);
@@ -90,18 +90,18 @@ static pstatus_t general_yCbCrToRGB_16s8u_P3AC4R_general(const INT16* const pSrc
{
for (x = 0; x < roi->width; x++)
{
- INT16 R, G, B;
+ INT64 R, G, B;
const INT32 divisor = 16;
- const INT32 Y = ((*pY++) + 4096) << divisor;
+ const INT32 Y = (INT32)((UINT32)((*pY++) + 4096) << divisor);
const INT32 Cb = (*pCb++);
const INT32 Cr = (*pCr++);
- const INT32 CrR = Cr * (INT32)(1.402525f * (1 << divisor));
- const INT32 CrG = Cr * (INT32)(0.714401f * (1 << divisor));
- const INT32 CbG = Cb * (INT32)(0.343730f * (1 << divisor));
- const INT32 CbB = Cb * (INT32)(1.769905f * (1 << divisor));
- R = ((INT16)((CrR + Y) >> divisor) >> 5);
- G = ((INT16)((Y - CbG - CrG) >> divisor) >> 5);
- B = ((INT16)((CbB + Y) >> divisor) >> 5);
+ const INT64 CrR = Cr * (INT64)(1.402525f * (1 << divisor)) * 1LL;
+ const INT64 CrG = Cr * (INT64)(0.714401f * (1 << divisor)) * 1LL;
+ const INT64 CbG = Cb * (INT64)(0.343730f * (1 << divisor)) * 1LL;
+ const INT64 CbB = Cb * (INT64)(1.769905f * (1 << divisor)) * 1LL;
+ R = (INT64)((CrR + Y) >> (divisor + 5));
+ G = (INT64)((Y - CbG - CrG) >> (divisor + 5));
+ B = (INT64)((CbB + Y) >> (divisor + 5));
pRGB = (*writePixel)(pRGB, formatSize, DstFormat, CLIP(R), CLIP(G), CLIP(B), 0xFF);
}
@@ -170,7 +170,7 @@ static pstatus_t general_yCbCrToRGB_16s16s_P3P3(const INT16* const pSrc[3], INT3
INT32 y = (INT32)(*yptr++);
INT32 cb = (INT32)(*cbptr++);
INT32 cr = (INT32)(*crptr++);
- INT32 r, g, b;
+ INT64 r, g, b;
/*
* This is the slow floating point version kept here for reference.
* y = y + 4096; // 128<<5=4096 so that we can scale the sum by>>5
@@ -191,10 +191,10 @@ static pstatus_t general_yCbCrToRGB_16s16s_P3P3(const INT16* const pSrc[3], INT3
* G: 0.344 << 16 = 22544, 0.714 << 16 = 46792
* B: 1.770 << 16 = 115998
*/
- y = (y + 4096) << 16;
- r = y + cr * 91947;
- g = y - cb * 22544 - cr * 46792;
- b = y + cb * 115998;
+ y = (INT32)((UINT32)(y + 4096) << 16);
+ r = y + cr * 91947LL;
+ g = y - cb * 22544LL - cr * 46792LL;
+ b = y + cb * 115998LL;
*rptr++ = CLIP(r >> 21);
*gptr++ = CLIP(g >> 21);
*bptr++ = CLIP(b >> 21);
diff --git a/libfreerdp/primitives/prim_shift.c b/libfreerdp/primitives/prim_shift.c
index 3fabfe26e..cab9481cc 100644
--- a/libfreerdp/primitives/prim_shift.c
+++ b/libfreerdp/primitives/prim_shift.c
@@ -26,9 +26,11 @@ static INLINE pstatus_t general_lShiftC_16s(const INT16* pSrc, UINT32 val, INT16
{
if (val == 0)
return PRIMITIVES_SUCCESS;
+ if (val >= 16)
+ return -1;
while (len--)
- *pDst++ = *pSrc++ << val;
+ *pDst++ = (INT16)((UINT16)*pSrc++ << val);
return PRIMITIVES_SUCCESS;
}
@@ -38,6 +40,8 @@ static INLINE pstatus_t general_rShiftC_16s(const INT16* pSrc, UINT32 val, INT16
{
if (val == 0)
return PRIMITIVES_SUCCESS;
+ if (val >= 16)
+ return -1;
while (len--)
*pDst++ = *pSrc++ >> val;
@@ -51,9 +55,11 @@ static INLINE pstatus_t general_lShiftC_16u(const UINT16* pSrc, UINT32 val, UINT
{
if (val == 0)
return PRIMITIVES_SUCCESS;
+ if (val >= 16)
+ return -1;
while (len--)
- *pDst++ = *pSrc++ << val;
+ *pDst++ = (INT16)((UINT16)*pSrc++ << val);
return PRIMITIVES_SUCCESS;
}
@@ -64,6 +70,8 @@ static INLINE pstatus_t general_rShiftC_16u(const UINT16* pSrc, UINT32 val, UINT
{
if (val == 0)
return PRIMITIVES_SUCCESS;
+ if (val >= 16)
+ return -1;
while (len--)
*pDst++ = *pSrc++ >> val;
diff --git a/libfreerdp/primitives/prim_shift_opt.c b/libfreerdp/primitives/prim_shift_opt.c
index 481363a1b..2515dfbac 100644
--- a/libfreerdp/primitives/prim_shift_opt.c
+++ b/libfreerdp/primitives/prim_shift_opt.c
@@ -39,13 +39,13 @@ static primitives_t* generic = NULL;
#if !defined(WITH_IPP) || defined(ALL_PRIMITIVES_VERSIONS)
/* ------------------------------------------------------------------------- */
SSE3_SCD_ROUTINE(sse2_lShiftC_16s, INT16, generic->lShiftC_16s, _mm_slli_epi16,
- *dptr++ = *sptr++ << val)
+ *dptr++ = (INT16)((UINT16)*sptr++ << val))
/* ------------------------------------------------------------------------- */
SSE3_SCD_ROUTINE(sse2_rShiftC_16s, INT16, generic->rShiftC_16s, _mm_srai_epi16,
*dptr++ = *sptr++ >> val)
/* ------------------------------------------------------------------------- */
SSE3_SCD_ROUTINE(sse2_lShiftC_16u, UINT16, generic->lShiftC_16u, _mm_slli_epi16,
- *dptr++ = *sptr++ << val)
+ *dptr++ = (INT16)((UINT16)*sptr++ << val))
/* ------------------------------------------------------------------------- */
SSE3_SCD_ROUTINE(sse2_rShiftC_16u, UINT16, generic->rShiftC_16u, _mm_srli_epi16,
*dptr++ = *sptr++ >> val)
diff --git a/libfreerdp/primitives/prim_templates.h b/libfreerdp/primitives/prim_templates.h
index 47872651e..46996e2c7 100644
--- a/libfreerdp/primitives/prim_templates.h
+++ b/libfreerdp/primitives/prim_templates.h
@@ -51,6 +51,10 @@
const _type_* sptr = pSrc; \
_type_* dptr = pDst; \
size_t count; \
+ if (val == 0) \
+ return PRIMITIVES_SUCCESS; \
+ if (val >= 16) \
+ return -1; \
if (len < 16) /* pointless if too small */ \
{ \
return _fallback_(pSrc, val, pDst, len); \
diff --git a/libfreerdp/primitives/test/TestPrimitivesShift.c b/libfreerdp/primitives/test/TestPrimitivesShift.c
index 448c2d1a2..487e188e9 100644
--- a/libfreerdp/primitives/test/TestPrimitivesShift.c
+++ b/libfreerdp/primitives/test/TestPrimitivesShift.c
@@ -29,7 +29,18 @@ static BOOL test_lShift_16s_func(void)
UINT32 val;
winpr_RAND((BYTE*)&val, sizeof(val));
winpr_RAND((BYTE*)src, sizeof(src));
- val = (val % (FUNC_TEST_SIZE - 1)) + 1;
+ val = val % 16;
+ /* Negative tests */
+ status = generic->lShiftC_16s(src + 1, 16, d1 + 1, FUNC_TEST_SIZE);
+
+ if (status == PRIMITIVES_SUCCESS)
+ return FALSE;
+
+ status = optimized->lShiftC_16s(src + 1, 16, d1 + 1, FUNC_TEST_SIZE);
+
+ if (status == PRIMITIVES_SUCCESS)
+ return FALSE;
+
/* Aligned */
status = generic->lShiftC_16s(src + 1, val, d1 + 1, FUNC_TEST_SIZE);
@@ -63,7 +74,19 @@ static BOOL test_lShift_16u_func(void)
UINT32 val;
winpr_RAND((BYTE*)&val, sizeof(val));
winpr_RAND((BYTE*)src, sizeof(src));
- val = (val % (FUNC_TEST_SIZE - 1)) + 1;
+ val = val % 16;
+
+ /* Negative tests */
+ status = generic->lShiftC_16u(src + 1, 16, d1 + 1, FUNC_TEST_SIZE);
+
+ if (status == PRIMITIVES_SUCCESS)
+ return FALSE;
+
+ status = optimized->lShiftC_16u(src + 1, 16, d1 + 1, FUNC_TEST_SIZE);
+
+ if (status == PRIMITIVES_SUCCESS)
+ return FALSE;
+
/* Aligned */
status = generic->lShiftC_16u(src + 1, val, d1 + 1, FUNC_TEST_SIZE);
@@ -97,7 +120,19 @@ static BOOL test_rShift_16s_func(void)
UINT32 val;
winpr_RAND((BYTE*)&val, sizeof(val));
winpr_RAND((BYTE*)src, sizeof(src));
- val = (val % (FUNC_TEST_SIZE - 1)) + 1;
+ val = val % 16;
+
+ /* Negative Tests */
+ status = generic->rShiftC_16s(src + 1, 16, d1 + 1, FUNC_TEST_SIZE);
+
+ if (status == PRIMITIVES_SUCCESS)
+ return FALSE;
+
+ status = optimized->rShiftC_16s(src + 1, 16, d1 + 1, FUNC_TEST_SIZE);
+
+ if (status == PRIMITIVES_SUCCESS)
+ return FALSE;
+
/* Aligned */
status = generic->rShiftC_16s(src + 1, val, d1 + 1, FUNC_TEST_SIZE);
@@ -131,7 +166,18 @@ static BOOL test_rShift_16u_func(void)
UINT32 val;
winpr_RAND((BYTE*)&val, sizeof(val));
winpr_RAND((BYTE*)src, sizeof(src));
- val = (val % (FUNC_TEST_SIZE - 1)) + 1;
+ val = val % 16;
+ /* Negative tests */
+ status = generic->rShiftC_16u(src + 1, 16, d1 + 1, FUNC_TEST_SIZE);
+
+ if (status == PRIMITIVES_SUCCESS)
+ return FALSE;
+
+ status = optimized->rShiftC_16u(src + 1, 16, d1 + 1, FUNC_TEST_SIZE);
+
+ if (status == PRIMITIVES_SUCCESS)
+ return FALSE;
+
/* Aligned */
status = generic->rShiftC_16u(src + 1, val, d1 + 1, FUNC_TEST_SIZE);
@@ -166,7 +212,19 @@ static BOOL test_ShiftWrapper_16s_func(void)
INT32 val;
winpr_RAND((BYTE*)&tmp, sizeof(tmp));
winpr_RAND((BYTE*)src, sizeof(src));
- val = (tmp % (FUNC_TEST_SIZE - 1)) + 1;
+ val = tmp % 16;
+
+ /* Negative tests */
+ status = generic->shiftC_16s(src + 1, 16, d1 + 1, FUNC_TEST_SIZE);
+
+ if (status == PRIMITIVES_SUCCESS)
+ return FALSE;
+
+ status = optimized->shiftC_16s(src + 1, 16, d1 + 1, FUNC_TEST_SIZE);
+
+ if (status == PRIMITIVES_SUCCESS)
+ return FALSE;
+
/* Aligned */
status = generic->shiftC_16s(src + 1, val, d1 + 1, FUNC_TEST_SIZE);
@@ -221,7 +279,18 @@ static BOOL test_ShiftWrapper_16u_func(void)
INT32 val;
winpr_RAND((BYTE*)&tmp, sizeof(tmp));
winpr_RAND((BYTE*)src, sizeof(src));
- val = (tmp % (FUNC_TEST_SIZE - 1)) + 1;
+ val = tmp % 16;
+
+ /* Negative */
+ status = generic->shiftC_16u(src + 1, 16, d1 + 1, FUNC_TEST_SIZE);
+ if (status == PRIMITIVES_SUCCESS)
+ return FALSE;
+
+ status = optimized->shiftC_16u(src + 1, 16, d1 + 1, FUNC_TEST_SIZE);
+
+ if (status == PRIMITIVES_SUCCESS)
+ return FALSE;
+
/* Aligned */
status = generic->shiftC_16u(src + 1, val, d1 + 1, FUNC_TEST_SIZE);
@@ -275,6 +344,7 @@ static BOOL test_lShift_16s_speed(void)
winpr_RAND((BYTE*)src, sizeof(src));
winpr_RAND((BYTE*)&val, sizeof(val));
+ val = val % 16;
if (!speed_test("lShift_16s", "aligned", g_Iterations, (speed_test_fkt)generic->lShiftC_16s,
(speed_test_fkt)optimized->lShiftC_16s, src, val, dst, MAX_TEST_SIZE))
return FALSE;
@@ -294,6 +364,7 @@ static BOOL test_lShift_16u_speed(void)
winpr_RAND((BYTE*)&val, sizeof(val));
winpr_RAND((BYTE*)src, sizeof(src));
+ val = val % 16;
if (!speed_test("lShift_16u", "aligned", g_Iterations, (speed_test_fkt)generic->lShiftC_16u,
(speed_test_fkt)optimized->lShiftC_16u, src, val, dst, MAX_TEST_SIZE))
return FALSE;
@@ -313,6 +384,7 @@ static BOOL test_rShift_16s_speed(void)
winpr_RAND((BYTE*)src, sizeof(src));
winpr_RAND((BYTE*)&val, sizeof(val));
+ val = val % 16;
if (!speed_test("rShift_16s", "aligned", g_Iterations, (speed_test_fkt)generic->rShiftC_16s,
(speed_test_fkt)optimized->rShiftC_16s, src, val, dst, MAX_TEST_SIZE))
return FALSE;
@@ -332,6 +404,7 @@ static BOOL test_rShift_16u_speed(void)
winpr_RAND((BYTE*)&val, sizeof(val));
winpr_RAND((BYTE*)src, sizeof(src));
+ val = val % 16;
if (!speed_test("rShift_16u", "aligned", g_Iterations, (speed_test_fkt)generic->rShiftC_16u,
(speed_test_fkt)optimized->rShiftC_16u, src, val, dst, MAX_TEST_SIZE))
return FALSE;
diff --git a/scripts/update-settings-tests b/scripts/update-settings-tests
index 25f15714b..48e79d2fc 100755
--- a/scripts/update-settings-tests
+++ b/scripts/update-settings-tests
@@ -49,6 +49,103 @@ def write_str(f, entry_dict):
for val in values:
write_str_case(f, entry_types.index(entry_type), val)
f.write('};\n\n')
+ f.write('\n')
+ f.write('BOOL freerdp_settings_clone_keys(rdpSettings* dst, const rdpSettings* src)\n')
+ f.write('{\n')
+ f.write('\tsize_t x;\n')
+ f.write('\tfor(x=0; x<ARRAYSIZE(settings_map); x++)\n')
+ f.write('\t{\n')
+ f.write('\t\tconst struct settings_str_entry* cur = &settings_map[x];\n')
+ f.write('\t\tswitch(cur->type)\n')
+ f.write('\t\t{\n')
+ f.write('\t\t\tcase 0: /* bool */\n')
+ f.write('\t\t\t{\n')
+ f.write('\t\t\t\tBOOL sval = freerdp_settings_get_bool(src, cur->id);\n')
+ f.write('\t\t\t\tif (!freerdp_settings_set_bool(dst, cur->id, sval))\n')
+ f.write('\t\t\t\t\treturn FALSE;\n')
+ f.write('\t\t\t}\n')
+ f.write('\t\t\tbreak;\n')
+ f.write('\t\t\tcase 1: /* UINT16 */\n')
+ f.write('\t\t\t{\n')
+ f.write('\t\t\t\tUINT16 sval = freerdp_settings_get_uint16(src, cur->id);\n')
+ f.write('\t\t\t\tif (!freerdp_settings_set_uint16(dst, cur->id, sval))\n')
+ f.write('\t\t\t\t\treturn FALSE;\n')
+ f.write('\t\t\t}\n')
+ f.write('\t\t\tbreak;\n')
+ f.write('\t\t\tcase 2: /* INT16 */\n')
+ f.write('\t\t\t{\n')
+ f.write('\t\t\t\tINT16 sval = freerdp_settings_get_int16(src, cur->id);\n')
+ f.write('\t\t\t\tif (!freerdp_settings_set_int16(dst, cur->id, sval))\n')
+ f.write('\t\t\t\t\treturn FALSE;\n')
+ f.write('\t\t\t}\n')
+ f.write('\t\t\tbreak;\n')
+ f.write('\t\t\tcase 3: /* UINT32 */\n')
+ f.write('\t\t\t{\n')
+ f.write('\t\t\t\tUINT32 sval = freerdp_settings_get_uint32(src, cur->id);\n')
+ f.write('\t\t\t\tif (!freerdp_settings_set_uint32(dst, cur->id, sval))\n')
+ f.write('\t\t\t\t\treturn FALSE;\n')
+ f.write('\t\t\t}\n')
+ f.write('\t\t\tbreak;\n')
+ f.write('\t\t\tcase 4: /* INT32 */\n')
+ f.write('\t\t\t{\n')
+ f.write('\t\t\t\tINT32 sval = freerdp_settings_get_int32(src, cur->id);\n')
+ f.write('\t\t\t\tif (!freerdp_settings_set_int32(dst, cur->id, sval))\n')
+ f.write('\t\t\t\t\treturn FALSE;\n')
+ f.write('\t\t\t}\n')
+ f.write('\t\t\tbreak;\n')
+ f.write('\t\t\tcase 5: /* UINT64 */\n')
+ f.write('\t\t\t{\n')
+ f.write('\t\t\t\tUINT64 sval = freerdp_settings_get_uint64(src, cur->id);\n')
+ f.write('\t\t\t\tif (!freerdp_settings_set_uint64(dst, cur->id, sval))\n')
+ f.write('\t\t\t\t\treturn FALSE;\n')
+ f.write('\t\t\t}\n')
+ f.write('\t\t\tbreak;\n')
+ f.write('\t\t\tcase 6: /* INT64 */\n')
+ f.write('\t\t\t{\n')
+ f.write('\t\t\t\tINT64 sval = freerdp_settings_get_int64(src, cur->id);\n')
+ f.write('\t\t\t\tif (!freerdp_settings_set_int64(dst, cur->id, sval))\n')
+ f.write('\t\t\t\t\treturn FALSE;\n')
+ f.write('\t\t\t}\n')
+ f.write('\t\t\tbreak;\n')
+ f.write('\t\t\tcase 7: /* strings */\n')
+ f.write('\t\t\t{\n')
+ f.write('\t\t\t\tconst char* sval = freerdp_settings_get_string(src, cur->id);\n')
+ f.write('\t\t\t\tif (!freerdp_settings_set_string_(dst, cur->id, sval, FALSE))\n')
+ f.write('\t\t\t\t\treturn FALSE;\n')
+ f.write('\t\t\t}\n')
+ f.write('\t\t\tbreak;\n')
+ f.write('\t\t\tcase 8: /* pointer */\n')
+ f.write('\t\t\t{\n')
+ f.write('\t\t\t\tconst void* sval = freerdp_settings_get_pointer(src, cur->id);\n')
+ f.write('\t\t\t\tif (!freerdp_settings_set_pointer(dst, cur->id, sval))\n')
+ f.write('\t\t\t\t\treturn FALSE;\n')
+ f.write('\t\t\t}\n')
+ f.write('\t\t\tbreak;\n')
+
+ f.write('\t\t}\n')
+ f.write('\t}\n')
+ f.write('\treturn TRUE;\n')
+ f.write('}\n')
+ f.write('\n')
+ f.write('void freerdp_settings_free_keys(rdpSettings* dst, BOOL cleanup)\n')
+ f.write('{\n')
+ f.write('\tsize_t x;\n')
+ f.write('\tfor(x=0; x<ARRAYSIZE(settings_map); x++)\n')
+ f.write('\t{\n')
+ f.write('\t\tconst struct settings_str_entry* cur = &settings_map[x];\n')
+ f.write('\t\tswitch(cur->type)\n')
+ f.write('\t\t{\n')
+ f.write('\t\t\tcase 7: /* strings */\n')
+ f.write('\t\t\t\tfreerdp_settings_set_string_(dst, cur->id, NULL, cleanup);\n')
+ f.write('\t\t\tbreak;\n')
+ f.write('\t\t\tcase 8: /* pointer */\n')
+ f.write('\t\t\t\tfreerdp_settings_set_pointer(dst, cur->id, NULL);\n')
+ f.write('\t\t\tbreak;\n')
+ f.write('\t\t}\n')
+ f.write('\t}\n')
+ f.write('}\n')
+ f.write('\n')
+
f.write('SSIZE_T freerdp_settings_get_key_for_name(const char* value)\n')
f.write('{\n')
f.write('\tsize_t x;\n')
@@ -130,11 +227,15 @@ def write_getter(f, entry_dict, entry_type, entry_name):
def write_setter_case(f, val, isString, isPointer):
f.write('\t\tcase FreeRDP_' + val + ':\n')
- if not isString:
+ if isPointer:
+ f.write('\t\t\tsettings->' + val + ' = (void*)val;\n')
+ f.write('\t\t\tbreak;\n\n')
+ elif not isString:
f.write('\t\t\tsettings->' + val + ' = val;\n')
f.write('\t\t\tbreak;\n\n')
else:
- f.write('\t\t\tfree(settings->' + val + ');\n')
+ f.write('\t\t\tif (cleanup)\n')
+ f.write('\t\t\t\tfree(settings->' + val + ');\n')
f.write('\t\t\tsettings->' + val + ' = (val ? _strdup(val) : NULL);\n')
f.write('\t\t\treturn (!val || settings->' + val + ' != NULL);\n\n')
@@ -143,13 +244,20 @@ def write_setter(f, entry_dict, entry_type, entry_name):
isPointer = 'pointer' in entry_name
values = get_values(entry_dict, entry_type)
- f.write('BOOL freerdp_settings_set_' + entry_name.lower() + '(rdpSettings* settings, size_t id, ')
+ f.write('BOOL freerdp_settings_set_' + entry_name.lower())
+ if isString:
+ f.write('_')
+ f.write('(rdpSettings* settings, size_t id, ')
if isString or isPointer:
f.write('const ')
if not isPointer:
- f.write(entry_type + ' val)\n')
+ f.write(entry_type + ' val')
else:
- f.write('void* val)\n')
+ f.write('void* val')
+ if isString:
+ f.write(', BOOL cleanup)\n')
+ else:
+ f.write(')\n')
f.write('{\n')
f.write('\tif (!settings)\n')
f.write('\t\treturn FALSE;\n\n')
@@ -164,6 +272,20 @@ def write_setter(f, entry_dict, entry_type, entry_name):
f.write('\t}\n')
f.write('\treturn TRUE;\n')
f.write('}\n\n')
+ f.write('\n')
+ if isString:
+ f.write('BOOL freerdp_settings_set_' + entry_name.lower() + '(rdpSettings* settings, size_t id, ')
+ if isString or isPointer:
+ f.write('const ')
+ if not isPointer:
+ f.write(entry_type + ' val')
+ else:
+ f.write('void* val')
+ f.write(')\n')
+ f.write('{\n')
+ f.write('\treturn freerdp_settings_set_' + entry_name.lower() + '_(settings, id, val, TRUE);\n')
+ f.write('}\n')
+ f.write('\n')
name = os.path.dirname(os.path.realpath(__file__))
begin = "WARNING: this data structure is carefully padded for ABI stability!"
@@ -230,7 +352,7 @@ try:
write_getter(f, getter_list, 'char*', 'string')
write_setter(f, setter_list, 'char*', 'string')
write_getter(f, getter_list, '*', 'pointer')
-# write_setter(f, setter_list, '*', 'pointer')
+ write_setter(f, setter_list, '*', 'pointer')
f.write('\n')
@@ -238,6 +360,7 @@ try:
f.write('/* Generated by ' + '' + ' */\n\n')
f.write('#include <freerdp/settings.h>\n')
f.write('#include <freerdp/log.h>\n\n')
+ f.write('#include "../core/settings.h"\n\n')
f.write('#define TAG FREERDP_TAG("common.settings")\n\n')
getter_list = dict(type_list)
diff --git a/server/proxy/freerdp_proxy.c b/server/proxy/freerdp_proxy.c
index 3b348d094..d6888f424 100644
--- a/server/proxy/freerdp_proxy.c
+++ b/server/proxy/freerdp_proxy.c
@@ -24,6 +24,7 @@
#include "pf_log.h"
#include "pf_modules.h"
+#include <freerdp/version.h>
#include <freerdp/build-config.h>
#include <winpr/collections.h>
#include <stdlib.h>
@@ -85,11 +86,14 @@ int main(int argc, char* argv[])
char* config_path = "config.ini";
int status = -1;
+ WLog_INFO(TAG, "freerdp-proxy version info:");
+ WLog_INFO(TAG, "\tFreeRDP version: %s", FREERDP_VERSION_FULL);
+ WLog_INFO(TAG, "\tGit commit: %s", GIT_REVISION);
+ WLog_DBG(TAG, "\tBuild config: %s", freerdp_get_build_config());
+
if (argc >= 2)
config_path = argv[1];
- pf_server_register_signal_handlers();
-
config = pf_server_config_load(config_path);
if (!config)
goto fail;
@@ -107,6 +111,8 @@ int main(int argc, char* argv[])
if (!is_all_required_modules_loaded(config))
goto fail;
+ pf_server_register_signal_handlers();
+
server = pf_server_new(config);
if (!server)
goto fail;
diff --git a/server/proxy/pf_client.c b/server/proxy/pf_client.c
index aebba08af..0db33f88a 100644
--- a/server/proxy/pf_client.c
+++ b/server/proxy/pf_client.c
@@ -72,10 +72,11 @@ static void pf_client_on_error_info(void* ctx, ErrorInfoEventArgs* e)
freerdp_send_error_info(ps->context.rdp);
}
-static BOOL pf_client_load_rdpsnd(pClientContext* pc, proxyConfig* config)
+static BOOL pf_client_load_rdpsnd(pClientContext* pc)
{
rdpContext* context = (rdpContext*)pc;
pServerContext* ps = pc->pdata->ps;
+ proxyConfig* config = pc->pdata->config;
/*
* if AudioOutput is enabled in proxy and client connected with rdpsnd, use proxy as rdpsnd
@@ -98,6 +99,63 @@ static BOOL pf_client_load_rdpsnd(pClientContext* pc, proxyConfig* config)
return TRUE;
}
+static BOOL pf_client_passthrough_channels_init(pClientContext* pc)
+{
+ pServerContext* ps = pc->pdata->ps;
+ rdpSettings* settings = pc->context.settings;
+ proxyConfig* config = pc->pdata->config;
+ size_t i;
+
+ if (settings->ChannelCount + config->PassthroughCount >= settings->ChannelDefArraySize)
+ {
+ LOG_ERR(TAG, pc, "too many channels");
+ return FALSE;
+ }
+
+ for (i = 0; i < config->PassthroughCount; i++)
+ {
+ const char* channel_name = config->Passthrough[i];
+ CHANNEL_DEF channel = { 0 };
+
+ /* only connect connect this channel if already joined in peer connection */
+ if (!WTSVirtualChannelManagerIsChannelJoined(ps->vcm, channel_name))
+ {
+ LOG_INFO(TAG, ps, "client did not connected with channel %s, skipping passthrough",
+ channel_name);
+
+ continue;
+ }
+
+ channel.options = CHANNEL_OPTION_INITIALIZED; /* TODO: Export to config. */
+ strncpy(channel.name, channel_name, CHANNEL_NAME_LEN);
+
+ settings->ChannelDefArray[settings->ChannelCount++] = channel;
+ }
+
+ return TRUE;
+}
+
+static BOOL pf_client_use_peer_load_balance_info(pClientContext* pc)
+{
+ pServerContext* ps = pc->pdata->ps;
+ rdpSettings* settings = pc->context.settings;
+ DWORD lb_info_len;
+ const char* lb_info = freerdp_nego_get_routing_token(&ps->context, &lb_info_len);
+ if (!lb_info)
+ return TRUE;
+
+ free(settings->LoadBalanceInfo);
+
+ settings->LoadBalanceInfoLength = lb_info_len;
+ settings->LoadBalanceInfo = malloc(settings->LoadBalanceInfoLength);
+
+ if (!settings->LoadBalanceInfo)
+ return FALSE;
+
+ CopyMemory(settings->LoadBalanceInfo, lb_info, settings->LoadBalanceInfoLength);
+ return TRUE;
+}
+
/**
* Called before a connection is established.
*
@@ -135,6 +193,7 @@ static BOOL pf_client_pre_connect(freerdp* instance)
settings->DynamicResolutionUpdate = config->DisplayControl;
settings->AutoReconnectionEnabled = TRUE;
+
/**
* Register the channel listeners.
* They are required to set up / tear down channels if they are loaded.
@@ -144,45 +203,26 @@ static BOOL pf_client_pre_connect(freerdp* instance)
PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
pf_channels_on_client_channel_disconnect);
PubSub_SubscribeErrorInfo(instance->context->pubSub, pf_client_on_error_info);
-
/**
* Load all required plugins / channels / libraries specified by current
* settings.
*/
LOG_INFO(TAG, pc, "Loading addins");
+ if (!config->UseLoadBalanceInfo)
{
- /* add passthrough channels to channel def array */
- size_t i;
+ /* if target is static (i.e fetched from config). make sure to use peer's load-balance info,
+ * in order to support broker redirection.
+ */
- if (settings->ChannelCount + config->PassthroughCount >= settings->ChannelDefArraySize)
- {
- LOG_ERR(TAG, pc, "too many channels");
+ if (!pf_client_use_peer_load_balance_info(pc))
return FALSE;
- }
-
- for (i = 0; i < config->PassthroughCount; i++)
- {
- const char* channel_name = config->Passthrough[i];
- CHANNEL_DEF channel = { 0 };
-
- /* only connect connect this channel if already joined in peer connection */
- if (!WTSVirtualChannelManagerIsChannelJoined(ps->vcm, channel_name))
- {
- LOG_INFO(TAG, ps, "client did not connected with channel %s, skipping passthrough",
- channel_name);
-
- continue;
- }
-
- channel.options = CHANNEL_OPTION_INITIALIZED; /* TODO: Export to config. */
- strncpy(channel.name, channel_name, CHANNEL_NAME_LEN);
-
- settings->ChannelDefArray[settings->ChannelCount++] = channel;
- }
}
- if (!pf_client_load_rdpsnd(pc, config))
+ if (!pf_client_passthrough_channels_init(pc))
+ return FALSE;
+
+ if (!pf_client_load_rdpsnd(pc))
{
LOG_ERR(TAG, pc, "Failed to load rdpsnd client");
return FALSE;
diff --git a/server/shadow/freerdp-shadow-cli.1.in b/server/shadow/freerdp-shadow-cli.1.in
index 46f376d52..9c6ffe543 100644
--- a/server/shadow/freerdp-shadow-cli.1.in
+++ b/server/shadow/freerdp-shadow-cli.1.in
@@ -76,7 +76,7 @@ When run as user within a X session (for example from an xterm) a socket on
Successful program execution.
.TP
.B 1
-Otherweise.
+Otherwise.
.SH SEE ALSO
wlog(7)
diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt
index 650c5910b..a8b66038f 100644
--- a/winpr/CMakeLists.txt
+++ b/winpr/CMakeLists.txt
@@ -51,7 +51,7 @@ if (NOT WIN32)
endif()
# Soname versioning
-set(RAW_VERSION_STRING "2.1.0")
+set(RAW_VERSION_STRING "2.1.1")
if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag")
file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING)
elseif(USE_VERSION_FROM_GIT_TAG)
diff --git a/winpr/include/winpr/bitstream.h b/winpr/include/winpr/bitstream.h
index 29e8ca4de..0771ce958 100644
--- a/winpr/include/winpr/bitstream.h
+++ b/winpr/include/winpr/bitstream.h
@@ -52,39 +52,39 @@ extern "C"
{
(_bs->prefetch) = 0;
if (((UINT32)(_bs->pointer - _bs->buffer) + 4) < (_bs->capacity))
- (_bs->prefetch) |= (*(_bs->pointer + 4) << 24);
+ (_bs->prefetch) |= ((UINT32) * (_bs->pointer + 4) << 24);
if (((UINT32)(_bs->pointer - _bs->buffer) + 5) < (_bs->capacity))
- (_bs->prefetch) |= (*(_bs->pointer + 5) << 16);
+ (_bs->prefetch) |= ((UINT32) * (_bs->pointer + 5) << 16);
if (((UINT32)(_bs->pointer - _bs->buffer) + 6) < (_bs->capacity))
- (_bs->prefetch) |= (*(_bs->pointer + 6) << 8);
+ (_bs->prefetch) |= ((UINT32) * (_bs->pointer + 6) << 8);
if (((UINT32)(_bs->pointer - _bs->buffer) + 7) < (_bs->capacity))
- (_bs->prefetch) |= (*(_bs->pointer + 7) << 0);
+ (_bs->prefetch) |= ((UINT32) * (_bs->pointer + 7) << 0);
}
static INLINE void BitStream_Fetch(wBitStream* _bs)
{
(_bs->accumulator) = 0;
if (((UINT32)(_bs->pointer - _bs->buffer) + 0) < (_bs->capacity))
- (_bs->accumulator) |= (*(_bs->pointer + 0) << 24);
+ (_bs->accumulator) |= ((UINT32) * (_bs->pointer + 0) << 24);
if (((UINT32)(_bs->pointer - _bs->buffer) + 1) < (_bs->capacity))
- (_bs->accumulator) |= (*(_bs->pointer + 1) << 16);
+ (_bs->accumulator) |= ((UINT32) * (_bs->pointer + 1) << 16);
if (((UINT32)(_bs->pointer - _bs->buffer) + 2) < (_bs->capacity))
- (_bs->accumulator) |= (*(_bs->pointer + 2) << 8);
+ (_bs->accumulator) |= ((UINT32) * (_bs->pointer + 2) << 8);
if (((UINT32)(_bs->pointer - _bs->buffer) + 3) < (_bs->capacity))
- (_bs->accumulator) |= (*(_bs->pointer + 3) << 0);
+ (_bs->accumulator) |= ((UINT32) * (_bs->pointer + 3) << 0);
BitStream_Prefetch(_bs);
}
static INLINE void BitStream_Flush(wBitStream* _bs)
{
if (((UINT32)(_bs->pointer - _bs->buffer) + 0) < (_bs->capacity))
- *(_bs->pointer + 0) = (_bs->accumulator >> 24);
+ *(_bs->pointer + 0) = ((UINT32)_bs->accumulator >> 24);
if (((UINT32)(_bs->pointer - _bs->buffer) + 1) < (_bs->capacity))
- *(_bs->pointer + 1) = (_bs->accumulator >> 16);
+ *(_bs->pointer + 1) = ((UINT32)_bs->accumulator >> 16);
if (((UINT32)(_bs->pointer - _bs->buffer) + 2) < (_bs->capacity))
- *(_bs->pointer + 2) = (_bs->accumulator >> 8);
+ *(_bs->pointer + 2) = ((UINT32)_bs->accumulator >> 8);
if (((UINT32)(_bs->pointer - _bs->buffer) + 3) < (_bs->capacity))
- *(_bs->pointer + 3) = (_bs->accumulator >> 0);
+ *(_bs->pointer + 3) = ((UINT32)_bs->accumulator >> 0);
}
static INLINE void BitStream_Shift(wBitStream* _bs, UINT32 _nbits)
@@ -99,13 +99,13 @@ extern "C"
_bs->offset += _nbits;
if (_bs->offset < 32)
{
- _bs->mask = ((1 << _nbits) - 1);
+ _bs->mask = ((1UL << _nbits) - 1);
_bs->accumulator |= ((_bs->prefetch >> (32 - _nbits)) & _bs->mask);
_bs->prefetch <<= _nbits;
}
else
{
- _bs->mask = ((1 << _nbits) - 1);
+ _bs->mask = ((1UL << _nbits) - 1);
_bs->accumulator |= ((_bs->prefetch >> (32 - _nbits)) & _bs->mask);
_bs->prefetch <<= _nbits;
_bs->offset -= 32;
@@ -113,7 +113,7 @@ extern "C"
BitStream_Prefetch(_bs);
if (_bs->offset)
{
- _bs->mask = ((1 << _bs->offset) - 1);
+ _bs->mask = ((1UL << _bs->offset) - 1);
_bs->accumulator |= ((_bs->prefetch >> (32 - _bs->offset)) & _bs->mask);
_bs->prefetch <<= _bs->offset;
}
@@ -149,7 +149,7 @@ extern "C"
_bs->pointer += 4;
if (_bs->offset)
{
- _bs->mask = ((1 << _bs->offset) - 1);
+ _bs->mask = ((1UL << _bs->offset) - 1);
_bs->accumulator |= ((_bits & _bs->mask) << (32 - _bs->offset));
}
}
diff --git a/winpr/include/winpr/sam.h b/winpr/include/winpr/sam.h
index a11967b12..6d932dfca 100644
--- a/winpr/include/winpr/sam.h
+++ b/winpr/include/winpr/sam.h
@@ -23,13 +23,6 @@
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
-struct winpr_sam
-{
- FILE* fp;
- char* line;
- char* buffer;
- BOOL readOnly;
-};
typedef struct winpr_sam WINPR_SAM;
struct winpr_sam_entry
diff --git a/winpr/include/winpr/stream.h b/winpr/include/winpr/stream.h
index a5f10b03e..f351eaa15 100644
--- a/winpr/include/winpr/stream.h
+++ b/winpr/include/winpr/stream.h
@@ -74,60 +74,64 @@ extern "C"
Stream_Seek(_s, sizeof(_t)); \
} while (0)
-#define _stream_read_n16_le(_t, _s, _v, _p) \
- do \
- { \
- (_v) = (_t)(*(_s)->pointer) + (_t)(((_t)(*((_s)->pointer + 1))) << 8); \
- if (_p) \
- Stream_Seek(_s, sizeof(_t)); \
+#define _stream_read_n16_le(_t, _s, _v, _p) \
+ do \
+ { \
+ (_v) = (_t)((*(_s)->pointer) + (((UINT16)(*((_s)->pointer + 1))) << 8)); \
+ if (_p) \
+ Stream_Seek(_s, sizeof(_t)); \
} while (0)
-#define _stream_read_n16_be(_t, _s, _v, _p) \
- do \
- { \
- (_v) = (_t)(((_t)(*(_s)->pointer)) << 8) + (_t)(*((_s)->pointer + 1)); \
- if (_p) \
- Stream_Seek(_s, sizeof(_t)); \
- } while (0)
-
-#define _stream_read_n32_le(_t, _s, _v, _p) \
- do \
- { \
- (_v) = (_t)(*(_s)->pointer) + (((_t)(*((_s)->pointer + 1))) << 8) + \
- (((_t)(*((_s)->pointer + 2))) << 16) + (((_t)(*((_s)->pointer + 3))) << 24); \
- if (_p) \
- Stream_Seek(_s, sizeof(_t)); \
+#define _stream_read_n16_be(_t, _s, _v, _p) \
+ do \
+ { \
+ (_v) = (_t)((((UINT16)(*(_s)->pointer)) << 8) + (UINT16)(*((_s)->pointer + 1))); \
+ if (_p) \
+ Stream_Seek(_s, sizeof(_t)); \
} while (0)
-#define _stream_read_n32_be(_t, _s, _v, _p) \
+#define _stream_read_n32_le(_t, _s, _v, _p) \
do \
{ \
- (_v) = (((_t)(*((_s)->pointer))) << 24) + (((_t)(*((_s)->pointer + 1))) << 16) + \
- (((_t)(*((_s)->pointer + 2))) << 8) + (((_t)(*((_s)->pointer + 3)))); \
+ (_v) = (_t)((UINT32)(*(_s)->pointer) + (((UINT32)(*((_s)->pointer + 1))) << 8) + \
+ (((UINT32)(*((_s)->pointer + 2))) << 16) + \
+ ((((UINT32) * ((_s)->pointer + 3))) << 24)); \
if (_p) \
Stream_Seek(_s, sizeof(_t)); \
} while (0)
-#define _stream_read_n64_le(_t, _s, _v, _p) \
- do \
- { \
- (_v) = (_t)(*(_s)->pointer) + (((_t)(*((_s)->pointer + 1))) << 8) + \
- (((_t)(*((_s)->pointer + 2))) << 16) + (((_t)(*((_s)->pointer + 3))) << 24) + \
- (((_t)(*((_s)->pointer + 4))) << 32) + (((_t)(*((_s)->pointer + 5))) << 40) + \
- (((_t)(*((_s)->pointer + 6))) << 48) + (((_t)(*((_s)->pointer + 7))) << 56); \
- if (_p) \
- Stream_Seek(_s, sizeof(_t)); \
+#define _stream_read_n32_be(_t, _s, _v, _p) \
+ do \
+ { \
+ (_v) = (_t)(((((UINT32) * ((_s)->pointer))) << 24) + \
+ (((UINT32)(*((_s)->pointer + 1))) << 16) + \
+ (((UINT32)(*((_s)->pointer + 2))) << 8) + (((UINT32)(*((_s)->pointer + 3))))); \
+ if (_p) \
+ Stream_Seek(_s, sizeof(_t)); \
+ } while (0)
+
+#define _stream_read_n64_le(_t, _s, _v, _p) \
+ do \
+ { \
+ (_v) = (_t)( \
+ (UINT64)(*(_s)->pointer) + (((UINT64)(*((_s)->pointer + 1))) << 8) + \
+ (((UINT64)(*((_s)->pointer + 2))) << 16) + (((UINT64)(*((_s)->pointer + 3))) << 24) + \
+ (((UINT64)(*((_s)->pointer + 4))) << 32) + (((UINT64)(*((_s)->pointer + 5))) << 40) + \
+ (((UINT64)(*((_s)->pointer + 6))) << 48) + (((UINT64)(*((_s)->pointer + 7))) << 56)); \
+ if (_p) \
+ Stream_Seek(_s, sizeof(_t)); \
} while (0)
-#define _stream_read_n64_be(_t, _s, _v, _p) \
- do \
- { \
- (_v) = (((_t)(*((_s)->pointer))) << 56) + (((_t)(*((_s)->pointer + 1))) << 48) + \
- (((_t)(*((_s)->pointer + 2))) << 40) + (((_t)(*((_s)->pointer + 3))) << 32) + \
- (((_t)(*((_s)->pointer + 4))) << 24) + (((_t)(*((_s)->pointer + 5))) << 16) + \
- (((_t)(*((_s)->pointer + 6))) << 8) + (((_t)(*((_s)->pointer + 7)))); \
- if (_p) \
- Stream_Seek(_s, sizeof(_t)); \
+#define _stream_read_n64_be(_t, _s, _v, _p) \
+ do \
+ { \
+ (_v) = (_t)( \
+ (((UINT64)(*((_s)->pointer))) << 56) + (((UINT64)(*((_s)->pointer + 1))) << 48) + \
+ (((UINT64)(*((_s)->pointer + 2))) << 40) + (((UINT64)(*((_s)->pointer + 3))) << 32) + \
+ (((UINT64)(*((_s)->pointer + 4))) << 24) + (((UINT64)(*((_s)->pointer + 5))) << 16) + \
+ (((UINT64)(*((_s)->pointer + 6))) << 8) + (((UINT64)(*((_s)->pointer + 7))))); \
+ if (_p) \
+ Stream_Seek(_s, sizeof(_t)); \
} while (0)
#define Stream_Read_UINT8(_s, _v) _stream_read_n8(UINT8, _s, _v, TRUE)
diff --git a/winpr/libwinpr/crt/test/TestAlignment.c b/winpr/libwinpr/crt/test/TestAlignment.c
index 80986478f..0e4595b89 100644
--- a/winpr/libwinpr/crt/test/TestAlignment.c
+++ b/winpr/libwinpr/crt/test/TestAlignment.c
@@ -12,7 +12,7 @@ int TestAlignment(int argc, char* argv[])
/* Alignment should be 2^N where N is a positive integer */
alignment = 16;
- offset = 5;
+ offset = 8;
/* _aligned_malloc */
diff --git a/winpr/libwinpr/crt/utf.c b/winpr/libwinpr/crt/utf.c
index 8ab7e39bb..8c8d2a841 100644
--- a/winpr/libwinpr/crt/utf.c
+++ b/winpr/libwinpr/crt/utf.c
@@ -257,16 +257,24 @@ static const BYTE firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF16toUTF8(const WCHAR** sourceStart, const WCHAR* sourceEnd,
- BYTE** targetStart, BYTE* targetEnd, ConversionFlags flags)
+ BYTE** targetStart, BYTE* te, ConversionFlags flags)
{
- BYTE* target;
+ size_t pos = 0;
+ size_t end = 0;
const WCHAR* source;
- BOOL computeLength;
- ConversionResult result;
- computeLength = (!targetEnd) ? TRUE : FALSE;
+ const BOOL computeLength = (!te) ? TRUE : FALSE;
+ ConversionResult result = conversionOK;
+
+ if (targetStart && te)
+ {
+ const size_t s = (size_t)*targetStart;
+ const size_t e = (size_t)te;
+ if (s > e)
+ return sourceIllegal;
+ end = e - s;
+ }
+
source = *sourceStart;
- target = *targetStart;
- result = conversionOK;
while (source < sourceEnd)
{
@@ -345,12 +353,12 @@ ConversionResult ConvertUTF16toUTF8(const WCHAR** sourceStart, const WCHAR* sour
ch = UNI_REPLACEMENT_CHAR;
}
- target += bytesToWrite;
+ pos += bytesToWrite;
- if ((target > targetEnd) && (!computeLength))
+ if ((pos > end) && (!computeLength))
{
source = oldSource; /* Back up source pointer! */
- target -= bytesToWrite;
+ pos -= bytesToWrite;
result = targetExhausted;
break;
}
@@ -361,19 +369,19 @@ ConversionResult ConvertUTF16toUTF8(const WCHAR** sourceStart, const WCHAR* sour
{
/* note: everything falls through. */
case 4:
- *--target = (BYTE)((ch | byteMark) & byteMask);
+ (*targetStart)[--pos] = (BYTE)((ch | byteMark) & byteMask);
ch >>= 6;
case 3:
- *--target = (BYTE)((ch | byteMark) & byteMask);
+ (*targetStart)[--pos] = (BYTE)((ch | byteMark) & byteMask);
ch >>= 6;
case 2:
- *--target = (BYTE)((ch | byteMark) & byteMask);
+ (*targetStart)[--pos] = (BYTE)((ch | byteMark) & byteMask);
ch >>= 6;
case 1:
- *--target = (BYTE)(ch | firstByteMark[bytesToWrite]);
+ (*targetStart)[--pos] = (BYTE)(ch | firstByteMark[bytesToWrite]);
}
}
else
@@ -382,24 +390,27 @@ ConversionResult ConvertUTF16toUTF8(const WCHAR** sourceStart, const WCHAR* sour
{
/* note: everything falls through. */
case 4:
- --target;
+ --pos;
case 3:
- --target;
+ --pos;
case 2:
- --target;
+ --pos;
case 1:
- --target;
+ --pos;
}
}
- target += bytesToWrite;
+ pos += bytesToWrite;
}
*sourceStart = source;
- *targetStart = target;
+ if (targetStart && *targetStart)
+ *targetStart = &(*targetStart)[pos];
+ else if (targetStart)
+ *targetStart = (BYTE*)pos;
return result;
}
@@ -503,14 +514,24 @@ BOOL isLegalUTF8Sequence(const BYTE* source, const BYTE* sourceEnd)
ConversionResult ConvertUTF8toUTF16(const BYTE** sourceStart, const BYTE* sourceEnd,
WCHAR** targetStart, WCHAR* targetEnd, ConversionFlags flags)
{
- WCHAR* target;
+ size_t target = 0;
+ size_t end = 0;
const BYTE* source;
BOOL computeLength;
ConversionResult result;
computeLength = (!targetEnd) ? TRUE : FALSE;
result = conversionOK;
source = *sourceStart;
- target = *targetStart;
+
+ if (targetStart && targetEnd)
+ {
+ const size_t s = (size_t)*targetStart;
+ const size_t e = (size_t)targetEnd;
+ if (s > e)
+ return sourceIllegal;
+
+ end = ((size_t)(targetEnd)) - ((size_t)(*targetStart));
+ }
while (source < sourceEnd)
{
@@ -561,7 +582,7 @@ ConversionResult ConvertUTF8toUTF16(const BYTE** sourceStart, const BYTE* source
ch -= offsetsFromUTF8[extraBytesToRead];
- if ((target >= targetEnd) && (!computeLength))
+ if ((target >= end) && (!computeLength))
{
source -= (extraBytesToRead + 1); /* Back up source pointer! */
result = targetExhausted;
@@ -583,23 +604,15 @@ ConversionResult ConvertUTF8toUTF16(const BYTE** sourceStart, const BYTE* source
else
{
if (!computeLength)
- {
- Data_Write_UINT16(target, UNI_REPLACEMENT_CHAR);
- target++;
- }
- else
- target++;
+ Data_Write_UINT16(&(*targetStart)[target], UNI_REPLACEMENT_CHAR);
+ target++;
}
}
else
{
if (!computeLength)
- {
- Data_Write_UINT16(target, ch); /* normal case */
- target++;
- }
- else
- target++;
+ Data_Write_UINT16(&(*targetStart)[target], ch); /* normal case */
+ target++;
}
}
else if (ch > UNI_MAX_UTF16)
@@ -613,18 +626,14 @@ ConversionResult ConvertUTF8toUTF16(const BYTE** sourceStart, const BYTE* source
else
{
if (!computeLength)
- {
- Data_Write_UINT16(target, UNI_REPLACEMENT_CHAR);
- target++;
- }
- else
- target++;
+ Data_Write_UINT16(&(*targetStart)[target], UNI_REPLACEMENT_CHAR);
+ target++;
}
}
else
{
/* target is a character in range 0xFFFF - 0x10FFFF. */
- if ((target + 1 >= targetEnd) && (!computeLength))
+ if ((target + 1 >= end) && (!computeLength))
{
source -= (extraBytesToRead + 1); /* Back up source pointer! */
result = targetExhausted;
@@ -637,11 +646,9 @@ ConversionResult ConvertUTF8toUTF16(const BYTE** sourceStart, const BYTE* source
{
WCHAR wchar;
wchar = (ch >> halfShift) + UNI_SUR_HIGH_START;
- Data_Write_UINT16(target, wchar);
- target++;
+ Data_Write_UINT16(&(*targetStart)[target++], wchar);
wchar = (ch & halfMask) + UNI_SUR_LOW_START;
- Data_Write_UINT16(target, wchar);
- target++;
+ Data_Write_UINT16(&(*targetStart)[target++], wchar);
}
else
{
@@ -652,7 +659,10 @@ ConversionResult ConvertUTF8toUTF16(const BYTE** sourceStart, const BYTE* source
}
*sourceStart = source;
- *targetStart = target;
+ if (targetStart && (*targetStart))
+ *targetStart = &(*targetStart)[target];
+ else if (targetStart)
+ *targetStart = (WCHAR*)(target * sizeof(WCHAR));
return result;
}
diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.c b/winpr/libwinpr/smartcard/smartcard_pcsc.c
index f5f33a6b2..36c43af06 100644
--- a/winpr/libwinpr/smartcard/smartcard_pcsc.c
+++ b/winpr/libwinpr/smartcard/smartcard_pcsc.c
@@ -2930,6 +2930,7 @@ unsigned int determineMacOSXVersion(void)
long minorVersion = 0;
long patchVersion = 0;
int count = 0;
+ char* context = NULL;
mib[0] = CTL_KERN;
mib[1] = KERN_OSRELEASE;
@@ -2947,7 +2948,7 @@ unsigned int determineMacOSXVersion(void)
return 0;
}
- tok = strtok(kernelVersion, ".");
+ tok = strtok_s(kernelVersion, ".", &context);
errno = 0;
while (tok)
@@ -2979,7 +2980,7 @@ unsigned int determineMacOSXVersion(void)
break;
}
- tok = strtok(NULL, ".");
+ tok = strtok_s(NULL, ".", &context);
count++;
}
diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_message.c b/winpr/libwinpr/sspi/NTLM/ntlm_message.c
index 5fc6ec73b..314f5c147 100644
--- a/winpr/libwinpr/sspi/NTLM/ntlm_message.c
+++ b/winpr/libwinpr/sspi/NTLM/ntlm_message.c
@@ -367,12 +367,16 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu
SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buffer)
{
+ SECURITY_STATUS status = SEC_E_INVALID_TOKEN;
wStream* s;
- int length;
- PBYTE StartOffset;
- PBYTE PayloadOffset;
+ size_t length;
+ size_t StartOffset;
+ size_t PayloadOffset;
NTLM_AV_PAIR* AvTimestamp;
NTLM_CHALLENGE_MESSAGE* message;
+ if (!context || !buffer)
+ return SEC_E_INTERNAL_ERROR;
+
ntlm_generate_client_challenge(context);
message = &context->CHALLENGE_MESSAGE;
ZeroMemory(message, sizeof(NTLM_CHALLENGE_MESSAGE));
@@ -381,77 +385,51 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
if (!s)
return SEC_E_INTERNAL_ERROR;
- StartOffset = Stream_Pointer(s);
+ StartOffset = Stream_GetPosition(s);
if (ntlm_read_message_header(s, (NTLM_MESSAGE_HEADER*)message) < 0)
- {
- Stream_Free(s, FALSE);
- return SEC_E_INVALID_TOKEN;
- }
+ goto fail;
if (message->MessageType != MESSAGE_TYPE_CHALLENGE)
- {
- Stream_Free(s, FALSE);
- return SEC_E_INVALID_TOKEN;
- }
+ goto fail;
if (ntlm_read_message_fields(s, &(message->TargetName)) < 0) /* TargetNameFields (8 bytes) */
- {
- Stream_Free(s, FALSE);
- return SEC_E_INVALID_TOKEN;
- }
+ goto fail;
if (Stream_GetRemainingLength(s) < 4)
- {
- Stream_Free(s, FALSE);
- return SEC_E_INVALID_TOKEN;
- }
+ goto fail;
Stream_Read_UINT32(s, message->NegotiateFlags); /* NegotiateFlags (4 bytes) */
context->NegotiateFlags = message->NegotiateFlags;
if (Stream_GetRemainingLength(s) < 8)
- {
- Stream_Free(s, FALSE);
- return SEC_E_INVALID_TOKEN;
- }
+ goto fail;
Stream_Read(s, message->ServerChallenge, 8); /* ServerChallenge (8 bytes) */
CopyMemory(context->ServerChallenge, message->ServerChallenge, 8);
if (Stream_GetRemainingLength(s) < 8)
- {
- Stream_Free(s, FALSE);
- return SEC_E_INVALID_TOKEN;
- }
+ goto fail;
Stream_Read(s, message->Reserved, 8); /* Reserved (8 bytes), should be ignored */
if (ntlm_read_message_fields(s, &(message->TargetInfo)) < 0) /* TargetInfoFields (8 bytes) */
- {
- Stream_Free(s, FALSE);
- return SEC_E_INVALID_TOKEN;
- }
+ goto fail;
if (context->NegotiateFlags & NTLMSSP_NEGOTIATE_VERSION)
{
if (ntlm_read_version_info(s, &(message->Version)) < 0) /* Version (8 bytes) */
- {
- Stream_Free(s, FALSE);
- return SEC_E_INVALID_TOKEN;
- }
+ goto fail;
}
/* Payload (variable) */
- PayloadOffset = Stream_Pointer(s);
+ PayloadOffset = Stream_GetPosition(s);
+ status = SEC_E_INTERNAL_ERROR;
if (message->TargetName.Len > 0)
{
if (ntlm_read_message_fields_buffer(s, &(message->TargetName)) < 0)
- {
- Stream_Free(s, FALSE);
- return SEC_E_INTERNAL_ERROR;
- }
+ goto fail;
}
if (message->TargetInfo.Len > 0)
@@ -459,10 +437,7 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
size_t cbAvTimestamp;
if (ntlm_read_message_fields_buffer(s, &(message->TargetInfo)) < 0)
- {
- Stream_Free(s, FALSE);
- return SEC_E_INTERNAL_ERROR;
- }
+ goto fail;
context->ChallengeTargetInfo.pvBuffer = message->TargetInfo.Buffer;
context->ChallengeTargetInfo.cbBuffer = message->TargetInfo.Len;
@@ -474,7 +449,7 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
PBYTE ptr = ntlm_av_pair_get_value_pointer(AvTimestamp);
if (!ptr)
- return SEC_E_INTERNAL_ERROR;
+ goto fail;
if (context->NTLMv2)
context->UseMIC = TRUE;
@@ -484,14 +459,14 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
}
length = (PayloadOffset - StartOffset) + message->TargetName.Len + message->TargetInfo.Len;
+ if (length > buffer->cbBuffer)
+ goto fail;
if (!sspi_SecBufferAlloc(&context->ChallengeMessage, length))
- {
- Stream_Free(s, FALSE);
- return SEC_E_INTERNAL_ERROR;
- }
+ goto fail;
- CopyMemory(context->ChallengeMessage.pvBuffer, StartOffset, length);
+ if (context->ChallengeMessage.pvBuffer)
+ CopyMemory(context->ChallengeMessage.pvBuffer, Stream_Buffer(s) + StartOffset, length);
#ifdef WITH_DEBUG_NTLM
WLog_DBG(TAG, "CHALLENGE_MESSAGE (length = %d)", length);
winpr_HexDump(TAG, WLOG_DEBUG, context->ChallengeMessage.pvBuffer,
@@ -517,10 +492,7 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
if (context->NTLMv2)
{
if (ntlm_construct_authenticate_target_info(context) < 0)
- {
- Stream_Free(s, FALSE);
- return SEC_E_INTERNAL_ERROR;
- }
+ goto fail;
sspi_SecBufferFree(&context->ChallengeTargetInfo);
context->ChallengeTargetInfo.pvBuffer = context->AuthenticateTargetInfo.pvBuffer;
@@ -530,16 +502,10 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
ntlm_generate_timestamp(context); /* Timestamp */
if (ntlm_compute_lm_v2_response(context) < 0) /* LmChallengeResponse */
- {
- Stream_Free(s, FALSE);
- return SEC_E_INTERNAL_ERROR;
- }
+ goto fail;
if (ntlm_compute_ntlm_v2_response(context) < 0) /* NtChallengeResponse */
- {
- Stream_Free(s, FALSE);
- return SEC_E_INTERNAL_ERROR;
- }
+ goto fail;
ntlm_generate_key_exchange_key(context); /* KeyExchangeKey */
ntlm_generate_random_session_key(context); /* RandomSessionKey */
@@ -579,8 +545,10 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf
#endif
context->state = NTLM_STATE_AUTHENTICATE;
ntlm_free_message_fields_buffer(&(message->TargetName));
+ status = SEC_I_CONTINUE_NEEDED;
+fail:
Stream_Free(s, FALSE);
- return SEC_I_CONTINUE_NEEDED;
+ return status;
}
SECURITY_STATUS ntlm_write_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buffer)
diff --git a/winpr/libwinpr/sspi/sspi_winpr.c b/winpr/libwinpr/sspi/sspi_winpr.c
index 5bd897d02..7db9b0e00 100644
--- a/winpr/libwinpr/sspi/sspi_winpr.c
+++ b/winpr/libwinpr/sspi/sspi_winpr.c
@@ -241,9 +241,12 @@ void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials)
passwordLength *= 2;
}
- memset(credentials->identity.User, 0, userLength);
- memset(credentials->identity.Domain, 0, domainLength);
- memset(credentials->identity.Password, 0, passwordLength);
+ if (credentials->identity.User)
+ memset(credentials->identity.User, 0, userLength);
+ if (credentials->identity.Domain)
+ memset(credentials->identity.Domain, 0, domainLength);
+ if (credentials->identity.Password)
+ memset(credentials->identity.Password, 0, passwordLength);
free(credentials->identity.User);
free(credentials->identity.Domain);
free(credentials->identity.Password);
diff --git a/winpr/libwinpr/sspi/test/TestNTLM.c b/winpr/libwinpr/sspi/test/TestNTLM.c
index 83abe70db..82d266fe6 100644
--- a/winpr/libwinpr/sspi/test/TestNTLM.c
+++ b/winpr/libwinpr/sspi/test/TestNTLM.c
@@ -470,10 +470,15 @@ void test_ntlm_server_free(TEST_NTLM_SERVER* ntlm)
int TestNTLM(int argc, char* argv[])
{
int status;
+ int rc = -1;
PSecBuffer pSecBuffer;
- TEST_NTLM_CLIENT* client;
- TEST_NTLM_SERVER* server;
+ TEST_NTLM_CLIENT* client = NULL;
+ TEST_NTLM_SERVER* server = NULL;
BOOL DynamicTest = TRUE;
+
+ WINPR_UNUSED(argc);
+ WINPR_UNUSED(argv);
+
/**
* Client Initialization
*/
@@ -482,7 +487,7 @@ int TestNTLM(int argc, char* argv[])
if (!client)
{
printf("Memory allocation failed");
- return -1;
+ goto fail;
}
status = test_ntlm_client_init(client, TEST_NTLM_USER, TEST_NTLM_DOMAIN, TEST_NTLM_PASSWORD);
@@ -490,7 +495,7 @@ int TestNTLM(int argc, char* argv[])
if (status < 0)
{
printf("test_ntlm_client_init failure\n");
- return -1;
+ goto fail;
}
/**
@@ -501,7 +506,7 @@ int TestNTLM(int argc, char* argv[])
if (!server)
{
printf("Memory allocation failed\n");
- return -1;
+ goto fail;
}
status = test_ntlm_server_init(server);
@@ -509,7 +514,7 @@ int TestNTLM(int argc, char* argv[])
if (status < 0)
{
printf("test_ntlm_server_init failure\n");
- return -1;
+ goto fail;
}
/**
@@ -520,7 +525,7 @@ int TestNTLM(int argc, char* argv[])
if (status < 0)
{
printf("test_ntlm_client_authenticate failure\n");
- return -1;
+ goto fail;
}
if (!DynamicTest)
@@ -557,7 +562,7 @@ int TestNTLM(int argc, char* argv[])
if (!pSecBuffer->pvBuffer)
{
printf("Memory allocation failed\n");
- return -1;
+ goto fail;
}
CopyMemory(pSecBuffer->pvBuffer, TEST_NTLM_NEGOTIATE, pSecBuffer->cbBuffer);
@@ -578,7 +583,7 @@ int TestNTLM(int argc, char* argv[])
if (status < 0)
{
printf("test_ntlm_server_authenticate failure\n");
- return -1;
+ goto fail;
}
if (!DynamicTest)
@@ -616,7 +621,7 @@ int TestNTLM(int argc, char* argv[])
if (!pSecBuffer->pvBuffer)
{
printf("Memory allocation failed\n");
- return -1;
+ goto fail;
}
CopyMemory(pSecBuffer->pvBuffer, TEST_NTLM_CHALLENGE, pSecBuffer->cbBuffer);
@@ -643,7 +648,7 @@ int TestNTLM(int argc, char* argv[])
if (status < 0)
{
printf("test_ntlm_client_authenticate failure\n");
- return -1;
+ goto fail;
}
pSecBuffer = &(client->outputBuffer[0]);
@@ -656,7 +661,7 @@ int TestNTLM(int argc, char* argv[])
if (!pSecBuffer->pvBuffer)
{
printf("Memory allocation failed\n");
- return -1;
+ goto fail;
}
CopyMemory(pSecBuffer->pvBuffer, TEST_NTLM_AUTHENTICATE, pSecBuffer->cbBuffer);
@@ -676,13 +681,16 @@ int TestNTLM(int argc, char* argv[])
if (status < 0)
{
printf("test_ntlm_server_authenticate failure\n");
- return -1;
+ goto fail;
}
+ rc = 0;
+
+fail:
/**
* Cleanup & Termination
*/
test_ntlm_client_free(client);
test_ntlm_server_free(server);
- return 0;
+ return rc;
}
diff --git a/winpr/libwinpr/timezone/timezone.c b/winpr/libwinpr/timezone/timezone.c
index 80bc51c2a..5475cb67a 100644
--- a/winpr/libwinpr/timezone/timezone.c
+++ b/winpr/libwinpr/timezone/timezone.c
@@ -248,12 +248,14 @@ static BOOL winpr_match_unix_timezone_identifier_with_list(const char* tzid, con
{
char* p;
char* list_copy;
+ char* context = NULL;
+
list_copy = _strdup(list);
if (!list_copy)
return FALSE;
- p = strtok(list_copy, " ");
+ p = strtok_s(list_copy, " ", &context);
while (p != NULL)
{
@@ -263,7 +265,7 @@ static BOOL winpr_match_unix_timezone_identifier_with_list(const char* tzid, con
return TRUE;
}
- p = strtok(NULL, " ");
+ p = strtok_s(NULL, " ", &context);
}
free(list_copy);
diff --git a/winpr/libwinpr/utils/collections/PubSub.c b/winpr/libwinpr/utils/collections/PubSub.c
index f0a19485f..466dde689 100644
--- a/winpr/libwinpr/utils/collections/PubSub.c
+++ b/winpr/libwinpr/utils/collections/PubSub.c
@@ -112,15 +112,10 @@ int PubSub_Subscribe(wPubSub* pubSub, const char* EventName, pEventHandler Event
{
status = 0;
- if (event->EventHandlerCount <= MAX_EVENT_HANDLERS)
- {
- event->EventHandlers[event->EventHandlerCount] = EventHandler;
- event->EventHandlerCount++;
- }
+ if (event->EventHandlerCount < MAX_EVENT_HANDLERS)
+ event->EventHandlers[event->EventHandlerCount++] = EventHandler;
else
- {
status = -1;
- }
}
if (pubSub->synchronized)
diff --git a/winpr/libwinpr/utils/ini.c b/winpr/libwinpr/utils/ini.c
index e1a20e716..656ca6acf 100644
--- a/winpr/libwinpr/utils/ini.c
+++ b/winpr/libwinpr/utils/ini.c
@@ -206,6 +206,16 @@ static char* IniFile_Load_GetNextLine(wIniFile* ini)
return ini->line;
}
+static void IniFile_Key_Free(wIniFileKey* key)
+{
+ if (!key)
+ return;
+
+ free(key->name);
+ free(key->value);
+ free(key);
+}
+
static wIniFileKey* IniFile_Key_New(const char* name, const char* value)
{
wIniFileKey* key;
@@ -222,9 +232,7 @@ static wIniFileKey* IniFile_Key_New(const char* name, const char* value)
if (!key->name || !key->value)
{
- free(key->name);
- free(key->value);
- free(key);
+ IniFile_Key_Free(key);
return NULL;
}
}
@@ -232,16 +240,6 @@ static wIniFileKey* IniFile_Key_New(const char* name, const char* value)
return key;
}
-static void IniFile_Key_Free(wIniFileKey* key)
-{
- if (!key)
- return;
-
- free(key->name);
- free(key->value);
- free(key);
-}
-
static wIniFileSection* IniFile_Section_New(const char* name)
{
wIniFileSection* section;
@@ -821,5 +819,6 @@ void IniFile_Free(wIniFile* ini)
IniFile_Section_Free(ini->sections[index]);
free(ini->sections);
+ free(ini->buffer);
free(ini);
}
diff --git a/winpr/libwinpr/utils/lodepng/lodepng.c b/winpr/libwinpr/utils/lodepng/lodepng.c
index 227d46906..87f85080e 100644
--- a/winpr/libwinpr/utils/lodepng/lodepng.c
+++ b/winpr/libwinpr/utils/lodepng/lodepng.c
@@ -327,7 +327,8 @@ static void string_set(char** out, const char* in)
static unsigned lodepng_read32bitInt(const unsigned char* buffer)
{
- return (unsigned)((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]);
+ return (unsigned)(((unsigned)buffer[0] << 24) | ((unsigned)buffer[1] << 16) |
+ ((unsigned)buffer[2] << 8) | buffer[3]);
}
#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)
diff --git a/winpr/libwinpr/utils/sam.c b/winpr/libwinpr/utils/sam.c
index b76302477..b4af5b34b 100644
--- a/winpr/libwinpr/utils/sam.c
+++ b/winpr/libwinpr/utils/sam.c
@@ -43,6 +43,15 @@
#endif
#define TAG WINPR_TAG("utils")
+struct winpr_sam
+{
+ FILE* fp;
+ char* line;
+ char* buffer;
+ char* context;
+ BOOL readOnly;
+};
+
WINPR_SAM* SamOpen(const char* filename, BOOL readOnly)
{
FILE* fp = NULL;
@@ -98,6 +107,7 @@ static BOOL SamLookupStart(WINPR_SAM* sam)
if (fileSize < 1)
return FALSE;
+ sam->context = NULL;
sam->buffer = (char*)malloc(fileSize + 2);
if (!sam->buffer)
@@ -120,7 +130,7 @@ static BOOL SamLookupStart(WINPR_SAM* sam)
sam->buffer[fileSize] = '\n';
sam->buffer[fileSize + 1] = '\0';
- sam->line = strtok(sam->buffer, "\n");
+ sam->line = strtok_s(sam->buffer, "\n", &sam->context);
return TRUE;
}
@@ -300,7 +310,7 @@ WINPR_SAM_ENTRY* SamLookupUserA(WINPR_SAM* sam, LPSTR User, UINT32 UserLength, L
}
SamResetEntry(entry);
- sam->line = strtok(NULL, "\n");
+ sam->line = strtok_s(NULL, "\n", &sam->context);
}
out_fail:
@@ -415,7 +425,7 @@ WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength,
}
SamResetEntry(entry);
- sam->line = strtok(NULL, "\n");
+ sam->line = strtok_s(NULL, "\n", &sam->context);
}
out_fail:
diff --git a/winpr/libwinpr/utils/test/TestIni.c b/winpr/libwinpr/utils/test/TestIni.c
index 9734072fd..9a07769d7 100644
--- a/winpr/libwinpr/utils/test/TestIni.c
+++ b/winpr/libwinpr/utils/test/TestIni.c
@@ -38,40 +38,48 @@ const char TEST_INI_03[] = "[FreeRDS]\n"
int TestIni(int argc, char* argv[])
{
+ int rc = -1;
int i, j;
int nKeys;
int nSections;
UINT32 iValue;
- wIniFile* ini;
+ wIniFile* ini = NULL;
const char* sValue;
- char** keyNames;
- char** sectionNames;
+ char** keyNames = NULL;
+ char** sectionNames = NULL;
/* First Sample */
ini = IniFile_New();
- IniFile_ReadBuffer(ini, TEST_INI_01);
+ if (!ini)
+ goto fail;
+
+ if (IniFile_ReadBuffer(ini, TEST_INI_01) < 0)
+ goto fail;
+
+ free(sectionNames);
sectionNames = IniFile_GetSectionNames(ini, &nSections);
+ if (!sectionNames && (nSections > 0))
+ goto fail;
for (i = 0; i < nSections; i++)
{
+ free(keyNames);
keyNames = IniFile_GetSectionKeyNames(ini, sectionNames[i], &nKeys);
printf("[%s]\n", sectionNames[i]);
-
+ if (!keyNames && (nKeys > 0))
+ goto fail;
for (j = 0; j < nKeys; j++)
{
sValue = IniFile_GetKeyValueString(ini, sectionNames[i], keyNames[j]);
printf("%s = %s\n", keyNames[j], sValue);
}
-
- free(keyNames);
}
- free(sectionNames);
iValue = IniFile_GetKeyValueInt(ini, "first_section", "one");
if (iValue != 1)
{
printf("IniFile_GetKeyValueInt failure\n");
- return -1;
+ goto fail;
}
iValue = IniFile_GetKeyValueInt(ini, "first_section", "five");
@@ -79,7 +87,7 @@ int TestIni(int argc, char* argv[])
if (iValue != 5)
{
printf("IniFile_GetKeyValueInt failure\n");
- return -1;
+ goto fail;
}
sValue = IniFile_GetKeyValueString(ini, "first_section", "animal");
@@ -87,7 +95,7 @@ int TestIni(int argc, char* argv[])
if (strcmp(sValue, "BIRD") != 0)
{
printf("IniFile_GetKeyValueString failure\n");
- return -1;
+ goto fail;
}
sValue = IniFile_GetKeyValueString(ini, "second_section", "path");
@@ -95,7 +103,7 @@ int TestIni(int argc, char* argv[])
if (strcmp(sValue, "/usr/local/bin") != 0)
{
printf("IniFile_GetKeyValueString failure\n");
- return -1;
+ goto fail;
}
sValue = IniFile_GetKeyValueString(ini, "second_section", "URL");
@@ -103,40 +111,47 @@ int TestIni(int argc, char* argv[])
if (strcmp(sValue, "http://www.example.com/~username") != 0)
{
printf("IniFile_GetKeyValueString failure\n");
- return -1;
+ goto fail;
}
IniFile_Free(ini);
/* Second Sample */
ini = IniFile_New();
- IniFile_ReadBuffer(ini, TEST_INI_02);
+ if (!ini)
+ goto fail;
+ if (IniFile_ReadBuffer(ini, TEST_INI_02) < 0)
+ goto fail;
+ free(sectionNames);
sectionNames = IniFile_GetSectionNames(ini, &nSections);
+ if (!sectionNames && (nSections > 0))
+ goto fail;
for (i = 0; i < nSections; i++)
{
+ free(keyNames);
keyNames = IniFile_GetSectionKeyNames(ini, sectionNames[i], &nKeys);
printf("[%s]\n", sectionNames[i]);
+ if (!keyNames && (nKeys > 0))
+ goto fail;
for (j = 0; j < nKeys; j++)
{
sValue = IniFile_GetKeyValueString(ini, sectionNames[i], keyNames[j]);
printf("%s = %s\n", keyNames[j], sValue);
}
-
- free(keyNames);
}
- free(sectionNames);
IniFile_Free(ini);
/* Third sample - invalid input */
ini = IniFile_New();
if (IniFile_ReadBuffer(ini, TEST_INI_03) != -1)
- {
- IniFile_Free(ini);
- return -1;
- }
+ goto fail;
+ rc = 0;
+fail:
+ free(keyNames);
+ free(sectionNames);
IniFile_Free(ini);
return 0;
}
diff --git a/winpr/tools/makecert-cli/winpr-makecert.1.in b/winpr/tools/makecert-cli/winpr-makecert.1.in
index 57be0ffbb..9478b5212 100644
--- a/winpr/tools/makecert-cli/winpr-makecert.1.in
+++ b/winpr/tools/makecert-cli/winpr-makecert.1.in
@@ -106,7 +106,7 @@ The certificate has the serial number 22 and is valid for 12 years (144 months).
Successful program execution.
.TP
.B 1
-Otherweise.
+Otherwise.
.SH SEE ALSO