When looking for symbols in the "main" module we must search both the main
authorTor Lillqvist <tml@iki.fi>
Wed, 22 Mar 2000 22:34:48 +0000 (22:34 +0000)
committerTor Lillqvist <tml@src.gnome.org>
Wed, 22 Mar 2000 22:34:48 +0000 (22:34 +0000)
2000-03-23  Tor Lillqvist  <tml@iki.fi>

* gmodule-win32.c (_g_module_symbol): When looking for symbols in
the "main" module we must search both the main program and all
currently loaded DLLs. Not only the main program, or even just the
DLLs loaded as gmodules.  Libglade requires this.

Thus we need to get a list of all modules in the current
process. There are two alternative APIs to do this: PSAPI and
Toolhelp. The former is only available on NT (including Win2k),
the latter on Win9x and Win2k. Check which one works, and use
that.

Code for using PSAPI and Toolhelp was borrowed from the Dr. Mingw
tool written by José Fonseca <em96115@fe.up.pt>. Thanks.

gmodule/ChangeLog
gmodule/gmodule-win32.c

index fa58bd49ba514931e623d2a22e5eb66cd9df0272..b40bbfd898fb72279416eba794066e8e123b2378 100644 (file)
@@ -1,3 +1,19 @@
+2000-03-23  Tor Lillqvist  <tml@iki.fi>
+
+       * gmodule-win32.c (_g_module_symbol): When looking for symbols in
+       the "main" module we must search both the main program and all
+       currently loaded DLLs. Not only the main program, or even just the
+       DLLs loaded as gmodules.  Libglade requires this.
+
+       Thus we need to get a list of all modules in the current
+       process. There are two alternative APIs to do this: PSAPI and
+       Toolhelp. The former is only available on NT (including Win2k),
+       the latter on Win9x and Win2k. Check which one works, and use
+       that.
+
+       Code for using PSAPI and Toolhelp was borrowed from the Dr. Mingw
+       tool written by José Fonseca <em96115@fe.up.pt>. Thanks.
+
 2000-03-04  Tor Lillqvist  <tml@iki.fi>
 
        * gmodule-win32.c: Call g_win32_error_message() to get the error
index 5654ce089faa8c33e7793ff921b01bd4727aa89e..6bcef9ff14e83ee7e37264dc6b1898406e994d85 100644 (file)
@@ -33,6 +33,8 @@
 
 #include <stdio.h>
 #include <windows.h>
+#include <psapi.h>
+#include <tlhelp32.h>
 
 static void
 set_error (void)
@@ -57,24 +59,133 @@ _g_module_open (const gchar *file_name,
   return handle;
 }
 
+static gint dummy;
+static gpointer null_module_handle = &dummy;
+  
 static gpointer
 _g_module_self (void)
 {
-  HMODULE handle;
-  
-  handle = GetModuleHandle (NULL);
-  if (!handle)
-    set_error ();
-  
-  return handle;
+  return null_module_handle;
 }
 
 static void
 _g_module_close (gpointer handle,
                 gboolean is_unref)
 {
-  if (!FreeLibrary (handle))
-    set_error ();
+  if (handle != null_module_handle)
+    if (!FreeLibrary (handle))
+      set_error ();
+}
+
+static gpointer
+find_in_any_module_using_toolhelp (const gchar *symbol_name)
+{
+  typedef HANDLE (WINAPI *PFNCREATETOOLHELP32SNAPSHOT)(DWORD, DWORD);
+  static PFNCREATETOOLHELP32SNAPSHOT pfnCreateToolhelp32Snapshot = NULL;
+
+  typedef BOOL (WINAPI *PFNMODULE32FIRST)(HANDLE, LPMODULEENTRY32);
+  static PFNMODULE32FIRST pfnModule32First= NULL;
+
+  typedef BOOL (WINAPI *PFNMODULE32NEXT)(HANDLE, LPMODULEENTRY32);
+  static PFNMODULE32NEXT pfnModule32Next = NULL;
+
+  static HMODULE kernel32;
+
+  HANDLE snapshot; 
+  MODULEENTRY32 me32;
+
+  gpointer p;
+
+  if (!pfnCreateToolhelp32Snapshot || !pfnModule32First || !pfnModule32Next)
+    {
+      if (!kernel32)
+       if (!(kernel32 = GetModuleHandle ("kernel32.dll")))
+         return NULL;
+
+      if (!(pfnCreateToolhelp32Snapshot = (PFNCREATETOOLHELP32SNAPSHOT) GetProcAddress (kernel32, "CreateToolhelp32Snapshot"))
+         || !(pfnModule32First = (PFNMODULE32FIRST) GetProcAddress (kernel32, "Module32First"))
+         || !(pfnModule32Next = (PFNMODULE32NEXT) GetProcAddress (kernel32, "Module32Next")))
+       return NULL;
+    }
+
+  if ((snapshot = (*pfnCreateToolhelp32Snapshot) (TH32CS_SNAPMODULE, 0)) == (HANDLE) -1)
+    return NULL;
+
+  me32.dwSize = sizeof (me32);
+  p = NULL;
+  if ((*pfnModule32First) (snapshot, &me32))
+    {
+      do {
+       if ((p = GetProcAddress (me32.hModule, symbol_name)) != NULL)
+         break;
+      } while ((*pfnModule32Next) (snapshot, &me32));
+    }
+
+  CloseHandle (snapshot);
+
+  return p;
+}
+
+static gpointer
+find_in_any_module_using_psapi (const gchar *symbol_name)
+{
+  static HMODULE psapi = NULL;
+
+  typedef BOOL (WINAPI *PFNENUMPROCESSMODULES) (HANDLE, HMODULE *, DWORD, LPDWORD) ;
+  static PFNENUMPROCESSMODULES pfnEnumProcessModules = NULL;
+
+  HMODULE *modules;
+  HMODULE dummy;
+  gint i, size;
+  DWORD needed;
+  
+  gpointer p;
+
+  if (!pfnEnumProcessModules)
+    {
+      if (!psapi)
+       if ((psapi = LoadLibrary ("psapi.dll")) == NULL)
+         return NULL;
+
+      if (!(pfnEnumProcessModules = (PFNENUMPROCESSMODULES) GetProcAddress (psapi, "EnumProcessModules")))
+       return NULL;
+    }
+
+  if (!(*pfnEnumProcessModules) (GetCurrentProcess (), &dummy,
+                                sizeof (HMODULE), &needed))
+    return NULL;
+
+  size = needed + 10 * sizeof (HMODULE);
+  modules = g_malloc (size);
+
+  if (!(*pfnEnumProcessModules) (GetCurrentProcess (), modules,
+                                size, &needed)
+      || needed > size)
+    {
+      g_free (modules);
+      return NULL;
+    }
+  
+  p = NULL;
+  for (i = 0; i < needed / sizeof (HMODULE); i++)
+    if ((p = GetProcAddress (modules[i], symbol_name)) != NULL)
+      break;
+
+  g_free (modules);
+
+  return p;
+}
+
+static gpointer
+find_in_any_module (const gchar *symbol_name)
+{
+  gpointer result;
+
+  if ((result = find_in_any_module_using_toolhelp (symbol_name)) == NULL
+      && (result = find_in_any_module_using_psapi (symbol_name)) == NULL)
+    return NULL;
+  else
+    return result;
 }
 
 static gpointer
@@ -83,7 +194,11 @@ _g_module_symbol (gpointer     handle,
 {
   gpointer p;
   
-  p = GetProcAddress (handle, symbol_name);
+  if (handle == null_module_handle)
+    p = find_in_any_module (symbol_name);
+  else
+    p = GetProcAddress (handle, symbol_name);
+
   if (!p)
     set_error ();