GUACAMOLE-249: Load FreeRDP plugins regardless of entry point interface.

Most plugins built into FreeRDP implement the PVIRTUALCHANNELENTRYEX
entry point, but the FreeRDP standard function for loading plugins only
supports PVIRTUALCHANNELENTRY. It appears that only the commandline
argument parser included with FreeRDP was updated to leverage the new
entry points.
This commit is contained in:
Michael Jumper 2019-10-06 14:44:06 -07:00
parent b89ed7ff15
commit 16be3af03c
5 changed files with 124 additions and 7 deletions

View File

@ -34,6 +34,7 @@ nodist_libguac_client_rdp_la_SOURCES = \
libguac_client_rdp_la_SOURCES = \ libguac_client_rdp_la_SOURCES = \
audio_input.c \ audio_input.c \
channels.c \
client.c \ client.c \
decompose.c \ decompose.c \
dvc.c \ dvc.c \
@ -103,6 +104,7 @@ noinst_HEADERS = \
guac_svc/svc_service.h \ guac_svc/svc_service.h \
audio_input.h \ audio_input.h \
client.h \ client.h \
channels.h \
decompose.h \ decompose.h \
dvc.h \ dvc.h \
error.h \ error.h \

View File

@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "config.h"
#include <freerdp/channels/channels.h>
#include <freerdp/freerdp.h>
int guac_freerdp_channels_load_plugin(rdpChannels* channels,
rdpSettings* settings, const char* name, void* data) {
/* Load plugin using "ex" version of the channel plugin entry point, if it exists */
PVIRTUALCHANNELENTRYEX entry_ex = (PVIRTUALCHANNELENTRYEX) (void*) freerdp_load_channel_addin_entry(name,
NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC | FREERDP_ADDIN_CHANNEL_ENTRYEX);
if (entry_ex != NULL)
return freerdp_channels_client_load_ex(channels, settings, entry_ex, data);
/* Lacking the "ex" entry point, attempt to load using the non-ex version */
PVIRTUALCHANNELENTRY entry = freerdp_load_channel_addin_entry(name,
NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC);
if (entry != NULL)
return freerdp_channels_client_load(channels, settings, entry, data);
/* The plugin does not exist / cannot be loaded */
return 1;
}

View File

@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#ifndef GUAC_RDP_CHANNELS_H
#define GUAC_RDP_CHANNELS_H
#include "config.h"
#include <freerdp/channels/channels.h>
#include <freerdp/freerdp.h>
/**
* Loads the FreeRDP plugin having the given name. This function is a drop-in
* replacement for freerdp_channels_load_plugin() which additionally loads
* plugins implementing the PVIRTUALCHANNELENTRYEX version of the channel
* plugin entry point. The freerdp_channels_load_plugin() function which is
* part of FreeRDP can load only plugins which implement the
* PVIRTUALCHANNELENTRY version of the entry point.
*
* @param channels
* The rdpChannels structure with which the plugin should be registered
* once loaded. This structure should be retrieved directly from the
* relevant FreeRDP instance.
*
* @param settings
* The rdpSettings structure associated with the FreeRDP instance, already
* populated with any settings applicable to the plugin being loaded.
*
* @param name
* The name of the plugin to load. If the plugin is not statically built
* into FreeRDP, this name will determine the filename of the library to be
* loaded dynamically. For a plugin named "NAME", the library called
* "libNAME-client" will be loaded from the "freerdp2" subdirectory of the
* main directory containing the FreeRDP libraries.
*
* @param data
* Arbitrary data to be passed to the plugin entry point. For most plugins
* which are built into FreeRDP, this will be another reference to the
* rdpSettings struct. The source of the relevant plugin must be consulted
* to determine the proper value to pass here.
*
* @return
* Zero if the plugin was loaded successfully, non-zero if the plugin could
* not be loaded.
*/
int guac_freerdp_channels_load_plugin(rdpChannels* channels,
rdpSettings* settings, const char* name, void* data);
#endif

View File

@ -19,6 +19,7 @@
#include "config.h" #include "config.h"
#include "common/list.h" #include "common/list.h"
#include "channels.h"
#include "dvc.h" #include "dvc.h"
#include "rdp.h" #include "rdp.h"
@ -147,8 +148,9 @@ int guac_rdp_load_drdynvc(rdpContext* context, guac_rdp_dvc_list* list) {
} }
/* Load virtual channel management plugin */ /* Load virtual channel management plugin */
return freerdp_channels_load_plugin(channels, context->instance->settings, return guac_freerdp_channels_load_plugin(channels,
"drdynvc", context->instance->settings); context->instance->settings, "drdynvc",
context->instance->settings);
} }

View File

@ -20,6 +20,7 @@
#include "config.h" #include "config.h"
#include "audio_input.h" #include "audio_input.h"
#include "channels.h"
#include "client.h" #include "client.h"
#include "common/cursor.h" #include "common/cursor.h"
#include "common/display.h" #include "common/display.h"
@ -148,7 +149,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
} }
/* Load clipboard plugin */ /* Load clipboard plugin */
if (freerdp_channels_load_plugin(channels, instance->settings, if (guac_freerdp_channels_load_plugin(channels, instance->settings,
"cliprdr", NULL)) "cliprdr", NULL))
guac_client_log(client, GUAC_LOG_WARNING, guac_client_log(client, GUAC_LOG_WARNING,
"Failed to load cliprdr plugin. Clipboard will not work."); "Failed to load cliprdr plugin. Clipboard will not work.");
@ -159,14 +160,14 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
|| settings->audio_enabled) { || settings->audio_enabled) {
/* Load RDPDR plugin */ /* Load RDPDR plugin */
if (freerdp_channels_load_plugin(channels, instance->settings, if (guac_freerdp_channels_load_plugin(channels, instance->settings,
"guacdr", client)) "guacdr", client))
guac_client_log(client, GUAC_LOG_WARNING, guac_client_log(client, GUAC_LOG_WARNING,
"Failed to load guacdr plugin. Drive redirection and " "Failed to load guacdr plugin. Drive redirection and "
"printing will not work. Sound MAY not work."); "printing will not work. Sound MAY not work.");
/* Load RDPSND plugin */ /* Load RDPSND plugin */
if (freerdp_channels_load_plugin(channels, instance->settings, if (guac_freerdp_channels_load_plugin(channels, instance->settings,
"guacsnd", client)) "guacsnd", client))
guac_client_log(client, GUAC_LOG_WARNING, guac_client_log(client, GUAC_LOG_WARNING,
"Failed to load guacsnd alongside guacdr plugin. Sound " "Failed to load guacsnd alongside guacdr plugin. Sound "
@ -179,7 +180,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
if (settings->remote_app != NULL) { if (settings->remote_app != NULL) {
/* Attempt to load rail */ /* Attempt to load rail */
if (freerdp_channels_load_plugin(channels, instance->settings, if (guac_freerdp_channels_load_plugin(channels, instance->settings,
"rail", instance->settings)) "rail", instance->settings))
guac_client_log(client, GUAC_LOG_WARNING, guac_client_log(client, GUAC_LOG_WARNING,
"Failed to load rail plugin. RemoteApp will not work."); "Failed to load rail plugin. RemoteApp will not work.");
@ -196,7 +197,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
guac_rdp_svc* svc = guac_rdp_alloc_svc(client, *current); guac_rdp_svc* svc = guac_rdp_alloc_svc(client, *current);
/* Attempt to load guacsvc plugin for new static channel */ /* Attempt to load guacsvc plugin for new static channel */
if (freerdp_channels_load_plugin(channels, instance->settings, if (guac_freerdp_channels_load_plugin(channels, instance->settings,
"guacsvc", svc)) { "guacsvc", svc)) {
guac_client_log(client, GUAC_LOG_WARNING, guac_client_log(client, GUAC_LOG_WARNING,
"Cannot create static channel \"%s\": failed to load guacsvc plugin.", "Cannot create static channel \"%s\": failed to load guacsvc plugin.",