20#include <freerdp/config.h>
21#include <freerdp/log.h>
22#include <freerdp/client/channels.h>
24#define TAG FREERDP_TAG("genericdynvc")
28 if (!plugin || !plugin->dynvc_name)
30 const size_t len = strlen(plugin->dynvc_name);
31 plugin->dynvc_name[len + 1] = (char)val;
38 if (!plugin || !plugin->dynvc_name)
40 const size_t len = strlen(plugin->dynvc_name);
41 return plugin->dynvc_name[len + 1];
44static UINT generic_on_close(IWTSVirtualChannelCallback* pChannelCallback)
47 WINPR_ASSERT(callback);
55 WINPR_ASSERT(plugin->channel_callbacks);
57 IFCALLRESULT(CHANNEL_RC_OK, plugin->channel_callbacks->OnClose, pChannelCallback);
58 generic_update_connected_state(plugin, FALSE);
63static UINT generic_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
64 IWTSVirtualChannel* pChannel,
65 WINPR_ATTR_UNUSED BYTE* Data,
66 WINPR_ATTR_UNUSED BOOL* pbAccept,
67 IWTSVirtualChannelCallback** ppCallback)
71 if (!listener_callback || !listener_callback->plugin)
72 return ERROR_INTERNAL_ERROR;
75 WLog_Print(plugin->log, WLOG_TRACE,
"...");
77 if (generic_get_connected_state(plugin))
79 WLog_Print(plugin->log, WLOG_ERROR,
"Channel already connected, terminating.");
80 return ERROR_DEVICE_ALREADY_ATTACHED;
87 WLog_Print(plugin->log, WLOG_ERROR,
"calloc failed!");
88 return CHANNEL_RC_NO_MEMORY;
92 callback->iface = *plugin->channel_callbacks;
93 callback->iface.OnClose = generic_on_close;
95 callback->plugin = listener_callback->plugin;
96 callback->channel_mgr = listener_callback->channel_mgr;
97 callback->channel = pChannel;
99 listener_callback->channel_callback = callback;
100 listener_callback->channel = pChannel;
102 *ppCallback = &callback->iface;
103 generic_update_connected_state(plugin, TRUE);
104 return CHANNEL_RC_OK;
107static UINT generic_dynvc_plugin_initialize(IWTSPlugin* pPlugin,
108 IWTSVirtualChannelManager* pChannelMgr)
114 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
117 return ERROR_INVALID_PARAMETER;
119 if (plugin->initialized)
121 WLog_ERR(TAG,
"[%s] channel initialized twice, aborting", plugin->dynvc_name);
122 return ERROR_INVALID_DATA;
125 WLog_Print(plugin->log, WLOG_TRACE,
"...");
128 if (!listener_callback)
130 WLog_Print(plugin->log, WLOG_ERROR,
"calloc failed!");
131 return CHANNEL_RC_NO_MEMORY;
134 plugin->listener_callback = listener_callback;
135 listener_callback->iface.OnNewChannelConnection = generic_on_new_channel_connection;
136 listener_callback->plugin = pPlugin;
137 listener_callback->channel_mgr = pChannelMgr;
138 rc = pChannelMgr->CreateListener(pChannelMgr, plugin->dynvc_name, 0, &listener_callback->iface,
141 plugin->listener->pInterface = plugin->iface.pInterface;
142 plugin->initialized = (rc == CHANNEL_RC_OK);
146static UINT generic_plugin_terminated(IWTSPlugin* pPlugin)
149 UINT error = CHANNEL_RC_OK;
152 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
154 WLog_Print(plugin->log, WLOG_TRACE,
"...");
157 plugin->initialized = FALSE;
159 if (plugin->terminatePluginFn)
160 plugin->terminatePluginFn(plugin);
162 if (plugin->listener_callback)
164 IWTSVirtualChannelManager* mgr = plugin->listener_callback->channel_mgr;
166 IFCALL(mgr->DestroyListener, mgr, plugin->listener);
169 free(plugin->listener_callback);
170 free(plugin->dynvc_name);
175static UINT generic_dynvc_plugin_attached(IWTSPlugin* pPlugin)
178 UINT error = CHANNEL_RC_OK;
181 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
183 pluginn->attached = TRUE;
187static UINT generic_dynvc_plugin_detached(IWTSPlugin* pPlugin)
190 UINT error = CHANNEL_RC_OK;
193 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
195 plugin->attached = FALSE;
199UINT freerdp_generic_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints,
const char* logTag,
200 const char* name,
size_t pluginSize,
size_t channelCallbackSize,
201 const IWTSVirtualChannelCallback* channel_callbacks,
202 DYNVC_PLUGIN_INIT_FN initPluginFn,
203 DYNVC_PLUGIN_TERMINATE_FN terminatePluginFn)
206 UINT error = CHANNEL_RC_INITIALIZATION_ERROR;
208 WINPR_ASSERT(pEntryPoints);
209 WINPR_ASSERT(pEntryPoints->GetPlugin);
210 WINPR_ASSERT(logTag);
212 WINPR_ASSERT(pluginSize >=
sizeof(*plugin));
216 if (plugin !=
nullptr)
217 return CHANNEL_RC_ALREADY_INITIALIZED;
222 WLog_ERR(TAG,
"calloc failed!");
223 return CHANNEL_RC_NO_MEMORY;
226 plugin->log = WLog_Get(logTag);
227 plugin->attached = TRUE;
228 plugin->channel_callbacks = channel_callbacks;
229 plugin->channelCallbackSize = channelCallbackSize;
230 plugin->iface.Initialize = generic_dynvc_plugin_initialize;
231 plugin->iface.Connected =
nullptr;
232 plugin->iface.Disconnected =
nullptr;
233 plugin->iface.Terminated = generic_plugin_terminated;
234 plugin->iface.Attached = generic_dynvc_plugin_attached;
235 plugin->iface.Detached = generic_dynvc_plugin_detached;
236 plugin->terminatePluginFn = terminatePluginFn;
240 rdpSettings* settings = pEntryPoints->GetRdpSettings(pEntryPoints);
241 rdpContext* context = pEntryPoints->GetRdpContext(pEntryPoints);
243 error = initPluginFn(plugin, context, settings);
244 if (error != CHANNEL_RC_OK)
250 const size_t len = strlen(name);
251 plugin->dynvc_name = calloc(len + 2,
sizeof(
char));
252 if (!plugin->dynvc_name)
254 strncpy(plugin->dynvc_name, name, len);
256 error = pEntryPoints->RegisterPlugin(pEntryPoints, name, &plugin->iface);
257 if (error == CHANNEL_RC_OK)
261 generic_plugin_terminated(&plugin->iface);