04f695d22de38e15d4a199142b400023df9e5f1c
[mono.git] / mono / utils / mono-dl-windows.c
1 /*
2  * mono-dl.c: Interface to the dynamic linker
3  *
4  * Author:
5  *    Mono Team (http://www.mono-project.com)
6  *
7  * Copyright 2001-2004 Ximian, Inc.
8  * Copyright 2004-2009 Novell, Inc.
9  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
10  */
11 #include <config.h>
12
13 #if defined(HOST_WIN32)
14
15 #include "mono/utils/mono-dl.h"
16 #include "mono/utils/mono-dl-windows.h"
17 #include "mono/utils/mono-embed.h"
18 #include "mono/utils/mono-path.h"
19
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <ctype.h>
23 #include <string.h>
24 #include <glib.h>
25
26 #include <windows.h>
27 #include <psapi.h>
28
29 const char*
30 mono_dl_get_so_prefix (void)
31 {
32         return "";
33 }
34
35 const char**
36 mono_dl_get_so_suffixes (void)
37 {
38         static const char *suffixes[] = {
39                 ".dll",
40                 "",
41         };
42         return suffixes;
43 }
44
45 void*
46 mono_dl_open_file (const char *file, int flags)
47 {
48         gpointer hModule = NULL;
49         if (file) {
50                 gunichar2* file_utf16 = g_utf8_to_utf16 (file, strlen (file), NULL, NULL, NULL);
51
52 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
53                 guint last_sem = SetErrorMode (SEM_FAILCRITICALERRORS);
54 #endif
55                 guint32 last_error = 0;
56
57                 hModule = LoadLibrary (file_utf16);
58                 if (!hModule)
59                         last_error = GetLastError ();
60
61 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
62                 SetErrorMode (last_sem);
63 #endif
64
65                 g_free (file_utf16);
66
67                 if (!hModule)
68                         SetLastError (last_error);
69         } else {
70                 hModule = GetModuleHandle (NULL);
71         }
72         return hModule;
73 }
74
75 void
76 mono_dl_close_handle (MonoDl *module)
77 {
78         if (!module->main_module)
79                 FreeLibrary (module->handle);
80 }
81
82 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
83 void*
84 mono_dl_lookup_symbol_in_process (const char *symbol_name)
85 {
86         HMODULE *modules;
87         DWORD buffer_size = sizeof (HMODULE) * 1024;
88         DWORD needed, i;
89         gpointer proc = NULL;
90
91         /* get the symbol from the loaded DLLs */
92         modules = (HMODULE *) g_malloc (buffer_size);
93         if (modules == NULL)
94                 return NULL;
95
96         if (!EnumProcessModules (GetCurrentProcess (), modules,
97                                  buffer_size, &needed)) {
98                 g_free (modules);
99                 return NULL;
100         }
101
102         /* check whether the supplied buffer was too small, realloc, retry */
103         if (needed > buffer_size) {
104                 g_free (modules);
105
106                 buffer_size = needed;
107                 modules = (HMODULE *) g_malloc (buffer_size);
108
109                 if (modules == NULL)
110                         return NULL;
111
112                 if (!EnumProcessModules (GetCurrentProcess (), modules,
113                                          buffer_size, &needed)) {
114                         g_free (modules);
115                         return NULL;
116                 }
117         }
118
119         for (i = 0; i < needed / sizeof (HANDLE); i++) {
120                 proc = GetProcAddress (modules [i], symbol_name);
121                 if (proc != NULL) {
122                         g_free (modules);
123                         return proc;
124                 }
125         }
126
127         g_free (modules);
128         return NULL;
129 }
130 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
131
132 void*
133 mono_dl_lookup_symbol (MonoDl *module, const char *symbol_name)
134 {
135         gpointer proc = NULL;
136
137         /* get the symbol directly from the specified module */
138         if (!module->main_module)
139                 return GetProcAddress (module->handle, symbol_name);
140
141         /* get the symbol from the main module */
142         proc = GetProcAddress (module->handle, symbol_name);
143         if (proc != NULL)
144                 return proc;
145
146         /* get the symbol from the loaded DLLs */
147         return mono_dl_lookup_symbol_in_process (symbol_name);
148 }
149
150 int
151 mono_dl_convert_flags (int flags)
152 {
153         return 0;
154 }
155
156 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
157 char*
158 mono_dl_current_error_string (void)
159 {
160         char* ret = NULL;
161         wchar_t* buf = NULL;
162         DWORD code = GetLastError ();
163
164         if (FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
165                 code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buf, 0, NULL))
166         {
167                 ret = g_utf16_to_utf8 (buf, wcslen(buf), NULL, NULL, NULL);
168                 LocalFree (buf);
169         } else {
170                 g_assert_not_reached ();
171         }
172         return ret;
173 }
174 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
175
176 int
177 mono_dl_get_executable_path (char *buf, int buflen)
178 {
179         return -1; //TODO
180 }
181
182 const char*
183 mono_dl_get_system_dir (void)
184 {
185         return NULL;
186 }
187 #endif