Build mono runtime under none desktop Windows API family, adjustments and cleanup.
[mono.git] / eglib / src / gmodule-win32.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 <config.h>
32 #include <glib.h>
33 #include <windows.h>
34 #include <psapi.h>
35 #include <gmodule-win32-internals.h>
36
37 #define LIBSUFFIX ".dll"
38 #define LIBPREFIX ""
39
40 struct _GModule {
41         HMODULE handle;
42         int main_module;
43 };
44
45 GModule *
46 g_module_open (const gchar *file, GModuleFlags flags)
47 {
48         GModule *module;
49         module = g_malloc (sizeof (GModule));
50         if (module == NULL)
51                 return NULL;
52
53         if (file != NULL) {
54                 gunichar2 *file16;
55                 file16 = u8to16(file); 
56                 module->main_module = FALSE;
57                 module->handle = LoadLibraryW (file16);
58                 g_free(file16);
59                 if (!module->handle) {
60                         g_free (module);
61                         return NULL;
62                 }
63                         
64         } else {
65                 module->main_module = TRUE;
66                 module->handle = GetModuleHandle (NULL);
67         }
68
69         return module;
70 }
71
72 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
73 gpointer
74 w32_find_symbol (const gchar *symbol_name)
75 {
76         HMODULE *modules;
77         DWORD buffer_size = sizeof (HMODULE) * 1024;
78         DWORD needed, i;
79
80         modules = (HMODULE *) g_malloc (buffer_size);
81
82         if (modules == NULL)
83                 return NULL;
84
85         if (!EnumProcessModules (GetCurrentProcess (), modules,
86                                  buffer_size, &needed)) {
87                 g_free (modules);
88                 return NULL;
89         }
90
91         /* check whether the supplied buffer was too small, realloc, retry */
92         if (needed > buffer_size) {
93                 g_free (modules);
94
95                 buffer_size = needed;
96                 modules = (HMODULE *) g_malloc (buffer_size);
97
98                 if (modules == NULL)
99                         return NULL;
100
101                 if (!EnumProcessModules (GetCurrentProcess (), modules,
102                                          buffer_size, &needed)) {
103                         g_free (modules);
104                         return NULL;
105                 }
106         }
107
108         for (i = 0; i < needed / sizeof (HANDLE); i++) {
109                 gpointer proc = (gpointer)(intptr_t)GetProcAddress (modules [i], symbol_name);
110                 if (proc != NULL) {
111                         g_free (modules);
112                         return proc;
113                 }
114         }
115
116         g_free (modules);
117         return NULL;
118 }
119 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
120
121 gboolean
122 g_module_symbol (GModule *module, const gchar *symbol_name, gpointer *symbol)
123 {
124         if (module == NULL || symbol_name == NULL || symbol == NULL)
125                 return FALSE;
126
127         if (module->main_module) {
128                 *symbol = (gpointer)(intptr_t)GetProcAddress (module->handle, symbol_name);
129                 if (*symbol != NULL)
130                         return TRUE;
131
132                 *symbol = w32_find_symbol (symbol_name);
133                 return *symbol != NULL;
134         } else {
135                 *symbol = (gpointer)(intptr_t)GetProcAddress (module->handle, symbol_name);
136                 return *symbol != NULL;
137         }
138 }
139
140 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
141 const gchar *
142 g_module_error (void)
143 {
144         gchar* ret = NULL;
145         TCHAR* buf = NULL;
146         DWORD code = GetLastError ();
147
148         /* FIXME: buf must not be NULL! */
149         FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, 
150                 code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 0, NULL);
151
152         ret = u16to8 (buf);
153         LocalFree(buf);
154
155         return ret;
156 }
157 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
158
159 gboolean
160 g_module_close (GModule *module)
161 {
162         HMODULE handle;
163         int main_module;
164
165         if (module == NULL || module->handle == NULL)
166                 return FALSE;
167
168         handle = module->handle;
169         main_module = module->main_module;
170         module->handle = NULL;
171         g_free (module);
172         return (main_module ? 1 : (0 == FreeLibrary (handle)));
173 }
174
175 gchar *
176 g_module_build_path (const gchar *directory, const gchar *module_name)
177 {
178         char *lib_prefix = "";
179         
180         if (module_name == NULL)
181                 return NULL;
182
183         if (strncmp (module_name, "lib", 3) != 0)
184                 lib_prefix = LIBPREFIX;
185         
186         if (directory && *directory){ 
187                 
188                 return g_strdup_printf ("%s/%s%s" LIBSUFFIX, directory, lib_prefix, module_name);
189         }
190         return g_strdup_printf ("%s%s" LIBSUFFIX, lib_prefix, module_name); 
191 }