Fix changelog email address
[freerdp-ubuntu-pcb-backport.git] / libfreerdp-core / extension.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Client
3  * FreeRDP Extension Plugin Interface
4  *
5  * Copyright 2010-2011 Vic Lee
6  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <freerdp/freerdp.h>
25 #include <freerdp/utils/print.h>
26 #include <freerdp/utils/memory.h>
27
28 #include "extension.h"
29
30 #ifdef _WIN32
31 #define DLOPEN(f) LoadLibraryA(f)
32 #define DLSYM(f, n) GetProcAddress(f, n)
33 #define DLCLOSE(f) FreeLibrary(f)
34 #define PATH_SEPARATOR '\\'
35 #define PLUGIN_EXT "dll"
36 #else
37 #include <dlfcn.h>
38 #define DLOPEN(f) dlopen(f, RTLD_LOCAL | RTLD_LAZY)
39 #define DLSYM(f, n) dlsym(f, n)
40 #define DLCLOSE(f) dlclose(f)
41 #define PATH_SEPARATOR '/'
42
43 #ifdef __APPLE__
44 #define PLUGIN_EXT "dylib"
45 #else
46 #define PLUGIN_EXT "so"
47 #endif 
48
49 #endif
50
51 static uint32 FREERDP_CC extension_register_plugin(rdpExtPlugin* plugin)
52 {
53         rdpExtension* ext = (rdpExtension*) plugin->ext;
54
55         if (ext->num_plugins >= FREERDP_EXT_MAX_COUNT)
56         {
57                 printf("extension_register_extension: maximum number of plugins reached.\n");
58                 return 1;
59         }
60
61         ext->plugins[ext->num_plugins++] = plugin;
62         return 0;
63 }
64
65 static uint32 FREERDP_CC extension_register_pre_connect_hook(rdpExtPlugin* plugin, PFREERDP_EXTENSION_HOOK hook)
66 {
67         rdpExtension* ext = (rdpExtension*) plugin->ext;
68
69         if (ext->num_pre_connect_hooks >= FREERDP_EXT_MAX_COUNT)
70         {
71                 printf("extension_register_pre_connect_hook: maximum plugin reached.\n");
72                 return 1;
73         }
74
75         ext->pre_connect_hooks[ext->num_pre_connect_hooks] = hook;
76         ext->pre_connect_hooks_instances[ext->num_pre_connect_hooks] = plugin;
77         ext->num_pre_connect_hooks++;
78         return 0;
79 }
80
81 static uint32 FREERDP_CC extension_register_post_connect_hook(rdpExtPlugin* plugin, PFREERDP_EXTENSION_HOOK hook)
82 {
83         rdpExtension* ext = (rdpExtension*) plugin->ext;
84
85         if (ext->num_post_connect_hooks >= FREERDP_EXT_MAX_COUNT)
86         {
87                 printf("extension_register_post_connect_hook: maximum plugin reached.\n");
88                 return 1;
89         }
90
91         ext->post_connect_hooks[ext->num_post_connect_hooks] = hook;
92         ext->post_connect_hooks_instances[ext->num_post_connect_hooks] = plugin;
93         ext->num_post_connect_hooks++;
94
95         return 0;
96 }
97
98 static int extension_load_plugins(rdpExtension* extension)
99 {
100         int i;
101         void* han;
102         char path[256];
103         rdpSettings* settings;
104         PFREERDP_EXTENSION_ENTRY entry;
105         FREERDP_EXTENSION_ENTRY_POINTS entryPoints;
106
107         settings = extension->instance->settings;
108
109         entryPoints.ext = extension;
110         entryPoints.pRegisterExtension = extension_register_plugin;
111         entryPoints.pRegisterPreConnectHook = extension_register_pre_connect_hook;
112         entryPoints.pRegisterPostConnectHook = extension_register_post_connect_hook;
113
114         for (i = 0; settings->extensions[i].name[0]; i++)
115         {
116                 if (strchr(settings->extensions[i].name, PATH_SEPARATOR) == NULL)
117                         snprintf(path, sizeof(path), EXT_PATH "/%s." PLUGIN_EXT, settings->extensions[i].name);
118                 else
119                         snprintf(path, sizeof(path), "%s", settings->extensions[i].name);
120
121                 han = DLOPEN(path);
122                 printf("extension_load_plugins: %s\n", path);
123                 if (han == NULL)
124                 {
125                         printf("extension_load_plugins: failed to load %s\n", path);
126                         continue;
127                 }
128
129                 entry = (PFREERDP_EXTENSION_ENTRY) DLSYM(han, FREERDP_EXT_EXPORT_FUNC_NAME);
130                 if (entry == NULL)
131                 {
132                         DLCLOSE(han);
133                         printf("extension_load_plugins: failed to find export function in %s\n", path);
134                         continue;
135                 }
136
137                 entryPoints.data = extension->instance->settings->extensions[i].data;
138                 if (entry(&entryPoints) != 0)
139                 {
140                         DLCLOSE(han);
141                         printf("extension_load_plugins: %s entry returns error.\n", path);
142                         continue;
143                 }
144         }
145
146         return 0;
147 }
148
149 static int extension_init_plugins(rdpExtension* extension)
150 {
151         int i;
152
153         for (i = 0; i < extension->num_plugins; i++)
154                 extension->plugins[i]->init(extension->plugins[i], extension->instance);
155
156         return 0;
157 }
158
159 static int extension_uninit_plugins(rdpExtension* extension)
160 {
161         int i;
162
163         for (i = 0; i < extension->num_plugins; i++)
164                 extension->plugins[i]->uninit(extension->plugins[i], extension->instance);
165
166         return 0;
167 }
168
169
170 int extension_pre_connect(rdpExtension* extension)
171 {
172         int i;
173
174         for (i = 0; i < extension->num_pre_connect_hooks; i++)
175                 extension->pre_connect_hooks[i](extension->pre_connect_hooks_instances[i], extension->instance);
176
177         return 0;
178 }
179
180 int extension_post_connect(rdpExtension* ext)
181 {
182         int i;
183
184         for (i = 0; i < ext->num_post_connect_hooks; i++)
185                 ext->post_connect_hooks[i](ext->post_connect_hooks_instances[i], ext->instance);
186
187         return 0;
188 }
189
190 rdpExtension* extension_new(freerdp* instance)
191 {
192         rdpExtension* extension = NULL;
193
194         if (instance != NULL)
195         {
196                 extension = xnew(rdpExtension);
197
198                 extension->instance = instance;
199
200                 extension_load_plugins(extension);
201                 extension_init_plugins(extension);
202         }
203
204         return extension;
205 }
206
207 void extension_free(rdpExtension* extension)
208 {
209         if (extension != NULL)
210         {
211                 extension_uninit_plugins(extension);
212                 xfree(extension);
213         }
214 }