[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] emacs-25 24be1c8: Improve MS-Windows implementation in dyn
From: |
Eli Zaretskii |
Subject: |
[Emacs-diffs] emacs-25 24be1c8: Improve MS-Windows implementation in dynlib.c |
Date: |
Fri, 20 Nov 2015 11:36:11 +0000 |
branch: emacs-25
commit 24be1c8460895ccec8a84e53966b324e35cac6c9
Author: Eli Zaretskii <address@hidden>
Commit: Eli Zaretskii <address@hidden>
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.
---
src/dynlib.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----
src/w32.c | 5 +++
2 files changed, 100 insertions(+), 9 deletions(-)
diff --git a/src/dynlib.c b/src/dynlib.c
index 1b66c4a..47ffb41 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/>. */
#include "dynlib.h"
-#if defined _WIN32
+#ifdef WINDOWSNT
/* MS-Windows systems. */
-#include <windows.h>
+#include <errno.h>
+#include "lisp.h"
+#include "w32.h"
+
+static DWORD dynlib_last_err;
+
+/* This needs to be called at startup to countermand any non-zero
+ values recorded by temacs. */
+void
+dynlib_reset_last_error (void)
+{
+ dynlib_last_err = 0;
+}
dynlib_handle_ptr
-dynlib_open (const char *path)
+dynlib_open (const char *dll_fname)
{
+ HMODULE hdll;
+ char dll_fname_local[MAX_UTF8_PATH];
- return (dynlib_handle_ptr) LoadLibrary (path);
+ if (!dll_fname)
+ {
+ errno = ENOTSUP;
+ return NULL;
+ }
+
+ if (!dll_fname)
+ hdll = GetModuleHandle (NULL);
+ else
+ {
+ /* LoadLibrary wants backslashes. */
+ strcpy (dll_fname_local, dll_fname);
+ unixtodos_filename (dll_fname_local);
+
+ if (w32_unicode_filenames)
+ {
+ wchar_t dll_fname_w[MAX_PATH];
+
+ filename_to_utf16 (dll_fname_local, dll_fname_w);
+ hdll = LoadLibraryW (dll_fname_w);
+ }
+ else
+ {
+ char dll_fname_a[MAX_PATH];
+
+ filename_to_ansi (dll_fname_local, dll_fname_a);
+ hdll = LoadLibraryA (dll_fname_a);
+ }
+ }
+
+ if (!hdll)
+ dynlib_last_err = GetLastError ();
+
+ return (dynlib_handle_ptr) hdll;
}
void *
dynlib_sym (dynlib_handle_ptr h, const char *sym)
{
- return GetProcAddress ((HMODULE) h, sym);
+ FARPROC sym_addr = NULL;
+
+ if (!h || h == INVALID_HANDLE_VALUE || !sym)
+ {
+ dynlib_last_err = ERROR_INVALID_PARAMETER;
+ return NULL;
+ }
+
+ sym_addr = GetProcAddress ((HMODULE) h, sym);
+ if (!sym_addr)
+ dynlib_last_err = GetLastError ();
+
+ return (void *)sym_addr;
}
bool
dynlib_addr (void *ptr, const char **path, const char **sym)
{
- return false; /* not implemented */
+ return false; /* Not implemented yet. */
}
const char *
dynlib_error (void)
{
- /* TODO: use GetLastError(), FormatMessage(), ... */
- return "Can't load DLL";
+ char *error_string = NULL;
+
+ if (dynlib_last_err)
+ {
+ error_string = w32_strerror (dynlib_last_err);
+ dynlib_last_err = 0;
+ }
+
+ return error_string;
}
int
dynlib_close (dynlib_handle_ptr h)
{
- return FreeLibrary ((HMODULE) h) != 0;
+ if (!h || h == INVALID_HANDLE_VALUE)
+ {
+ dynlib_last_err = ERROR_INVALID_PARAMETER;
+ return -1;
+ }
+ /* If the handle is for the main module (the .exe file), it
+ shouldn't be passed to FreeLibrary, because GetModuleHandle
+ doesn't increment the refcount, but FreeLibrary does decrement
+ it. I don't think this should matter for the main module, but
+ just in case, we avoid the call here, relying on another call to
+ GetModuleHandle to return the same value. */
+ if (h == GetModuleHandle (NULL))
+ return 0;
+
+ if (!FreeLibrary ((HMODULE) h))
+ {
+ dynlib_last_err = GetLastError ();
+ return -1;
+ }
+
+ return 0;
}
#elif defined HAVE_UNISTD_H
diff --git a/src/w32.c b/src/w32.c
index 15cfd92..9601012 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -9379,6 +9379,11 @@ globals_of_w32 (void)
w32_unicode_filenames = 0;
else
w32_unicode_filenames = 1;
+
+#ifdef HAVE_MODULES
+ extern void dynlib_reset_last_error (void);
+ dynlib_reset_last_error ();
+#endif
}
/* For make-serial-process */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] emacs-25 24be1c8: Improve MS-Windows implementation in dynlib.c,
Eli Zaretskii <=