dynamic channels: mutualize things for listeners and plugins
The same code is copied in all dynamic channels to create a plugin, have a listener, and manage the channel lifecycle. This patch does a mutualization effort so that channels only have to code things that are specific to them.
This commit is contained in:
parent
ffcb25a925
commit
3478051f15
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
209
channels/client/generic_dynvc.c
Normal file
209
channels/client/generic_dynvc.c
Normal file
@ -0,0 +1,209 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Dynamic channel
|
||||
*
|
||||
* Copyright 2022 David Fort <contact@hardening-consulting.com>
|
||||
*
|
||||
* 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 <freerdp/log.h>
|
||||
#include <freerdp/client/channels.h>
|
||||
|
||||
#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;
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -57,6 +57,7 @@ struct s_geometry_client_context
|
||||
void* custom;
|
||||
|
||||
pcMappedGeometryAdded MappedGeometryAdded;
|
||||
UINT32 remoteVersion;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
Loading…
Reference in New Issue
Block a user