[eglib] Move definition of GPid to eglib-config.h
[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 = LoadLibrary (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         FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, 
145                 code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 0, NULL);
146
147         ret = u16to8 (buf);
148         LocalFree(buf);
149
150         return ret;
151 }
152
153 gboolean
154 g_module_close (GModule *module)
155 {
156         HMODULE handle;
157         int main_module;
158
159         if (module == NULL || module->handle == NULL)
160                 return FALSE;
161
162         handle = module->handle;
163         main_module = module->main_module;
164         module->handle = NULL;
165         g_free (module);
166         return (main_module ? 1 : (0 == FreeLibrary (handle)));
167 }
168
169 gchar *
170 g_module_build_path (const gchar *directory, const gchar *module_name)
171 {
172         char *lib_prefix = "";
173         
174         if (module_name == NULL)
175                 return NULL;
176
177         if (strncmp (module_name, "lib", 3) != 0)
178                 lib_prefix = LIBPREFIX;
179         
180         if (directory && *directory){ 
181                 
182                 return g_strdup_printf ("%s/%s%s" LIBSUFFIX, directory, lib_prefix, module_name);
183         }
184         return g_strdup_printf ("%s%s" LIBSUFFIX, lib_prefix, module_name); 
185 }