aboutsummaryrefslogtreecommitdiffstats
path: root/src/dynlib.c
diff options
context:
space:
mode:
authorEli Zaretskii2015-11-20 13:34:15 +0200
committerEli Zaretskii2015-11-20 13:34:15 +0200
commit24be1c8460895ccec8a84e53966b324e35cac6c9 (patch)
treea9c2112a0013bc30c8385c2a96caf0519a7a81c3 /src/dynlib.c
parentbd715e3d3d214f61172beb78f858ac43d8ce0a78 (diff)
downloademacs-24be1c8460895ccec8a84e53966b324e35cac6c9.tar.gz
emacs-24be1c8460895ccec8a84e53966b324e35cac6c9.zip
Improve MS-Windows implementation in dynlib.c
* src/dynlib.c [WINDOWSNT]: Include errno.h, lisp.h, and w32.h. No need to include windows.h, as w32.h already does that. <dynlib_last_err>: New static variable. (dynlib_reset_last_error): New function. (dynlib_open): Convert forward slashes to backslashes. Convert file names from UTF-8 to either UTF-16 or the current ANSI codepage, and call either LoadLibraryW or LoadLibraryA. If the argument is NULL, return a handle to the main module, like 'dlopen' does. Record the error, if any, for use by dynlib_error. (dynlib_sym): Check the handle for validity. Record the error, if any, for use by dynlib_error. (dynlib_error): Call w32_strerror to produce the error string, and zero out the last error code, like dlerror does. (dynlib_close): Check the handle for validity. Record the error, if any, for use by dynlib_error. Don't call FreeLibrary with a handle for the main module. * src/w32.c (globals_of_w32): Call dynlib_reset_last_error.
Diffstat (limited to 'src/dynlib.c')
-rw-r--r--src/dynlib.c104
1 files changed, 95 insertions, 9 deletions
diff --git a/src/dynlib.c b/src/dynlib.c
index 1b66c4ad8e8..47ffb418140 100644
--- a/src/dynlib.c
+++ b/src/dynlib.c
@@ -28,42 +28,128 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
28 28
29#include "dynlib.h" 29#include "dynlib.h"
30 30
31#if defined _WIN32 31#ifdef WINDOWSNT
32 32
33/* MS-Windows systems. */ 33/* MS-Windows systems. */
34 34
35#include <windows.h> 35#include <errno.h>
36#include "lisp.h"
37#include "w32.h"
38
39static DWORD dynlib_last_err;
40
41/* This needs to be called at startup to countermand any non-zero
42 values recorded by temacs. */
43void
44dynlib_reset_last_error (void)
45{
46 dynlib_last_err = 0;
47}
36 48
37dynlib_handle_ptr 49dynlib_handle_ptr
38dynlib_open (const char *path) 50dynlib_open (const char *dll_fname)
39{ 51{
52 HMODULE hdll;
53 char dll_fname_local[MAX_UTF8_PATH];
40 54
41 return (dynlib_handle_ptr) LoadLibrary (path); 55 if (!dll_fname)
56 {
57 errno = ENOTSUP;
58 return NULL;
59 }
60
61 if (!dll_fname)
62 hdll = GetModuleHandle (NULL);
63 else
64 {
65 /* LoadLibrary wants backslashes. */
66 strcpy (dll_fname_local, dll_fname);
67 unixtodos_filename (dll_fname_local);
68
69 if (w32_unicode_filenames)
70 {
71 wchar_t dll_fname_w[MAX_PATH];
72
73 filename_to_utf16 (dll_fname_local, dll_fname_w);
74 hdll = LoadLibraryW (dll_fname_w);
75 }
76 else
77 {
78 char dll_fname_a[MAX_PATH];
79
80 filename_to_ansi (dll_fname_local, dll_fname_a);
81 hdll = LoadLibraryA (dll_fname_a);
82 }
83 }
84
85 if (!hdll)
86 dynlib_last_err = GetLastError ();
87
88 return (dynlib_handle_ptr) hdll;
42} 89}
43 90
44void * 91void *
45dynlib_sym (dynlib_handle_ptr h, const char *sym) 92dynlib_sym (dynlib_handle_ptr h, const char *sym)
46{ 93{
47 return GetProcAddress ((HMODULE) h, sym); 94 FARPROC sym_addr = NULL;
95
96 if (!h || h == INVALID_HANDLE_VALUE || !sym)
97 {
98 dynlib_last_err = ERROR_INVALID_PARAMETER;
99 return NULL;
100 }
101
102 sym_addr = GetProcAddress ((HMODULE) h, sym);
103 if (!sym_addr)
104 dynlib_last_err = GetLastError ();
105
106 return (void *)sym_addr;
48} 107}
49 108
50bool 109bool
51dynlib_addr (void *ptr, const char **path, const char **sym) 110dynlib_addr (void *ptr, const char **path, const char **sym)
52{ 111{
53 return false; /* not implemented */ 112 return false; /* Not implemented yet. */
54} 113}
55 114
56const char * 115const char *
57dynlib_error (void) 116dynlib_error (void)
58{ 117{
59 /* TODO: use GetLastError(), FormatMessage(), ... */ 118 char *error_string = NULL;
60 return "Can't load DLL"; 119
120 if (dynlib_last_err)
121 {
122 error_string = w32_strerror (dynlib_last_err);
123 dynlib_last_err = 0;
124 }
125
126 return error_string;
61} 127}
62 128
63int 129int
64dynlib_close (dynlib_handle_ptr h) 130dynlib_close (dynlib_handle_ptr h)
65{ 131{
66 return FreeLibrary ((HMODULE) h) != 0; 132 if (!h || h == INVALID_HANDLE_VALUE)
133 {
134 dynlib_last_err = ERROR_INVALID_PARAMETER;
135 return -1;
136 }
137 /* If the handle is for the main module (the .exe file), it
138 shouldn't be passed to FreeLibrary, because GetModuleHandle
139 doesn't increment the refcount, but FreeLibrary does decrement
140 it. I don't think this should matter for the main module, but
141 just in case, we avoid the call here, relying on another call to
142 GetModuleHandle to return the same value. */
143 if (h == GetModuleHandle (NULL))
144 return 0;
145
146 if (!FreeLibrary ((HMODULE) h))
147 {
148 dynlib_last_err = GetLastError ();
149 return -1;
150 }
151
152 return 0;
67} 153}
68 154
69#elif defined HAVE_UNISTD_H 155#elif defined HAVE_UNISTD_H