* TODO: Remove 'List' entries.
[mono.git] / eglib / src / gmodule.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  *
8  * (C) 2006 Novell, Inc.
9  * (C) 2006 Jonathan Chambers
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining
12  * a copy of this software and associated documentation files (the
13  * "Software"), to deal in the Software without restriction, including
14  * without limitation the rights to use, copy, modify, merge, publish,
15  * distribute, sublicense, and/or sell copies of the Software, and to
16  * permit persons to whom the Software is furnished to do so, subject to
17  * the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be
20  * included in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29  */
30 #include <glib.h>
31
32 #ifdef G_OS_UNIX
33 #include <dlfcn.h>
34
35 /* For Linux and Solaris, need to add others as we port this */
36 #define LIBSUFFIX "lib"
37 #define LIBPREFIX ".so"
38
39 struct _GModule {
40         void *handle;
41 };
42
43 GModule *
44 g_module_open (const gchar *file, GModuleFlags flags)
45 {
46         int f = 0;
47         GModule *module;
48
49         flags &= G_MODULE_BIND_MASK;
50         if ((flags & G_MODULE_BIND_LAZY) != 0)
51                 f |= RTLD_LAZY;
52         if ((flags & G_MODULE_BIND_LOCAL) != 0)
53                 f |= RTLD_LOCAL;
54
55         module = g_malloc (sizeof (GModule));
56         if (module == NULL)
57                 return NULL;
58
59         module->handle = dlopen (file, f);
60         return module;
61 }
62
63 gboolean
64 g_module_symbol (GModule *module, const gchar *symbol_name, gpointer *symbol)
65 {
66         if (symbol_name == NULL || symbol == NULL)
67                 return FALSE;
68
69         if (module == NULL || module->handle == NULL)
70                 return FALSE;
71
72         *symbol = dlsym (module->handle, symbol_name);
73         return (*symbol != NULL);
74 }
75
76 const gchar *
77 g_module_error (void)
78 {
79         return dlerror ();
80 }
81
82 gboolean
83 g_module_close (GModule *module)
84 {
85         void *handle;
86         if (module == NULL || module->handle == NULL)
87                 return FALSE;
88
89         handle = module->handle;
90         module->handle = NULL;
91         g_free (module);
92         return (0 == dlclose (handle));
93 }
94
95 #elif defined (G_OS_WIN32)
96 #include <windows.h>
97
98 #define LIBSUFFIX ".dll"
99 #define LIBPREFIX 
100
101 struct _GModule {
102         HMODULE handle;
103 };
104
105 GModule *
106 g_module_open (const gchar *file, GModuleFlags flags)
107 {
108         GModule *module;
109         module = g_malloc (sizeof (GModule));
110         if (module == NULL)
111                 return NULL;
112
113         module->handle = LoadLibrary (file);
114         return module;
115 }
116
117 gboolean
118 g_module_symbol (GModule *module, const gchar *symbol_name, gpointer *symbol)
119 {
120         if (symbol_name == NULL || symbol == NULL)
121                 return FALSE;
122
123         if (module == NULL || module->handle == NULL)
124                 return FALSE;
125
126         *symbol = GetProcAddress (module->handle, symbol_name);
127         return (*symbol != NULL);
128 }
129
130 const gchar *
131 g_module_error (void)
132 {
133         gchar* ret = NULL;
134         TCHAR* buf = NULL;
135         DWORD code = GetLastError ();
136
137         FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, 
138                 code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 0, NULL);
139
140         ret = g_strdup (buf);
141         LocalFree(buf);
142
143         return ret;
144 }
145
146 gboolean
147 g_module_close (GModule *module)
148 {
149         HMODULE handle;
150         if (module == NULL || module->handle == NULL)
151                 return FALSE;
152
153         handle = module->handle;
154         module->handle = NULL;
155         g_free (module);
156         return (0 == FreeLibrary (handle));
157 }
158
159 #else
160
161 #define LIBSUFFIX
162 #define LIBPREFIX
163
164 GModule *
165 g_module_open (const gchar *file, GModuleFlags flags)
166 {
167         g_error ("g_module_open not implemented on this platform");
168         return NULL;
169 }
170
171 gboolean
172 g_module_symbol (GModule *module, const gchar *symbol_name, gpointer *symbol)
173 {
174         g_error ("g_module_open not implemented on this platform");
175         return FALSE;
176 }
177
178 const gchar *
179 g_module_error (void)
180 {
181         g_error ("g_module_open not implemented on this platform");
182         return NULL;
183 }
184
185 gboolean
186 g_module_close (GModule *module)
187 {
188         g_error ("g_module_open not implemented on this platform");
189         return FALSE;
190 }
191 #endif
192
193 gchar *
194 g_module_build_path (const gchar *directory, const gchar *module_name)
195 {
196         if (module_name == NULL)
197                 return NULL;
198
199         if (directory)
200                 return g_strdup_printf ("%s/" LIBPREFIX "%s" LIBSUFFIX, directory, module_name);
201         return g_strdup_printf (LIBPREFIX "%s" LIBSUFFIX, module_name); 
202 }