emacs-diffs
[Top][All Lists]
Advanced

[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  */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]