diff options
| author | Eli Zaretskii | 2015-11-20 13:34:15 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2015-11-20 13:34:15 +0200 |
| commit | 24be1c8460895ccec8a84e53966b324e35cac6c9 (patch) | |
| tree | a9c2112a0013bc30c8385c2a96caf0519a7a81c3 /src/dynlib.c | |
| parent | bd715e3d3d214f61172beb78f858ac43d8ce0a78 (diff) | |
| download | emacs-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.c | 104 |
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 | |||
| 39 | static DWORD dynlib_last_err; | ||
| 40 | |||
| 41 | /* This needs to be called at startup to countermand any non-zero | ||
| 42 | values recorded by temacs. */ | ||
| 43 | void | ||
| 44 | dynlib_reset_last_error (void) | ||
| 45 | { | ||
| 46 | dynlib_last_err = 0; | ||
| 47 | } | ||
| 36 | 48 | ||
| 37 | dynlib_handle_ptr | 49 | dynlib_handle_ptr |
| 38 | dynlib_open (const char *path) | 50 | dynlib_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 | ||
| 44 | void * | 91 | void * |
| 45 | dynlib_sym (dynlib_handle_ptr h, const char *sym) | 92 | dynlib_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 | ||
| 50 | bool | 109 | bool |
| 51 | dynlib_addr (void *ptr, const char **path, const char **sym) | 110 | dynlib_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 | ||
| 56 | const char * | 115 | const char * |
| 57 | dynlib_error (void) | 116 | dynlib_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 | ||
| 63 | int | 129 | int |
| 64 | dynlib_close (dynlib_handle_ptr h) | 130 | dynlib_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 |