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