diff --git a/channels/drdynvc/audin/audin_main.c b/channels/drdynvc/audin/audin_main.c index b6a58df6b..095c53967 100644 --- a/channels/drdynvc/audin/audin_main.c +++ b/channels/drdynvc/audin/audin_main.c @@ -221,6 +221,7 @@ static boolean audin_receive_wave_data(uint8* data, int size, void* user_data) AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) user_data; error = audin_send_incoming_data_pdu((IWTSVirtualChannelCallback*) callback); + if (error != 0) return false; @@ -270,7 +271,7 @@ static int audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, STRE static int audin_process_format_change(IWTSVirtualChannelCallback* pChannelCallback, STREAM* s) { AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; - AUDIN_PLUGIN * audin = (AUDIN_PLUGIN *) callback->plugin; + AUDIN_PLUGIN * audin = (AUDIN_PLUGIN*) callback->plugin; uint32 NewFormat; audinFormat* format; @@ -299,9 +300,7 @@ static int audin_process_format_change(IWTSVirtualChannelCallback* pChannelCallb return 0; } -static int audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, - uint32 cbSize, - uint8* pBuffer) +static int audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, uint32 cbSize, uint8* pBuffer) { int error; STREAM* s; @@ -361,9 +360,7 @@ static int audin_on_close(IWTSVirtualChannelCallback* pChannelCallback) } static int audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, - IWTSVirtualChannel* pChannel, - uint8* Data, - int* pbAccept, + IWTSVirtualChannel* pChannel, uint8* Data, int* pbAccept, IWTSVirtualChannelCallback** ppCallback) { AUDIN_CHANNEL_CALLBACK* callback; @@ -395,6 +392,7 @@ static int audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage audin->listener_callback->iface.OnNewChannelConnection = audin_on_new_channel_connection; audin->listener_callback->plugin = pPlugin; audin->listener_callback->channel_mgr = pChannelMgr; + return pChannelMgr->CreateListener(pChannelMgr, "AUDIO_INPUT", 0, (IWTSListenerCallback*) audin->listener_callback, NULL); } @@ -411,6 +409,7 @@ static int audin_plugin_terminated(IWTSPlugin* pPlugin) IFCALL(audin->device->Free, audin->device); audin->device = NULL; } + xfree(audin->listener_callback); xfree(audin); @@ -439,23 +438,25 @@ static boolean audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, R FREERDP_AUDIN_DEVICE_ENTRY_POINTS entryPoints; if (strrchr(name, '.') != NULL) - entry = (PFREERDP_AUDIN_DEVICE_ENTRY)freerdp_load_plugin(name, AUDIN_DEVICE_EXPORT_FUNC_NAME); + { + entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_plugin(name, AUDIN_DEVICE_EXPORT_FUNC_NAME); + } else { fullname = xzalloc(strlen(name) + 8); strcpy(fullname, "audin_"); strcat(fullname, name); - entry = (PFREERDP_AUDIN_DEVICE_ENTRY)freerdp_load_plugin(fullname, AUDIN_DEVICE_EXPORT_FUNC_NAME); + entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_plugin(fullname, AUDIN_DEVICE_EXPORT_FUNC_NAME); xfree(fullname); } + if (entry == NULL) - { return false; - } entryPoints.plugin = pPlugin; entryPoints.pRegisterAudinDevice = audin_register_device_plugin; entryPoints.plugin_data = data; + if (entry(&entryPoints) != 0) { DEBUG_WARN("%s entry returns error.", name); @@ -471,7 +472,7 @@ static boolean audin_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* d AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; RDP_PLUGIN_DATA default_data[2] = { { 0 }, { 0 } }; - if (data->data[0] && (strcmp((char*)data->data[0], "audin") == 0 || strstr((char*)data->data[0], "/audin.") != NULL) ) + if (data->data[0] && (strcmp((char*)data->data[0], "audin") == 0 || strstr((char*) data->data[0], "/audin.") != NULL)) { if (data->data[1] && strcmp((char*)data->data[1], "format") == 0) { @@ -490,7 +491,7 @@ static boolean audin_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* d } else if (data->data[1] && ((char*)data->data[1])[0]) { - return audin_load_device_plugin(pPlugin, (char*)data->data[1], data); + return audin_load_device_plugin(pPlugin, (char*) data->data[1], data); } else { @@ -498,7 +499,9 @@ static boolean audin_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* d default_data[0].data[0] = "audin"; default_data[0].data[1] = "pulse"; default_data[0].data[2] = ""; + ret = audin_load_device_plugin(pPlugin, "pulse", default_data); + if (!ret) { default_data[0].size = sizeof(RDP_PLUGIN_DATA); @@ -507,6 +510,7 @@ static boolean audin_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* d default_data[0].data[2] = "default"; ret = audin_load_device_plugin(pPlugin, "alsa", default_data); } + return ret; } } @@ -520,6 +524,7 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) AUDIN_PLUGIN* audin; audin = (AUDIN_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "audin"); + if (audin == NULL) { audin = xnew(AUDIN_PLUGIN); @@ -532,10 +537,7 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) } if (error == 0) - { - audin_process_plugin_data((IWTSPlugin*) audin, - pEntryPoints->GetPluginData(pEntryPoints)); - } + audin_process_plugin_data((IWTSPlugin*) audin, pEntryPoints->GetPluginData(pEntryPoints)); return error; } diff --git a/channels/drdynvc/dvcman.c b/channels/drdynvc/dvcman.c index 645a3d7e2..d24b11489 100644 --- a/channels/drdynvc/dvcman.c +++ b/channels/drdynvc/dvcman.c @@ -80,18 +80,15 @@ struct _DVCMAN_CHANNEL STREAM* dvc_data; }; -static int dvcman_get_configuration(IWTSListener* pListener, - void** ppPropertyBag) +static int dvcman_get_configuration(IWTSListener* pListener, void** ppPropertyBag) { *ppPropertyBag = NULL; return 1; } static int dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr, - const char* pszChannelName, - uint32 ulFlags, - IWTSListenerCallback* pListenerCallback, - IWTSListener** ppListener) + const char* pszChannelName, uint32 ulFlags, + IWTSListenerCallback* pListenerCallback, IWTSListener** ppListener) { DVCMAN* dvcman = (DVCMAN*)pChannelMgr; DVCMAN_LISTENER* listener; @@ -118,13 +115,13 @@ static int dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr, } } -static int dvcman_push_event(IWTSVirtualChannelManager* pChannelMgr, - RDP_EVENT* pEvent) +static int dvcman_push_event(IWTSVirtualChannelManager* pChannelMgr, RDP_EVENT* pEvent) { - DVCMAN* dvcman = (DVCMAN*)pChannelMgr; int error; + DVCMAN* dvcman = (DVCMAN*) pChannelMgr; error = drdynvc_push_event(dvcman->drdynvc, pEvent); + if (error == 0) { DEBUG_DVC("event_type %d pushed.", pEvent->event_type); @@ -133,13 +130,13 @@ static int dvcman_push_event(IWTSVirtualChannelManager* pChannelMgr, { DEBUG_WARN("event_type %d push failed.", pEvent->event_type); } + return error; } -static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, - const char* name, IWTSPlugin* pPlugin) +static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name, IWTSPlugin* pPlugin) { - DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*)pEntryPoints)->dvcman; + DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman; if (dvcman->num_plugins < MAX_PLUGINS) { @@ -155,11 +152,10 @@ static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, } } -IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, - const char* name) +IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name) { - DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*)pEntryPoints)->dvcman; int i; + DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman; for (i = 0; i < dvcman->num_plugins; i++) { @@ -169,12 +165,13 @@ IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, return dvcman->plugins[i]; } } + return NULL; } RDP_PLUGIN_DATA* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { - return ((DVCMAN_ENTRY_POINTS*)pEntryPoints)->plugin_data; + return ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->plugin_data; } IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin) @@ -187,7 +184,7 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin) dvcman->drdynvc = plugin; dvcman->channels = list_new(); - return (IWTSVirtualChannelManager*)dvcman; + return (IWTSVirtualChannelManager*) dvcman; } int dvcman_load_plugin(IWTSVirtualChannelManager* pChannelMgr, RDP_PLUGIN_DATA* data) @@ -197,19 +194,19 @@ int dvcman_load_plugin(IWTSVirtualChannelManager* pChannelMgr, RDP_PLUGIN_DATA* while (data && data->size > 0) { - pDVCPluginEntry = freerdp_load_plugin((char*)data->data[0], "DVCPluginEntry"); + pDVCPluginEntry = freerdp_load_plugin((char*) data->data[0], "DVCPluginEntry"); if (pDVCPluginEntry != NULL) { entryPoints.iface.RegisterPlugin = dvcman_register_plugin; entryPoints.iface.GetPlugin = dvcman_get_plugin; entryPoints.iface.GetPluginData = dvcman_get_plugin_data; - entryPoints.dvcman = (DVCMAN*)pChannelMgr; + entryPoints.dvcman = (DVCMAN*) pChannelMgr; entryPoints.plugin_data = data; - pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*)&entryPoints); + pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*) &entryPoints); } - data = (RDP_PLUGIN_DATA*)(((void*)data) + data->size); + data = (RDP_PLUGIN_DATA*)(((void*) data) + data->size); } return 0; @@ -219,69 +216,75 @@ static void dvcman_channel_free(DVCMAN_CHANNEL* channel) { if (channel->channel_callback) channel->channel_callback->OnClose(channel->channel_callback); + xfree(channel); } void dvcman_free(IWTSVirtualChannelManager* pChannelMgr) { - DVCMAN* dvcman = (DVCMAN*)pChannelMgr; int i; IWTSPlugin* pPlugin; DVCMAN_LISTENER* listener; DVCMAN_CHANNEL* channel; + DVCMAN* dvcman = (DVCMAN*) pChannelMgr; - while ((channel = (DVCMAN_CHANNEL*)list_dequeue(dvcman->channels)) != NULL) + while ((channel = (DVCMAN_CHANNEL*) list_dequeue(dvcman->channels)) != NULL) dvcman_channel_free(channel); + list_free(dvcman->channels); + for (i = 0; i < dvcman->num_listeners; i++) { - listener = (DVCMAN_LISTENER*)dvcman->listeners[i]; + listener = (DVCMAN_LISTENER*) dvcman->listeners[i]; xfree(listener->channel_name); xfree(listener); } + for (i = 0; i < dvcman->num_plugins; i++) { pPlugin = dvcman->plugins[i]; + if (pPlugin->Terminated) pPlugin->Terminated(pPlugin); } + xfree(dvcman); } int dvcman_init(IWTSVirtualChannelManager* pChannelMgr) { - DVCMAN* dvcman = (DVCMAN*)pChannelMgr; int i; IWTSPlugin* pPlugin; + DVCMAN* dvcman = (DVCMAN*) pChannelMgr; for (i = 0; i < dvcman->num_plugins; i++) { pPlugin = dvcman->plugins[i]; + if (pPlugin->Initialize) pPlugin->Initialize(pPlugin, pChannelMgr); } + return 0; } -static int dvcman_write_channel(IWTSVirtualChannel* pChannel, - uint32 cbSize, - uint8* pBuffer, - void* pReserved) +static int dvcman_write_channel(IWTSVirtualChannel* pChannel, uint32 cbSize, uint8* pBuffer, void* pReserved) { - DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*)pChannel; + DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel; return drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize); } static int dvcman_close_channel_iface(IWTSVirtualChannel* pChannel) { - DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*)pChannel; + DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel; DVCMAN* dvcman = channel->dvcman; DEBUG_DVC("id=%d", channel->channel_id); if (list_remove(dvcman->channels, channel) == NULL) DEBUG_WARN("channel not found"); + dvcman_channel_free(channel); return 1; @@ -289,16 +292,17 @@ static int dvcman_close_channel_iface(IWTSVirtualChannel* pChannel) int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId, const char* ChannelName) { - DVCMAN* dvcman = (DVCMAN*)pChannelMgr; int i; + int bAccept; DVCMAN_LISTENER* listener; DVCMAN_CHANNEL* channel; - int bAccept; IWTSVirtualChannelCallback* pCallback; + DVCMAN* dvcman = (DVCMAN*) pChannelMgr; for (i = 0; i < dvcman->num_listeners; i++) { listener = (DVCMAN_LISTENER*)dvcman->listeners[i]; + if (strcmp(listener->channel_name, ChannelName) == 0) { channel = xnew(DVCMAN_CHANNEL); @@ -309,13 +313,15 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 Channel bAccept = 1; pCallback = NULL; + if (listener->listener_callback->OnNewChannelConnection(listener->listener_callback, - (IWTSVirtualChannel*)channel, NULL, &bAccept, &pCallback) == 0 && bAccept == 1) + (IWTSVirtualChannel*) channel, NULL, &bAccept, &pCallback) == 0 && bAccept == 1) { DEBUG_DVC("listener %s created new channel %d", listener->channel_name, channel->channel_id); channel->channel_callback = pCallback; list_add(dvcman->channels, channel); + return 0; } else @@ -326,21 +332,23 @@ int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 Channel } } } + return 1; } static DVCMAN_CHANNEL* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId) { - DVCMAN* dvcman = (DVCMAN*)pChannelMgr; LIST_ITEM* curr; + DVCMAN* dvcman = (DVCMAN*) pChannelMgr; for (curr = dvcman->channels->head; curr; curr = curr->next) { - if (((DVCMAN_CHANNEL*)curr->data)->channel_id == ChannelId) + if (((DVCMAN_CHANNEL*) curr->data)->channel_id == ChannelId) { return (DVCMAN_CHANNEL*)curr->data; } } + return NULL; } @@ -350,19 +358,23 @@ int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelI IWTSVirtualChannel* ichannel; channel = dvcman_find_channel_by_id(pChannelMgr, ChannelId); + if (channel == NULL) { DEBUG_WARN("ChannelId %d not found!", ChannelId); return 1; } + if (channel->dvc_data) { stream_free(channel->dvc_data); channel->dvc_data = NULL; } + DEBUG_DVC("dvcman_close_channel: channel %d closed", ChannelId); ichannel = (IWTSVirtualChannel*)channel; ichannel->Close(ichannel); + return 0; } @@ -371,13 +383,16 @@ int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, ui DVCMAN_CHANNEL* channel; channel = dvcman_find_channel_by_id(pChannelMgr, ChannelId); + if (channel == NULL) { DEBUG_WARN("ChannelId %d not found!", ChannelId); return 1; } + if (channel->dvc_data) stream_free(channel->dvc_data); + channel->dvc_data = stream_new(length); return 0; @@ -385,10 +400,11 @@ int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, ui int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, uint32 ChannelId, uint8* data, uint32 data_size) { - DVCMAN_CHANNEL* channel; int error = 0; + DVCMAN_CHANNEL* channel; channel = dvcman_find_channel_by_id(pChannelMgr, ChannelId); + if (channel == NULL) { DEBUG_WARN("ChannelId %d not found!", ChannelId); @@ -405,7 +421,9 @@ int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, uint32 C channel->dvc_data = NULL; return 1; } + stream_write(channel->dvc_data, data, data_size); + if (stream_get_length(channel->dvc_data) >= stream_get_size(channel->dvc_data)) { error = channel->channel_callback->OnDataReceived(channel->channel_callback, @@ -416,8 +434,7 @@ int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, uint32 C } else { - error = channel->channel_callback->OnDataReceived(channel->channel_callback, - data_size, data); + error = channel->channel_callback->OnDataReceived(channel->channel_callback, data_size, data); } return error; diff --git a/include/freerdp/utils/load_plugin.h b/include/freerdp/utils/load_plugin.h index 11bd4852b..9b698d0b4 100644 --- a/include/freerdp/utils/load_plugin.h +++ b/include/freerdp/utils/load_plugin.h @@ -21,7 +21,13 @@ #define __LOAD_PLUGIN_UTILS_H #include +#include +FREERDP_API void* freerdp_open_library(const char* file); +FREERDP_API void* freerdp_get_library_symbol(void* library, const char* name); +FREERDP_API boolean freerdp_close_library(void* library); +FREERDP_API void* freerdp_load_library_symbol(const char* file, const char* name); FREERDP_API void* freerdp_load_plugin(const char* name, const char* entry_name); +FREERDP_API void* freerdp_load_channel_plugin(rdpSettings* settings, const char* name, const char* entry_name); #endif /* __LOAD_PLUGIN_UTILS_H */ diff --git a/libfreerdp-channels/libchannels.c b/libfreerdp-channels/libchannels.c index c16548bc1..cb0a06b46 100644 --- a/libfreerdp-channels/libchannels.c +++ b/libfreerdp-channels/libchannels.c @@ -684,6 +684,7 @@ int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, c lib = channels->libs_data + channels->num_libs_data; lib->entry = (PVIRTUALCHANNELENTRY) freerdp_load_plugin(name, CHANNEL_EXPORT_FUNC_NAME); + //lib->entry = (PVIRTUALCHANNELENTRY) freerdp_load_channel_plugin(settings, name, CHANNEL_EXPORT_FUNC_NAME); if (lib->entry == NULL) { diff --git a/libfreerdp-utils/load_plugin.c b/libfreerdp-utils/load_plugin.c index 72a60722b..adab66eef 100644 --- a/libfreerdp-utils/load_plugin.c +++ b/libfreerdp-utils/load_plugin.c @@ -44,10 +44,82 @@ #endif +void* freerdp_open_library(const char* file) +{ + void* library; + + library = DLOPEN(file); + + if (library == NULL) + { + printf("freerdp_load_library: failed to open %s: %s\n", file, DLERROR()); + return NULL; + } + + return library; +} + +void* freerdp_get_library_symbol(void* library, const char* name) +{ + void* symbol; + + symbol = DLSYM(library, name); + + if (symbol == NULL) + { + printf("freerdp_get_library_symbol: failed to load %s: %s\n", name, DLERROR()); + return NULL; + } + + return symbol; +} + +boolean freerdp_close_library(void* library) +{ + int status; + + status = DLCLOSE(library); + +#ifdef _WIN32 + if (status != 0) +#else + if (status == 0) +#endif + { + printf("freerdp_free_library: failed to close: %s\n", DLERROR()); + return false; + } + + return true; +} + +void* freerdp_load_library_symbol(const char* file, const char* name) +{ + void* library; + void* symbol; + + library = DLOPEN(file); + + if (library == NULL) + { + printf("freerdp_load_library_symbol: failed to open %s: %s\n", file, DLERROR()); + return NULL; + } + + symbol = DLSYM(library, name); + + if (symbol == NULL) + { + printf("freerdp_load_library_symbol: failed to load %s: %s\n", file, DLERROR()); + return NULL; + } + + return symbol; +} + void* freerdp_load_plugin(const char* name, const char* entry_name) { char* path; - void* module; void* entry; char* suffixed_name; @@ -64,28 +136,74 @@ void* freerdp_load_plugin(const char* name, const char* entry_name) path = xstrdup(suffixed_name); } - module = DLOPEN(path); - - if (module == NULL) - { - printf("freerdp_load_plugin: failed to open %s: %s\n", path, DLERROR()); - xfree(suffixed_name); - xfree(path); - return NULL; - } - - entry = DLSYM(module, entry_name); - - if (entry == NULL) - { - printf("freerdp_load_plugin: failed to load %s: %s\n", path, DLERROR()); - xfree(suffixed_name); - xfree(path); - return NULL; - } + entry = freerdp_load_library_symbol(path, entry_name); xfree(suffixed_name); xfree(path); + if (entry == NULL) + { + printf("freerdp_load_plugin: failed to load %s/%s\n", name, entry_name); + return NULL; + } + + return entry; +} + +void* freerdp_load_channel_plugin(rdpSettings* settings, const char* name, const char* entry_name) +{ + char* path; + void* entry; + char* suffixed_name; + + suffixed_name = freerdp_append_shared_library_suffix((char*) name); + + if (!freerdp_path_contains_separator(suffixed_name)) + { + /* no explicit path given, use default path */ + + if (!settings->development_mode) + { + path = freerdp_construct_path(PLUGIN_PATH, suffixed_name); + } + else + { + char* dot; + char* plugin_name; + char* channels_path; + char* channel_subpath; + + dot = strrchr(suffixed_name, '.'); + plugin_name = xmalloc((dot - suffixed_name) + 1); + strncpy(plugin_name, suffixed_name, (dot - suffixed_name)); + plugin_name[(dot - suffixed_name)] = '\0'; + + channels_path = freerdp_construct_path(settings->development_path, "channels"); + channel_subpath = freerdp_construct_path(channels_path, plugin_name); + + path = freerdp_construct_path(channel_subpath, suffixed_name); + + xfree(plugin_name); + xfree(channels_path); + xfree(channel_subpath); + } + } + else + { + /* explicit path given, use it instead of default path */ + path = xstrdup(suffixed_name); + } + + entry = freerdp_load_library_symbol(path, entry_name); + + xfree(suffixed_name); + xfree(path); + + if (entry == NULL) + { + printf("freerdp_load_channel_plugin: failed to load %s/%s\n", name, entry_name); + return NULL; + } + return entry; }