/* * 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 "dvc.h" #include "guac_list.h" #include "rdp.h" #include #include #include #include #include guac_rdp_dvc_list* guac_rdp_dvc_list_alloc() { guac_rdp_dvc_list* list = malloc(sizeof(guac_rdp_dvc_list)); /* Initialize with empty backing list */ list->channels = guac_common_list_alloc(); list->channel_count = 0; return list; } void guac_rdp_dvc_list_add(guac_rdp_dvc_list* list, const char* name, ...) { va_list args; guac_rdp_dvc* dvc = malloc(sizeof(guac_rdp_dvc)); va_start(args, name); /* Count number of arguments (excluding terminating NULL) */ dvc->argc = 1; while (va_arg(args, char*) != NULL) dvc->argc++; /* Reset va_list */ va_end(args); va_start(args, name); /* Copy argument values into DVC entry */ dvc->argv = malloc(sizeof(char*) * dvc->argc); dvc->argv[0] = strdup(name); int i; for (i = 1; i < dvc->argc; i++) dvc->argv[i] = strdup(va_arg(args, char*)); va_end(args); /* Add entry to DVC list */ guac_common_list_add(list->channels, dvc); /* Update channel count */ list->channel_count++; } void guac_rdp_dvc_list_free(guac_rdp_dvc_list* list) { /* For each channel */ guac_common_list_element* current = list->channels->head; while (current != NULL) { /* Free arguments declaration for current channel */ guac_rdp_dvc* dvc = (guac_rdp_dvc*) current->data; /* Free the underlying arguments list if not delegated to FreeRDP */ if (dvc->argv != NULL) { /* Free each argument value */ for (int i = 0; i < dvc->argc; i++) free(dvc->argv[i]); free(dvc->argv); } free(dvc); current = current->next; } /* Free underlying list */ guac_common_list_free(list->channels); /* Free the DVC list itself */ free(list); } int guac_rdp_load_drdynvc(rdpContext* context, guac_rdp_dvc_list* list) { guac_client* client = ((rdp_freerdp_context*) context)->client; rdpChannels* channels = context->channels; /* Skip if no channels will be loaded */ if (list->channel_count == 0) return 0; /* For each channel */ guac_common_list_element* current = list->channels->head; while (current != NULL) { /* Get channel arguments */ guac_rdp_dvc* dvc = (guac_rdp_dvc*) current->data; current = current->next; /* guac_rdp_dvc_list_add() guarantees at one argument */ assert(dvc->argc >= 1); /* guac_rdp_load_drdynvc() MUST only be invoked once */ assert(dvc->argv != NULL); /* Log registration of plugin for current channel */ guac_client_log(client, GUAC_LOG_DEBUG, "Registering DVC plugin \"%s\"", dvc->argv[0]); /* Register plugin with FreeRDP */ ADDIN_ARGV* args = malloc(sizeof(ADDIN_ARGV)); args->argc = dvc->argc; args->argv = dvc->argv; freerdp_dynamic_channel_collection_add(context->settings, args); /* Rely on FreeRDP to free argv storage */ dvc->argv = NULL; } /* Load virtual channel management plugin */ return freerdp_channels_load_plugin(channels, context->settings, "drdynvc", context->settings); }