diff options
Diffstat (limited to '')
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); |