| /* |
| * 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); |
| |
| } |
| |