Merge branch 'master' of github.com:mono/mono
[mono.git] / eglib / src / gmodule-unix.c
1 /*
2  * gmodule.c: dl* functions, glib style
3  *
4  * Author:
5  *   Gonzalo Paniagua Javier (gonzalo@novell.com)
6  *   Jonathan Chambers (joncham@gmail.com)
7  *   Robert Jordan (robertj@gmx.net)
8  *
9  * (C) 2006 Novell, Inc.
10  * (C) 2006 Jonathan Chambers
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining
13  * a copy of this software and associated documentation files (the
14  * "Software"), to deal in the Software without restriction, including
15  * without limitation the rights to use, copy, modify, merge, publish,
16  * distribute, sublicense, and/or sell copies of the Software, and to
17  * permit persons to whom the Software is furnished to do so, subject to
18  * the following conditions:
19  *
20  * The above copyright notice and this permission notice shall be
21  * included in all copies or substantial portions of the Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30  */
31 #include <glib.h>
32 #include <gmodule.h>
33
34 #if defined(__native_client__)
35 GModule *
36 g_module_open (const gchar *file, GModuleFlags flags)
37 {
38         printf("dlopen() not supported on Native Client.\n");
39         return NULL;
40 }
41
42
43 gboolean
44 g_module_symbol (GModule *module, const gchar *symbol_name, gpointer *symbol)
45 {
46         return FALSE;
47 }
48
49
50 const gchar*
51 g_module_error(void)
52 {
53         return "dlopen not supported on Native Client.";
54 }
55
56 gboolean
57 g_module_close (GModule *module)
58 {
59         return FALSE;
60 }
61
62 gchar*
63 g_module_build_path (const gchar *directory, const gchar *module_name)
64 {
65         return NULL;
66 }
67
68 #else
69
70 #ifdef G_OS_UNIX
71 #include <dlfcn.h>
72
73 /* For Linux and Solaris, need to add others as we port this */
74 #define LIBPREFIX "lib"
75 #define LIBSUFFIX ".so"
76
77 struct _GModule {
78         void *handle;
79 };
80
81 GModule *
82 g_module_open (const gchar *file, GModuleFlags flags)
83 {
84         int f = 0;
85         GModule *module;
86         void *handle;
87         
88         flags &= G_MODULE_BIND_MASK;
89         if ((flags & G_MODULE_BIND_LAZY) != 0)
90                 f |= RTLD_LAZY;
91         if ((flags & G_MODULE_BIND_LOCAL) != 0)
92                 f |= RTLD_LOCAL;
93
94         handle = dlopen (file, f);
95         if (handle == NULL)
96                 return NULL;
97         
98         module = g_new (GModule,1);
99         module->handle = handle;
100         
101         return module;
102 }
103
104 gboolean
105 g_module_symbol (GModule *module, const gchar *symbol_name, gpointer *symbol)
106 {
107         if (symbol_name == NULL || symbol == NULL)
108                 return FALSE;
109
110         if (module == NULL || module->handle == NULL)
111                 return FALSE;
112
113         *symbol = dlsym (module->handle, symbol_name);
114         return (*symbol != NULL);
115 }
116
117 const gchar *
118 g_module_error (void)
119 {
120         return dlerror ();
121 }
122
123 gboolean
124 g_module_close (GModule *module)
125 {
126         void *handle;
127         if (module == NULL || module->handle == NULL)
128                 return FALSE;
129
130         handle = module->handle;
131         module->handle = NULL;
132         g_free (module);
133         return (0 == dlclose (handle));
134 }
135
136 #elif defined (G_OS_WIN32)
137 #include <windows.h>
138 #include <psapi.h>
139
140 #define LIBSUFFIX ".dll"
141 #define LIBPREFIX ""
142
143 struct _GModule {
144         HMODULE handle;
145         int main_module;
146 };
147
148 GModule *
149 g_module_open (const gchar *file, GModuleFlags flags)
150 {
151         GModule *module;
152         module = g_malloc (sizeof (GModule));
153         if (module == NULL)
154                 return NULL;
155
156         if (file != NULL) {
157                 gunichar2 *file16;
158                 file16 = u8to16(file); 
159                 module->main_module = FALSE;
160                 module->handle = LoadLibrary (file16);
161                 g_free(file16);
162                 if (!module->handle) {
163                         g_free (module);
164                         return NULL;
165                 }
166                         
167         } else {
168                 module->main_module = TRUE;
169                 module->handle = GetModuleHandle (NULL);
170         }
171
172         return module;
173 }
174
175 static gpointer
176 w32_find_symbol (const gchar *symbol_name)
177 {
178         HMODULE *modules;
179         DWORD buffer_size = sizeof (HMODULE) * 1024;
180         DWORD needed, i;
181
182         modules = (HMODULE *) g_malloc (buffer_size);
183
184         if (modules == NULL)
185                 return NULL;
186
187         if (!EnumProcessModules (GetCurrentProcess (), modules,
188                                  buffer_size, &needed)) {
189                 g_free (modules);
190                 return NULL;
191         }
192
193         /* check whether the supplied buffer was too small, realloc, retry */
194         if (needed > buffer_size) {
195                 g_free (modules);
196
197                 buffer_size = needed;
198                 modules = (HMODULE *) g_malloc (buffer_size);
199
200                 if (modules == NULL)
201                         return NULL;
202
203                 if (!EnumProcessModules (GetCurrentProcess (), modules,
204                                          buffer_size, &needed)) {
205                         g_free (modules);
206                         return NULL;
207                 }
208         }
209
210         for (i = 0; i < needed / sizeof (HANDLE); i++) {
211                 gpointer proc = (gpointer)(intptr_t)GetProcAddress (modules [i], symbol_name);
212                 if (proc != NULL) {
213                         g_free (modules);
214                         return proc;
215                 }
216         }
217
218         g_free (modules);
219         return NULL;
220 }
221
222 gboolean
223 g_module_symbol (GModule *module, const gchar *symbol_name, gpointer *symbol)
224 {
225         if (module == NULL || symbol_name == NULL || symbol == NULL)
226                 return FALSE;
227
228         if (module->main_module) {
229                 *symbol = (gpointer)(intptr_t)GetProcAddress (module->handle, symbol_name);
230                 if (*symbol != NULL)
231                         return TRUE;
232
233                 *symbol = w32_find_symbol (symbol_name);
234                 return *symbol != NULL;
235         } else {
236                 *symbol = (gpointer)(intptr_t)GetProcAddress (module->handle, symbol_name);
237                 return *symbol != NULL;
238         }
239 }
240
241 const gchar *
242 g_module_error (void)
243 {
244         gchar* ret = NULL;
245         TCHAR* buf = NULL;
246         DWORD code = GetLastError ();
247
248         FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, 
249                 code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 0, NULL);
250
251         ret = u16to8 (buf);
252         LocalFree(buf);
253
254         return ret;
255 }
256
257 gboolean
258 g_module_close (GModule *module)
259 {
260         HMODULE handle;
261         int main_module;
262
263         if (module == NULL || module->handle == NULL)
264                 return FALSE;
265
266         handle = module->handle;
267         main_module = module->main_module;
268         module->handle = NULL;
269         g_free (module);
270         return (main_module ? 1 : (0 == FreeLibrary (handle)));
271 }
272
273 #else
274
275 #define LIBSUFFIX ""
276 #define LIBPREFIX ""
277
278 GModule *
279 g_module_open (const gchar *file, GModuleFlags flags)
280 {
281         g_error ("%s", "g_module_open not implemented on this platform");
282         return NULL;
283 }
284
285 gboolean
286 g_module_symbol (GModule *module, const gchar *symbol_name, gpointer *symbol)
287 {
288         g_error ("%s", "g_module_open not implemented on this platform");
289         return FALSE;
290 }
291
292 const gchar *
293 g_module_error (void)
294 {
295         g_error ("%s", "g_module_open not implemented on this platform");
296         return NULL;
297 }
298
299 gboolean
300 g_module_close (GModule *module)
301 {
302         g_error ("%s", "g_module_open not implemented on this platform");
303         return FALSE;
304 }
305 #endif
306
307 gchar *
308 g_module_build_path (const gchar *directory, const gchar *module_name)
309 {
310         char *lib_prefix = "";
311         
312         if (module_name == NULL)
313                 return NULL;
314
315         if (strncmp (module_name, "lib", 3) != 0)
316                 lib_prefix = LIBPREFIX;
317         
318         if (directory && *directory){ 
319                 
320                 return g_strdup_printf ("%s/%s%s" LIBSUFFIX, directory, lib_prefix, module_name);
321         }
322         return g_strdup_printf ("%s%s" LIBSUFFIX, lib_prefix, module_name); 
323 }
324
325 #endif /* __native_client__ */
326