Blame gmodule/gmodule-win32.c

Packit ae235b
/* GMODULE - GLIB wrapper code for dynamic module loading
Packit ae235b
 * Copyright (C) 1998, 2000 Tim Janik
Packit ae235b
 *
Packit ae235b
 * Win32 GMODULE implementation
Packit ae235b
 * Copyright (C) 1998 Tor Lillqvist
Packit ae235b
 *
Packit ae235b
 * This library is free software; you can redistribute it and/or
Packit ae235b
 * modify it under the terms of the GNU Lesser General Public
Packit ae235b
 * License as published by the Free Software Foundation; either
Packit ae235b
 * version 2.1 of the License, or (at your option) any later version.
Packit ae235b
 *
Packit ae235b
 * This library is distributed in the hope that it will be useful,
Packit ae235b
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit ae235b
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
Packit ae235b
 * Lesser General Public License for more details.
Packit ae235b
 *
Packit ae235b
 * You should have received a copy of the GNU Lesser General Public
Packit ae235b
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit ae235b
 */
Packit ae235b
Packit ae235b
/*
Packit ae235b
 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
Packit ae235b
 * file for a list of people on the GLib Team.  See the ChangeLog
Packit ae235b
 * files for a list of changes.  These files are distributed with
Packit ae235b
 * GLib at ftp://ftp.gtk.org/pub/gtk/. 
Packit ae235b
 */
Packit ae235b
Packit ae235b
/* 
Packit ae235b
 * MT safe
Packit ae235b
 */
Packit ae235b
#include "config.h"
Packit ae235b
Packit ae235b
#include <stdio.h>
Packit ae235b
#include <windows.h>
Packit ae235b
Packit ae235b
#include <tlhelp32.h>
Packit ae235b
Packit ae235b
#ifdef G_WITH_CYGWIN
Packit ae235b
#include <sys/cygwin.h>
Packit ae235b
#endif
Packit ae235b
Packit ae235b
static void
Packit ae235b
set_error (const gchar *format,
Packit ae235b
	   ...)
Packit ae235b
{
Packit ae235b
  gchar *error;
Packit ae235b
  gchar *detail;
Packit ae235b
  gchar *message;
Packit ae235b
  va_list args;
Packit ae235b
Packit ae235b
  error = g_win32_error_message (GetLastError ());
Packit ae235b
Packit ae235b
  va_start (args, format);
Packit ae235b
  detail = g_strdup_vprintf (format, args);
Packit ae235b
  va_end (args);
Packit ae235b
Packit ae235b
  message = g_strconcat (detail, error, NULL);
Packit ae235b
Packit ae235b
  g_module_set_error (message);
Packit ae235b
  g_free (message);
Packit ae235b
  g_free (detail);
Packit ae235b
  g_free (error);
Packit ae235b
}
Packit ae235b
Packit ae235b
/* --- functions --- */
Packit ae235b
static gpointer
Packit ae235b
_g_module_open (const gchar *file_name,
Packit ae235b
		gboolean     bind_lazy,
Packit ae235b
		gboolean     bind_local)
Packit ae235b
{
Packit ae235b
  HINSTANCE handle;
Packit ae235b
  wchar_t *wfilename;
Packit ae235b
  DWORD old_mode;
Packit ae235b
  BOOL success;
Packit ae235b
#ifdef G_WITH_CYGWIN
Packit ae235b
  gchar tmp[MAX_PATH];
Packit ae235b
Packit ae235b
  cygwin_conv_to_win32_path(file_name, tmp);
Packit ae235b
  file_name = tmp;
Packit ae235b
#endif
Packit ae235b
  wfilename = g_utf8_to_utf16 (file_name, -1, NULL, NULL, NULL);
Packit ae235b
Packit ae235b
  /* suppress error dialog */
Packit ae235b
  success = SetThreadErrorMode (SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS, &old_mode);
Packit ae235b
  if (!success)
Packit ae235b
    set_error ("");
Packit ae235b
  handle = LoadLibraryW (wfilename);
Packit ae235b
  if (success)
Packit ae235b
    SetThreadErrorMode (old_mode, NULL);
Packit ae235b
  g_free (wfilename);
Packit ae235b
      
Packit ae235b
  if (!handle)
Packit ae235b
    set_error ("'%s': ", file_name);
Packit ae235b
Packit ae235b
  return handle;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gint dummy;
Packit ae235b
static gpointer null_module_handle = &dummy;
Packit ae235b
  
Packit ae235b
static gpointer
Packit ae235b
_g_module_self (void)
Packit ae235b
{
Packit ae235b
  return null_module_handle;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
_g_module_close (gpointer handle,
Packit ae235b
		 gboolean is_unref)
Packit ae235b
{
Packit ae235b
  if (handle != null_module_handle)
Packit ae235b
    if (!FreeLibrary (handle))
Packit ae235b
      set_error ("");
Packit ae235b
}
Packit ae235b
Packit ae235b
static gpointer
Packit ae235b
find_in_any_module_using_toolhelp (const gchar *symbol_name)
Packit ae235b
{
Packit ae235b
  HANDLE snapshot; 
Packit ae235b
  MODULEENTRY32 me32;
Packit ae235b
Packit ae235b
  gpointer p;
Packit ae235b
Packit ae235b
  if ((snapshot = CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, 0)) == (HANDLE) -1)
Packit ae235b
    return NULL;
Packit ae235b
Packit ae235b
  me32.dwSize = sizeof (me32);
Packit ae235b
  p = NULL;
Packit ae235b
  if (Module32First (snapshot, &me32))
Packit ae235b
    {
Packit ae235b
      do {
Packit ae235b
	if ((p = GetProcAddress (me32.hModule, symbol_name)) != NULL)
Packit ae235b
	  break;
Packit ae235b
      } while (Module32Next (snapshot, &me32));
Packit ae235b
    }
Packit ae235b
Packit ae235b
  CloseHandle (snapshot);
Packit ae235b
Packit ae235b
  return p;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gpointer
Packit ae235b
find_in_any_module (const gchar *symbol_name)
Packit ae235b
{
Packit ae235b
  gpointer result;
Packit ae235b
Packit ae235b
  if ((result = find_in_any_module_using_toolhelp (symbol_name)) == NULL)
Packit ae235b
    return NULL;
Packit ae235b
  else
Packit ae235b
    return result;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gpointer
Packit ae235b
_g_module_symbol (gpointer     handle,
Packit ae235b
		  const gchar *symbol_name)
Packit ae235b
{
Packit ae235b
  gpointer p;
Packit ae235b
  
Packit ae235b
  if (handle == null_module_handle)
Packit ae235b
    {
Packit ae235b
      if ((p = GetProcAddress (GetModuleHandle (NULL), symbol_name)) == NULL)
Packit ae235b
	p = find_in_any_module (symbol_name);
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    p = GetProcAddress (handle, symbol_name);
Packit ae235b
Packit ae235b
  if (!p)
Packit ae235b
    set_error ("");
Packit ae235b
Packit ae235b
  return p;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gchar*
Packit ae235b
_g_module_build_path (const gchar *directory,
Packit ae235b
		      const gchar *module_name)
Packit ae235b
{
Packit ae235b
  gint k;
Packit ae235b
Packit ae235b
  k = strlen (module_name);
Packit ae235b
    
Packit ae235b
  if (directory && *directory)
Packit ae235b
    if (k > 4 && g_ascii_strcasecmp (module_name + k - 4, ".dll") == 0)
Packit ae235b
      return g_strconcat (directory, G_DIR_SEPARATOR_S, module_name, NULL);
Packit ae235b
#ifdef G_WITH_CYGWIN
Packit ae235b
    else if (strncmp (module_name, "lib", 3) == 0 || strncmp (module_name, "cyg", 3) == 0)
Packit ae235b
      return g_strconcat (directory, G_DIR_SEPARATOR_S, module_name, ".dll", NULL);
Packit ae235b
    else
Packit ae235b
      return g_strconcat (directory, G_DIR_SEPARATOR_S, "cyg", module_name, ".dll", NULL);
Packit ae235b
#else
Packit ae235b
    else if (strncmp (module_name, "lib", 3) == 0)
Packit ae235b
      return g_strconcat (directory, G_DIR_SEPARATOR_S, module_name, ".dll", NULL);
Packit ae235b
    else
Packit ae235b
      return g_strconcat (directory, G_DIR_SEPARATOR_S, "lib", module_name, ".dll", NULL);
Packit ae235b
#endif
Packit ae235b
  else if (k > 4 && g_ascii_strcasecmp (module_name + k - 4, ".dll") == 0)
Packit ae235b
    return g_strdup (module_name);
Packit ae235b
#ifdef G_WITH_CYGWIN
Packit ae235b
  else if (strncmp (module_name, "lib", 3) == 0 || strncmp (module_name, "cyg", 3) == 0)
Packit ae235b
    return g_strconcat (module_name, ".dll", NULL);
Packit ae235b
  else
Packit ae235b
    return g_strconcat ("cyg", module_name, ".dll", NULL);
Packit ae235b
#else
Packit ae235b
  else if (strncmp (module_name, "lib", 3) == 0)
Packit ae235b
    return g_strconcat (module_name, ".dll", NULL);
Packit ae235b
  else
Packit ae235b
    return g_strconcat ("lib", module_name, ".dll", NULL);
Packit ae235b
#endif
Packit ae235b
}