FreeRDP
Loading...
Searching...
No Matches
generic_dynvc.c
1
20#include <freerdp/config.h>
21#include <freerdp/log.h>
22#include <freerdp/client/channels.h>
23
24#define TAG FREERDP_TAG("genericdynvc")
25
26static UINT generic_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
27 IWTSVirtualChannel* pChannel,
28 WINPR_ATTR_UNUSED BYTE* Data,
29 WINPR_ATTR_UNUSED BOOL* pbAccept,
30 IWTSVirtualChannelCallback** ppCallback)
31{
32 GENERIC_CHANNEL_CALLBACK* callback = NULL;
33 GENERIC_DYNVC_PLUGIN* plugin = NULL;
34 GENERIC_LISTENER_CALLBACK* listener_callback = (GENERIC_LISTENER_CALLBACK*)pListenerCallback;
35
36 if (!listener_callback || !listener_callback->plugin)
37 return ERROR_INTERNAL_ERROR;
38
39 plugin = (GENERIC_DYNVC_PLUGIN*)listener_callback->plugin;
40 WLog_Print(plugin->log, WLOG_TRACE, "...");
41
42 callback = (GENERIC_CHANNEL_CALLBACK*)calloc(1, plugin->channelCallbackSize);
43 if (!callback)
44 {
45 WLog_Print(plugin->log, WLOG_ERROR, "calloc failed!");
46 return CHANNEL_RC_NO_MEMORY;
47 }
48
49 /* implant configured channel callbacks */
50 callback->iface = *plugin->channel_callbacks;
51
52 callback->plugin = listener_callback->plugin;
53 callback->channel_mgr = listener_callback->channel_mgr;
54 callback->channel = pChannel;
55
56 listener_callback->channel_callback = callback;
57 listener_callback->channel = pChannel;
58
59 *ppCallback = (IWTSVirtualChannelCallback*)callback;
60 return CHANNEL_RC_OK;
61}
62
63static UINT generic_dynvc_plugin_initialize(IWTSPlugin* pPlugin,
64 IWTSVirtualChannelManager* pChannelMgr)
65{
66 UINT rc = 0;
67 GENERIC_LISTENER_CALLBACK* listener_callback = NULL;
69
70 if (!plugin)
71 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
72
73 if (!pChannelMgr)
74 return ERROR_INVALID_PARAMETER;
75
76 if (plugin->initialized)
77 {
78 WLog_ERR(TAG, "[%s] channel initialized twice, aborting", plugin->dynvc_name);
79 return ERROR_INVALID_DATA;
80 }
81
82 WLog_Print(plugin->log, WLOG_TRACE, "...");
83 listener_callback = (GENERIC_LISTENER_CALLBACK*)calloc(1, sizeof(GENERIC_LISTENER_CALLBACK));
84 if (!listener_callback)
85 {
86 WLog_Print(plugin->log, WLOG_ERROR, "calloc failed!");
87 return CHANNEL_RC_NO_MEMORY;
88 }
89
90 plugin->listener_callback = listener_callback;
91 listener_callback->iface.OnNewChannelConnection = generic_on_new_channel_connection;
92 listener_callback->plugin = pPlugin;
93 listener_callback->channel_mgr = pChannelMgr;
94 rc = pChannelMgr->CreateListener(pChannelMgr, plugin->dynvc_name, 0, &listener_callback->iface,
95 &plugin->listener);
96
97 plugin->listener->pInterface = plugin->iface.pInterface;
98 plugin->initialized = (rc == CHANNEL_RC_OK);
99 return rc;
100}
101
102static UINT generic_plugin_terminated(IWTSPlugin* pPlugin)
103{
104 GENERIC_DYNVC_PLUGIN* plugin = (GENERIC_DYNVC_PLUGIN*)pPlugin;
105 UINT error = CHANNEL_RC_OK;
106
107 if (!plugin)
108 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
109
110 WLog_Print(plugin->log, WLOG_TRACE, "...");
111
112 /* some channels (namely rdpei), look at initialized to see if they should continue to run */
113 plugin->initialized = FALSE;
114
115 if (plugin->terminatePluginFn)
116 plugin->terminatePluginFn(plugin);
117
118 if (plugin->listener_callback)
119 {
120 IWTSVirtualChannelManager* mgr = plugin->listener_callback->channel_mgr;
121 if (mgr)
122 IFCALL(mgr->DestroyListener, mgr, plugin->listener);
123 }
124
125 free(plugin->listener_callback);
126 free(plugin->dynvc_name);
127 free(plugin);
128 return error;
129}
130
131static UINT generic_dynvc_plugin_attached(IWTSPlugin* pPlugin)
132{
133 GENERIC_DYNVC_PLUGIN* pluginn = (GENERIC_DYNVC_PLUGIN*)pPlugin;
134 UINT error = CHANNEL_RC_OK;
135
136 if (!pluginn)
137 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
138
139 pluginn->attached = TRUE;
140 return error;
141}
142
143static UINT generic_dynvc_plugin_detached(IWTSPlugin* pPlugin)
144{
145 GENERIC_DYNVC_PLUGIN* plugin = (GENERIC_DYNVC_PLUGIN*)pPlugin;
146 UINT error = CHANNEL_RC_OK;
147
148 if (!plugin)
149 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
150
151 plugin->attached = FALSE;
152 return error;
153}
154
155UINT freerdp_generic_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* logTag,
156 const char* name, size_t pluginSize, size_t channelCallbackSize,
157 const IWTSVirtualChannelCallback* channel_callbacks,
158 DYNVC_PLUGIN_INIT_FN initPluginFn,
159 DYNVC_PLUGIN_TERMINATE_FN terminatePluginFn)
160{
161 GENERIC_DYNVC_PLUGIN* plugin = NULL;
162 UINT error = CHANNEL_RC_INITIALIZATION_ERROR;
163
164 WINPR_ASSERT(pEntryPoints);
165 WINPR_ASSERT(pEntryPoints->GetPlugin);
166 WINPR_ASSERT(logTag);
167 WINPR_ASSERT(name);
168 WINPR_ASSERT(pluginSize >= sizeof(*plugin));
169 WINPR_ASSERT(channelCallbackSize >= sizeof(GENERIC_CHANNEL_CALLBACK));
170
171 plugin = (GENERIC_DYNVC_PLUGIN*)pEntryPoints->GetPlugin(pEntryPoints, name);
172 if (plugin != NULL)
173 return CHANNEL_RC_ALREADY_INITIALIZED;
174
175 plugin = (GENERIC_DYNVC_PLUGIN*)calloc(1, pluginSize);
176 if (!plugin)
177 {
178 WLog_ERR(TAG, "calloc failed!");
179 return CHANNEL_RC_NO_MEMORY;
180 }
181
182 plugin->log = WLog_Get(logTag);
183 plugin->attached = TRUE;
184 plugin->channel_callbacks = channel_callbacks;
185 plugin->channelCallbackSize = channelCallbackSize;
186 plugin->iface.Initialize = generic_dynvc_plugin_initialize;
187 plugin->iface.Connected = NULL;
188 plugin->iface.Disconnected = NULL;
189 plugin->iface.Terminated = generic_plugin_terminated;
190 plugin->iface.Attached = generic_dynvc_plugin_attached;
191 plugin->iface.Detached = generic_dynvc_plugin_detached;
192 plugin->terminatePluginFn = terminatePluginFn;
193
194 if (initPluginFn)
195 {
196 rdpSettings* settings = pEntryPoints->GetRdpSettings(pEntryPoints);
197 rdpContext* context = pEntryPoints->GetRdpContext(pEntryPoints);
198
199 error = initPluginFn(plugin, context, settings);
200 if (error != CHANNEL_RC_OK)
201 goto error;
202 }
203
204 plugin->dynvc_name = _strdup(name);
205 if (!plugin->dynvc_name)
206 goto error;
207
208 error = pEntryPoints->RegisterPlugin(pEntryPoints, name, &plugin->iface);
209 if (error == CHANNEL_RC_OK)
210 return error;
211
212error:
213 generic_plugin_terminated(&plugin->iface);
214 return error;
215}