summaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--channels/audin/client/alsa/audin_alsa.c2
-rw-r--r--channels/audin/client/oss/CMakeLists.txt7
-rw-r--r--channels/audin/client/oss/audin_oss.c27
-rw-r--r--channels/client/addin.c9
-rw-r--r--channels/client/generic_dynvc.c2
-rw-r--r--channels/cliprdr/client/cliprdr_main.c3
-rw-r--r--channels/cliprdr/cliprdr_common.c2
-rw-r--r--channels/cliprdr/server/cliprdr_main.c4
-rw-r--r--channels/drdynvc/client/drdynvc_main.c34
-rw-r--r--channels/drive/client/drive_main.c2
-rw-r--r--channels/location/CMakeLists.txt4
-rw-r--r--channels/location/ChannelOptions.cmake3
-rw-r--r--channels/location/client/CMakeLists.txt30
-rw-r--r--channels/location/client/location_main.c473
-rw-r--r--channels/parallel/client/parallel_main.c26
-rw-r--r--channels/printer/client/printer_main.c126
-rw-r--r--channels/printer/client/win/printer_win.c5
-rw-r--r--channels/rail/client/rail_orders.c7
-rw-r--r--channels/rail/rail_common.c28
-rw-r--r--channels/rdpdr/client/rdpdr_main.c6
-rw-r--r--channels/rdpdr/server/rdpdr_main.c9
-rw-r--r--channels/rdpecam/CMakeLists.txt4
-rw-r--r--channels/rdpecam/ChannelOptions.cmake1
-rw-r--r--channels/rdpecam/client/CMakeLists.txt0
-rw-r--r--channels/rdpgfx/client/rdpgfx_main.c1
-rw-r--r--channels/rdpsnd/client/alsa/rdpsnd_alsa.c16
-rw-r--r--channels/rdpsnd/client/oss/CMakeLists.txt6
-rw-r--r--channels/rdpsnd/client/oss/rdpsnd_oss.c24
-rw-r--r--channels/rdpsnd/client/pulse/rdpsnd_pulse.c2
-rw-r--r--channels/server/CMakeLists.txt5
-rw-r--r--channels/urbdrc/client/data_transfer.c3
-rw-r--r--channels/urbdrc/client/libusb/libusb_udevice.c2
32 files changed, 748 insertions, 125 deletions
diff --git a/channels/audin/client/alsa/audin_alsa.c b/channels/audin/client/alsa/audin_alsa.c
index be3e52a..b1edb82 100644
--- a/channels/audin/client/alsa/audin_alsa.c
+++ b/channels/audin/client/alsa/audin_alsa.c
@@ -55,7 +55,7 @@ typedef struct
rdpContext* rdpcontext;
wLog* log;
- int bytes_per_frame;
+ size_t bytes_per_frame;
} AudinALSADevice;
static snd_pcm_format_t audin_alsa_format(UINT32 wFormatTag, UINT32 bitPerChannel)
diff --git a/channels/audin/client/oss/CMakeLists.txt b/channels/audin/client/oss/CMakeLists.txt
index 6b747e4..5b4dac9 100644
--- a/channels/audin/client/oss/CMakeLists.txt
+++ b/channels/audin/client/oss/CMakeLists.txt
@@ -30,7 +30,12 @@ set(${MODULE_PREFIX}_LIBS
)
include_directories(..)
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${OSS_INCLUDE_DIRS})
-
+configure_file(
+ ${CMAKE_SOURCE_DIR}/cmake/oss-includes.h.in
+ ${CMAKE_CURRENT_BINARY_DIR}/oss-includes.h
+ @ONLY
+)
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
diff --git a/channels/audin/client/oss/audin_oss.c b/channels/audin/client/oss/audin_oss.c
index 979a800..c42c089 100644
--- a/channels/audin/client/oss/audin_oss.c
+++ b/channels/audin/client/oss/audin_oss.c
@@ -37,11 +37,7 @@
#include <libgen.h>
#include <limits.h>
#include <unistd.h>
-#if defined(__OpenBSD__)
-#include <soundcard.h>
-#else
-#include <sys/soundcard.h>
-#endif
+#include <oss-includes.h>
#include <sys/ioctl.h>
#include <freerdp/freerdp.h>
@@ -67,15 +63,15 @@ typedef struct
rdpContext* rdpcontext;
} AudinOSSDevice;
-#define OSS_LOG_ERR(_text, _error) \
- do \
- { \
- if (_error != 0) \
- { \
- char buffer[256] = { 0 }; \
- WLog_ERR(TAG, "%s: %i - %s\n", _text, _error, \
- winpr_strerror(_error, buffer, sizeof(buffer))); \
- } \
+#define OSS_LOG_ERR(_text, _error) \
+ do \
+ { \
+ if ((_error) != 0) \
+ { \
+ char buffer[256] = { 0 }; \
+ WLog_ERR(TAG, "%s: %i - %s\n", (_text), (_error), \
+ winpr_strerror((_error), buffer, sizeof(buffer))); \
+ } \
} while (0)
static UINT32 audin_oss_get_format(const AUDIO_FORMAT* format)
@@ -233,7 +229,8 @@ static DWORD WINAPI audin_oss_thread_func(LPVOID arg)
if (ioctl(pcm_handle, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1)
OSS_LOG_ERR("SNDCTL_DSP_SETFRAGMENT failed", errno);
- buffer_size = (oss->FramesPerPacket * oss->format.nChannels * (oss->format.wBitsPerSample / 8));
+ buffer_size =
+ (1ull * oss->FramesPerPacket * oss->format.nChannels * (oss->format.wBitsPerSample / 8ull));
buffer = (BYTE*)calloc((buffer_size + sizeof(void*)), sizeof(BYTE));
if (NULL == buffer)
diff --git a/channels/client/addin.c b/channels/client/addin.c
index 6d87f6c..2f3b990 100644
--- a/channels/client/addin.c
+++ b/channels/client/addin.c
@@ -104,19 +104,19 @@ static FREERDP_ADDIN** freerdp_channels_list_client_static_addins(LPCSTR pszName
for (size_t i = 0; CLIENT_STATIC_ADDIN_TABLE[i].name != NULL; i++)
{
FREERDP_ADDIN* pAddin = (FREERDP_ADDIN*)calloc(1, sizeof(FREERDP_ADDIN));
-
+ const STATIC_ADDIN_TABLE* table = &CLIENT_STATIC_ADDIN_TABLE[i];
if (!pAddin)
{
WLog_ERR(TAG, "calloc failed!");
goto error_out;
}
- sprintf_s(pAddin->cName, ARRAYSIZE(pAddin->cName), "%s", CLIENT_STATIC_ADDIN_TABLE[i].name);
+ sprintf_s(pAddin->cName, ARRAYSIZE(pAddin->cName), "%s", table->name);
pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
pAddin->dwFlags |= FREERDP_ADDIN_STATIC;
pAddin->dwFlags |= FREERDP_ADDIN_NAME;
ppAddins[nAddins++] = pAddin;
- subsystems = (const STATIC_SUBSYSTEM_ENTRY*)CLIENT_STATIC_ADDIN_TABLE[i].table;
+ subsystems = table->table;
for (size_t j = 0; subsystems[j].name != NULL; j++)
{
@@ -128,8 +128,7 @@ static FREERDP_ADDIN** freerdp_channels_list_client_static_addins(LPCSTR pszName
goto error_out;
}
- sprintf_s(pAddin->cName, ARRAYSIZE(pAddin->cName), "%s",
- CLIENT_STATIC_ADDIN_TABLE[i].name);
+ sprintf_s(pAddin->cName, ARRAYSIZE(pAddin->cName), "%s", table->name);
sprintf_s(pAddin->cSubsystem, ARRAYSIZE(pAddin->cSubsystem), "%s", subsystems[j].name);
pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
pAddin->dwFlags |= FREERDP_ADDIN_STATIC;
diff --git a/channels/client/generic_dynvc.c b/channels/client/generic_dynvc.c
index 263b5ce..6221470 100644
--- a/channels/client/generic_dynvc.c
+++ b/channels/client/generic_dynvc.c
@@ -53,6 +53,8 @@ static UINT generic_on_new_channel_connection(IWTSListenerCallback* pListenerCal
callback->channel = pChannel;
listener_callback->channel_callback = callback;
+ listener_callback->channel = pChannel;
+
*ppCallback = (IWTSVirtualChannelCallback*)callback;
return CHANNEL_RC_OK;
}
diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c
index 60ae27d..68eeb82 100644
--- a/channels/cliprdr/client/cliprdr_main.c
+++ b/channels/cliprdr/client/cliprdr_main.c
@@ -654,7 +654,10 @@ static UINT cliprdr_temp_directory(CliprdrClientContext* context,
if (Stream_Write_UTF16_String_From_UTF8(s, tmpDirCharLen - 1, tempDirectory->szTempDir,
ARRAYSIZE(tempDirectory->szTempDir), TRUE) < 0)
+ {
+ Stream_Free(s, TRUE);
return ERROR_INTERNAL_ERROR;
+ }
/* Path must be 260 UTF16 characters with '\0' termination.
* ensure this here */
Stream_Write_UINT16(s, 0);
diff --git a/channels/cliprdr/cliprdr_common.c b/channels/cliprdr/cliprdr_common.c
index d346cb1..f587f30 100644
--- a/channels/cliprdr/cliprdr_common.c
+++ b/channels/cliprdr/cliprdr_common.c
@@ -388,7 +388,7 @@ 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 = 0;
- int formatNameLength = 0;
+ size_t formatNameLength = 0;
const char* szFormatName = NULL;
const WCHAR* wszFormatName = NULL;
wStream sub1buffer = { 0 };
diff --git a/channels/cliprdr/server/cliprdr_main.c b/channels/cliprdr/server/cliprdr_main.c
index 9823f17..23a4331 100644
--- a/channels/cliprdr/server/cliprdr_main.c
+++ b/channels/cliprdr/server/cliprdr_main.c
@@ -119,7 +119,6 @@ static UINT cliprdr_server_capabilities(CliprdrServerContext* context,
const CLIPRDR_CAPABILITIES* capabilities)
{
size_t offset = 0;
- wStream* s = NULL;
WINPR_ASSERT(context);
WINPR_ASSERT(capabilities);
@@ -135,7 +134,7 @@ static UINT cliprdr_server_capabilities(CliprdrServerContext* context,
return ERROR_INVALID_PARAMETER;
}
- s = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN);
+ wStream* s = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN);
if (!s)
{
@@ -173,6 +172,7 @@ static UINT cliprdr_server_capabilities(CliprdrServerContext* context,
if (!Stream_SafeSeek(s, cap->capabilitySetLength))
{
WLog_ERR(TAG, "short stream");
+ Stream_Free(s, TRUE);
return ERROR_NO_DATA;
}
break;
diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c
index 0b85c0f..968d7e2 100644
--- a/channels/drdynvc/client/drdynvc_main.c
+++ b/channels/drdynvc/client/drdynvc_main.c
@@ -396,14 +396,13 @@ static void dvcman_channel_free(DVCMAN_CHANNEL* channel)
static void dvcman_channel_unref(DVCMAN_CHANNEL* channel)
{
- DVCMAN* dvcman = NULL;
-
WINPR_ASSERT(channel);
if (InterlockedDecrement(&channel->refCounter))
return;
- dvcman = channel->dvcman;
- HashTable_Remove(dvcman->channelsById, &channel->channel_id);
+ DVCMAN* dvcman = channel->dvcman;
+ if (dvcman)
+ HashTable_Remove(dvcman->channelsById, &channel->channel_id);
}
static UINT dvcchannel_send_close(DVCMAN_CHANNEL* channel)
@@ -457,7 +456,6 @@ static UINT dvcman_call_on_receive(DVCMAN_CHANNEL* channel, wStream* data)
static UINT dvcman_channel_close(DVCMAN_CHANNEL* channel, BOOL perRequest, BOOL fromHashTableFn)
{
UINT error = CHANNEL_RC_OK;
- drdynvcPlugin* drdynvc = NULL;
DrdynvcClientContext* context = NULL;
WINPR_ASSERT(channel);
@@ -466,20 +464,24 @@ static UINT dvcman_channel_close(DVCMAN_CHANNEL* channel, BOOL perRequest, BOOL
case DVC_CHANNEL_INIT:
break;
case DVC_CHANNEL_RUNNING:
- drdynvc = channel->dvcman->drdynvc;
- context = drdynvc->context;
- if (perRequest)
- WLog_Print(drdynvc->log, WLOG_DEBUG, "sending close confirm for '%s'",
- channel->channel_name);
-
- error = dvcchannel_send_close(channel);
- if (error != CHANNEL_RC_OK)
+ if (channel->dvcman)
{
- const char* msg = "error when sending close confirm for '%s'";
+ drdynvcPlugin* drdynvc = channel->dvcman->drdynvc;
+ WINPR_ASSERT(drdynvc);
+ context = drdynvc->context;
if (perRequest)
- msg = "error when sending closeRequest for '%s'";
+ WLog_Print(drdynvc->log, WLOG_DEBUG, "sending close confirm for '%s'",
+ channel->channel_name);
- WLog_Print(drdynvc->log, WLOG_DEBUG, msg, channel->channel_name);
+ error = dvcchannel_send_close(channel);
+ if (error != CHANNEL_RC_OK)
+ {
+ const char* msg = "error when sending close confirm for '%s'";
+ if (perRequest)
+ msg = "error when sending closeRequest for '%s'";
+
+ WLog_Print(drdynvc->log, WLOG_DEBUG, msg, channel->channel_name);
+ }
}
channel->state = DVC_CHANNEL_CLOSED;
diff --git a/channels/drive/client/drive_main.c b/channels/drive/client/drive_main.c
index 0fdc2e0..04f8d83 100644
--- a/channels/drive/client/drive_main.c
+++ b/channels/drive/client/drive_main.c
@@ -511,7 +511,7 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
/* http://msdn.microsoft.com/en-us/library/cc232101.aspx */
const WCHAR* diskType =
InitializeConstWCharFromUtf8("FAT32", LabelBuffer, ARRAYSIZE(LabelBuffer));
- const size_t diskTypeLen = (wcslen(diskType) + 1) * sizeof(WCHAR);
+ const size_t diskTypeLen = (_wcslen(diskType) + 1) * sizeof(WCHAR);
const size_t length = 12ul + diskTypeLen;
Stream_Write_UINT32(output, length); /* Length */
diff --git a/channels/location/CMakeLists.txt b/channels/location/CMakeLists.txt
index 5e77fcb..fbf920c 100644
--- a/channels/location/CMakeLists.txt
+++ b/channels/location/CMakeLists.txt
@@ -17,6 +17,10 @@
define_channel("location")
+if(WITH_CLIENT_CHANNELS)
+ add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
+endif()
+
if(WITH_SERVER_CHANNELS)
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()
diff --git a/channels/location/ChannelOptions.cmake b/channels/location/ChannelOptions.cmake
index 11f5e30..acffc26 100644
--- a/channels/location/ChannelOptions.cmake
+++ b/channels/location/ChannelOptions.cmake
@@ -1,6 +1,6 @@
set(OPTION_DEFAULT ON)
-set(OPTION_CLIENT_DEFAULT OFF)
+set(OPTION_CLIENT_DEFAULT ON)
set(OPTION_SERVER_DEFAULT ON)
define_channel_options(NAME "location" TYPE "dynamic"
@@ -8,5 +8,6 @@ define_channel_options(NAME "location" TYPE "dynamic"
SPECIFICATIONS "[MS-RDPEL]"
DEFAULT ${OPTION_DEFAULT})
+define_channel_client_options(${OPTION_CLIENT_DEFAULT})
define_channel_server_options(${OPTION_SERVER_DEFAULT})
diff --git a/channels/location/client/CMakeLists.txt b/channels/location/client/CMakeLists.txt
new file mode 100644
index 0000000..3c5a05a
--- /dev/null
+++ b/channels/location/client/CMakeLists.txt
@@ -0,0 +1,30 @@
+# FreeRDP: A Remote Desktop Protocol Implementation
+# FreeRDP cmake build script
+#
+# Copyright 2024 Armin Novak <anovak@thincast.com>
+# Copyright 2024 Thincast Technologies GmbH
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+define_channel_client("location")
+
+set(${MODULE_PREFIX}_SRCS
+ location_main.c
+)
+
+set(${MODULE_PREFIX}_LIBS
+ winpr
+)
+include_directories(..)
+
+add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")
diff --git a/channels/location/client/location_main.c b/channels/location/client/location_main.c
new file mode 100644
index 0000000..281070f
--- /dev/null
+++ b/channels/location/client/location_main.c
@@ -0,0 +1,473 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Location Virtual Channel Extension
+ *
+ * Copyright 2024 Armin Novak <anovak@thincast.com>
+ * Copyright 2024 Thincast Technologies GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <freerdp/config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <float.h>
+#include <math.h>
+
+#include <winpr/crt.h>
+#include <winpr/assert.h>
+#include <winpr/stream.h>
+
+#include <freerdp/client/channels.h>
+#include <freerdp/channels/log.h>
+#include <freerdp/channels/location.h>
+#include <freerdp/client/location.h>
+#include <freerdp/utils/encoded_types.h>
+
+#define TAG CHANNELS_TAG("location.client")
+
+/* implement [MS-RDPEL]
+ * https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpel/4397a0af-c821-4b75-9068-476fb579c327
+ */
+typedef struct
+{
+ GENERIC_DYNVC_PLUGIN baseDynPlugin;
+ LocationClientContext context;
+} LOCATION_PLUGIN;
+
+typedef struct
+{
+ GENERIC_CHANNEL_CALLBACK baseCb;
+ UINT32 serverVersion;
+ UINT32 clientVersion;
+ UINT32 serverFlags;
+ UINT32 clientFlags;
+} LOCATION_CALLBACK;
+
+static BOOL location_read_header(wLog* log, wStream* s, UINT16* ppduType, UINT32* ppduLength)
+{
+ WINPR_ASSERT(log);
+ WINPR_ASSERT(s);
+ WINPR_ASSERT(ppduType);
+ WINPR_ASSERT(ppduLength);
+
+ if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 6))
+ return FALSE;
+ Stream_Read_UINT16(s, *ppduType);
+ Stream_Read_UINT32(s, *ppduLength);
+ if (*ppduLength < 6)
+ {
+ WLog_Print(log, WLOG_ERROR,
+ "RDPLOCATION_HEADER::pduLengh=%" PRIu16 " < sizeof(RDPLOCATION_HEADER)[6]",
+ *ppduLength);
+ return FALSE;
+ }
+ return Stream_CheckAndLogRequiredLengthWLog(log, s, *ppduLength - 6ull);
+}
+
+static BOOL location_write_header(wStream* s, UINT16 pduType, UINT32 pduLength)
+{
+ if (!Stream_EnsureRemainingCapacity(s, 6))
+ return FALSE;
+ Stream_Write_UINT16(s, pduType);
+ Stream_Write_UINT32(s, pduLength + 6);
+ return Stream_EnsureRemainingCapacity(s, pduLength);
+}
+
+static BOOL location_read_server_ready_pdu(LOCATION_CALLBACK* callback, wStream* s, UINT16 pduSize)
+{
+ if (pduSize < 6 + 4)
+ return FALSE; // Short message
+
+ Stream_Read_UINT32(s, callback->serverVersion);
+ if (pduSize >= 6 + 4 + 4)
+ Stream_Read_UINT32(s, callback->serverFlags);
+ return TRUE;
+}
+
+static UINT location_channel_send(IWTSVirtualChannel* channel, wStream* s)
+{
+ const size_t len = Stream_GetPosition(s);
+ Stream_SetPosition(s, 2);
+ Stream_Write_UINT32(s, len);
+
+ WINPR_ASSERT(channel);
+ WINPR_ASSERT(channel->Write);
+ return channel->Write(channel, len, Stream_Buffer(s), NULL);
+}
+
+static UINT location_send_client_ready_pdu(const LOCATION_CALLBACK* callback)
+{
+ wStream sbuffer = { 0 };
+ char buffer[32] = { 0 };
+ wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
+ WINPR_ASSERT(s);
+
+ if (!location_write_header(s, PDUTYPE_CLIENT_READY, 8))
+ return ERROR_OUTOFMEMORY;
+
+ Stream_Write_UINT32(s, callback->clientVersion);
+ Stream_Write_UINT32(s, callback->clientFlags);
+ return location_channel_send(callback->baseCb.channel, s);
+}
+
+static const char* location_version_str(UINT32 version, char* buffer, size_t size)
+{
+ const char* str = NULL;
+ switch (version)
+ {
+ case RDPLOCATION_PROTOCOL_VERSION_100:
+ str = "RDPLOCATION_PROTOCOL_VERSION_100";
+ break;
+ case RDPLOCATION_PROTOCOL_VERSION_200:
+ str = "RDPLOCATION_PROTOCOL_VERSION_200";
+ break;
+ default:
+ str = "RDPLOCATION_PROTOCOL_VERSION_UNKNOWN";
+ break;
+ }
+
+ _snprintf(buffer, size, "%s [0x%08" PRIx32 "]", str, version);
+ return buffer;
+}
+
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+static UINT location_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data)
+{
+ LOCATION_CALLBACK* callback = (LOCATION_CALLBACK*)pChannelCallback;
+
+ WINPR_ASSERT(callback);
+
+ LOCATION_PLUGIN* plugin = (LOCATION_PLUGIN*)callback->baseCb.plugin;
+ WINPR_ASSERT(plugin);
+
+ UINT16 pduType = 0;
+ UINT32 pduLength = 0;
+ if (!location_read_header(plugin->baseDynPlugin.log, data, &pduType, &pduLength))
+ return ERROR_INVALID_DATA;
+
+ switch (pduType)
+ {
+ case PDUTYPE_SERVER_READY:
+ if (!location_read_server_ready_pdu(callback, data, pduLength))
+ return ERROR_INVALID_DATA;
+
+ switch (callback->serverVersion)
+ {
+ case RDPLOCATION_PROTOCOL_VERSION_200:
+ callback->clientVersion = RDPLOCATION_PROTOCOL_VERSION_200;
+ break;
+ case RDPLOCATION_PROTOCOL_VERSION_100:
+ callback->clientVersion = RDPLOCATION_PROTOCOL_VERSION_100;
+ break;
+ default:
+ callback->clientVersion = RDPLOCATION_PROTOCOL_VERSION_100;
+ if (callback->serverVersion > RDPLOCATION_PROTOCOL_VERSION_200)
+ callback->clientVersion = RDPLOCATION_PROTOCOL_VERSION_200;
+ break;
+ }
+
+ char cbuffer[64] = { 0 };
+ char sbuffer[64] = { 0 };
+ WLog_Print(plugin->baseDynPlugin.log, WLOG_DEBUG,
+ "Server version %s, client version %s",
+ location_version_str(callback->serverVersion, sbuffer, sizeof(sbuffer)),
+ location_version_str(callback->clientVersion, cbuffer, sizeof(cbuffer)));
+
+ if (!plugin->context.LocationStart)
+ {
+ WLog_Print(plugin->baseDynPlugin.log, WLOG_WARN,
+ "LocationStart=NULL, no location data will be sent");
+ return CHANNEL_RC_OK;
+ }
+ const UINT res =
+ plugin->context.LocationStart(&plugin->context, callback->clientVersion, 0);
+ if (res != CHANNEL_RC_OK)
+ return res;
+ return location_send_client_ready_pdu(callback);
+ default:
+ WLog_WARN(TAG, "invalid pduType=%s");
+ return ERROR_INVALID_DATA;
+ }
+}
+
+static UINT location_send_base_location3d(IWTSVirtualChannel* channel,
+ const RDPLOCATION_BASE_LOCATION3D_PDU* pdu)
+{
+ wStream sbuffer = { 0 };
+ char buffer[32] = { 0 };
+ wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
+ WINPR_ASSERT(s);
+ WINPR_ASSERT(channel);
+ WINPR_ASSERT(pdu);
+
+ if (pdu->source)
+ WLog_DBG(TAG,
+ "latitude=%lf, logitude=%lf, altitude=%" PRId32
+ ", speed=%lf, heading=%lf, haccuracy=%lf, source=%" PRIu8,
+ pdu->latitude, pdu->longitude, pdu->altitude, pdu->speed, pdu->heading,
+ pdu->horizontalAccuracy, *pdu->source);
+ else
+ WLog_DBG(TAG, "latitude=%lf, logitude=%lf, altitude=%" PRId32, pdu->latitude,
+ pdu->longitude, pdu->altitude);
+
+ if (!location_write_header(s, PDUTYPE_BASE_LOCATION3D, pdu->source ? 25 : 12))
+ return ERROR_OUTOFMEMORY;
+
+ if (!freerdp_write_four_byte_float(s, pdu->latitude) ||
+ !freerdp_write_four_byte_float(s, pdu->longitude) ||
+ !freerdp_write_four_byte_signed_integer(s, pdu->altitude))
+ return ERROR_INTERNAL_ERROR;
+
+ if (pdu->source)
+ {
+ if (!freerdp_write_four_byte_float(s, *pdu->speed) ||
+ !freerdp_write_four_byte_float(s, *pdu->heading) ||
+ !freerdp_write_four_byte_float(s, *pdu->horizontalAccuracy))
+ return ERROR_INTERNAL_ERROR;
+
+ Stream_Write_UINT8(s, *pdu->source);
+ }
+
+ return location_channel_send(channel, s);
+}
+
+static UINT location_send_location2d_delta(IWTSVirtualChannel* channel,
+ const RDPLOCATION_LOCATION2D_DELTA_PDU* pdu)
+{
+ wStream sbuffer = { 0 };
+ char buffer[32] = { 0 };
+ wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
+ WINPR_ASSERT(s);
+
+ WINPR_ASSERT(channel);
+ WINPR_ASSERT(pdu);
+
+ const BOOL ext = pdu->speedDelta && pdu->headingDelta;
+
+ if (ext)
+ WLog_DBG(TAG, "latitude=%lf, logitude=%lf, speed=%lf, heading=%lf", pdu->latitudeDelta,
+ pdu->longitudeDelta, pdu->speedDelta, pdu->headingDelta);
+ else
+ WLog_DBG(TAG, "latitude=%lf, logitude=%lf", pdu->latitudeDelta, pdu->longitudeDelta);
+
+ if (!location_write_header(s, PDUTYPE_LOCATION2D_DELTA, ext ? 16 : 8))
+ return ERROR_OUTOFMEMORY;
+
+ if (!freerdp_write_four_byte_float(s, pdu->latitudeDelta) ||
+ !freerdp_write_four_byte_float(s, pdu->longitudeDelta))
+ return ERROR_INTERNAL_ERROR;
+
+ if (ext)
+ {
+ if (!freerdp_write_four_byte_float(s, *pdu->speedDelta) ||
+ !freerdp_write_four_byte_float(s, *pdu->headingDelta))
+ return ERROR_INTERNAL_ERROR;
+ }
+
+ return location_channel_send(channel, s);
+}
+
+static UINT location_send_location3d_delta(IWTSVirtualChannel* channel,
+ const RDPLOCATION_LOCATION3D_DELTA_PDU* pdu)
+{
+ wStream sbuffer = { 0 };
+ char buffer[32] = { 0 };
+ wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
+ WINPR_ASSERT(s);
+
+ WINPR_ASSERT(channel);
+ WINPR_ASSERT(pdu);
+
+ const BOOL ext = pdu->speedDelta && pdu->headingDelta;
+
+ if (ext)
+ WLog_DBG(TAG, "latitude=%lf, logitude=%lf, altitude=%" PRId32 ", speed=%lf, heading=%lf",
+ pdu->latitudeDelta, pdu->longitudeDelta, pdu->altitudeDelta, pdu->speedDelta,
+ pdu->headingDelta);
+ else
+ WLog_DBG(TAG, "latitude=%lf, logitude=%lf, altitude=%" PRId32, pdu->latitudeDelta,
+ pdu->longitudeDelta, pdu->altitudeDelta);
+
+ if (!location_write_header(s, PDUTYPE_LOCATION3D_DELTA, ext ? 20 : 12))
+ return ERROR_OUTOFMEMORY;
+
+ if (!freerdp_write_four_byte_float(s, pdu->latitudeDelta) ||
+ !freerdp_write_four_byte_float(s, pdu->longitudeDelta) ||
+ !freerdp_write_four_byte_signed_integer(s, pdu->altitudeDelta))
+ return ERROR_INTERNAL_ERROR;
+
+ if (ext)
+ {
+ if (!freerdp_write_four_byte_float(s, *pdu->speedDelta) ||
+ !freerdp_write_four_byte_float(s, *pdu->headingDelta))
+ return ERROR_INTERNAL_ERROR;
+ }
+
+ return location_channel_send(channel, s);
+}
+
+static UINT location_send(LocationClientContext* context, LOCATION_PDUTYPE type, size_t count, ...)
+{
+ WINPR_ASSERT(context);
+
+ LOCATION_PLUGIN* loc = context->handle;
+ WINPR_ASSERT(loc);
+
+ GENERIC_LISTENER_CALLBACK* cb = loc->baseDynPlugin.listener_callback;
+ WINPR_ASSERT(cb);
+
+ IWTSVirtualChannel* channel = cb->channel;
+ WINPR_ASSERT(channel);
+
+ LOCATION_CALLBACK* callback = (LOCATION_CALLBACK*)loc->baseDynPlugin.channel_callbacks;
+ WINPR_ASSERT(callback);
+
+ UINT32 res = ERROR_INTERNAL_ERROR;
+ va_list ap;
+ va_start(ap, count);
+ switch (type)
+ {
+ case PDUTYPE_BASE_LOCATION3D:
+ if ((count != 3) && (count != 7))
+ res = ERROR_INVALID_PARAMETER;
+ else
+ {
+ RDPLOCATION_BASE_LOCATION3D_PDU pdu = { 0 };
+ LOCATIONSOURCE source = LOCATIONSOURCE_IP;
+ double speed = FP_NAN;
+ double heading = FP_NAN;
+ double horizontalAccuracy = FP_NAN;
+ pdu.latitude = va_arg(ap, double);
+ pdu.longitude = va_arg(ap, double);
+ pdu.altitude = va_arg(ap, INT32);
+ if ((count > 3) && (callback->clientVersion >= RDPLOCATION_PROTOCOL_VERSION_200))
+ {
+ speed = va_arg(ap, double);
+ heading = va_arg(ap, double);
+ horizontalAccuracy = va_arg(ap, double);
+ source = va_arg(ap, int);
+ pdu.speed = &speed;
+ pdu.heading = &heading;
+ pdu.horizontalAccuracy = &horizontalAccuracy;
+ pdu.source = &source;
+ }
+ res = location_send_base_location3d(channel, &pdu);
+ }
+ break;
+ case PDUTYPE_LOCATION2D_DELTA:
+ if ((count != 2) && (count != 4))
+ res = ERROR_INVALID_PARAMETER;
+ else
+ {
+ RDPLOCATION_LOCATION2D_DELTA_PDU pdu = { 0 };
+
+ pdu.latitudeDelta = va_arg(ap, double);
+ pdu.longitudeDelta = va_arg(ap, double);
+
+ double speedDelta = FP_NAN;
+ double headingDelta = FP_NAN;
+ if ((count > 2) && (callback->clientVersion >= RDPLOCATION_PROTOCOL_VERSION_200))
+ {
+ speedDelta = va_arg(ap, double);
+ headingDelta = va_arg(ap, double);
+ pdu.speedDelta = &speedDelta;
+ pdu.headingDelta = &headingDelta;
+ }
+ res = location_send_location2d_delta(channel, &pdu);
+ }
+ break;
+ case PDUTYPE_LOCATION3D_DELTA:
+ if ((count != 3) && (count != 5))
+ res = ERROR_INVALID_PARAMETER;
+ else
+ {
+ RDPLOCATION_LOCATION3D_DELTA_PDU pdu = { 0 };
+ double speedDelta = FP_NAN;
+ double headingDelta = FP_NAN;
+
+ pdu.latitudeDelta = va_arg(ap, double);
+ pdu.longitudeDelta = va_arg(ap, double);
+ pdu.altitudeDelta = va_arg(ap, INT32);
+ if ((count > 3) && (callback->clientVersion >= RDPLOCATION_PROTOCOL_VERSION_200))
+ {
+ speedDelta = va_arg(ap, double);
+ headingDelta = va_arg(ap, double);
+ pdu.speedDelta = &speedDelta;
+ pdu.headingDelta = &headingDelta;
+ }
+ res = location_send_location3d_delta(channel, &pdu);
+ }
+ break;
+ default:
+ res = ERROR_INVALID_PARAMETER;
+ break;
+ }
+ va_end(ap);
+ return res;
+}
+
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+static UINT location_on_close(IWTSVirtualChannelCallback* pChannelCallback)
+{
+ UINT res = CHANNEL_RC_OK;
+ GENERIC_CHANNEL_CALLBACK* callback = (GENERIC_CHANNEL_CALLBACK*)pChannelCallback;
+
+ if (callback)
+ {
+ LOCATION_PLUGIN* plugin = (LOCATION_PLUGIN*)callback->plugin;
+ WINPR_ASSERT(plugin);
+
+ res = IFCALLRESULT(CHANNEL_RC_OK, plugin->context.LocationStop, &plugin->context);
+ }
+ free(callback);
+
+ return res;
+}
+
+static UINT location_init(GENERIC_DYNVC_PLUGIN* plugin, rdpContext* context, rdpSettings* settings)
+{
+ LOCATION_PLUGIN* loc = (LOCATION_PLUGIN*)plugin;
+
+ WINPR_ASSERT(loc);
+
+ loc->context.LocationSend = location_send;
+ loc->context.handle = loc;
+ plugin->iface.pInterface = &loc->context;
+ return CHANNEL_RC_OK;
+}
+
+static const IWTSVirtualChannelCallback location_callbacks = { location_on_data_received,
+ NULL, /* Open */
+ location_on_close, NULL };
+
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+FREERDP_ENTRY_POINT(UINT location_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
+{
+ return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, LOCATION_DVC_CHANNEL_NAME,
+ sizeof(LOCATION_PLUGIN), sizeof(LOCATION_CALLBACK),
+ &location_callbacks, location_init, NULL);
+}
diff --git a/channels/parallel/client/parallel_main.c b/channels/parallel/client/parallel_main.c
index f0801e1..8f4d3c7 100644
--- a/channels/parallel/client/parallel_main.c
+++ b/channels/parallel/client/parallel_main.c
@@ -78,6 +78,10 @@ static UINT parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp)
{
char* path = NULL;
UINT32 PathLength = 0;
+
+ WINPR_ASSERT(parallel);
+ WINPR_ASSERT(irp);
+
if (!Stream_SafeSeek(irp->input, 28))
return ERROR_INVALID_DATA;
/* DesiredAccess(4) AllocationSize(8), FileAttributes(4) */
@@ -123,6 +127,9 @@ static UINT parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp)
*/
static UINT parallel_process_irp_close(PARALLEL_DEVICE* parallel, IRP* irp)
{
+ WINPR_ASSERT(parallel);
+ WINPR_ASSERT(irp);
+
if (close(parallel->file) < 0)
{
}
@@ -145,6 +152,10 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
UINT64 Offset = 0;
ssize_t status = 0;
BYTE* buffer = NULL;
+
+ WINPR_ASSERT(parallel);
+ WINPR_ASSERT(irp);
+
if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 12))
return ERROR_INVALID_DATA;
Stream_Read_UINT32(irp->input, Length);
@@ -201,6 +212,9 @@ static UINT parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp)
UINT64 Offset = 0;
ssize_t status = 0;
+ WINPR_ASSERT(parallel);
+ WINPR_ASSERT(irp);
+
if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 12))
return ERROR_INVALID_DATA;
@@ -240,6 +254,9 @@ static UINT parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp)
*/
static UINT parallel_process_irp_device_control(PARALLEL_DEVICE* parallel, IRP* irp)
{
+ WINPR_ASSERT(parallel);
+ WINPR_ASSERT(irp);
+
Stream_Write_UINT32(irp->output, 0); /* OutputBufferLength */
return irp->Complete(irp);
}
@@ -253,6 +270,9 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
{
UINT error = 0;
+ WINPR_ASSERT(parallel);
+ WINPR_ASSERT(irp);
+
switch (irp->MajorFunction)
{
case IRP_MJ_CREATE:
@@ -311,11 +331,10 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
static DWORD WINAPI parallel_thread_func(LPVOID arg)
{
- IRP* irp = NULL;
- wMessage message = { 0 };
PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*)arg;
UINT error = CHANNEL_RC_OK;
+ WINPR_ASSERT(parallel);
while (1)
{
if (!MessageQueue_Wait(parallel->queue))
@@ -325,6 +344,7 @@ static DWORD WINAPI parallel_thread_func(LPVOID arg)
break;
}
+ wMessage message = { 0 };
if (!MessageQueue_Peek(parallel->queue, &message, TRUE))
{
WLog_ERR(TAG, "MessageQueue_Peek failed!");
@@ -335,7 +355,7 @@ static DWORD WINAPI parallel_thread_func(LPVOID arg)
if (message.id == WMQ_QUIT)
break;
- irp = (IRP*)message.wParam;
+ IRP* irp = (IRP*)message.wParam;
if ((error = parallel_process_irp(parallel, irp)))
{
diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c
index 2aeb3f4..8d11f9b 100644
--- a/channels/printer/client/printer_main.c
+++ b/channels/printer/client/printer_main.c
@@ -62,6 +62,7 @@ typedef struct
HANDLE thread;
rdpContext* rdpcontext;
char port[64];
+ BOOL async;
} PRINTER_DEVICE;
typedef enum
@@ -684,8 +685,21 @@ static UINT printer_irp_request(DEVICE* device, IRP* irp)
WINPR_ASSERT(printer_dev);
WINPR_ASSERT(irp);
- InterlockedPushEntrySList(printer_dev->pIrpList, &(irp->ItemEntry));
- SetEvent(printer_dev->event);
+ if (printer_dev->async)
+ {
+ InterlockedPushEntrySList(printer_dev->pIrpList, &(irp->ItemEntry));
+ SetEvent(printer_dev->event);
+ }
+ else
+ {
+ UINT error = printer_process_irp(printer_dev, irp);
+ if (error)
+ {
+ WLog_ERR(TAG, "printer_process_irp failed with error %" PRIu32 "!", error);
+ return error;
+ }
+ }
+
return CHANNEL_RC_OK;
}
@@ -890,31 +904,34 @@ static UINT printer_free(DEVICE* device)
WINPR_ASSERT(printer_dev);
- SetEvent(printer_dev->stopEvent);
-
- if (WaitForSingleObject(printer_dev->thread, INFINITE) == WAIT_FAILED)
+ if (printer_dev->async)
{
- error = GetLastError();
- WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error);
+ SetEvent(printer_dev->stopEvent);
- /* The analyzer is confused by this premature return value.
- * Since this case can not be handled gracefully silence the
- * analyzer here. */
+ if (WaitForSingleObject(printer_dev->thread, INFINITE) == WAIT_FAILED)
+ {
+ error = GetLastError();
+ WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error);
+
+ /* The analyzer is confused by this premature return value.
+ * Since this case can not be handled gracefully silence the
+ * analyzer here. */
#ifndef __clang_analyzer__
- return error;
+ return error;
#endif
- }
+ }
- while ((irp = (IRP*)InterlockedPopEntrySList(printer_dev->pIrpList)) != NULL)
- {
- WINPR_ASSERT(irp->Discard);
- irp->Discard(irp);
- }
+ while ((irp = (IRP*)InterlockedPopEntrySList(printer_dev->pIrpList)) != NULL)
+ {
+ WINPR_ASSERT(irp->Discard);
+ irp->Discard(irp);
+ }
- CloseHandle(printer_dev->thread);
- CloseHandle(printer_dev->stopEvent);
- CloseHandle(printer_dev->event);
- winpr_aligned_free(printer_dev->pIrpList);
+ CloseHandle(printer_dev->thread);
+ CloseHandle(printer_dev->stopEvent);
+ CloseHandle(printer_dev->event);
+ winpr_aligned_free(printer_dev->pIrpList);
+ }
if (printer_dev->printer)
{
@@ -961,47 +978,62 @@ static UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrint
printer_dev->device.Free = printer_free;
printer_dev->rdpcontext = pEntryPoints->rdpcontext;
printer_dev->printer = printer;
- printer_dev->pIrpList = (WINPR_PSLIST_HEADER)winpr_aligned_malloc(sizeof(WINPR_SLIST_HEADER),
- MEMORY_ALLOCATION_ALIGNMENT);
- if (!printer_dev->pIrpList)
- {
- WLog_ERR(TAG, "_aligned_malloc failed!");
- error = CHANNEL_RC_NO_MEMORY;
- goto error_out;
- }
+ if (!freerdp_settings_get_bool(pEntryPoints->rdpcontext->settings,
+ FreeRDP_SynchronousStaticChannels))
+ printer_dev->async = TRUE;
if (!printer_load_from_config(pEntryPoints->rdpcontext->settings, printer, printer_dev))
goto error_out;
- InitializeSListHead(printer_dev->pIrpList);
-
- if (!(printer_dev->event = CreateEvent(NULL, TRUE, FALSE, NULL)))
+ if (printer_dev->async)
{
- WLog_ERR(TAG, "CreateEvent failed!");
- error = ERROR_INTERNAL_ERROR;
- goto error_out;
- }
+ printer_dev->pIrpList = (WINPR_PSLIST_HEADER)winpr_aligned_malloc(
+ sizeof(WINPR_SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
- if (!(printer_dev->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
- {
- WLog_ERR(TAG, "CreateEvent failed!");
- error = ERROR_INTERNAL_ERROR;
- goto error_out;
+ if (!printer_dev->pIrpList)
+ {
+ WLog_ERR(TAG, "_aligned_malloc failed!");
+ error = CHANNEL_RC_NO_MEMORY;
+ goto error_out;
+ }
+
+ InitializeSListHead(printer_dev->pIrpList);
+
+ printer_dev->event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (!printer_dev->event)
+ {
+ WLog_ERR(TAG, "CreateEvent failed!");
+ error = ERROR_INTERNAL_ERROR;
+ goto error_out;
+ }
+
+ printer_dev->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (!printer_dev->stopEvent)
+ {
+ WLog_ERR(TAG, "CreateEvent failed!");
+ error = ERROR_INTERNAL_ERROR;
+ goto error_out;
+ }
}
- if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, &printer_dev->device)))
+ error = pEntryPoints->RegisterDevice(pEntryPoints->devman, &printer_dev->device);
+ if (error)
{
WLog_ERR(TAG, "RegisterDevice failed with error %" PRIu32 "!", error);
goto error_out;
}
- if (!(printer_dev->thread =
- CreateThread(NULL, 0, printer_thread_func, (void*)printer_dev, 0, NULL)))
+ if (printer_dev->async)
{
- WLog_ERR(TAG, "CreateThread failed!");
- error = ERROR_INTERNAL_ERROR;
- goto error_out;
+ printer_dev->thread =
+ CreateThread(NULL, 0, printer_thread_func, (void*)printer_dev, 0, NULL);
+ if (!printer_dev->thread)
+ {
+ WLog_ERR(TAG, "CreateThread failed!");
+ error = ERROR_INTERNAL_ERROR;
+ goto error_out;
+ }
}
WINPR_ASSERT(printer->AddRef);
diff --git a/channels/printer/client/win/printer_win.c b/channels/printer/client/win/printer_win.c
index 9bd7589..7c62b40 100644
--- a/channels/printer/client/win/printer_win.c
+++ b/channels/printer/client/win/printer_win.c
@@ -136,7 +136,7 @@ static void printer_win_close_printjob(rdpPrintJob* printjob)
{
}
- if (!ClosePrinter(win_printer->hPrinter))
+ if (!EndDocPrinter(win_printer->hPrinter))
{
}
@@ -208,6 +208,9 @@ static void printer_win_free_printer(rdpPrinter* printer)
if (win_printer->printjob)
win_printer->printjob->printjob.Close((rdpPrintJob*)win_printer->printjob);
+ if (win_printer->hPrinter)
+ ClosePrinter(win_printer->hPrinter);
+
if (printer->backend)
printer->backend->ReleaseRef(printer->backend);
diff --git a/channels/rail/client/rail_orders.c b/channels/rail/client/rail_orders.c
index 7ac432e..b186eb3 100644
--- a/channels/rail/client/rail_orders.c
+++ b/channels/rail/client/rail_orders.c
@@ -469,6 +469,13 @@ static UINT rail_recv_handshake_ex_order(railPlugin* rail, wStream* s)
rail->channelBuildNumber = serverHandshake.buildNumber;
rail->channelFlags = serverHandshake.railHandshakeFlags;
+ {
+ char buffer[192] = { 0 };
+ WLog_DBG(TAG, "HandshakeFlags=%s [buildNumber=0x%08" PRIx32 "]",
+ rail_handshake_ex_flags_to_string(rail->channelFlags, buffer, sizeof(buffer)),
+ rail->channelBuildNumber);
+ }
+
if (rail->sendHandshake)
{
RAIL_HANDSHAKE_ORDER clientHandshake = { 0 };
diff --git a/channels/rail/rail_common.c b/channels/rail/rail_common.c
index fb6bc80..6deb968 100644
--- a/channels/rail/rail_common.c
+++ b/channels/rail/rail_common.c
@@ -589,3 +589,31 @@ BOOL rail_is_extended_spi_supported(UINT32 channelFlags)
{
return (channelFlags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_EXTENDED_SPI_SUPPORTED) ? TRUE : FALSE;
}
+
+const char* rail_handshake_ex_flags_to_string(UINT32 flags, char* buffer, size_t len)
+{
+ if (len < 1)
+ return NULL;
+
+ _snprintf(buffer, len, "{");
+ char* fbuffer = &buffer[1];
+ len--;
+
+ if (flags & TS_RAIL_ORDER_HANDSHAKEEX_FLAGS_HIDEF)
+ winpr_str_append("HIDEF", fbuffer, len, "|");
+ if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_EXTENDED_SPI_SUPPORTED)
+ winpr_str_append("EXTENDED_SPI_SUPPORTED", fbuffer, len, "|");
+ if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_SNAP_ARRANGE_SUPPORTED)
+ winpr_str_append("SNAP_ARRANGE_SUPPORTED", fbuffer, len, "|");
+ if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_TEXT_SCALE_SUPPORTED)
+ winpr_str_append("TEXT_SCALE_SUPPORTED", fbuffer, len, "|");
+ if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_CARET_BLINK_SUPPORTED)
+ winpr_str_append("CARET_BLINK_SUPPORTED", fbuffer, len, "|");
+ if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_EXTENDED_SPI_2_SUPPORTED)
+ winpr_str_append("EXTENDED_SPI_2_SUPPORTED", fbuffer, len, "|");
+
+ char number[16] = { 0 };
+ _snprintf(number, sizeof(number), "[0x%08" PRIx32 "]", flags);
+ winpr_str_append(number, buffer, len, "}");
+ return buffer;
+}
diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c
index 53f5011..2ffa951 100644
--- a/channels/rdpdr/client/rdpdr_main.c
+++ b/channels/rdpdr/client/rdpdr_main.c
@@ -1154,10 +1154,13 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr)
{
const char DynamicDrives[] = "DynamicDrives";
const RDPDR_DRIVE* drive = (const RDPDR_DRIVE*)device;
+ if (!drive->Path)
+ continue;
+
BOOL hotplugAll = strncmp(drive->Path, "*", 2) == 0;
BOOL hotplugLater = strncmp(drive->Path, DynamicDrives, sizeof(DynamicDrives)) == 0;
- if (drive->Path && (hotplugAll || hotplugLater))
+ if (hotplugAll || hotplugLater)
{
if (!rdpdr->async)
{
@@ -1274,7 +1277,6 @@ static UINT rdpdr_send_client_name_request(rdpdrPlugin* rdpdr)
WINPR_ASSERT(rdpdr->computerName);
computerNameW = ConvertUtf8ToWCharAlloc(rdpdr->computerName, &computerNameLenW);
computerNameLenW *= sizeof(WCHAR);
- WINPR_ASSERT(computerNameLenW >= 0);
if (computerNameLenW > 0)
computerNameLenW += sizeof(WCHAR); // also write '\0'
diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c
index bad6e23..f5353e3 100644
--- a/channels/rdpdr/server/rdpdr_main.c
+++ b/channels/rdpdr/server/rdpdr_main.c
@@ -2278,7 +2278,10 @@ static UINT rdpdr_server_send_device_create_request(RdpdrServerContext* context,
/* Convert the path to Unicode. */
if (Stream_Write_UTF16_String_From_UTF8(s, pathLength / sizeof(WCHAR), path,
pathLength / sizeof(WCHAR), TRUE) < 0)
+ {
+ Stream_Free(s, TRUE);
return ERROR_INTERNAL_ERROR;
+ }
return rdpdr_seal_send_free_request(context, s);
}
@@ -2418,7 +2421,10 @@ static UINT rdpdr_server_send_device_query_directory_request(RdpdrServerContext*
{
if (Stream_Write_UTF16_String_From_UTF8(s, pathLength / sizeof(WCHAR), path,
pathLength / sizeof(WCHAR), TRUE) < 0)
+ {
+ Stream_Free(s, TRUE);
return ERROR_INTERNAL_ERROR;
+ }
}
return rdpdr_seal_send_free_request(context, s);
@@ -2468,7 +2474,10 @@ static UINT rdpdr_server_send_device_file_rename_request(RdpdrServerContext* con
{
if (Stream_Write_UTF16_String_From_UTF8(s, pathLength / sizeof(WCHAR), path,
pathLength / sizeof(WCHAR), TRUE) < 0)
+ {
+ Stream_Free(s, TRUE);
return ERROR_INTERNAL_ERROR;
+ }
}
return rdpdr_seal_send_free_request(context, s);
diff --git a/channels/rdpecam/CMakeLists.txt b/channels/rdpecam/CMakeLists.txt
index 63ed410..220d586 100644
--- a/channels/rdpecam/CMakeLists.txt
+++ b/channels/rdpecam/CMakeLists.txt
@@ -20,3 +20,7 @@ define_channel("rdpecam")
if(WITH_SERVER_CHANNELS)
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()
+
+if(WITH_CLIENT_CHANNELS)
+ add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
+endif()
diff --git a/channels/rdpecam/ChannelOptions.cmake b/channels/rdpecam/ChannelOptions.cmake
index 7528d11..b094e03 100644
--- a/channels/rdpecam/ChannelOptions.cmake
+++ b/channels/rdpecam/ChannelOptions.cmake
@@ -9,4 +9,5 @@ define_channel_options(NAME "rdpecam" TYPE "dynamic"
DEFAULT ${OPTION_DEFAULT})
define_channel_server_options(${OPTION_SERVER_DEFAULT})
+define_channel_client_options(${OPTION_CLIENT_DEFAULT})
diff --git a/channels/rdpecam/client/CMakeLists.txt b/channels/rdpecam/client/CMakeLists.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/channels/rdpecam/client/CMakeLists.txt
diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c
index dd59c8b..aeaa2de 100644
--- a/channels/rdpgfx/client/rdpgfx_main.c
+++ b/channels/rdpgfx/client/rdpgfx_main.c
@@ -2093,6 +2093,7 @@ static UINT rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback
if (status < 0)
{
WLog_Print(gfx->log, WLOG_ERROR, "zgfx_decompress failure! status: %d", status);
+ free(pDstData);
return ERROR_INTERNAL_ERROR;
}
diff --git a/channels/rdpsnd/client/alsa/rdpsnd_alsa.c b/channels/rdpsnd/client/alsa/rdpsnd_alsa.c
index 97f0ba0..9751bbe 100644
--- a/channels/rdpsnd/client/alsa/rdpsnd_alsa.c
+++ b/channels/rdpsnd/client/alsa/rdpsnd_alsa.c
@@ -57,14 +57,14 @@ typedef struct
snd_pcm_uframes_t period_size;
} rdpsndAlsaPlugin;
-#define SND_PCM_CHECK(_func, _status) \
- do \
- { \
- if (_status < 0) \
- { \
- WLog_ERR(TAG, "%s: %d\n", _func, _status); \
- return -1; \
- } \
+#define SND_PCM_CHECK(_func, _status) \
+ do \
+ { \
+ if ((_status) < 0) \
+ { \
+ WLog_ERR(TAG, "%s: %d\n", (_func), (_status)); \
+ return -1; \
+ } \
} while (0)
static int rdpsnd_alsa_set_hw_params(rdpsndAlsaPlugin* alsa)
diff --git a/channels/rdpsnd/client/oss/CMakeLists.txt b/channels/rdpsnd/client/oss/CMakeLists.txt
index 83bd59f..c495752 100644
--- a/channels/rdpsnd/client/oss/CMakeLists.txt
+++ b/channels/rdpsnd/client/oss/CMakeLists.txt
@@ -30,6 +30,12 @@ set(${MODULE_PREFIX}_LIBS
)
include_directories(..)
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${OSS_INCLUDE_DIRS})
+configure_file(
+ ${CMAKE_SOURCE_DIR}/cmake/oss-includes.h.in
+ ${CMAKE_CURRENT_BINARY_DIR}/oss-includes.h
+ @ONLY
+)
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
diff --git a/channels/rdpsnd/client/oss/rdpsnd_oss.c b/channels/rdpsnd/client/oss/rdpsnd_oss.c
index 54869ab..84105fd 100644
--- a/channels/rdpsnd/client/oss/rdpsnd_oss.c
+++ b/channels/rdpsnd/client/oss/rdpsnd_oss.c
@@ -37,11 +37,7 @@
#include <libgen.h>
#include <limits.h>
#include <unistd.h>
-#if defined(__OpenBSD__)
-#include <soundcard.h>
-#else
-#include <sys/soundcard.h>
-#endif
+#include <oss-includes.h>
#include <sys/ioctl.h>
#include <freerdp/types.h>
@@ -64,15 +60,15 @@ typedef struct
AUDIO_FORMAT format;
} rdpsndOssPlugin;
-#define OSS_LOG_ERR(_text, _error) \
- do \
- { \
- if (_error != 0) \
- { \
- char ebuffer[256] = { 0 }; \
- WLog_ERR(TAG, "%s: %i - %s", _text, _error, \
- winpr_strerror(_error, ebuffer, sizeof(ebuffer))); \
- } \
+#define OSS_LOG_ERR(_text, _error) \
+ do \
+ { \
+ if ((_error) != 0) \
+ { \
+ char ebuffer[256] = { 0 }; \
+ WLog_ERR(TAG, "%s: %i - %s", (_text), (_error), \
+ winpr_strerror((_error), ebuffer, sizeof(ebuffer))); \
+ } \
} while (0)
static int rdpsnd_oss_get_format(const AUDIO_FORMAT* format)
diff --git a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c
index 59b2076..2b09680 100644
--- a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c
+++ b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c
@@ -752,7 +752,7 @@ FREERDP_ENTRY_POINT(UINT pulse_freerdp_rdpsnd_client_subsystem_entry(
if (pa_threaded_mainloop_start(pulse->mainloop) < 0)
{
pa_threaded_mainloop_unlock(pulse->mainloop);
- return FALSE;
+ goto error;
}
pa_threaded_mainloop_unlock(pulse->mainloop);
diff --git a/channels/server/CMakeLists.txt b/channels/server/CMakeLists.txt
index 1f49c3b..8ffb184 100644
--- a/channels/server/CMakeLists.txt
+++ b/channels/server/CMakeLists.txt
@@ -30,11 +30,6 @@ endforeach()
add_library(${MODULE_NAME} STATIC ${${MODULE_PREFIX}_SRCS})
-if (WITH_LIBRARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION})
-endif()
-
-
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr freerdp)
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} PARENT_SCOPE)
diff --git a/channels/urbdrc/client/data_transfer.c b/channels/urbdrc/client/data_transfer.c
index 7a7e5a2..56f3267 100644
--- a/channels/urbdrc/client/data_transfer.c
+++ b/channels/urbdrc/client/data_transfer.c
@@ -705,7 +705,10 @@ static UINT urb_control_transfer(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callb
if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
{
if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
+ {
+ Stream_Free(out, TRUE);
return ERROR_INVALID_DATA;
+ }
Stream_Copy(s, out, OutputBufferSize);
}
diff --git a/channels/urbdrc/client/libusb/libusb_udevice.c b/channels/urbdrc/client/libusb/libusb_udevice.c
index c226eb8..331adec 100644
--- a/channels/urbdrc/client/libusb/libusb_udevice.c
+++ b/channels/urbdrc/client/libusb/libusb_udevice.c
@@ -877,7 +877,7 @@ static UINT32 libusb_udev_control_query_device_text(IUDEVICE* idev, UINT32 TextT
* not honor strings with multi '\0' characters well.
*/
const size_t rchar = _wcsnlen((WCHAR*)&data[2], sizeof(data) / 2);
- len = MIN((BYTE)ret, slen);
+ len = MIN((BYTE)ret - 2, slen);
len = MIN(len, inSize);
len = MIN(len, rchar * 2 + sizeof(WCHAR));
memcpy(Buffer, &data[2], len);