Imported Upstream version 0.63.0
[hcoop/debian/courier-authlib.git] / libltdl / loaders / loadlibrary.c
1 /* loader-loadlibrary.c -- dynamic linking for Win32
2
3 Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006,
4 2007, 2008 Free Software Foundation, Inc.
5 Written by Thomas Tanner, 1998
6
7 NOTE: The canonical source of this file is maintained with the
8 GNU Libtool package. Report bugs to bug-libtool@gnu.org.
9
10 GNU Libltdl is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
14
15 As a special exception to the GNU Lesser General Public License,
16 if you distribute this file as part of a program or library that
17 is built using GNU Libtool, you may include this file under the
18 same distribution terms that you use for the rest of that program.
19
20 GNU Libltdl is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU Lesser General Public License for more details.
24
25 You should have received a copy of the GNU Lesser General Public
26 License along with GNU Libltdl; see the file COPYING.LIB. If not, a
27 copy can be downloaded from http://www.gnu.org/licenses/lgpl.html,
28 or obtained by writing to the Free Software Foundation, Inc.,
29 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30 */
31
32 #include "lt__private.h"
33 #include "lt_dlloader.h"
34
35 #if defined(__CYGWIN__)
36 # include <sys/cygwin.h>
37 #endif
38
39 /* Use the preprocessor to rename non-static symbols to avoid namespace
40 collisions when the loader code is statically linked into libltdl.
41 Use the "<module_name>_LTX_" prefix so that the symbol addresses can
42 be fetched from the preloaded symbol list by lt_dlsym(): */
43 #define get_vtable loadlibrary_LTX_get_vtable
44
45 LT_BEGIN_C_DECLS
46 LT_SCOPE lt_dlvtable *get_vtable (lt_user_data loader_data);
47 LT_END_C_DECLS
48
49
50 /* Boilerplate code to set up the vtable for hooking this loader into
51 libltdl's loader list: */
52 static int vl_exit (lt_user_data loader_data);
53 static lt_module vm_open (lt_user_data loader_data, const char *filename,
54 lt_dladvise advise);
55 static int vm_close (lt_user_data loader_data, lt_module module);
56 static void * vm_sym (lt_user_data loader_data, lt_module module,
57 const char *symbolname);
58
59 static lt_dlinterface_id iface_id = 0;
60 static lt_dlvtable *vtable = 0;
61
62 /* Return the vtable for this loader, only the name and sym_prefix
63 attributes (plus the virtual function implementations, obviously)
64 change between loaders. */
65 lt_dlvtable *
66 get_vtable (lt_user_data loader_data)
67 {
68 if (!vtable)
69 {
70 vtable = (lt_dlvtable *) lt__zalloc (sizeof *vtable);
71 iface_id = lt_dlinterface_register ("ltdl loadlibrary", NULL);
72 }
73
74 if (vtable && !vtable->name)
75 {
76 vtable->name = "lt_loadlibrary";
77 vtable->module_open = vm_open;
78 vtable->module_close = vm_close;
79 vtable->find_sym = vm_sym;
80 vtable->dlloader_exit = vl_exit;
81 vtable->dlloader_data = loader_data;
82 vtable->priority = LT_DLLOADER_APPEND;
83 }
84
85 if (vtable && (vtable->dlloader_data != loader_data))
86 {
87 LT__SETERROR (INIT_LOADER);
88 return 0;
89 }
90
91 return vtable;
92 }
93
94
95
96 /* --- IMPLEMENTATION --- */
97
98
99 #include <windows.h>
100
101 /* A function called through the vtable when this loader is no
102 longer needed by the application. */
103 static int
104 vl_exit (lt_user_data LT__UNUSED loader_data)
105 {
106 vtable = NULL;
107 return 0;
108 }
109
110 /* A function called through the vtable to open a module with this
111 loader. Returns an opaque representation of the newly opened
112 module for processing with this loader's other vtable functions. */
113 static lt_module
114 vm_open (lt_user_data LT__UNUSED loader_data, const char *filename,
115 lt_dladvise LT__UNUSED advise)
116 {
117 lt_module module = 0;
118 char *ext;
119 char wpath[MAX_PATH];
120 size_t len;
121
122 if (!filename)
123 {
124 /* Get the name of main module */
125 *wpath = 0;
126 GetModuleFileName (NULL, wpath, sizeof (wpath));
127 filename = wpath;
128 }
129 else
130 {
131 len = LT_STRLEN (filename);
132
133 if (len >= MAX_PATH)
134 {
135 LT__SETERROR (CANNOT_OPEN);
136 return 0;
137 }
138
139 #if HAVE_DECL_CYGWIN_CONV_PATH
140 if (cygwin_conv_path (CCP_POSIX_TO_WIN_A, filename, wpath, MAX_PATH))
141 {
142 LT__SETERROR (CANNOT_OPEN);
143 return 0;
144 }
145 len = 0;
146 #elif defined(__CYGWIN__)
147 cygwin_conv_to_full_win32_path (filename, wpath);
148 len = 0;
149 #else
150 strcpy(wpath, filename);
151 #endif
152
153 ext = strrchr (wpath, '.');
154 if (!ext)
155 {
156 /* Append a `.' to stop Windows from adding an
157 implicit `.dll' extension. */
158 if (!len)
159 len = LT_STRLEN (wpath);
160
161 if (len + 1 >= MAX_PATH)
162 {
163 LT__SETERROR (CANNOT_OPEN);
164 return 0;
165 }
166
167 wpath[len] = '.';
168 wpath[len+1] = '\0';
169 }
170 }
171
172 {
173 /* Silence dialog from LoadLibrary on some failures.
174 No way to get the error mode, but to set it,
175 so set it twice to preserve any previous flags. */
176 UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS);
177 SetErrorMode(errormode | SEM_FAILCRITICALERRORS);
178
179 module = LoadLibrary (wpath);
180
181 /* Restore the error mode. */
182 SetErrorMode(errormode);
183 }
184
185 /* libltdl expects this function to fail if it is unable
186 to physically load the library. Sadly, LoadLibrary
187 will search the loaded libraries for a match and return
188 one of them if the path search load fails.
189
190 We check whether LoadLibrary is returning a handle to
191 an already loaded module, and simulate failure if we
192 find one. */
193 {
194 lt_dlhandle cur = 0;
195
196 while ((cur = lt_dlhandle_iterate (iface_id, cur)))
197 {
198 if (!cur->module)
199 {
200 cur = 0;
201 break;
202 }
203
204 if (cur->module == module)
205 {
206 break;
207 }
208 }
209
210 if (cur || !module)
211 {
212 LT__SETERROR (CANNOT_OPEN);
213 module = 0;
214 }
215 }
216
217 return module;
218 }
219
220
221 /* A function called through the vtable when a particular module
222 should be unloaded. */
223 static int
224 vm_close (lt_user_data LT__UNUSED loader_data, lt_module module)
225 {
226 int errors = 0;
227
228 if (FreeLibrary((HMODULE) module) == 0)
229 {
230 LT__SETERROR (CANNOT_CLOSE);
231 ++errors;
232 }
233
234 return errors;
235 }
236
237
238 /* A function called through the vtable to get the address of
239 a symbol loaded from a particular module. */
240 static void *
241 vm_sym (lt_user_data LT__UNUSED loader_data, lt_module module, const char *name)
242 {
243 void *address = (void *) GetProcAddress ((HMODULE) module, name);
244
245 if (!address)
246 {
247 LT__SETERROR (SYMBOL_NOT_FOUND);
248 }
249
250 return address;
251 }