diff --git a/channels/ainput/client/ainput_main.c b/channels/ainput/client/ainput_main.c index dc8b481f7..92a6f377b 100644 --- a/channels/ainput/client/ainput_main.c +++ b/channels/ainput/client/ainput_main.c @@ -41,13 +41,10 @@ typedef struct AINPUT_PLUGIN_ AINPUT_PLUGIN; struct AINPUT_PLUGIN_ { - IWTSPlugin iface; - - GENERIC_LISTENER_CALLBACK* listener_callback; - IWTSListener* listener; + GENERIC_DYNVC_PLUGIN base; + AInputClientContext* context; UINT32 MajorVersion; UINT32 MinorVersion; - BOOL initialized; }; /** @@ -101,7 +98,6 @@ static UINT ainput_send_input_event(AInputClientContext* context, UINT64 flags, time = GetTickCount64(); ainput = (AINPUT_PLUGIN*)context->handle; WINPR_ASSERT(ainput); - WINPR_ASSERT(ainput->listener_callback); if (ainput->MajorVersion != AINPUT_VERSION_MAJOR) { @@ -109,7 +105,7 @@ static UINT ainput_send_input_event(AInputClientContext* context, UINT64 flags, ainput->MajorVersion, ainput->MinorVersion); return CHANNEL_RC_UNSUPPORTED_VERSION; } - callback = ainput->listener_callback->channel_callback; + callback = ainput->base.listener_callback->channel_callback; WINPR_ASSERT(callback); { @@ -149,104 +145,30 @@ static UINT ainput_on_close(IWTSVirtualChannelCallback* pChannelCallback) return CHANNEL_RC_OK; } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT ainput_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, - IWTSVirtualChannel* pChannel, BYTE* Data, - BOOL* pbAccept, - IWTSVirtualChannelCallback** ppCallback) +static UINT init_plugin_cb(GENERIC_DYNVC_PLUGIN* base, rdpContext* rcontext, rdpSettings* settings) { - GENERIC_CHANNEL_CALLBACK* callback; - GENERIC_LISTENER_CALLBACK* listener_callback = (GENERIC_LISTENER_CALLBACK*)pListenerCallback; - - WINPR_ASSERT(listener_callback); - WINPR_UNUSED(Data); - WINPR_UNUSED(pbAccept); - - callback = (GENERIC_CHANNEL_CALLBACK*)calloc(1, sizeof(GENERIC_CHANNEL_CALLBACK)); - - if (!callback) - { - WLog_ERR(TAG, "calloc failed!"); + AINPUT_PLUGIN* ainput = (AINPUT_PLUGIN*)base; + AInputClientContext* context = (AInputClientContext*)calloc(1, sizeof(AInputClientContext)); + if (!context) return CHANNEL_RC_NO_MEMORY; - } - callback->iface.OnDataReceived = ainput_on_data_received; - callback->iface.OnClose = ainput_on_close; - callback->plugin = listener_callback->plugin; - callback->channel_mgr = listener_callback->channel_mgr; - callback->channel = pChannel; - listener_callback->channel_callback = callback; - - *ppCallback = &callback->iface; + context->handle = (void*)base; + context->AInputSendInputEvent = ainput_send_input_event; + ainput->context = context; + ainput->base.iface.pInterface = context; return CHANNEL_RC_OK; } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT ainput_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) +static void terminate_plugin_cb(GENERIC_DYNVC_PLUGIN* base) { - UINT status; - AINPUT_PLUGIN* ainput = (AINPUT_PLUGIN*)pPlugin; - - WINPR_ASSERT(ainput); - - if (ainput->initialized) - { - WLog_ERR(TAG, "[%s] channel initialized twice, aborting", AINPUT_DVC_CHANNEL_NAME); - return ERROR_INVALID_DATA; - } - ainput->listener_callback = - (GENERIC_LISTENER_CALLBACK*)calloc(1, sizeof(GENERIC_LISTENER_CALLBACK)); - - if (!ainput->listener_callback) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - ainput->listener_callback->iface.OnNewChannelConnection = ainput_on_new_channel_connection; - ainput->listener_callback->plugin = pPlugin; - ainput->listener_callback->channel_mgr = pChannelMgr; - - status = pChannelMgr->CreateListener(pChannelMgr, AINPUT_DVC_CHANNEL_NAME, 0, - &ainput->listener_callback->iface, &ainput->listener); - - ainput->listener->pInterface = ainput->iface.pInterface; - ainput->initialized = status == CHANNEL_RC_OK; - return status; + AINPUT_PLUGIN* ainput = (AINPUT_PLUGIN*)base; + free(ainput->context); } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT ainput_plugin_terminated(IWTSPlugin* pPlugin) -{ - AINPUT_PLUGIN* ainput = (AINPUT_PLUGIN*)pPlugin; - if (ainput && ainput->listener_callback) - { - IWTSVirtualChannelManager* mgr = ainput->listener_callback->channel_mgr; - if (mgr) - IFCALL(mgr->DestroyListener, mgr, ainput->listener); - } - if (ainput) - { - free(ainput->listener_callback); - free(ainput->iface.pInterface); - } - free(ainput); - - return CHANNEL_RC_OK; -} +static const IWTSVirtualChannelCallback ainput_functions = { ainput_on_data_received, + NULL, /* Open */ + ainput_on_close }; /** * Function description @@ -255,32 +177,7 @@ static UINT ainput_plugin_terminated(IWTSPlugin* pPlugin) */ UINT ainput_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { - UINT status = CHANNEL_RC_OK; - AINPUT_PLUGIN* ainput = (AINPUT_PLUGIN*)pEntryPoints->GetPlugin(pEntryPoints, "ainput"); - - if (!ainput) - { - AInputClientContext* context = (AInputClientContext*)calloc(1, sizeof(AInputClientContext)); - ainput = (AINPUT_PLUGIN*)calloc(1, sizeof(AINPUT_PLUGIN)); - - if (!ainput || !context) - { - free(context); - free(ainput); - - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - ainput->iface.Initialize = ainput_plugin_initialize; - ainput->iface.Terminated = ainput_plugin_terminated; - - context->handle = (void*)ainput; - context->AInputSendInputEvent = ainput_send_input_event; - ainput->iface.pInterface = (void*)context; - - status = pEntryPoints->RegisterPlugin(pEntryPoints, AINPUT_CHANNEL_NAME, &ainput->iface); - } - - return status; + return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, AINPUT_DVC_CHANNEL_NAME, + sizeof(AINPUT_PLUGIN), sizeof(GENERIC_CHANNEL_CALLBACK), + &ainput_functions, init_plugin_cb, terminate_plugin_cb); } diff --git a/channels/client/CMakeLists.txt b/channels/client/CMakeLists.txt index 8f7df531e..923683ae3 100644 --- a/channels/client/CMakeLists.txt +++ b/channels/client/CMakeLists.txt @@ -22,7 +22,8 @@ set(${MODULE_PREFIX}_SRCS ${CMAKE_CURRENT_BINARY_DIR}/tables.c ${CMAKE_CURRENT_SOURCE_DIR}/tables.h ${CMAKE_CURRENT_SOURCE_DIR}/addin.c - ${CMAKE_CURRENT_SOURCE_DIR}/addin.h) + ${CMAKE_CURRENT_SOURCE_DIR}/addin.h + ${CMAKE_CURRENT_SOURCE_DIR}/generic_dynvc.c) if(CHANNEL_STATIC_CLIENT_ENTRIES) list(REMOVE_DUPLICATES CHANNEL_STATIC_CLIENT_ENTRIES) diff --git a/channels/client/generic_dynvc.c b/channels/client/generic_dynvc.c new file mode 100644 index 000000000..b2e941e48 --- /dev/null +++ b/channels/client/generic_dynvc.c @@ -0,0 +1,209 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Dynamic channel + * + * Copyright 2022 David Fort + * + * 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 +#include +#include + +#define TAG FREERDP_TAG("genericdynvc") + +static UINT generic_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, + IWTSVirtualChannel* pChannel, BYTE* Data, + BOOL* pbAccept, + IWTSVirtualChannelCallback** ppCallback) +{ + GENERIC_CHANNEL_CALLBACK* callback; + GENERIC_DYNVC_PLUGIN* plugin; + GENERIC_LISTENER_CALLBACK* listener_callback = (GENERIC_LISTENER_CALLBACK*)pListenerCallback; + + if (!listener_callback || !listener_callback->plugin) + return ERROR_INTERNAL_ERROR; + + plugin = (GENERIC_DYNVC_PLUGIN*)listener_callback->plugin; + WLog_Print(plugin->log, WLOG_TRACE, "..."); + + callback = (GENERIC_CHANNEL_CALLBACK*)calloc(1, plugin->channelCallbackSize); + if (!callback) + { + WLog_Print(plugin->log, WLOG_ERROR, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + /* implant configured channel callbacks */ + callback->iface = *plugin->channel_callbacks; + + callback->plugin = listener_callback->plugin; + callback->channel_mgr = listener_callback->channel_mgr; + callback->channel = pChannel; + + listener_callback->channel_callback = callback; + *ppCallback = (IWTSVirtualChannelCallback*)callback; + return CHANNEL_RC_OK; +} + +static UINT generic_dynvc_plugin_initialize(IWTSPlugin* pPlugin, + IWTSVirtualChannelManager* pChannelMgr) +{ + UINT rc; + GENERIC_LISTENER_CALLBACK* listener_callback; + GENERIC_DYNVC_PLUGIN* plugin = (GENERIC_DYNVC_PLUGIN*)pPlugin; + + if (!plugin) + return CHANNEL_RC_BAD_CHANNEL_HANDLE; + + if (!pChannelMgr) + return ERROR_INVALID_PARAMETER; + + if (plugin->initialized) + { + WLog_ERR(TAG, "[%s] channel initialized twice, aborting", plugin->dynvc_name); + return ERROR_INVALID_DATA; + } + + WLog_Print(plugin->log, WLOG_TRACE, "..."); + listener_callback = (GENERIC_LISTENER_CALLBACK*)calloc(1, sizeof(GENERIC_LISTENER_CALLBACK)); + if (!listener_callback) + { + WLog_Print(plugin->log, WLOG_ERROR, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + plugin->listener_callback = listener_callback; + listener_callback->iface.OnNewChannelConnection = generic_on_new_channel_connection; + listener_callback->plugin = pPlugin; + listener_callback->channel_mgr = pChannelMgr; + rc = pChannelMgr->CreateListener(pChannelMgr, plugin->dynvc_name, 0, &listener_callback->iface, + &plugin->listener); + + plugin->listener->pInterface = plugin->iface.pInterface; + plugin->initialized = (rc == CHANNEL_RC_OK); + return rc; +} + +static UINT generic_plugin_terminated(IWTSPlugin* pPlugin) +{ + GENERIC_DYNVC_PLUGIN* plugin = (GENERIC_DYNVC_PLUGIN*)pPlugin; + UINT error = CHANNEL_RC_OK; + + if (!plugin) + return CHANNEL_RC_BAD_CHANNEL_HANDLE; + + WLog_Print(plugin->log, WLOG_TRACE, "..."); + + if (plugin->terminatePluginFn) + plugin->terminatePluginFn(plugin); + + if (plugin->listener_callback) + { + IWTSVirtualChannelManager* mgr = plugin->listener_callback->channel_mgr; + if (mgr) + IFCALL(mgr->DestroyListener, mgr, plugin->listener); + } + + free(plugin->listener_callback); + free(plugin->dynvc_name); + free(plugin); + return error; +} + +static UINT generic_dynvc_plugin_attached(IWTSPlugin* pPlugin) +{ + GENERIC_DYNVC_PLUGIN* pluginn = (GENERIC_DYNVC_PLUGIN*)pPlugin; + UINT error = CHANNEL_RC_OK; + + if (!pluginn) + return CHANNEL_RC_BAD_CHANNEL_HANDLE; + + pluginn->attached = TRUE; + return error; +} + +static UINT generic_dynvc_plugin_detached(IWTSPlugin* pPlugin) +{ + GENERIC_DYNVC_PLUGIN* plugin = (GENERIC_DYNVC_PLUGIN*)pPlugin; + UINT error = CHANNEL_RC_OK; + + if (!plugin) + return CHANNEL_RC_BAD_CHANNEL_HANDLE; + + plugin->attached = FALSE; + return error; +} + +UINT freerdp_generic_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* logTag, + const char* name, size_t pluginSize, size_t channelCallbackSize, + const IWTSVirtualChannelCallback* channel_callbacks, + DYNVC_PLUGIN_INIT_FN initPluginFn, + DYNVC_PLUGIN_TERMINATE_FN terminatePluginFn) +{ + GENERIC_DYNVC_PLUGIN* plugin; + UINT error = CHANNEL_RC_INITIALIZATION_ERROR; + + WINPR_ASSERT(pEntryPoints); + WINPR_ASSERT(pEntryPoints->GetPlugin); + WINPR_ASSERT(logTag); + WINPR_ASSERT(name); + WINPR_ASSERT(pluginSize >= sizeof(*plugin)); + WINPR_ASSERT(channelCallbackSize >= sizeof(GENERIC_CHANNEL_CALLBACK)); + + plugin = (GENERIC_DYNVC_PLUGIN*)pEntryPoints->GetPlugin(pEntryPoints, name); + if (plugin != NULL) + return CHANNEL_RC_ALREADY_INITIALIZED; + + plugin = (GENERIC_DYNVC_PLUGIN*)calloc(1, pluginSize); + if (!plugin) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + plugin->log = WLog_Get(logTag); + plugin->attached = TRUE; + plugin->channel_callbacks = channel_callbacks; + plugin->channelCallbackSize = channelCallbackSize; + plugin->iface.Initialize = generic_dynvc_plugin_initialize; + plugin->iface.Connected = NULL; + plugin->iface.Disconnected = NULL; + plugin->iface.Terminated = generic_plugin_terminated; + plugin->iface.Attached = generic_dynvc_plugin_attached; + plugin->iface.Detached = generic_dynvc_plugin_detached; + plugin->terminatePluginFn = terminatePluginFn; + + if (initPluginFn) + { + rdpSettings* settings = pEntryPoints->GetRdpSettings(pEntryPoints); + rdpContext* context = pEntryPoints->GetRdpContext(pEntryPoints); + + error = initPluginFn(plugin, context, settings); + if (error != CHANNEL_RC_OK) + goto error; + } + + plugin->dynvc_name = _strdup(name); + if (!plugin->dynvc_name) + goto error; + + error = pEntryPoints->RegisterPlugin(pEntryPoints, name, &plugin->iface); + if (error == CHANNEL_RC_OK) + return error; + +error: + generic_plugin_terminated(&plugin->iface); + return error; +} diff --git a/channels/disp/client/disp_main.c b/channels/disp/client/disp_main.c index d2eab97f5..a1aed67aa 100644 --- a/channels/disp/client/disp_main.c +++ b/channels/disp/client/disp_main.c @@ -44,15 +44,12 @@ typedef struct { - IWTSPlugin iface; - - IWTSListener* listener; - GENERIC_LISTENER_CALLBACK* listener_callback; + GENERIC_DYNVC_PLUGIN base; + DispClientContext* context; UINT32 MaxNumMonitors; UINT32 MaxMonitorAreaFactorA; UINT32 MaxMonitorAreaFactorB; - BOOL initialized; } DISP_PLUGIN; /** @@ -167,7 +164,7 @@ static UINT disp_recv_display_control_caps_pdu(GENERIC_CHANNEL_CALLBACK* callbac disp = (DISP_PLUGIN*)callback->plugin; WINPR_ASSERT(disp); - context = (DispClientContext*)disp->iface.pInterface; + context = disp->context; WINPR_ASSERT(context); if (!Stream_CheckAndLogRequiredLength(TAG, s, 12)) @@ -245,103 +242,6 @@ static UINT disp_on_close(IWTSVirtualChannelCallback* pChannelCallback) return CHANNEL_RC_OK; } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT disp_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, - IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept, - IWTSVirtualChannelCallback** ppCallback) -{ - GENERIC_CHANNEL_CALLBACK* callback; - GENERIC_LISTENER_CALLBACK* listener_callback = (GENERIC_LISTENER_CALLBACK*)pListenerCallback; - - WINPR_ASSERT(listener_callback); - WINPR_ASSERT(pChannel); - WINPR_ASSERT(pbAccept); - WINPR_ASSERT(ppCallback); - - callback = (GENERIC_CHANNEL_CALLBACK*)calloc(1, sizeof(GENERIC_CHANNEL_CALLBACK)); - - if (!callback) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - callback->iface.OnDataReceived = disp_on_data_received; - callback->iface.OnClose = disp_on_close; - callback->plugin = listener_callback->plugin; - callback->channel_mgr = listener_callback->channel_mgr; - callback->channel = pChannel; - listener_callback->channel_callback = callback; - *ppCallback = (IWTSVirtualChannelCallback*)callback; - return CHANNEL_RC_OK; -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT disp_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) -{ - UINT status; - DISP_PLUGIN* disp = (DISP_PLUGIN*)pPlugin; - - WINPR_ASSERT(disp); - WINPR_ASSERT(pChannelMgr); - - if (disp->initialized) - { - WLog_ERR(TAG, "[%s] channel initialized twice, aborting", DISP_DVC_CHANNEL_NAME); - return ERROR_INVALID_DATA; - } - disp->listener_callback = - (GENERIC_LISTENER_CALLBACK*)calloc(1, sizeof(GENERIC_LISTENER_CALLBACK)); - - if (!disp->listener_callback) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - disp->listener_callback->iface.OnNewChannelConnection = disp_on_new_channel_connection; - disp->listener_callback->plugin = pPlugin; - disp->listener_callback->channel_mgr = pChannelMgr; - status = pChannelMgr->CreateListener(pChannelMgr, DISP_DVC_CHANNEL_NAME, 0, - &disp->listener_callback->iface, &(disp->listener)); - disp->listener->pInterface = disp->iface.pInterface; - - disp->initialized = status == CHANNEL_RC_OK; - return status; -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT disp_plugin_terminated(IWTSPlugin* pPlugin) -{ - DISP_PLUGIN* disp = (DISP_PLUGIN*)pPlugin; - - WINPR_ASSERT(disp); - - if (disp->listener_callback) - { - IWTSVirtualChannelManager* mgr = disp->listener_callback->channel_mgr; - if (mgr) - IFCALL(mgr->DestroyListener, mgr, disp->listener); - free(disp->listener_callback); - } - - free(disp->iface.pInterface); - free(pPlugin); - return CHANNEL_RC_OK; -} - /** * Channel Client Interface */ @@ -362,11 +262,54 @@ static UINT disp_send_monitor_layout(DispClientContext* context, UINT32 NumMonit disp = (DISP_PLUGIN*)context->handle; WINPR_ASSERT(disp); - callback = disp->listener_callback->channel_callback; + callback = disp->base.listener_callback->channel_callback; return disp_send_display_control_monitor_layout_pdu(callback, NumMonitors, Monitors); } +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT disp_plugin_initialize(GENERIC_DYNVC_PLUGIN* base, rdpContext* rcontext, + rdpSettings* settings) +{ + DispClientContext* context; + DISP_PLUGIN* disp = (DISP_PLUGIN*)base; + + WINPR_ASSERT(disp); + disp->MaxNumMonitors = 16; + disp->MaxMonitorAreaFactorA = 8192; + disp->MaxMonitorAreaFactorB = 8192; + + context = (DispClientContext*)calloc(1, sizeof(*disp)); + if (!context) + { + WLog_Print(base->log, WLOG_ERROR, "unable to allocate DispClientContext"); + return CHANNEL_RC_NO_MEMORY; + } + + context->handle = (void*)disp; + context->SendMonitorLayout = disp_send_monitor_layout; + + disp->base.iface.pInterface = disp->context = context; + + return CHANNEL_RC_OK; +} + +static void disp_plugin_terminated(GENERIC_DYNVC_PLUGIN* base) +{ + DISP_PLUGIN* disp = (DISP_PLUGIN*)base; + + WINPR_ASSERT(disp); + + free(disp->context); +} + +static const IWTSVirtualChannelCallback disp_callbacks = { disp_on_data_received, NULL, /* Open */ + disp_on_close }; + /** * Function description * @@ -374,50 +317,8 @@ static UINT disp_send_monitor_layout(DispClientContext* context, UINT32 NumMonit */ UINT disp_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { - UINT error = CHANNEL_RC_OK; - DISP_PLUGIN* disp; - DispClientContext* context; - - WINPR_ASSERT(pEntryPoints); - - disp = (DISP_PLUGIN*)pEntryPoints->GetPlugin(pEntryPoints, DISP_CHANNEL_NAME); - - if (!disp) - { - disp = (DISP_PLUGIN*)calloc(1, sizeof(DISP_PLUGIN)); - - if (!disp) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - disp->iface.Initialize = disp_plugin_initialize; - disp->iface.Connected = NULL; - disp->iface.Disconnected = NULL; - disp->iface.Terminated = disp_plugin_terminated; - disp->MaxNumMonitors = 16; - disp->MaxMonitorAreaFactorA = 8192; - disp->MaxMonitorAreaFactorB = 8192; - context = (DispClientContext*)calloc(1, sizeof(DispClientContext)); - - if (!context) - { - WLog_ERR(TAG, "calloc failed!"); - free(disp); - return CHANNEL_RC_NO_MEMORY; - } - - context->handle = (void*)disp; - context->SendMonitorLayout = disp_send_monitor_layout; - disp->iface.pInterface = (void*)context; - error = pEntryPoints->RegisterPlugin(pEntryPoints, DISP_CHANNEL_NAME, &disp->iface); - } - else - { - WLog_ERR(TAG, "could not get disp Plugin."); - return CHANNEL_RC_BAD_CHANNEL; - } - - return error; + return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, DISP_DVC_CHANNEL_NAME, + sizeof(DISP_PLUGIN), sizeof(GENERIC_CHANNEL_CALLBACK), + &disp_callbacks, disp_plugin_initialize, + disp_plugin_terminated); } diff --git a/channels/echo/client/echo_main.c b/channels/echo/client/echo_main.c index 9ba4b4904..20f05ae1f 100644 --- a/channels/echo/client/echo_main.c +++ b/channels/echo/client/echo_main.c @@ -34,14 +34,9 @@ #define TAG CHANNELS_TAG("echo.client") - typedef struct { - IWTSPlugin iface; - - GENERIC_LISTENER_CALLBACK* listener_callback; - IWTSListener* listener; - BOOL initialized; + GENERIC_DYNVC_PLUGIN baseDynPlugin; } ECHO_PLUGIN; /** @@ -66,95 +61,15 @@ static UINT echo_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, */ static UINT echo_on_close(IWTSVirtualChannelCallback* pChannelCallback) { - GENERIC_CHANNEL_CALLBACK* callback = (GENERIC_CHANNEL_CALLBACK*)pChannelCallback; + GENERIC_CHANNEL_CALLBACK* callback = (GENERIC_CHANNEL_CALLBACK*)pChannelCallback; free(callback); return CHANNEL_RC_OK; } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT echo_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, - IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept, - IWTSVirtualChannelCallback** ppCallback) -{ - GENERIC_CHANNEL_CALLBACK* callback; - GENERIC_LISTENER_CALLBACK* listener_callback = (GENERIC_LISTENER_CALLBACK*)pListenerCallback; - - callback = (GENERIC_CHANNEL_CALLBACK*)calloc(1, sizeof(GENERIC_CHANNEL_CALLBACK)); - - if (!callback) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - callback->iface.OnDataReceived = echo_on_data_received; - callback->iface.OnClose = echo_on_close; - callback->plugin = listener_callback->plugin; - callback->channel_mgr = listener_callback->channel_mgr; - callback->channel = pChannel; - - *ppCallback = (IWTSVirtualChannelCallback*)callback; - - return CHANNEL_RC_OK; -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT echo_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) -{ - UINT status; - ECHO_PLUGIN* echo = (ECHO_PLUGIN*)pPlugin; - if (echo->initialized) - { - WLog_ERR(TAG, "[%s] channel initialized twice, aborting", ECHO_DVC_CHANNEL_NAME); - return ERROR_INVALID_DATA; - } - echo->listener_callback = (GENERIC_LISTENER_CALLBACK*)calloc(1, sizeof(GENERIC_LISTENER_CALLBACK)); - - if (!echo->listener_callback) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - echo->listener_callback->iface.OnNewChannelConnection = echo_on_new_channel_connection; - echo->listener_callback->plugin = pPlugin; - echo->listener_callback->channel_mgr = pChannelMgr; - - status = pChannelMgr->CreateListener(pChannelMgr, ECHO_DVC_CHANNEL_NAME, 0, - &echo->listener_callback->iface, &echo->listener); - - echo->initialized = status == CHANNEL_RC_OK; - return status; -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT echo_plugin_terminated(IWTSPlugin* pPlugin) -{ - ECHO_PLUGIN* echo = (ECHO_PLUGIN*)pPlugin; - if (echo && echo->listener_callback) - { - IWTSVirtualChannelManager* mgr = echo->listener_callback->channel_mgr; - if (mgr) - IFCALL(mgr->DestroyListener, mgr, echo->listener); - } - free(echo); - - return CHANNEL_RC_OK; -} +static const IWTSVirtualChannelCallback echo_callbacks = { echo_on_data_received, NULL, /* Open */ + echo_on_close }; /** * Function description @@ -163,28 +78,7 @@ static UINT echo_plugin_terminated(IWTSPlugin* pPlugin) */ UINT echo_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { - UINT status = CHANNEL_RC_OK; - ECHO_PLUGIN* echo; - - echo = (ECHO_PLUGIN*)pEntryPoints->GetPlugin(pEntryPoints, "echo"); - - if (!echo) - { - echo = (ECHO_PLUGIN*)calloc(1, sizeof(ECHO_PLUGIN)); - - if (!echo) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - echo->iface.Initialize = echo_plugin_initialize; - echo->iface.Connected = NULL; - echo->iface.Disconnected = NULL; - echo->iface.Terminated = echo_plugin_terminated; - - status = pEntryPoints->RegisterPlugin(pEntryPoints, "echo", &echo->iface); - } - - return status; + return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, ECHO_DVC_CHANNEL_NAME, + sizeof(ECHO_PLUGIN), sizeof(GENERIC_CHANNEL_CALLBACK), + &echo_callbacks, NULL, NULL); } diff --git a/channels/geometry/client/geometry_main.c b/channels/geometry/client/geometry_main.c index ada890da6..6c2efb68c 100644 --- a/channels/geometry/client/geometry_main.c +++ b/channels/geometry/client/geometry_main.c @@ -41,13 +41,8 @@ typedef struct { - IWTSPlugin iface; - - IWTSListener* listener; - GENERIC_LISTENER_CALLBACK* listener_callback; - + GENERIC_DYNVC_PLUGIN base; GeometryClientContext* context; - BOOL initialized; } GEOMETRY_PLUGIN; static UINT32 mappedGeometryHash(const void* v) @@ -68,7 +63,7 @@ static void freerdp_rgndata_reset(FREERDP_RGNDATA* data) data->nRectCount = 0; } -static UINT32 geometry_read_RGNDATA(wStream* s, UINT32 len, FREERDP_RGNDATA* rgndata) +static UINT32 geometry_read_RGNDATA(wLog* logger, wStream* s, UINT32 len, FREERDP_RGNDATA* rgndata) { UINT32 dwSize, iType; INT32 right, bottom; @@ -76,7 +71,7 @@ static UINT32 geometry_read_RGNDATA(wStream* s, UINT32 len, FREERDP_RGNDATA* rgn if (len < 32) { - WLog_ERR(TAG, "invalid RGNDATA"); + WLog_Print(logger, WLOG_ERROR, "invalid RGNDATA"); return ERROR_INVALID_DATA; } @@ -84,7 +79,7 @@ static UINT32 geometry_read_RGNDATA(wStream* s, UINT32 len, FREERDP_RGNDATA* rgn if (dwSize != 32) { - WLog_ERR(TAG, "invalid RGNDATA dwSize"); + WLog_Print(logger, WLOG_ERROR, "invalid RGNDATA dwSize"); return ERROR_INVALID_DATA; } @@ -92,7 +87,7 @@ static UINT32 geometry_read_RGNDATA(wStream* s, UINT32 len, FREERDP_RGNDATA* rgn if (iType != RDH_RECTANGLE) { - WLog_ERR(TAG, "iType %" PRIu32 " for RGNDATA is not supported", iType); + WLog_Print(logger, WLOG_ERROR, "iType %" PRIu32 " for RGNDATA is not supported", iType); return ERROR_UNSUPPORTED_TYPE; } @@ -116,7 +111,7 @@ static UINT32 geometry_read_RGNDATA(wStream* s, UINT32 len, FREERDP_RGNDATA* rgn if (len / (4 * 4) < rgndata->nRectCount) { - WLog_ERR(TAG, "not enough data for region rectangles"); + WLog_Print(logger, WLOG_ERROR, "not enough data for region rectangles"); } if (rgndata->nRectCount) @@ -126,7 +121,8 @@ static UINT32 geometry_read_RGNDATA(wStream* s, UINT32 len, FREERDP_RGNDATA* rgn if (!tmp) { - WLog_ERR(TAG, "unable to allocate memory for %" PRIu32 " RECTs", rgndata->nRectCount); + WLog_Print(logger, WLOG_ERROR, "unable to allocate memory for %" PRIu32 " RECTs", + rgndata->nRectCount); return CHANNEL_RC_NO_MEMORY; } rgndata->rects = tmp; @@ -165,11 +161,13 @@ static UINT geometry_recv_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream* s) GEOMETRY_PLUGIN* geometry; GeometryClientContext* context; UINT ret = CHANNEL_RC_OK; - UINT32 version, updateType, geometryType; + UINT32 updateType, geometryType; UINT64 id; + wLog* logger; geometry = (GEOMETRY_PLUGIN*)callback->plugin; - context = (GeometryClientContext*)geometry->iface.pInterface; + logger = geometry->base.log; + context = (GeometryClientContext*)geometry->base.iface.pInterface; if (!Stream_CheckAndLogRequiredLength(TAG, s, 4)) return ERROR_INVALID_DATA; @@ -178,11 +176,11 @@ static UINT geometry_recv_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream* s) if (length < 73 || !Stream_CheckAndLogRequiredLength(TAG, s, (length - 4))) { - WLog_ERR(TAG, "invalid packet length"); + WLog_Print(logger, WLOG_ERROR, "invalid packet length"); return ERROR_INVALID_DATA; } - Stream_Read_UINT32(s, version); + Stream_Read_UINT32(s, context->remoteVersion); Stream_Read_UINT64(s, id); Stream_Read_UINT32(s, updateType); Stream_Seek_UINT32(s); /* flags */ @@ -193,18 +191,19 @@ static UINT geometry_recv_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream* s) { if (!mappedGeometry) { - WLog_ERR(TAG, "geometry 0x%" PRIx64 " not found here, ignoring clear command", id); + WLog_Print(logger, WLOG_ERROR, + "geometry 0x%" PRIx64 " not found here, ignoring clear command", id); return CHANNEL_RC_OK; } - WLog_DBG(TAG, "clearing geometry 0x%" PRIx64 "", id); + WLog_Print(logger, WLOG_DEBUG, "clearing geometry 0x%" PRIx64 "", id); if (mappedGeometry->MappedGeometryClear && !mappedGeometry->MappedGeometryClear(mappedGeometry)) return ERROR_INTERNAL_ERROR; if (!HashTable_Remove(context->geometries, &id)) - WLog_ERR(TAG, "geometry not removed from geometries"); + WLog_Print(logger, WLOG_ERROR, "geometry not removed from geometries"); } else if (updateType == GEOMETRY_UPDATE) { @@ -213,7 +212,7 @@ static UINT geometry_recv_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream* s) if (!mappedGeometry) { newOne = TRUE; - WLog_DBG(TAG, "creating geometry 0x%" PRIx64 "", id); + WLog_Print(logger, WLOG_DEBUG, "creating geometry 0x%" PRIx64 "", id); mappedGeometry = calloc(1, sizeof(MAPPED_GEOMETRY)); if (!mappedGeometry) return CHANNEL_RC_NO_MEMORY; @@ -224,14 +223,15 @@ static UINT geometry_recv_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream* s) if (!HashTable_Insert(context->geometries, &(mappedGeometry->mappingId), mappedGeometry)) { - WLog_ERR(TAG, "unable to register geometry 0x%" PRIx64 " in the table", id); + WLog_Print(logger, WLOG_ERROR, + "unable to register geometry 0x%" PRIx64 " in the table", id); free(mappedGeometry); return CHANNEL_RC_NO_MEMORY; } } else { - WLog_DBG(TAG, "updating geometry 0x%" PRIx64 "", id); + WLog_Print(logger, WLOG_DEBUG, "updating geometry 0x%" PRIx64 "", id); } Stream_Read_UINT64(s, mappedGeometry->topLevelId); @@ -247,6 +247,9 @@ static UINT geometry_recv_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream* s) Stream_Read_INT32(s, mappedGeometry->topLevelBottom); Stream_Read_UINT32(s, geometryType); + if (geometryType != 0x02) + WLog_Print(logger, WLOG_DEBUG, "geometryType should be set to 0x02 and is 0x%" PRIx32, + geometryType); Stream_Read_UINT32(s, cbGeometryBuffer); if (!Stream_CheckAndLogRequiredLength(TAG, s, cbGeometryBuffer)) @@ -254,7 +257,7 @@ static UINT geometry_recv_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream* s) if (cbGeometryBuffer) { - ret = geometry_read_RGNDATA(s, cbGeometryBuffer, &mappedGeometry->geometry); + ret = geometry_read_RGNDATA(logger, s, cbGeometryBuffer, &mappedGeometry->geometry); if (ret != CHANNEL_RC_OK) return ret; } @@ -268,7 +271,7 @@ static UINT geometry_recv_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream* s) if (context->MappedGeometryAdded && !context->MappedGeometryAdded(context, mappedGeometry)) { - WLog_ERR(TAG, "geometry added callback failed"); + WLog_Print(logger, WLOG_ERROR, "geometry added callback failed"); ret = ERROR_INTERNAL_ERROR; } } @@ -277,14 +280,14 @@ static UINT geometry_recv_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream* s) if (mappedGeometry->MappedGeometryUpdate && !mappedGeometry->MappedGeometryUpdate(mappedGeometry)) { - WLog_ERR(TAG, "geometry update callback failed"); + WLog_Print(logger, WLOG_ERROR, "geometry update callback failed"); ret = ERROR_INTERNAL_ERROR; } } } else { - WLog_ERR(TAG, "unknown updateType=%" PRIu32 "", updateType); + WLog_Print(logger, WLOG_ERROR, "unknown updateType=%" PRIu32 "", updateType); ret = CHANNEL_RC_OK; } @@ -313,101 +316,6 @@ static UINT geometry_on_close(IWTSVirtualChannelCallback* pChannelCallback) return CHANNEL_RC_OK; } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT geometry_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, - IWTSVirtualChannel* pChannel, BYTE* Data, - BOOL* pbAccept, - IWTSVirtualChannelCallback** ppCallback) -{ - GENERIC_CHANNEL_CALLBACK* callback; - GENERIC_LISTENER_CALLBACK* listener_callback = (GENERIC_LISTENER_CALLBACK*)pListenerCallback; - - WINPR_UNUSED(Data); - WINPR_UNUSED(pbAccept); - - callback = (GENERIC_CHANNEL_CALLBACK*)calloc(1, sizeof(GENERIC_CHANNEL_CALLBACK)); - - if (!callback) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - callback->iface.OnDataReceived = geometry_on_data_received; - callback->iface.OnClose = geometry_on_close; - callback->plugin = listener_callback->plugin; - callback->channel_mgr = listener_callback->channel_mgr; - callback->channel = pChannel; - listener_callback->channel_callback = callback; - *ppCallback = (IWTSVirtualChannelCallback*)callback; - return CHANNEL_RC_OK; -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT geometry_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) -{ - UINT status; - GEOMETRY_PLUGIN* geometry = (GEOMETRY_PLUGIN*)pPlugin; - if (geometry->initialized) - { - WLog_ERR(TAG, "[%s] channel initialized twice, aborting", GEOMETRY_DVC_CHANNEL_NAME); - return ERROR_INVALID_DATA; - } - geometry->listener_callback = - (GENERIC_LISTENER_CALLBACK*)calloc(1, sizeof(GENERIC_LISTENER_CALLBACK)); - - if (!geometry->listener_callback) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - geometry->listener_callback->iface.OnNewChannelConnection = geometry_on_new_channel_connection; - geometry->listener_callback->plugin = pPlugin; - geometry->listener_callback->channel_mgr = pChannelMgr; - status = - pChannelMgr->CreateListener(pChannelMgr, GEOMETRY_DVC_CHANNEL_NAME, 0, - &geometry->listener_callback->iface, &(geometry->listener)); - geometry->listener->pInterface = geometry->iface.pInterface; - - geometry->initialized = status == CHANNEL_RC_OK; - return status; -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT geometry_plugin_terminated(IWTSPlugin* pPlugin) -{ - GEOMETRY_PLUGIN* geometry = (GEOMETRY_PLUGIN*)pPlugin; - GeometryClientContext* context = (GeometryClientContext*)geometry->iface.pInterface; - - if (geometry && geometry->listener_callback) - { - IWTSVirtualChannelManager* mgr = geometry->listener_callback->channel_mgr; - if (mgr) - IFCALL(mgr->DestroyListener, mgr, geometry->listener); - } - - if (context) - HashTable_Free(context->geometries); - - free(geometry->listener_callback); - free(geometry->iface.pInterface); - free(pPlugin); - return CHANNEL_RC_OK; -} - static void mappedGeometryUnref_void(void* arg) { MAPPED_GEOMETRY* g = (MAPPED_GEOMETRY*)arg; @@ -418,6 +326,59 @@ static void mappedGeometryUnref_void(void* arg) * Channel Client Interface */ +static const IWTSVirtualChannelCallback geometry_callbacks = { geometry_on_data_received, + NULL, /* Open */ + geometry_on_close }; + +static UINT init_plugin_cb(GENERIC_DYNVC_PLUGIN* base, rdpContext* rcontext, rdpSettings* settings) +{ + GeometryClientContext* context; + GEOMETRY_PLUGIN* geometry = (GEOMETRY_PLUGIN*)base; + + WINPR_ASSERT(base); + WINPR_UNUSED(settings); + + context = (GeometryClientContext*)calloc(1, sizeof(GeometryClientContext)); + if (!context) + { + WLog_Print(base->log, WLOG_ERROR, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + context->geometries = HashTable_New(FALSE); + if (!context->geometries) + { + WLog_Print(base->log, WLOG_ERROR, "unable to allocate geometries"); + free(context); + return CHANNEL_RC_NO_MEMORY; + } + + HashTable_SetHashFunction(context->geometries, mappedGeometryHash); + { + wObject* obj = HashTable_KeyObject(context->geometries); + obj->fnObjectEquals = mappedGeometryKeyCompare; + } + { + wObject* obj = HashTable_ValueObject(context->geometries); + obj->fnObjectFree = mappedGeometryUnref_void; + } + context->handle = (void*)geometry; + + geometry->context = context; + geometry->base.iface.pInterface = (void*)context; + + return CHANNEL_RC_OK; +} + +static void terminate_plugin_cb(GENERIC_DYNVC_PLUGIN* base) +{ + GEOMETRY_PLUGIN* geometry = (GEOMETRY_PLUGIN*)base; + + if (geometry->context) + HashTable_Free(geometry->context->geometries); + free(geometry->context); +} + /** * Function description * @@ -425,58 +386,7 @@ static void mappedGeometryUnref_void(void* arg) */ UINT geometry_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { - UINT error = CHANNEL_RC_OK; - GEOMETRY_PLUGIN* geometry; - GeometryClientContext* context; - geometry = (GEOMETRY_PLUGIN*)pEntryPoints->GetPlugin(pEntryPoints, "geometry"); - - if (!geometry) - { - geometry = (GEOMETRY_PLUGIN*)calloc(1, sizeof(GEOMETRY_PLUGIN)); - - if (!geometry) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - geometry->iface.Initialize = geometry_plugin_initialize; - geometry->iface.Connected = NULL; - geometry->iface.Disconnected = NULL; - geometry->iface.Terminated = geometry_plugin_terminated; - context = (GeometryClientContext*)calloc(1, sizeof(GeometryClientContext)); - - if (!context) - { - WLog_ERR(TAG, "calloc failed!"); - goto error_context; - } - - context->geometries = HashTable_New(FALSE); - HashTable_SetHashFunction(context->geometries, mappedGeometryHash); - { - wObject* obj = HashTable_KeyObject(context->geometries); - obj->fnObjectEquals = mappedGeometryKeyCompare; - } - { - wObject* obj = HashTable_ValueObject(context->geometries); - obj->fnObjectFree = mappedGeometryUnref_void; - } - - context->handle = (void*)geometry; - geometry->iface.pInterface = (void*)context; - geometry->context = context; - error = pEntryPoints->RegisterPlugin(pEntryPoints, "geometry", &geometry->iface); - } - else - { - WLog_ERR(TAG, "could not get geometry Plugin."); - return CHANNEL_RC_BAD_CHANNEL; - } - - return error; - -error_context: - free(geometry); - return CHANNEL_RC_NO_MEMORY; + return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, GEOMETRY_DVC_CHANNEL_NAME, + sizeof(GEOMETRY_PLUGIN), sizeof(GENERIC_CHANNEL_CALLBACK), + &geometry_callbacks, init_plugin_cb, terminate_plugin_cb); } diff --git a/channels/rdpei/client/rdpei_main.c b/channels/rdpei/client/rdpei_main.c index 9209b0887..fdccb9f03 100644 --- a/channels/rdpei/client/rdpei_main.c +++ b/channels/rdpei/client/rdpei_main.c @@ -66,10 +66,7 @@ typedef struct { - IWTSPlugin iface; - - IWTSListener* listener; - GENERIC_LISTENER_CALLBACK* listener_callback; + GENERIC_DYNVC_PLUGIN base; RdpeiClientContext* context; @@ -87,7 +84,6 @@ typedef struct CRITICAL_SECTION lock; rdpContext* rdpcontext; - BOOL initialized; HANDLE thread; HANDLE event; } RDPEI_PLUGIN; @@ -343,14 +339,14 @@ static UINT rdpei_send_pen_frame(RdpeiClientContext* context, RDPINPUT_PEN_FRAME if (!context) return ERROR_INTERNAL_ERROR; rdpei = (RDPEI_PLUGIN*)context->handle; - if (!rdpei || !rdpei->listener_callback) + if (!rdpei || !rdpei->base.listener_callback) return ERROR_INTERNAL_ERROR; if (!rdpei || !rdpei->rdpcontext) return ERROR_INTERNAL_ERROR; if (freerdp_settings_get_bool(rdpei->rdpcontext->settings, FreeRDP_SuspendInput)) return CHANNEL_RC_OK; - callback = rdpei->listener_callback->channel_callback; + callback = rdpei->base.listener_callback->channel_callback; /* Just ignore the event if the channel is not connected */ if (!callback) return CHANNEL_RC_OK; @@ -444,7 +440,7 @@ static DWORD WINAPI rdpei_periodic_update(LPVOID arg) goto out; } - context = (RdpeiClientContext*)rdpei->iface.pInterface; + context = rdpei->context; if (!context) { @@ -452,7 +448,7 @@ static DWORD WINAPI rdpei_periodic_update(LPVOID arg) goto out; } - while (rdpei->initialized) + while (rdpei->base.initialized) { status = WaitForSingleObject(rdpei->event, 20); @@ -794,8 +790,10 @@ static UINT rdpei_recv_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream* s) UINT16 eventId; UINT32 pduLength; UINT error; + if (!s) return ERROR_INTERNAL_ERROR; + if (!Stream_CheckAndLogRequiredLength(TAG, s, 6)) return ERROR_INVALID_DATA; @@ -870,142 +868,16 @@ static UINT rdpei_on_close(IWTSVirtualChannelCallback* pChannelCallback) if (callback) { RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)callback->plugin; - if (rdpei && rdpei->listener_callback) + if (rdpei && rdpei->base.listener_callback) { - if (rdpei->listener_callback->channel_callback == callback) - rdpei->listener_callback->channel_callback = NULL; + if (rdpei->base.listener_callback->channel_callback == callback) + rdpei->base.listener_callback->channel_callback = NULL; } } free(callback); return CHANNEL_RC_OK; } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT rdpei_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, - IWTSVirtualChannel* pChannel, BYTE* Data, - BOOL* pbAccept, IWTSVirtualChannelCallback** ppCallback) -{ - GENERIC_CHANNEL_CALLBACK* callback; - GENERIC_LISTENER_CALLBACK* listener_callback = (GENERIC_LISTENER_CALLBACK*)pListenerCallback; - if (!listener_callback) - return ERROR_INTERNAL_ERROR; - callback = (GENERIC_CHANNEL_CALLBACK*)calloc(1, sizeof(GENERIC_CHANNEL_CALLBACK)); - - WINPR_UNUSED(Data); - WINPR_UNUSED(pbAccept); - - if (!callback) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - callback->iface.OnDataReceived = rdpei_on_data_received; - callback->iface.OnClose = rdpei_on_close; - callback->plugin = listener_callback->plugin; - callback->channel_mgr = listener_callback->channel_mgr; - callback->channel = pChannel; - listener_callback->channel_callback = callback; - *ppCallback = (IWTSVirtualChannelCallback*)callback; - return CHANNEL_RC_OK; -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT rdpei_plugin_terminated(IWTSPlugin* pPlugin) -{ - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)pPlugin; - - if (!pPlugin) - return ERROR_INVALID_PARAMETER; - - if (rdpei) - { - IWTSVirtualChannelManager* mgr = NULL; - - rdpei->initialized = FALSE; - if (rdpei->event) - SetEvent(rdpei->event); - - if (rdpei->thread) - { - WaitForSingleObject(rdpei->thread, INFINITE); - CloseHandle(rdpei->thread); - } - if (rdpei->event) - CloseHandle(rdpei->event); - - if (rdpei->listener_callback) - mgr = rdpei->listener_callback->channel_mgr; - - if (mgr) - IFCALL(mgr->DestroyListener, mgr, rdpei->listener); - } - DeleteCriticalSection(&rdpei->lock); - free(rdpei->listener_callback); - free(rdpei->context); - free(rdpei); - return CHANNEL_RC_OK; -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT rdpei_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) -{ - UINT error; - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)pPlugin; - - if (rdpei->initialized) - { - WLog_ERR(TAG, "[%s] channel initialized twice, aborting", RDPEI_DVC_CHANNEL_NAME); - return ERROR_INVALID_DATA; - } - rdpei->listener_callback = - (GENERIC_LISTENER_CALLBACK*)calloc(1, sizeof(GENERIC_LISTENER_CALLBACK)); - - if (!rdpei->listener_callback) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - rdpei->listener_callback->iface.OnNewChannelConnection = rdpei_on_new_channel_connection; - rdpei->listener_callback->plugin = pPlugin; - rdpei->listener_callback->channel_mgr = pChannelMgr; - - if ((error = pChannelMgr->CreateListener(pChannelMgr, RDPEI_DVC_CHANNEL_NAME, 0, - &rdpei->listener_callback->iface, &(rdpei->listener)))) - { - WLog_ERR(TAG, "ChannelMgr->CreateListener failed with error %" PRIu32 "!", error); - goto error_out; - } - - rdpei->listener->pInterface = rdpei->iface.pInterface; - - InitializeCriticalSection(&rdpei->lock); - rdpei->event = CreateEventA(NULL, TRUE, FALSE, NULL); - if (!rdpei->event) - goto error_out; - rdpei->thread = CreateThread(NULL, 0, rdpei_periodic_update, rdpei, 0, NULL); - if (!rdpei->thread) - goto error_out; - rdpei->initialized = TRUE; - return error; -error_out: - rdpei_plugin_terminated(pPlugin); - return error; -} - /** * Channel Client Interface */ @@ -1040,7 +912,7 @@ UINT rdpei_send_frame(RdpeiClientContext* context, RDPINPUT_TOUCH_FRAME* frame) GENERIC_CHANNEL_CALLBACK* callback; UINT error; - callback = rdpei->listener_callback->channel_callback; + callback = rdpei->base.listener_callback->channel_callback; /* Just ignore the event if the channel is not connected */ if (!callback) @@ -1437,6 +1309,91 @@ static UINT rdpei_pen_raw_event(RdpeiClientContext* context, INT32 externalId, U return error; } +static UINT init_plugin_cb(GENERIC_DYNVC_PLUGIN* base, rdpContext* rcontext, rdpSettings* settings) +{ + RdpeiClientContext* context; + RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)base; + + WINPR_ASSERT(base); + WINPR_UNUSED(settings); + + rdpei->version = RDPINPUT_PROTOCOL_V300; + rdpei->currentFrameTime = 0; + rdpei->previousFrameTime = 0; + rdpei->maxTouchContacts = MAX_CONTACTS; + rdpei->maxPenContacts = MAX_PEN_CONTACTS; + rdpei->rdpcontext = rcontext; + + InitializeCriticalSection(&rdpei->lock); + rdpei->event = CreateEventA(NULL, TRUE, FALSE, NULL); + if (!rdpei->event) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + context = (RdpeiClientContext*)calloc(1, sizeof(*context)); + if (!context) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + context->clientFeaturesMask = UINT32_MAX; + context->handle = (void*)rdpei; + context->GetVersion = rdpei_get_version; + context->GetFeatures = rdpei_get_features; + context->AddContact = rdpei_add_contact; + context->TouchBegin = rdpei_touch_begin; + context->TouchUpdate = rdpei_touch_update; + context->TouchEnd = rdpei_touch_end; + context->TouchCancel = rdpei_touch_cancel; + context->TouchRawEvent = rdpei_touch_raw_event; + context->AddPen = rdpei_add_pen; + context->PenBegin = rdpei_pen_begin; + context->PenUpdate = rdpei_pen_update; + context->PenEnd = rdpei_pen_end; + context->PenCancel = rdpei_pen_cancel; + context->PenRawEvent = rdpei_pen_raw_event; + + rdpei->context = context; + rdpei->base.iface.pInterface = (void*)context; + + rdpei->thread = CreateThread(NULL, 0, rdpei_periodic_update, rdpei, 0, NULL); + if (!rdpei->thread) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + return CHANNEL_RC_OK; +} + +static void terminate_plugin_cb(GENERIC_DYNVC_PLUGIN* base) +{ + RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)base; + WINPR_ASSERT(rdpei); + + if (rdpei->event) + SetEvent(rdpei->event); + + if (rdpei->thread) + { + WaitForSingleObject(rdpei->thread, INFINITE); + CloseHandle(rdpei->thread); + } + + if (rdpei->event) + CloseHandle(rdpei->event); + + DeleteCriticalSection(&rdpei->lock); + free(rdpei->context); +} + +static const IWTSVirtualChannelCallback geometry_callbacks = { rdpei_on_data_received, + NULL, /* Open */ + rdpei_on_close }; + /** * Function description * @@ -1444,71 +1401,7 @@ static UINT rdpei_pen_raw_event(RdpeiClientContext* context, INT32 externalId, U */ UINT rdpei_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { - UINT error; - RDPEI_PLUGIN* rdpei = NULL; - RdpeiClientContext* context = NULL; - rdpei = (RDPEI_PLUGIN*)pEntryPoints->GetPlugin(pEntryPoints, "rdpei"); - - if (!rdpei) - { - rdpei = (RDPEI_PLUGIN*)calloc(1, sizeof(RDPEI_PLUGIN)); - - if (!rdpei) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - rdpei->iface.Initialize = rdpei_plugin_initialize; - rdpei->iface.Connected = NULL; - rdpei->iface.Disconnected = NULL; - rdpei->iface.Terminated = rdpei_plugin_terminated; - rdpei->version = RDPINPUT_PROTOCOL_V300; - rdpei->currentFrameTime = 0; - rdpei->previousFrameTime = 0; - rdpei->maxTouchContacts = MAX_CONTACTS; - rdpei->maxPenContacts = MAX_PEN_CONTACTS; - rdpei->rdpcontext = pEntryPoints->GetRdpContext(pEntryPoints); - - context = (RdpeiClientContext*)calloc(1, sizeof(RdpeiClientContext)); - - if (!context) - { - WLog_ERR(TAG, "calloc failed!"); - error = CHANNEL_RC_NO_MEMORY; - goto error_out; - } - - context->clientFeaturesMask = UINT32_MAX; - context->handle = (void*)rdpei; - context->GetVersion = rdpei_get_version; - context->GetFeatures = rdpei_get_features; - context->AddContact = rdpei_add_contact; - context->TouchBegin = rdpei_touch_begin; - context->TouchUpdate = rdpei_touch_update; - context->TouchEnd = rdpei_touch_end; - context->TouchCancel = rdpei_touch_cancel; - context->TouchRawEvent = rdpei_touch_raw_event; - context->AddPen = rdpei_add_pen; - context->PenBegin = rdpei_pen_begin; - context->PenUpdate = rdpei_pen_update; - context->PenEnd = rdpei_pen_end; - context->PenCancel = rdpei_pen_cancel; - context->PenRawEvent = rdpei_pen_raw_event; - - rdpei->context = context; - rdpei->iface.pInterface = (void*)context; - - if ((error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpei", &rdpei->iface))) - { - WLog_ERR(TAG, "EntryPoints->RegisterPlugin failed with error %" PRIu32 "!", error); - error = CHANNEL_RC_NO_MEMORY; - goto error_out; - } - } - - return CHANNEL_RC_OK; -error_out: - rdpei_plugin_terminated(&rdpei->iface); - return error; + return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, RDPEI_DVC_CHANNEL_NAME, + sizeof(RDPEI_PLUGIN), sizeof(GENERIC_CHANNEL_CALLBACK), + &geometry_callbacks, init_plugin_cb, terminate_plugin_cb); } diff --git a/channels/rdpgfx/client/rdpgfx_codec.c b/channels/rdpgfx/client/rdpgfx_codec.c index 28976b65d..7de6f6f79 100644 --- a/channels/rdpgfx/client/rdpgfx_codec.c +++ b/channels/rdpgfx/client/rdpgfx_codec.c @@ -128,7 +128,7 @@ static UINT rdpgfx_decode_AVC420(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd UINT error; wStream* s; RDPGFX_AVC420_BITMAP_STREAM h264; - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; s = Stream_New(cmd->data, cmd->length); if (!s) @@ -173,7 +173,7 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd size_t pos1, pos2; wStream* s; RDPGFX_AVC444_BITMAP_STREAM h264 = { 0 }; - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; s = Stream_New(cmd->data, cmd->length); if (!s) @@ -259,7 +259,7 @@ fail: UINT rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) { UINT error = CHANNEL_RC_OK; - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; PROFILER_ENTER(context->SurfaceProfiler) switch (cmd->codecId) diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index d485c29a0..a6f4a3c83 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -115,10 +115,10 @@ static UINT rdpgfx_send_caps_advertise_pdu(RdpgfxClientContext* context, gfx = (RDPGFX_PLUGIN*)context->handle; - if (!gfx || !gfx->listener_callback) + if (!gfx || !gfx->base.listener_callback) return ERROR_BAD_ARGUMENTS; - callback = gfx->listener_callback->channel_callback; + callback = gfx->base.listener_callback->channel_callback; header.flags = 0; header.cmdId = RDPGFX_CMDID_CAPSADVERTISE; @@ -205,7 +205,7 @@ static UINT rdpgfx_send_supported_caps(GENERIC_CHANNEL_CALLBACK* callback) if (!gfx) return ERROR_BAD_CONFIGURATION; - context = (RdpgfxClientContext*)gfx->iface.pInterface; + context = gfx->context; if (!context) return ERROR_BAD_CONFIGURATION; @@ -365,8 +365,10 @@ static UINT rdpgfx_recv_caps_confirm_pdu(GENERIC_CHANNEL_CALLBACK* callback, wSt RDPGFX_CAPS_CONFIRM_PDU pdu = { 0 }; WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; + WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; + pdu.capsSet = &capsSet; if (!Stream_CheckAndLogRequiredLength(TAG, s, 12)) @@ -404,10 +406,10 @@ static UINT rdpgfx_send_frame_acknowledge_pdu(RdpgfxClientContext* context, gfx = (RDPGFX_PLUGIN*)context->handle; - if (!gfx || !gfx->listener_callback) + if (!gfx || !gfx->base.listener_callback) return ERROR_BAD_CONFIGURATION; - callback = gfx->listener_callback->channel_callback; + callback = gfx->base.listener_callback->channel_callback; if (!callback) return ERROR_BAD_CONFIGURATION; @@ -460,10 +462,10 @@ static UINT rdpgfx_send_qoe_frame_acknowledge_pdu(RdpgfxClientContext* context, gfx = (RDPGFX_PLUGIN*)context->handle; - if (!gfx || !gfx->listener_callback) + if (!gfx || !gfx->base.listener_callback) return ERROR_BAD_CONFIGURATION; - callback = gfx->listener_callback->channel_callback; + callback = gfx->base.listener_callback->channel_callback; if (!callback) return ERROR_BAD_CONFIGURATION; @@ -506,8 +508,10 @@ static UINT rdpgfx_recv_reset_graphics_pdu(GENERIC_CHANNEL_CALLBACK* callback, w WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; + WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + + RdpgfxClientContext* context = gfx->context; UINT error = CHANNEL_RC_OK; GraphicsResetEventArgs graphicsReset = { 0 }; @@ -592,7 +596,7 @@ static UINT rdpgfx_recv_evict_cache_entry_pdu(GENERIC_CHANNEL_CALLBACK* callback WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; UINT error = CHANNEL_RC_OK; if (!Stream_CheckAndLogRequiredLength(TAG, s, 2)) @@ -707,7 +711,7 @@ static UINT rdpgfx_save_persistent_cache(RDPGFX_PLUGIN* gfx) WINPR_ASSERT(gfx); WINPR_ASSERT(gfx->rdpcontext); rdpSettings* settings = gfx->rdpcontext->settings; - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; WINPR_ASSERT(context); WINPR_ASSERT(settings); @@ -774,10 +778,10 @@ static UINT rdpgfx_send_cache_import_offer_pdu(RdpgfxClientContext* context, gfx = (RDPGFX_PLUGIN*)context->handle; - if (!gfx || !gfx->listener_callback) + if (!gfx || !gfx->base.listener_callback) return ERROR_BAD_CONFIGURATION; - callback = gfx->listener_callback->channel_callback; + callback = gfx->base.listener_callback->channel_callback; if (!callback) return ERROR_BAD_CONFIGURATION; @@ -839,7 +843,7 @@ static UINT rdpgfx_send_cache_offer(RDPGFX_PLUGIN* gfx) WINPR_ASSERT(gfx); WINPR_ASSERT(gfx->rdpcontext); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; rdpSettings* settings = gfx->rdpcontext->settings; if (!settings->BitmapCachePersistEnabled) @@ -923,7 +927,7 @@ static UINT rdpgfx_load_cache_import_reply(RDPGFX_PLUGIN* gfx, RDPGFX_CACHE_IMPO WINPR_ASSERT(gfx); WINPR_ASSERT(gfx->rdpcontext); rdpSettings* settings = gfx->rdpcontext->settings; - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; WINPR_ASSERT(settings); WINPR_ASSERT(reply); @@ -990,7 +994,7 @@ static UINT rdpgfx_recv_cache_import_reply_pdu(GENERIC_CHANNEL_CALLBACK* callbac WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; UINT error = CHANNEL_RC_OK; if (!Stream_CheckAndLogRequiredLength(TAG, s, 2)) @@ -1044,7 +1048,7 @@ static UINT rdpgfx_recv_create_surface_pdu(GENERIC_CHANNEL_CALLBACK* callback, w WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; UINT error = CHANNEL_RC_OK; if (!Stream_CheckAndLogRequiredLength(TAG, s, 7)) @@ -1082,7 +1086,7 @@ static UINT rdpgfx_recv_delete_surface_pdu(GENERIC_CHANNEL_CALLBACK* callback, w WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; UINT error = CHANNEL_RC_OK; if (!Stream_CheckAndLogRequiredLength(TAG, s, 2)) @@ -1114,7 +1118,7 @@ static UINT rdpgfx_recv_start_frame_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStr WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; UINT error = CHANNEL_RC_OK; if (!Stream_CheckAndLogRequiredLength(TAG, s, RDPGFX_START_FRAME_PDU_SIZE)) @@ -1151,7 +1155,7 @@ static UINT rdpgfx_recv_end_frame_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStrea WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; UINT error = CHANNEL_RC_OK; if (!Stream_CheckAndLogRequiredLength(TAG, s, RDPGFX_END_FRAME_PDU_SIZE)) @@ -1340,7 +1344,7 @@ static UINT rdpgfx_recv_wire_to_surface_2_pdu(GENERIC_CHANNEL_CALLBACK* callback WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; UINT error = CHANNEL_RC_OK; if (!Stream_CheckAndLogRequiredLength(TAG, s, RDPGFX_WIRE_TO_SURFACE_PDU_2_SIZE)) @@ -1412,7 +1416,7 @@ static UINT rdpgfx_recv_delete_encoding_context_pdu(GENERIC_CHANNEL_CALLBACK* ca WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; UINT error = CHANNEL_RC_OK; if (!Stream_CheckAndLogRequiredLength(TAG, s, 6)) @@ -1450,7 +1454,7 @@ static UINT rdpgfx_recv_solid_fill_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStre WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; UINT error; if (!Stream_CheckAndLogRequiredLength(TAG, s, 8)) @@ -1519,7 +1523,7 @@ static UINT rdpgfx_recv_surface_to_surface_pdu(GENERIC_CHANNEL_CALLBACK* callbac WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; UINT error; if (!Stream_CheckAndLogRequiredLength(TAG, s, 14)) @@ -1591,8 +1595,9 @@ static UINT rdpgfx_recv_surface_to_cache_pdu(GENERIC_CHANNEL_CALLBACK* callback, RDPGFX_SURFACE_TO_CACHE_PDU pdu = { 0 }; WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; + WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; UINT error; if (!Stream_CheckAndLogRequiredLength(TAG, s, 20)) @@ -1642,7 +1647,7 @@ static UINT rdpgfx_recv_cache_to_surface_pdu(GENERIC_CHANNEL_CALLBACK* callback, RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; UINT error = CHANNEL_RC_OK; if (!Stream_CheckAndLogRequiredLength(TAG, s, 6)) @@ -1704,8 +1709,9 @@ static UINT rdpgfx_recv_map_surface_to_output_pdu(GENERIC_CHANNEL_CALLBACK* call RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU pdu = { 0 }; WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; + WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; UINT error = CHANNEL_RC_OK; if (!Stream_CheckAndLogRequiredLength(TAG, s, 12)) @@ -1738,8 +1744,9 @@ static UINT rdpgfx_recv_map_surface_to_scaled_output_pdu(GENERIC_CHANNEL_CALLBAC RDPGFX_MAP_SURFACE_TO_SCALED_OUTPUT_PDU pdu = { 0 }; WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; + WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; UINT error = CHANNEL_RC_OK; if (!Stream_CheckAndLogRequiredLength(TAG, s, 20)) @@ -1779,8 +1786,9 @@ static UINT rdpgfx_recv_map_surface_to_window_pdu(GENERIC_CHANNEL_CALLBACK* call RDPGFX_MAP_SURFACE_TO_WINDOW_PDU pdu = { 0 }; WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; + WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; UINT error = CHANNEL_RC_OK; if (!Stream_CheckAndLogRequiredLength(TAG, s, 18)) @@ -1814,7 +1822,7 @@ static UINT rdpgfx_recv_map_surface_to_scaled_window_pdu(GENERIC_CHANNEL_CALLBAC WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; UINT error = CHANNEL_RC_OK; if (!Stream_CheckAndLogRequiredLength(TAG, s, 26)) @@ -2109,7 +2117,7 @@ static UINT rdpgfx_on_open(IWTSVirtualChannelCallback* pChannelCallback) WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + RdpgfxClientContext* context = gfx->context; UINT error = CHANNEL_RC_OK; BOOL do_caps_advertise = TRUE; gfx->sendFrameAcks = TRUE; @@ -2140,9 +2148,11 @@ static UINT rdpgfx_on_close(IWTSVirtualChannelCallback* pChannelCallback) GENERIC_CHANNEL_CALLBACK* callback = (GENERIC_CHANNEL_CALLBACK*)pChannelCallback; WINPR_ASSERT(callback); RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; + if (!gfx) goto fail; - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; + + RdpgfxClientContext* context = gfx->context; DEBUG_RDPGFX(gfx->log, "OnClose"); error = rdpgfx_save_persistent_cache(gfx); @@ -2170,102 +2180,14 @@ fail: return CHANNEL_RC_OK; } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT rdpgfx_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, - IWTSVirtualChannel* pChannel, BYTE* Data, - BOOL* pbAccept, - IWTSVirtualChannelCallback** ppCallback) +static void terminate_plugin_cb(GENERIC_DYNVC_PLUGIN* base) { - GENERIC_CHANNEL_CALLBACK* callback; - GENERIC_LISTENER_CALLBACK* listener_callback = (GENERIC_LISTENER_CALLBACK*)pListenerCallback; - - WINPR_ASSERT(listener_callback); - WINPR_ASSERT(pChannel); - WINPR_ASSERT(ppCallback); - - callback = (GENERIC_CHANNEL_CALLBACK*)calloc(1, sizeof(GENERIC_CHANNEL_CALLBACK)); - - if (!callback) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - callback->iface.OnDataReceived = rdpgfx_on_data_received; - callback->iface.OnOpen = rdpgfx_on_open; - callback->iface.OnClose = rdpgfx_on_close; - callback->plugin = listener_callback->plugin; - callback->channel_mgr = listener_callback->channel_mgr; - callback->channel = pChannel; - listener_callback->channel_callback = callback; - *ppCallback = &callback->iface; - return CHANNEL_RC_OK; -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT rdpgfx_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) -{ - UINT error; - RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)pPlugin; - + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)base; WINPR_ASSERT(gfx); - WINPR_ASSERT(pChannelMgr); + RdpgfxClientContext* context = gfx->context; - if (gfx->initialized) - { - WLog_ERR(TAG, "[%s] channel initialized twice, aborting", RDPGFX_DVC_CHANNEL_NAME); - return ERROR_INVALID_DATA; - } - gfx->listener_callback = - (GENERIC_LISTENER_CALLBACK*)calloc(1, sizeof(GENERIC_LISTENER_CALLBACK)); - - if (!gfx->listener_callback) - { - WLog_Print(gfx->log, WLOG_ERROR, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - gfx->listener_callback->iface.OnNewChannelConnection = rdpgfx_on_new_channel_connection; - gfx->listener_callback->plugin = pPlugin; - gfx->listener_callback->channel_mgr = pChannelMgr; - - WINPR_ASSERT(pChannelMgr->CreateListener); - error = pChannelMgr->CreateListener(pChannelMgr, RDPGFX_DVC_CHANNEL_NAME, 0, - &gfx->listener_callback->iface, &(gfx->listener)); - gfx->listener->pInterface = gfx->iface.pInterface; - DEBUG_RDPGFX(gfx->log, "Initialize"); - - gfx->initialized = error == CHANNEL_RC_OK; - return error; -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT rdpgfx_plugin_terminated(IWTSPlugin* pPlugin) -{ - RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)pPlugin; - WINPR_ASSERT(gfx); - RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; DEBUG_RDPGFX(gfx->log, "Terminated"); - if (gfx && gfx->listener_callback) - { - IWTSVirtualChannelManager* mgr = gfx->listener_callback->channel_mgr; - if (mgr) - IFCALL(mgr->DestroyListener, mgr, gfx->listener); - } rdpgfx_client_context_free(context); - return CHANNEL_RC_OK; } /** @@ -2390,49 +2312,41 @@ static void* rdpgfx_get_cache_slot_data(RdpgfxClientContext* context, UINT16 cac return pData; } -RdpgfxClientContext* rdpgfx_client_context_new(rdpContext* rdpcontext) +static UINT init_plugin_cb(GENERIC_DYNVC_PLUGIN* base, rdpContext* rcontext, rdpSettings* settings) { - RDPGFX_PLUGIN* gfx; RdpgfxClientContext* context; + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)base; - WINPR_ASSERT(rdpcontext); + WINPR_ASSERT(base); + gfx->rdpcontext = rcontext; - gfx = (RDPGFX_PLUGIN*)calloc(1, sizeof(RDPGFX_PLUGIN)); - - if (!gfx) - { - WLog_ERR(TAG, "calloc failed!"); - return NULL; - } - - gfx->log = WLog_Get(TAG); - - if (!gfx->log) - { - free(gfx); - WLog_ERR(TAG, "Failed to acquire reference to WLog %s", TAG); - return NULL; - } - - gfx->rdpcontext = rdpcontext; gfx->SurfaceTable = HashTable_New(TRUE); - if (!gfx->SurfaceTable) { - free(gfx); - WLog_ERR(TAG, "HashTable_New failed!"); - return NULL; + WLog_ERR(TAG, "HashTable_New for surfaces failed !"); + return CHANNEL_RC_NO_MEMORY; } gfx->MaxCacheSlots = freerdp_settings_get_bool(gfx->rdpcontext->settings, FreeRDP_GfxSmallCache) ? 4096 : 25600; - context = (RdpgfxClientContext*)calloc(1, sizeof(RdpgfxClientContext)); + context = (RdpgfxClientContext*)calloc(1, sizeof(RdpgfxClientContext)); if (!context) { - free(gfx); - WLog_ERR(TAG, "calloc failed!"); - return NULL; + WLog_ERR(TAG, "context calloc failed!"); + HashTable_Free(gfx->SurfaceTable); + gfx->SurfaceTable = NULL; + return CHANNEL_RC_NO_MEMORY; + } + + gfx->zgfx = zgfx_context_new(FALSE); + if (!gfx->zgfx) + { + WLog_ERR(TAG, "zgfx_context_new failed!"); + HashTable_Free(gfx->SurfaceTable); + gfx->SurfaceTable = NULL; + free(context); + return CHANNEL_RC_NO_MEMORY; } context->handle = (void*)gfx; @@ -2446,18 +2360,9 @@ RdpgfxClientContext* rdpgfx_client_context_new(rdpContext* rdpcontext) context->CacheImportOffer = rdpgfx_send_cache_import_offer_pdu; context->QoeFrameAcknowledge = rdpgfx_send_qoe_frame_acknowledge_pdu; - gfx->iface.pInterface = (void*)context; - gfx->zgfx = zgfx_context_new(FALSE); - - if (!gfx->zgfx) - { - free(gfx); - free(context); - WLog_ERR(TAG, "zgfx_context_new failed!"); - return NULL; - } - - return context; + gfx->base.iface.pInterface = (void*)context; + gfx->context = context; + return CHANNEL_RC_OK; } void rdpgfx_client_context_free(RdpgfxClientContext* context) @@ -2473,12 +2378,6 @@ void rdpgfx_client_context_free(RdpgfxClientContext* context) free_surfaces(context, gfx->SurfaceTable); evict_cache_slots(context, gfx->MaxCacheSlots, gfx->CacheSlots); - if (gfx->listener_callback) - { - free(gfx->listener_callback); - gfx->listener_callback = NULL; - } - if (gfx->zgfx) { zgfx_context_free(gfx->zgfx); @@ -2487,9 +2386,11 @@ void rdpgfx_client_context_free(RdpgfxClientContext* context) HashTable_Free(gfx->SurfaceTable); free(context); - free(gfx); } +static const IWTSVirtualChannelCallback rdpgfx_callbacks = { rdpgfx_on_data_received, + rdpgfx_on_open, rdpgfx_on_close }; + /** * Function description * @@ -2497,36 +2398,7 @@ void rdpgfx_client_context_free(RdpgfxClientContext* context) */ UINT rdpgfx_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { - UINT error = CHANNEL_RC_OK; - RDPGFX_PLUGIN* gfx; - RdpgfxClientContext* context; - - WINPR_ASSERT(pEntryPoints); - WINPR_ASSERT(pEntryPoints->GetPlugin); - - gfx = (RDPGFX_PLUGIN*)pEntryPoints->GetPlugin(pEntryPoints, "rdpgfx"); - - if (!gfx) - { - WINPR_ASSERT(pEntryPoints->GetRdpContext); - context = rdpgfx_client_context_new(pEntryPoints->GetRdpContext(pEntryPoints)); - - if (!context) - { - WLog_ERR(TAG, "rdpgfx_client_context_new failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - gfx = (RDPGFX_PLUGIN*)context->handle; - - gfx->iface.Initialize = rdpgfx_plugin_initialize; - gfx->iface.Connected = NULL; - gfx->iface.Disconnected = NULL; - gfx->iface.Terminated = rdpgfx_plugin_terminated; - - WINPR_ASSERT(pEntryPoints->RegisterPlugin); - error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpgfx", &gfx->iface); - } - - return error; + return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, RDPGFX_DVC_CHANNEL_NAME, + sizeof(RDPGFX_PLUGIN), sizeof(GENERIC_CHANNEL_CALLBACK), + &rdpgfx_callbacks, init_plugin_cb, terminate_plugin_cb); } diff --git a/channels/rdpgfx/client/rdpgfx_main.h b/channels/rdpgfx/client/rdpgfx_main.h index 6de5241c7..41ce4afd5 100644 --- a/channels/rdpgfx/client/rdpgfx_main.h +++ b/channels/rdpgfx/client/rdpgfx_main.h @@ -36,10 +36,7 @@ typedef struct { - IWTSPlugin iface; - - IWTSListener* listener; - GENERIC_LISTENER_CALLBACK* listener_callback; + GENERIC_DYNVC_PLUGIN base; ZGFX_CONTEXT* zgfx; UINT32 UnacknowledgedFrames; @@ -58,7 +55,7 @@ typedef struct wLog* log; RDPGFX_CAPSET ConnectionCaps; - BOOL initialized; + RdpgfxClientContext* context; } RDPGFX_PLUGIN; #endif /* FREERDP_CHANNEL_RDPGFX_CLIENT_MAIN_H */ diff --git a/include/freerdp/client/channels.h b/include/freerdp/client/channels.h index 60293a8a8..33a43b9c2 100644 --- a/include/freerdp/client/channels.h +++ b/include/freerdp/client/channels.h @@ -41,6 +41,25 @@ typedef struct GENERIC_CHANNEL_CALLBACK* channel_callback; } GENERIC_LISTENER_CALLBACK; +typedef struct GENERIC_DYNVC_PLUGIN GENERIC_DYNVC_PLUGIN; +typedef UINT (*DYNVC_PLUGIN_INIT_FN)(GENERIC_DYNVC_PLUGIN* plugin, rdpContext* context, + rdpSettings* settings); +typedef void (*DYNVC_PLUGIN_TERMINATE_FN)(GENERIC_DYNVC_PLUGIN* plugin); + +struct GENERIC_DYNVC_PLUGIN +{ + IWTSPlugin iface; + GENERIC_LISTENER_CALLBACK* listener_callback; + IWTSListener* listener; + BOOL attached; + BOOL initialized; + wLog* log; + char* dynvc_name; + size_t channelCallbackSize; + const IWTSVirtualChannelCallback* channel_callbacks; + DYNVC_PLUGIN_TERMINATE_FN terminatePluginFn; +}; + #ifdef __cplusplus extern "C" { @@ -57,6 +76,13 @@ extern "C" LPCSTR lpType, DWORD dwFlags); FREERDP_API void freerdp_channels_addin_list_free(FREERDP_ADDIN** ppAddins); + FREERDP_API BOOL freerdp_initialize_generic_dynvc_plugin(GENERIC_DYNVC_PLUGIN* plugin); + FREERDP_API UINT freerdp_generic_DVCPluginEntry( + IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* logTag, const char* name, + size_t pluginSize, size_t channelCallbackSize, + const IWTSVirtualChannelCallback* channel_callbacks, DYNVC_PLUGIN_INIT_FN initPluginFn, + DYNVC_PLUGIN_TERMINATE_FN terminatePluginFn); + #ifdef __cplusplus } #endif diff --git a/include/freerdp/client/geometry.h b/include/freerdp/client/geometry.h index aa335a45b..202ad2c71 100644 --- a/include/freerdp/client/geometry.h +++ b/include/freerdp/client/geometry.h @@ -57,6 +57,7 @@ struct s_geometry_client_context void* custom; pcMappedGeometryAdded MappedGeometryAdded; + UINT32 remoteVersion; }; #ifdef __cplusplus