# HG changeset patch
# Node ID 87e243a36b52
# Parent  0edea2beaa95
diff --git a/libpurple/protocols/bonjour/dns_sd_proxy.c b/libpurple/protocols/bonjour/dns_sd_proxy.c
--- a/libpurple/protocols/bonjour/dns_sd_proxy.c
+++ b/libpurple/protocols/bonjour/dns_sd_proxy.c
@@ -18,6 +18,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
  */
 
+#include <gmodule.h>
+
 #include <purple.h>
 
 #include "dns_sd_proxy.h"
@@ -55,26 +57,35 @@ gboolean dns_sd_available(void) {
 	static gboolean loaded = FALSE;
 
 	if (!initialized) {
+		GModule *dnssd = NULL;
 		initialized = TRUE;
-		if ((_DNSServiceAddRecord = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "DNSServiceAddRecord"))
-				&& (_DNSServiceBrowse = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "DNSServiceBrowse"))
-				&& (_DNSServiceConstructFullName = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "DNSServiceConstructFullName"))
-				&& (_DNSServiceGetAddrInfo = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "DNSServiceGetAddrInfo"))
-				&& (_DNSServiceProcessResult = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "DNSServiceProcessResult"))
-				&& (_DNSServiceQueryRecord = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "DNSServiceQueryRecord"))
-				&& (_DNSServiceRefDeallocate = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "DNSServiceRefDeallocate"))
-				&& (_DNSServiceRefSockFD = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "DNSServiceRefSockFD"))
-				&& (_DNSServiceRegister = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "DNSServiceRegister"))
-				&& (_DNSServiceResolve = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "DNSServiceResolve"))
-				&& (_DNSServiceRemoveRecord = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "DNSServiceRemoveRecord"))
-				&& (_DNSServiceUpdateRecord = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "DNSServiceUpdateRecord"))
-				&& (_TXTRecordCreate = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "TXTRecordCreate"))
-				&& (_TXTRecordDeallocate = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "TXTRecordDeallocate"))
-				&& (_TXTRecordGetBytesPtr = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "TXTRecordGetBytesPtr"))
-				&& (_TXTRecordGetLength = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "TXTRecordGetLength"))
-				&& (_TXTRecordGetValuePtr = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "TXTRecordGetValuePtr"))
-				&& (_TXTRecordSetValue = (gpointer)wpurple_find_and_loadproc("dnssd.dll", "TXTRecordSetValue"))) {
+		if((dnssd = g_module_open("dnssd.dll", 0)) != NULL &&
+		   g_module_symbol(dnssd, "DNSServiceAddRecord", (gpointer *)&_DNSServiceAddRecord) &&
+		   g_module_symbol(dnssd, "DNSServiceBrowse", (gpointer *)&_DNSServiceBrowse) &&
+		   g_module_symbol(dnssd, "DNSServiceConstructFullName", (gpointer *)&_DNSServiceConstructFullName) &&
+		   g_module_symbol(dnssd, "DNSServiceGetAddrInfo", (gpointer *)&_DNSServiceGetAddrInfo) &&
+		   g_module_symbol(dnssd, "DNSServiceProcessResult", (gpointer *)&_DNSServiceProcessResult) &&
+		   g_module_symbol(dnssd, "DNSServiceQueryRecord", (gpointer *)&_DNSServiceQueryRecord) &&
+		   g_module_symbol(dnssd, "DNSServiceRefDeallocate", (gpointer *)&_DNSServiceRefDeallocate) &&
+		   g_module_symbol(dnssd, "DNSServiceRefSockFD", (gpointer *)&_DNSServiceRefSockFD) &&
+		   g_module_symbol(dnssd, "DNSServiceRegister", (gpointer *)&_DNSServiceRegister) &&
+		   g_module_symbol(dnssd, "DNSServiceResolve", (gpointer *)&_DNSServiceResolve) &&
+		   g_module_symbol(dnssd, "DNSServiceRemoveRecord", (gpointer *)&_DNSServiceRemoveRecord) &&
+		   g_module_symbol(dnssd, "DNSServiceUpdateRecord", (gpointer *)&_DNSServiceUpdateRecord) &&
+		   g_module_symbol(dnssd, "TXTRecordCreate", (gpointer *)&_TXTRecordCreate) &&
+		   g_module_symbol(dnssd, "TXTRecordDeallocate", (gpointer *)&_TXTRecordDeallocate) &&
+		   g_module_symbol(dnssd, "TXTRecordGetBytesPtr", (gpointer *)&_TXTRecordGetBytesPtr) &&
+		   g_module_symbol(dnssd, "TXTRecordGetLength", (gpointer *)&_TXTRecordGetLength) &&
+		   g_module_symbol(dnssd, "TXTRecordGetValuePtr", (gpointer *)&_TXTRecordGetValuePtr) &&
+		   g_module_symbol(dnssd, "TXTRecordSetValue", (gpointer *)&_TXTRecordSetValue))
+		{
+			/* TODO: The dnssd module leaks, but there's not a good
+			 * place to put the cleanup yet, as there's quite a bit
+			 * of abstraction between mDNS API here to the actual
+			 * plugin unload. */
 			loaded = TRUE;
+		} else {
+			g_clear_pointer(&dnssd, g_module_close);
 		}
 	}
 	return loaded;
diff --git a/libpurple/protocols/bonjour/meson.build b/libpurple/protocols/bonjour/meson.build
--- a/libpurple/protocols/bonjour/meson.build
+++ b/libpurple/protocols/bonjour/meson.build
@@ -19,9 +19,11 @@ if IS_WIN32
 		'dns_sd_proxy.c', 'dns_sd_proxy.h', 'mdns_dns_sd.c', 'mdns_dns_sd.h',
 		'mdns_win32.c'
 	]
+	gmodule = dependency('gmodule-2.0')
 	bonjour_link_args = ['-lnetapi32']
 else
 	BONJOUR_SOURCES += ['mdns_avahi.c']
+	gmodule = []
 	bonjour_link_args = []
 endif
 
@@ -36,7 +38,7 @@ if DYNAMIC_BONJOUR
 	    c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="Purple-Bonjour"'],
 	    gnu_symbol_visibility : 'hidden',
 	    link_args : bonjour_link_args,
-	    dependencies : [libxml, avahi, libpurple_dep, glib, ws2_32],
+	    dependencies : [libxml, avahi, libpurple_dep, glib, gmodule, ws2_32],
 	    install : true,
 	    install_dir : PURPLE_PLUGINDIR)
 
diff --git a/libpurple/win32/win32dep.h b/libpurple/win32/win32dep.h
--- a/libpurple/win32/win32dep.h
+++ b/libpurple/win32/win32dep.h
@@ -43,9 +43,6 @@ G_BEGIN_DECLS
 /**
  ** win32dep.c
  **/
-/* Windows helper functions */
-PURPLE_AVAILABLE_IN_ALL
-FARPROC wpurple_find_and_loadproc(const char *dllname, const char *procedure);
 
 /* Determine Purple paths */
 PURPLE_AVAILABLE_IN_ALL
diff --git a/libpurple/win32/win32dep.c b/libpurple/win32/win32dep.c
--- a/libpurple/win32/win32dep.c
+++ b/libpurple/win32/win32dep.c
@@ -48,49 +48,6 @@ static HINSTANCE libpurpledll_hInstance 
  *  PUBLIC CODE
  */
 
-/* Determine whether the specified dll contains the specified procedure.
-   If so, load it (if not already loaded). */
-FARPROC wpurple_find_and_loadproc(const char *dllname, const char *procedure) {
-	HMODULE hmod;
-	BOOL did_load = FALSE;
-	FARPROC proc = 0;
-
-	wchar_t *wc_dllname = g_utf8_to_utf16(dllname, -1, NULL, NULL, NULL);
-
-	if(!(hmod = GetModuleHandleW(wc_dllname))) {
-		if (purple_debug_is_verbose())
-			purple_debug_info("wpurple", "%s not already loaded; loading it...\n", dllname);
-		if(!(hmod = LoadLibraryW(wc_dllname))) {
-			purple_debug_error("wpurple", "Could not load: %s (%s)\n", dllname,
-				g_win32_error_message(GetLastError()));
-			g_free(wc_dllname);
-			return NULL;
-		}
-		else
-			did_load = TRUE;
-	}
-
-	g_free(wc_dllname);
-	wc_dllname = NULL;
-
-	if((proc = GetProcAddress(hmod, procedure))) {
-		if (purple_debug_is_verbose()) {
-			purple_debug_info("wpurple", "This version of %s contains %s\n",
-				dllname, procedure);
-		}
-		return proc;
-	}
-	else {
-		purple_debug_warning("wpurple", "Function %s not found in dll %s\n",
-			procedure, dllname);
-		if(did_load) {
-			/* unload dll */
-			FreeLibrary(hmod);
-		}
-		return NULL;
-	}
-}
-
 /* Determine Purple Paths during Runtime */
 
 /* Get paths to special Windows folders. */
diff --git a/pidgin/meson.build b/pidgin/meson.build
--- a/pidgin/meson.build
+++ b/pidgin/meson.build
@@ -158,6 +158,17 @@ libpidgin_SOURCES += pidgin_resource
 pidgin_filebase = 'pidgin-3'
 pidgin_include_base = pidgin_filebase / 'pidgin'
 
+_libpidgin_dependencies = [
+	glib,
+	gplugin_gtk_dep,
+	gtk,
+	IOKIT,
+	json,
+	libadwaita,
+	math,
+	libpurple_dep,
+]
+
 if IS_WIN32
 	libpidgin_SOURCES += [
 		'pidgin.c',
@@ -184,6 +195,10 @@ if IS_WIN32
 		'win32/winpidgin.c',
 		pidgin_WIN32_RESOURCES,
 	]
+
+	_libpidgin_dependencies += [
+		dependency('gmodule-2.0'),
+	]
 endif
 
 PIDGIN_H_INCLUDES = []
@@ -206,17 +221,6 @@ pidgin_version_h = configure_file(input 
 install_headers(libpidgin_headers, subdir : pidgin_include_base)
 install_headers(libpidgin_prefs_headers, subdir : pidgin_include_base / 'prefs')
 
-_libpidgin_dependencies = [
-	glib,
-	gplugin_gtk_dep,
-	gtk,
-	IOKIT,
-	json,
-	libadwaita,
-	math,
-	libpurple_dep,
-]
-
 libpidgin_built_sources = [
 ]
 
diff --git a/pidgin/win32/gtkwin32dep.c b/pidgin/win32/gtkwin32dep.c
--- a/pidgin/win32/gtkwin32dep.c
+++ b/pidgin/win32/gtkwin32dep.c
@@ -33,6 +33,7 @@
 
 #include <glib.h>
 #include <glib/gstdio.h>
+#include <gmodule.h>
 #include <gtk/gtk.h>
 
 #include <purple.h>
@@ -47,6 +48,7 @@
 /*
  *  GLOBALS
  */
+static GModule *exchndl = NULL;
 HINSTANCE exe_hInstance = 0;
 HINSTANCE dll_hInstance = 0;
 HWND messagewin_hwnd;
@@ -128,16 +130,16 @@ static HWND winpidgin_message_window_ini
 void winpidgin_init(void) {
 	typedef void (__cdecl* LPFNSETLOGFILE)(const LPCSTR);
 	LPFNSETLOGFILE MySetLogFile;
-	gchar *exchndl_dll_path;
+	char *exchndl_dll_path = NULL;
 
 	if (purple_debug_is_verbose())
 		purple_debug_misc("winpidgin", "winpidgin_init start\n");
 
 	exchndl_dll_path = g_build_filename(wpurple_bin_dir(), "exchndl.dll", NULL);
-	MySetLogFile = (gpointer)wpurple_find_and_loadproc(exchndl_dll_path, "SetLogFile");
-	g_free(exchndl_dll_path);
-	exchndl_dll_path = NULL;
-	if (MySetLogFile) {
+	exchndl = g_module_open(exchndl_dll_path, 0);
+	g_clear_pointer(&exchndl_dll_path, g_free);
+
+	if(exchndl != NULL && g_module_symbol(exchndl, "SetLogFile", (gpointer)&MySetLogFile)) {
 		gchar *debug_dir, *locale_debug_dir;
 
 		debug_dir = g_build_filename(purple_cache_dir(), "pidgin.RPT", NULL);
@@ -149,6 +151,8 @@ void winpidgin_init(void) {
 
 		g_free(debug_dir);
 		g_free(locale_debug_dir);
+	} else {
+		g_clear_pointer(&exchndl, g_module_close);
 	}
 
 	messagewin_hwnd = winpidgin_message_window_init();
@@ -165,6 +169,7 @@ void winpidgin_cleanup(void) {
 	if(messagewin_hwnd)
 		DestroyWindow(messagewin_hwnd);
 
+	g_clear_pointer(&exchndl, g_module_close);
 }
 
 /* DLL initializer */
