channels.c (4946B)
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20#include "plugins/channels.h" 21#include "rdp.h" 22 23#include <freerdp/channels/channels.h> 24#include <freerdp/freerdp.h> 25#include <freerdp/addin.h> 26#include <guacamole/mem.h> 27#include <winpr/wtypes.h> 28 29#include <stdarg.h> 30#include <stdlib.h> 31#include <string.h> 32 33int guac_rdp_wrapped_entry_ex_count = 0; 34 35int guac_rdp_wrapped_entry_count = 0; 36 37PVIRTUALCHANNELENTRYEX guac_rdp_wrapped_entry_ex[GUAC_RDP_MAX_CHANNELS] = { NULL }; 38 39PVIRTUALCHANNELENTRY guac_rdp_wrapped_entry[GUAC_RDP_MAX_CHANNELS] = { NULL }; 40 41PVIRTUALCHANNELENTRYEX guac_rdp_plugin_wrap_entry_ex(guac_client* client, 42 PVIRTUALCHANNELENTRYEX entry_ex) { 43 44 /* Do not wrap if there is insufficient space to store the wrapped 45 * function */ 46 if (guac_rdp_wrapped_entry_ex_count == GUAC_RDP_MAX_CHANNELS) { 47 guac_client_log(client, GUAC_LOG_WARNING, "Maximum number of static " 48 "channels has been reached. Further FreeRDP plugins and " 49 "channel support may fail to load."); 50 return entry_ex; 51 } 52 53 /* Generate wrapped version of provided entry point */ 54 PVIRTUALCHANNELENTRYEX wrapper = guac_rdp_entry_ex_wrappers[guac_rdp_wrapped_entry_ex_count]; 55 guac_rdp_wrapped_entry_ex[guac_rdp_wrapped_entry_ex_count] = entry_ex; 56 guac_rdp_wrapped_entry_ex_count++; 57 58 return wrapper; 59 60} 61 62PVIRTUALCHANNELENTRY guac_rdp_plugin_wrap_entry(guac_client* client, 63 PVIRTUALCHANNELENTRY entry) { 64 65 /* Do not wrap if there is insufficient space to store the wrapped 66 * function */ 67 if (guac_rdp_wrapped_entry_count == GUAC_RDP_MAX_CHANNELS) { 68 guac_client_log(client, GUAC_LOG_WARNING, "Maximum number of static " 69 "channels has been reached. Further FreeRDP plugins and " 70 "channel support may fail to load."); 71 return entry; 72 } 73 74 /* Generate wrapped version of provided entry point */ 75 PVIRTUALCHANNELENTRY wrapper = guac_rdp_entry_wrappers[guac_rdp_wrapped_entry_count]; 76 guac_rdp_wrapped_entry[guac_rdp_wrapped_entry_count] = entry; 77 guac_rdp_wrapped_entry_count++; 78 79 return wrapper; 80 81} 82 83int guac_freerdp_channels_load_plugin(rdpContext* context, 84 const char* name, void* data) { 85 86 guac_client* client = ((rdp_freerdp_context*) context)->client; 87 88 /* Load plugin using "ex" version of the channel plugin entry point, if it exists */ 89 PVIRTUALCHANNELENTRYEX entry_ex = (PVIRTUALCHANNELENTRYEX) (void*) freerdp_load_channel_addin_entry(name, 90 NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC | FREERDP_ADDIN_CHANNEL_ENTRYEX); 91 92 if (entry_ex != NULL) { 93 entry_ex = guac_rdp_plugin_wrap_entry_ex(client, entry_ex); 94 return freerdp_channels_client_load_ex(context->channels, context->settings, entry_ex, data); 95 } 96 97 /* Lacking the "ex" entry point, attempt to load using the non-ex version */ 98 PVIRTUALCHANNELENTRY entry = freerdp_load_channel_addin_entry(name, 99 NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC); 100 101 if (entry != NULL) { 102 entry = guac_rdp_plugin_wrap_entry(client, entry); 103 return freerdp_channels_client_load(context->channels, context->settings, entry, data); 104 } 105 106 /* The plugin does not exist / cannot be loaded */ 107 return 1; 108 109} 110 111void guac_freerdp_dynamic_channel_collection_add(rdpSettings* settings, 112 const char* name, ...) { 113 114 va_list args; 115 116 ADDIN_ARGV* freerdp_args = malloc(sizeof(ADDIN_ARGV)); 117 118 va_start(args, name); 119 120 /* Count number of arguments (excluding terminating NULL) */ 121 freerdp_args->argc = 1; 122 while (va_arg(args, char*) != NULL) 123 freerdp_args->argc++; 124 125 /* Reset va_list */ 126 va_end(args); 127 va_start(args, name); 128 129 /* Copy argument values into DVC entry */ 130 freerdp_args->argv = malloc(guac_mem_ckd_mul_or_die(sizeof(char*), freerdp_args->argc)); 131 freerdp_args->argv[0] = strdup(name); 132 int i; 133 for (i = 1; i < freerdp_args->argc; i++) 134 freerdp_args->argv[i] = strdup(va_arg(args, char*)); 135 136 va_end(args); 137 138 /* Register plugin with FreeRDP */ 139 settings->SupportDynamicChannels = TRUE; 140 freerdp_dynamic_channel_collection_add(settings, freerdp_args); 141 142} 143