blob: 0048b8915587932ccf5d12d792144cc47a454dd3 [file] [log] [blame]
/*
* 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 "plugins/channels.h"
#include "rdp.h"
#include <freerdp/channels/channels.h>
#include <freerdp/freerdp.h>
#include <freerdp/addin.h>
#include <winpr/wtypes.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
int guac_rdp_wrapped_entry_ex_count = 0;
int guac_rdp_wrapped_entry_count = 0;
PVIRTUALCHANNELENTRYEX guac_rdp_wrapped_entry_ex[GUAC_RDP_MAX_CHANNELS] = { NULL };
PVIRTUALCHANNELENTRY guac_rdp_wrapped_entry[GUAC_RDP_MAX_CHANNELS] = { NULL };
PVIRTUALCHANNELENTRYEX guac_rdp_plugin_wrap_entry_ex(guac_client* client,
PVIRTUALCHANNELENTRYEX entry_ex) {
/* Do not wrap if there is insufficient space to store the wrapped
* function */
if (guac_rdp_wrapped_entry_ex_count == GUAC_RDP_MAX_CHANNELS) {
guac_client_log(client, GUAC_LOG_WARNING, "Maximum number of static "
"channels has been reached. Further FreeRDP plugins and "
"channel support may fail to load.");
return entry_ex;
}
/* Generate wrapped version of provided entry point */
PVIRTUALCHANNELENTRYEX wrapper = guac_rdp_entry_ex_wrappers[guac_rdp_wrapped_entry_ex_count];
guac_rdp_wrapped_entry_ex[guac_rdp_wrapped_entry_ex_count] = entry_ex;
guac_rdp_wrapped_entry_ex_count++;
return wrapper;
}
PVIRTUALCHANNELENTRY guac_rdp_plugin_wrap_entry(guac_client* client,
PVIRTUALCHANNELENTRY entry) {
/* Do not wrap if there is insufficient space to store the wrapped
* function */
if (guac_rdp_wrapped_entry_count == GUAC_RDP_MAX_CHANNELS) {
guac_client_log(client, GUAC_LOG_WARNING, "Maximum number of static "
"channels has been reached. Further FreeRDP plugins and "
"channel support may fail to load.");
return entry;
}
/* Generate wrapped version of provided entry point */
PVIRTUALCHANNELENTRY wrapper = guac_rdp_entry_wrappers[guac_rdp_wrapped_entry_count];
guac_rdp_wrapped_entry[guac_rdp_wrapped_entry_count] = entry;
guac_rdp_wrapped_entry_count++;
return wrapper;
}
int guac_freerdp_channels_load_plugin(rdpContext* context,
const char* name, void* data) {
guac_client* client = ((rdp_freerdp_context*) context)->client;
/* 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) {
entry_ex = guac_rdp_plugin_wrap_entry_ex(client, entry_ex);
return freerdp_channels_client_load_ex(context->channels, context->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) {
entry = guac_rdp_plugin_wrap_entry(client, entry);
return freerdp_channels_client_load(context->channels, context->settings, entry, data);
}
/* The plugin does not exist / cannot be loaded */
return 1;
}
void guac_freerdp_dynamic_channel_collection_add(rdpSettings* settings,
const char* name, ...) {
va_list args;
ADDIN_ARGV* freerdp_args = malloc(sizeof(ADDIN_ARGV));
va_start(args, name);
/* Count number of arguments (excluding terminating NULL) */
freerdp_args->argc = 1;
while (va_arg(args, char*) != NULL)
freerdp_args->argc++;
/* Reset va_list */
va_end(args);
va_start(args, name);
/* Copy argument values into DVC entry */
freerdp_args->argv = malloc(sizeof(char*) * freerdp_args->argc);
freerdp_args->argv[0] = strdup(name);
int i;
for (i = 1; i < freerdp_args->argc; i++)
freerdp_args->argv[i] = strdup(va_arg(args, char*));
va_end(args);
/* Register plugin with FreeRDP */
settings->SupportDynamicChannels = TRUE;
freerdp_dynamic_channel_collection_add(settings, freerdp_args);
}