diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 76ce472c7..3e58b1145 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -1166,6 +1166,13 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr) if (drive->Path && (hotplugAll || hotplugLater)) { + if (!rdpdr->async) + { + WLog_Print(rdpdr->log, WLOG_WARN, + "Drive hotplug is not supported in synchronous mode!"); + continue; + } + if (hotplugAll) first_hotplug(rdpdr); @@ -1952,12 +1959,23 @@ static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, void* Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); - if (!MessageQueue_Post(rdpdr->queue, NULL, 0, (void*)data_in, NULL)) + if (rdpdr->async) { - WLog_Print(rdpdr->log, WLOG_ERROR, "MessageQueue_Post failed!"); - return ERROR_INTERNAL_ERROR; + if (!MessageQueue_Post(rdpdr->queue, NULL, 0, (void*)data_in, NULL)) + { + WLog_Print(rdpdr->log, WLOG_ERROR, "MessageQueue_Post failed!"); + return ERROR_INTERNAL_ERROR; + } + rdpdr->data_in = NULL; + } + else + { + UINT error = rdpdr_process_receive(rdpdr, data_in); + Stream_Release(data_in); + rdpdr->data_in = NULL; + if (error) + return error; } - rdpdr->data_in = NULL; } return CHANNEL_RC_OK; @@ -2103,22 +2121,35 @@ static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, LPVOID pDa WINPR_UNUSED(pData); WINPR_UNUSED(dataLength); - rdpdr->queue = MessageQueue_New(NULL); - - if (!rdpdr->queue) + if (rdpdr->async) { - WLog_Print(rdpdr->log, WLOG_ERROR, "MessageQueue_New failed!"); - return CHANNEL_RC_NO_MEMORY; + rdpdr->queue = MessageQueue_New(NULL); + + if (!rdpdr->queue) + { + WLog_Print(rdpdr->log, WLOG_ERROR, "MessageQueue_New failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + obj = MessageQueue_Object(rdpdr->queue); + obj->fnObjectFree = queue_free; + + if (!(rdpdr->thread = CreateThread(NULL, 0, rdpdr_virtual_channel_client_thread, + (void*)rdpdr, 0, NULL))) + { + WLog_Print(rdpdr->log, WLOG_ERROR, "CreateThread failed!"); + return ERROR_INTERNAL_ERROR; + } } - - obj = MessageQueue_Object(rdpdr->queue); - obj->fnObjectFree = queue_free; - - if (!(rdpdr->thread = - CreateThread(NULL, 0, rdpdr_virtual_channel_client_thread, (void*)rdpdr, 0, NULL))) + else { - WLog_Print(rdpdr->log, WLOG_ERROR, "CreateThread failed!"); - return ERROR_INTERNAL_ERROR; + UINT error = rdpdr_process_connect(rdpdr); + if (error) + { + WLog_Print(rdpdr->log, WLOG_ERROR, + "rdpdr_process_connect failed with error %" PRIu32 "!", error); + return error; + } } return rdpdr->channelEntryPoints.pVirtualChannelOpenEx(rdpdr->InitHandle, &rdpdr->OpenHandle, @@ -2297,6 +2328,9 @@ FREERDP_ENTRY_POINT(BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS p (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER)) { rdpdr->rdpcontext = pEntryPointsEx->context; + if (!freerdp_settings_get_bool(rdpdr->rdpcontext->settings, + FreeRDP_SynchronousStaticChannels)) + rdpdr->async = TRUE; } CopyMemory(&(rdpdr->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)); diff --git a/channels/rdpdr/client/rdpdr_main.h b/channels/rdpdr/client/rdpdr_main.h index 50627569a..91131cb4d 100644 --- a/channels/rdpdr/client/rdpdr_main.h +++ b/channels/rdpdr/client/rdpdr_main.h @@ -112,6 +112,7 @@ typedef struct rdpContext* rdpcontext; wStreamPool* pool; wLog* log; + BOOL async; } rdpdrPlugin; BOOL rdpdr_state_advance(rdpdrPlugin* rdpdr, enum RDPDR_CHANNEL_STATE next); diff --git a/channels/rdpsnd/client/rdpsnd_main.c b/channels/rdpsnd/client/rdpsnd_main.c index 06f906533..ce325fe92 100644 --- a/channels/rdpsnd/client/rdpsnd_main.c +++ b/channels/rdpsnd/client/rdpsnd_main.c @@ -114,6 +114,7 @@ struct rdpsnd_plugin size_t references; BOOL OnOpenCalled; + BOOL async; }; static const char* rdpsnd_is_dyn_str(BOOL dynamic) @@ -1167,10 +1168,19 @@ static UINT rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin, voi Stream_SealLength(plugin->data_in); Stream_SetPosition(plugin->data_in, 0); - if (!MessageQueue_Post(plugin->queue, NULL, 0, plugin->data_in, NULL)) - return ERROR_INTERNAL_ERROR; - - plugin->data_in = NULL; + if (plugin->async) + { + if (!MessageQueue_Post(plugin->queue, NULL, 0, plugin->data_in, NULL)) + return ERROR_INTERNAL_ERROR; + plugin->data_in = NULL; + } + else + { + UINT error = rdpsnd_recv_pdu(plugin, plugin->data_in); + plugin->data_in = NULL; + if (error) + return error; + } } return CHANNEL_RC_OK; @@ -1420,19 +1430,22 @@ static DWORD WINAPI play_thread(LPVOID arg) static UINT rdpsnd_virtual_channel_event_initialized(rdpsndPlugin* rdpsnd) { - wObject obj = { 0 }; - if (!rdpsnd) return ERROR_INVALID_PARAMETER; - obj.fnObjectFree = _queue_free; - rdpsnd->queue = MessageQueue_New(&obj); - if (!rdpsnd->queue) - return CHANNEL_RC_NO_MEMORY; + if (rdpsnd->async) + { + wObject obj = { 0 }; - rdpsnd->thread = CreateThread(NULL, 0, play_thread, rdpsnd, 0, NULL); - if (!rdpsnd->thread) - return CHANNEL_RC_INITIALIZATION_ERROR; + obj.fnObjectFree = _queue_free; + rdpsnd->queue = MessageQueue_New(&obj); + if (!rdpsnd->queue) + return CHANNEL_RC_NO_MEMORY; + + rdpsnd->thread = CreateThread(NULL, 0, play_thread, rdpsnd, 0, NULL); + if (!rdpsnd->thread) + return CHANNEL_RC_INITIALIZATION_ERROR; + } if (!allocate_internals(rdpsnd)) return CHANNEL_RC_NO_MEMORY; @@ -1573,6 +1586,9 @@ FREERDP_ENTRY_POINT(BOOL VCAPITYPE rdpsnd_VirtualChannelEntryEx(PCHANNEL_ENTRY_P (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER)) { rdpsnd->rdpcontext = pEntryPointsEx->context; + if (!freerdp_settings_get_bool(rdpsnd->rdpcontext->settings, + FreeRDP_SynchronousStaticChannels)) + rdpsnd->async = TRUE; } CopyMemory(&(rdpsnd->channelEntryPoints), pEntryPoints, @@ -1636,10 +1652,19 @@ static UINT rdpsnd_on_data_received(IWTSVirtualChannelCallback* pChannelCallback Stream_SealLength(copy); Stream_SetPosition(copy, 0); - if (!MessageQueue_Post(plugin->queue, NULL, 0, copy, NULL)) + if (plugin->async) { - Stream_Release(copy); - return ERROR_INTERNAL_ERROR; + if (!MessageQueue_Post(plugin->queue, NULL, 0, copy, NULL)) + { + Stream_Release(copy); + return ERROR_INTERNAL_ERROR; + } + } + else + { + UINT error = rdpsnd_recv_pdu(plugin, copy); + if (error) + return error; } return CHANNEL_RC_OK; @@ -1807,6 +1832,10 @@ FREERDP_ENTRY_POINT(UINT rdpsnd_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoin WINPR_ASSERT(pEntryPoints->GetRdpContext); rdpsnd->rdpcontext = pEntryPoints->GetRdpContext(pEntryPoints); + if (!freerdp_settings_get_bool(rdpsnd->rdpcontext->settings, + FreeRDP_SynchronousDynamicChannels)) + rdpsnd->async = TRUE; + /* user data pointer is not const, cast to avoid warning. */ cnv.cev = pEntryPoints->GetPluginData(pEntryPoints); WINPR_ASSERT(pEntryPoints->GetPluginData); diff --git a/include/freerdp/settings_types_private.h b/include/freerdp/settings_types_private.h index caf747686..6d23110b6 100644 --- a/include/freerdp/settings_types_private.h +++ b/include/freerdp/settings_types_private.h @@ -760,7 +760,8 @@ struct rdp_settings SETTINGS_DEPRECATED(ALIGN64 UINT32 StaticChannelCount); /* 4928 */ SETTINGS_DEPRECATED(ALIGN64 UINT32 StaticChannelArraySize); /* 4929 */ SETTINGS_DEPRECATED(ALIGN64 ADDIN_ARGV** StaticChannelArray); /* 4930 */ - UINT64 padding5056[5056 - 4931]; /* 4931 */ + SETTINGS_DEPRECATED(ALIGN64 BOOL SynchronousStaticChannels); /* 4931 */ + UINT64 padding5056[5056 - 4932]; /* 4932 */ /** * Dynamic Virtual Channels diff --git a/libfreerdp/common/settings_getters.c b/libfreerdp/common/settings_getters.c index ae1f76cfd..ecec04477 100644 --- a/libfreerdp/common/settings_getters.c +++ b/libfreerdp/common/settings_getters.c @@ -576,6 +576,9 @@ BOOL freerdp_settings_get_bool(const rdpSettings* settings, FreeRDP_Settings_Key case FreeRDP_SynchronousDynamicChannels: return settings->SynchronousDynamicChannels; + case FreeRDP_SynchronousStaticChannels: + return settings->SynchronousStaticChannels; + case FreeRDP_TcpKeepAlive: return settings->TcpKeepAlive; @@ -1337,6 +1340,10 @@ BOOL freerdp_settings_set_bool(rdpSettings* settings, FreeRDP_Settings_Keys_Bool settings->SynchronousDynamicChannels = cnv.c; break; + case FreeRDP_SynchronousStaticChannels: + settings->SynchronousStaticChannels = cnv.c; + break; + case FreeRDP_TcpKeepAlive: settings->TcpKeepAlive = cnv.c; break; diff --git a/libfreerdp/common/settings_str.h b/libfreerdp/common/settings_str.h index def13ca6f..a3c71fb09 100644 --- a/libfreerdp/common/settings_str.h +++ b/libfreerdp/common/settings_str.h @@ -243,6 +243,8 @@ static const struct settings_str_entry settings_map[] = { { FreeRDP_SuspendInput, FREERDP_SETTINGS_TYPE_BOOL, "FreeRDP_SuspendInput" }, { FreeRDP_SynchronousDynamicChannels, FREERDP_SETTINGS_TYPE_BOOL, "FreeRDP_SynchronousDynamicChannels" }, + { FreeRDP_SynchronousStaticChannels, FREERDP_SETTINGS_TYPE_BOOL, + "FreeRDP_SynchronousStaticChannels" }, { FreeRDP_TcpKeepAlive, FREERDP_SETTINGS_TYPE_BOOL, "FreeRDP_TcpKeepAlive" }, { FreeRDP_TlsSecurity, FREERDP_SETTINGS_TYPE_BOOL, "FreeRDP_TlsSecurity" }, { FreeRDP_ToggleFullscreen, FREERDP_SETTINGS_TYPE_BOOL, "FreeRDP_ToggleFullscreen" }, diff --git a/libfreerdp/core/test/settings_property_lists.h b/libfreerdp/core/test/settings_property_lists.h index 51d3bdf81..fb280e65e 100644 --- a/libfreerdp/core/test/settings_property_lists.h +++ b/libfreerdp/core/test/settings_property_lists.h @@ -176,6 +176,7 @@ static const size_t bool_list_indices[] = { FreeRDP_SurfaceFrameMarkerEnabled, FreeRDP_SuspendInput, FreeRDP_SynchronousDynamicChannels, + FreeRDP_SynchronousStaticChannels, FreeRDP_TcpKeepAlive, FreeRDP_TlsSecurity, FreeRDP_ToggleFullscreen,