ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/libltdl/loaders/loadlibrary.c
Revision: 4901
Committed: Sat Nov 22 18:31:53 2014 UTC (11 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 10836 byte(s)
Log Message:
- autoreconf

File Contents

# User Rev Content
1 michael 945 /* loader-loadlibrary.c -- dynamic linking for Win32
2    
3 michael 4901 Copyright (C) 1998-2000, 2004-2008, 2010-2014 Free Software
4     Foundation, Inc.
5 michael 945 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 michael 4901 #if defined __CYGWIN__
36 michael 945 # 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 michael 1094 #define LOCALFREE(mem) LT_STMT_START { \
102     if (mem) { LocalFree ((void *)mem); mem = NULL; } } LT_STMT_END
103     #define LOADLIB__SETERROR(errmsg) LT__SETERRORSTR (loadlibraryerror (errmsg))
104     #define LOADLIB_SETERROR(errcode) LOADLIB__SETERROR (LT__STRERROR (errcode))
105    
106     static const char *loadlibraryerror (const char *default_errmsg);
107     static DWORD WINAPI wrap_getthreaderrormode (void);
108     static DWORD WINAPI fallback_getthreaderrormode (void);
109     static BOOL WINAPI wrap_setthreaderrormode (DWORD mode, DWORD *oldmode);
110     static BOOL WINAPI fallback_setthreaderrormode (DWORD mode, DWORD *oldmode);
111    
112     typedef DWORD (WINAPI getthreaderrormode_type) (void);
113     typedef BOOL (WINAPI setthreaderrormode_type) (DWORD, DWORD *);
114    
115     static getthreaderrormode_type *getthreaderrormode = wrap_getthreaderrormode;
116     static setthreaderrormode_type *setthreaderrormode = wrap_setthreaderrormode;
117     static char *error_message = 0;
118    
119    
120 michael 945 /* A function called through the vtable when this loader is no
121     longer needed by the application. */
122     static int
123     vl_exit (lt_user_data LT__UNUSED loader_data)
124     {
125     vtable = NULL;
126 michael 1094 LOCALFREE (error_message);
127 michael 945 return 0;
128     }
129    
130     /* A function called through the vtable to open a module with this
131     loader. Returns an opaque representation of the newly opened
132     module for processing with this loader's other vtable functions. */
133     static lt_module
134     vm_open (lt_user_data LT__UNUSED loader_data, const char *filename,
135     lt_dladvise LT__UNUSED advise)
136     {
137     lt_module module = 0;
138     char *ext;
139     char wpath[MAX_PATH];
140     size_t len;
141    
142     if (!filename)
143     {
144     /* Get the name of main module */
145     *wpath = 0;
146     GetModuleFileName (NULL, wpath, sizeof (wpath));
147     filename = wpath;
148     }
149     else
150     {
151     len = LT_STRLEN (filename);
152    
153     if (len >= MAX_PATH)
154     {
155     LT__SETERROR (CANNOT_OPEN);
156     return 0;
157     }
158    
159     #if HAVE_DECL_CYGWIN_CONV_PATH
160     if (cygwin_conv_path (CCP_POSIX_TO_WIN_A, filename, wpath, MAX_PATH))
161     {
162     LT__SETERROR (CANNOT_OPEN);
163     return 0;
164     }
165     len = 0;
166 michael 4901 #elif defined __CYGWIN__
167 michael 945 cygwin_conv_to_full_win32_path (filename, wpath);
168     len = 0;
169     #else
170     strcpy(wpath, filename);
171     #endif
172    
173     ext = strrchr (wpath, '.');
174     if (!ext)
175     {
176 michael 4901 /* Append a '.' to stop Windows from adding an
177     implicit '.dll' extension. */
178 michael 945 if (!len)
179 michael 1094 len = strlen (wpath);
180 michael 945
181     if (len + 1 >= MAX_PATH)
182     {
183     LT__SETERROR (CANNOT_OPEN);
184     return 0;
185     }
186    
187     wpath[len] = '.';
188     wpath[len+1] = '\0';
189     }
190     }
191    
192     {
193 michael 1094 /* Silence dialog from LoadLibrary on some failures. */
194     DWORD errormode = getthreaderrormode ();
195     DWORD last_error;
196 michael 945
197 michael 1094 setthreaderrormode (errormode | SEM_FAILCRITICALERRORS, NULL);
198    
199 michael 945 module = LoadLibrary (wpath);
200    
201     /* Restore the error mode. */
202 michael 1094 last_error = GetLastError ();
203     setthreaderrormode (errormode, NULL);
204     SetLastError (last_error);
205 michael 945 }
206    
207     /* libltdl expects this function to fail if it is unable
208     to physically load the library. Sadly, LoadLibrary
209     will search the loaded libraries for a match and return
210     one of them if the path search load fails.
211    
212     We check whether LoadLibrary is returning a handle to
213     an already loaded module, and simulate failure if we
214     find one. */
215     {
216     lt_dlhandle cur = 0;
217    
218     while ((cur = lt_dlhandle_iterate (iface_id, cur)))
219     {
220     if (!cur->module)
221     {
222     cur = 0;
223     break;
224     }
225    
226     if (cur->module == module)
227     {
228     break;
229     }
230     }
231    
232 michael 1094 if (!module)
233     LOADLIB_SETERROR (CANNOT_OPEN);
234     else if (cur)
235 michael 945 {
236     LT__SETERROR (CANNOT_OPEN);
237     module = 0;
238     }
239     }
240    
241     return module;
242     }
243    
244    
245     /* A function called through the vtable when a particular module
246     should be unloaded. */
247     static int
248     vm_close (lt_user_data LT__UNUSED loader_data, lt_module module)
249     {
250     int errors = 0;
251    
252 michael 1094 if (FreeLibrary ((HMODULE) module) == 0)
253 michael 945 {
254 michael 1094 LOADLIB_SETERROR (CANNOT_CLOSE);
255 michael 945 ++errors;
256     }
257    
258     return errors;
259     }
260    
261    
262     /* A function called through the vtable to get the address of
263     a symbol loaded from a particular module. */
264     static void *
265     vm_sym (lt_user_data LT__UNUSED loader_data, lt_module module, const char *name)
266     {
267     void *address = (void *) GetProcAddress ((HMODULE) module, name);
268    
269     if (!address)
270     {
271 michael 1094 LOADLIB_SETERROR (SYMBOL_NOT_FOUND);
272 michael 945 }
273    
274     return address;
275     }
276 michael 1094
277    
278    
279     /* --- HELPER FUNCTIONS --- */
280    
281    
282     /* Return the windows error message, or the passed in error message on
283     failure. */
284     static const char *
285     loadlibraryerror (const char *default_errmsg)
286     {
287     size_t len;
288     LOCALFREE (error_message);
289    
290     FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
291     FORMAT_MESSAGE_FROM_SYSTEM |
292     FORMAT_MESSAGE_IGNORE_INSERTS,
293     NULL,
294     GetLastError (),
295     0,
296     (char *) &error_message,
297     0, NULL);
298    
299     /* Remove trailing CRNL */
300     len = LT_STRLEN (error_message);
301     if (len && error_message[len - 1] == '\n')
302     error_message[--len] = LT_EOS_CHAR;
303     if (len && error_message[len - 1] == '\r')
304     error_message[--len] = LT_EOS_CHAR;
305    
306     return len ? error_message : default_errmsg;
307     }
308    
309 michael 4901 /* A function called through the getthreaderrormode variable that checks
310 michael 1094 if the system supports GetThreadErrorMode (or GetErrorMode) and arranges
311     for it or a fallback implementation to be called directly in the future.
312     The selected version is then called. */
313     static DWORD WINAPI
314     wrap_getthreaderrormode (void)
315     {
316     HMODULE kernel32 = GetModuleHandleA ("kernel32.dll");
317     getthreaderrormode
318     = (getthreaderrormode_type *) GetProcAddress (kernel32,
319     "GetThreadErrorMode");
320     if (!getthreaderrormode)
321     getthreaderrormode
322     = (getthreaderrormode_type *) GetProcAddress (kernel32,
323     "GetErrorMode");
324     if (!getthreaderrormode)
325     getthreaderrormode = fallback_getthreaderrormode;
326     return getthreaderrormode ();
327     }
328    
329     /* A function called through the getthreaderrormode variable for cases
330     where the system does not support GetThreadErrorMode or GetErrorMode */
331     static DWORD WINAPI
332     fallback_getthreaderrormode (void)
333     {
334     /* Prior to Windows Vista, the only way to get the current error
335     mode was to set a new one. In our case, we are setting a new
336     error mode right after "getting" it while ignoring the error
337     mode in effect when setting the new error mode, so that's
338     fairly ok. */
339     return (DWORD) SetErrorMode (SEM_FAILCRITICALERRORS);
340     }
341    
342 michael 4901 /* A function called through the setthreaderrormode variable that checks
343 michael 1094 if the system supports SetThreadErrorMode and arranges for it or a
344     fallback implementation to be called directly in the future.
345     The selected version is then called. */
346     static BOOL WINAPI
347     wrap_setthreaderrormode (DWORD mode, DWORD *oldmode)
348     {
349     HMODULE kernel32 = GetModuleHandleA ("kernel32.dll");
350     setthreaderrormode
351     = (setthreaderrormode_type *) GetProcAddress (kernel32,
352     "SetThreadErrorMode");
353     if (!setthreaderrormode)
354     setthreaderrormode = fallback_setthreaderrormode;
355     return setthreaderrormode (mode, oldmode);
356     }
357    
358     /* A function called through the setthreaderrormode variable for cases
359     where the system does not support SetThreadErrorMode. */
360     static BOOL WINAPI
361     fallback_setthreaderrormode (DWORD mode, DWORD *oldmode)
362     {
363     /* Prior to Windows 7, there was no way to set the thread local error
364     mode, so set the process global error mode instead. */
365     DWORD old = (DWORD) SetErrorMode (mode);
366     if (oldmode)
367     *oldmode = old;
368     return TRUE;
369     }

Properties

Name Value
svn:eol-style native