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.
This commit is contained in:
parent
bd715e3d3d
commit
24be1c8460
2 changed files with 100 additions and 9 deletions
104
src/dynlib.c
104
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
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Add table
Reference in a new issue