From 09e0c732f3c13f7ac1ba8c40e918092c642051a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andr=C3=A9=20Hentschel?= <nerv@dawncrow.de>
Date: Tue, 26 Aug 2014 00:59:37 +0200
Subject: wpcap: Load libpcap dynamically.

This is intended for packagers, without this patch libpcap easily becomes a fixed dependency of wine.
Something we don't want i guess.
---
 configure.ac           |   6 +-
 dlls/wpcap/Makefile.in |   1 -
 dlls/wpcap/wpcap.c     | 171 +++++++++++++++++++++++++++++++++++++++----------
 3 files changed, 140 insertions(+), 38 deletions(-)

diff --git a/configure.ac b/configure.ac
index 811e2aa..30b500a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1182,11 +1182,11 @@ test "x$ac_cv_lib_OpenCL_clGetPlatformInfo" != xyes && enable_opencl=${enable_op
 dnl **** Check for libpcap ****
 if test "$ac_cv_header_pcap_pcap_h" = "yes"
 then
-    AC_CHECK_LIB(pcap,pcap_create,[AC_SUBST(PCAP_LIBS,["-lpcap"])])
+    WINE_CHECK_SONAME(pcap,pcap_create,,,)
 fi
-WINE_NOTICE_WITH(pcap,[test "x$ac_cv_lib_pcap_pcap_create" != xyes],
+WINE_NOTICE_WITH(pcap,[test "x$ac_cv_lib_soname_pcap" = "x"],
                  [pcap ${notice_platform}development files not found, wpcap won't be supported.])
-test "x$ac_cv_lib_pcap_pcap_create" != xyes && enable_wpcap=${enable_wpcap:-no}
+test "x$ac_cv_lib_soname_pcap" = "x" && enable_wpcap=${enable_wpcap:-no}
 
 dnl **** Check for libxml2 ****
 
diff --git a/dlls/wpcap/Makefile.in b/dlls/wpcap/Makefile.in
index 91b4a95..aeef71a 100644
--- a/dlls/wpcap/Makefile.in
+++ b/dlls/wpcap/Makefile.in
@@ -1,6 +1,5 @@
 MODULE    = wpcap.dll
 DELAYIMPORTS = ws2_32
-EXTRALIBS = $(PCAP_LIBS)
 
 C_SRCS = \
 	wpcap.c
diff --git a/dlls/wpcap/wpcap.c b/dlls/wpcap/wpcap.c
index 44e8c2a..f9029c8 100644
--- a/dlls/wpcap/wpcap.c
+++ b/dlls/wpcap/wpcap.c
@@ -18,6 +18,9 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "config.h"
+#include "wine/port.h"
+#include "wine/library.h"
 #include <pcap/pcap.h>
 #include "winsock2.h"
 #include "windef.h"
@@ -40,47 +43,128 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
 #define PCAP_SRC_IFLOCAL        3
 #endif
 
+static void          (*ppcap_breakloop)(pcap_t *);
+static void          (*ppcap_close)(pcap_t *);
+static int           (*ppcap_compile)(pcap_t *, struct bpf_program *, const char *, int, unsigned int);
+static int           (*ppcap_datalink)(pcap_t *);
+static int           (*ppcap_datalink_name_to_val)(const char *);
+static const char*   (*ppcap_datalink_val_to_description)(int);
+static const char*   (*ppcap_datalink_val_to_name)(int);
+static int           (*ppcap_dispatch)(pcap_t *, int, pcap_handler, u_char *);
+static void          (*ppcap_dump)(u_char *, const struct pcap_pkthdr *, const u_char *);
+static pcap_dumper_t* (*ppcap_dump_open)(pcap_t *, const char *);
+static int           (*ppcap_findalldevs)(pcap_if_t **, char *);
+static void          (*ppcap_freealldevs)(pcap_if_t *);
+static void          (*ppcap_freecode)(struct bpf_program *);
+static char*         (*ppcap_geterr)(pcap_t *);
+static int           (*ppcap_getnonblock)(pcap_t *, char *);
+static const char*   (*ppcap_lib_version)(void);
+static int           (*ppcap_list_datalinks)(pcap_t *, int **);
+static char*         (*ppcap_lookupdev)(char *);
+static int           (*ppcap_lookupnet)(const char *, unsigned int *, unsigned int *, char *);
+static int           (*ppcap_loop)(pcap_t *, int, pcap_handler, u_char *);
+static int           (*ppcap_major_version)(pcap_t *);
+static int           (*ppcap_minor_version)(pcap_t *);
+static const u_char* (*ppcap_next)(pcap_t *, struct pcap_pkthdr *);
+static int           (*ppcap_next_ex)(pcap_t *, struct pcap_pkthdr **, const u_char **);
+static pcap_t*       (*ppcap_open_live)(const char *, int, int, int, char *);
+static int           (*ppcap_sendpacket)(pcap_t *, const u_char *, int);
+static int           (*ppcap_set_datalink)(pcap_t *, int);
+static int           (*ppcap_setfilter)(pcap_t *, struct bpf_program *);
+static int           (*ppcap_setnonblock)(pcap_t *, int, char *);
+static int           (*ppcap_snapshot)(pcap_t *);
+static int           (*ppcap_stats)(pcap_t *, struct pcap_stat *);
+
+static void *pcap_handle = NULL;
+
+static BOOL load_functions(void)
+{
+    pcap_handle = wine_dlopen(SONAME_LIBPCAP, RTLD_NOW, NULL, 0);
+
+    if (!pcap_handle)
+    {
+        FIXME("Wine cannot find the library %s, wpcap.dll not working.\n", SONAME_LIBPCAP);
+        return FALSE;
+    }
+
+    #define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(pcap_handle, #f, NULL, 0)) == NULL){WARN("Can't find symbol %s\n", #f); return FALSE;}
+    LOAD_FUNCPTR(pcap_breakloop);
+    LOAD_FUNCPTR(pcap_close);
+    LOAD_FUNCPTR(pcap_compile);
+    LOAD_FUNCPTR(pcap_datalink);
+    LOAD_FUNCPTR(pcap_datalink_name_to_val);
+    LOAD_FUNCPTR(pcap_datalink_val_to_description);
+    LOAD_FUNCPTR(pcap_datalink_val_to_name);
+    LOAD_FUNCPTR(pcap_dispatch);
+    LOAD_FUNCPTR(pcap_dump);
+    LOAD_FUNCPTR(pcap_dump_open);
+    LOAD_FUNCPTR(pcap_findalldevs);
+    LOAD_FUNCPTR(pcap_freealldevs);
+    LOAD_FUNCPTR(pcap_freecode);
+    LOAD_FUNCPTR(pcap_geterr);
+    LOAD_FUNCPTR(pcap_getnonblock);
+    LOAD_FUNCPTR(pcap_lib_version);
+    LOAD_FUNCPTR(pcap_list_datalinks);
+    LOAD_FUNCPTR(pcap_lookupdev);
+    LOAD_FUNCPTR(pcap_lookupnet);
+    LOAD_FUNCPTR(pcap_loop);
+    LOAD_FUNCPTR(pcap_major_version);
+    LOAD_FUNCPTR(pcap_minor_version);
+    LOAD_FUNCPTR(pcap_next);
+    LOAD_FUNCPTR(pcap_next_ex);
+    LOAD_FUNCPTR(pcap_open_live);
+    LOAD_FUNCPTR(pcap_sendpacket);
+    LOAD_FUNCPTR(pcap_set_datalink);
+    LOAD_FUNCPTR(pcap_setfilter);
+    LOAD_FUNCPTR(pcap_setnonblock);
+    LOAD_FUNCPTR(pcap_snapshot);
+    LOAD_FUNCPTR(pcap_stats);
+    #undef LOAD_FUNCPTR
+
+    return TRUE;
+}
+
 void CDECL wine_pcap_breakloop(pcap_t *p)
 {
     TRACE("(%p)\n", p);
-    return pcap_breakloop(p);
+    return ppcap_breakloop(p);
 }
 
 void CDECL wine_pcap_close(pcap_t *p)
 {
     TRACE("(%p)\n", p);
-    pcap_close(p);
+    return ppcap_close(p);
 }
 
 int CDECL wine_pcap_compile(pcap_t *p, struct bpf_program *program, const char *buf, int optimize,
                             unsigned int mask)
 {
     TRACE("(%p %p %s %i %u)\n", p, program, debugstr_a(buf), optimize, mask);
-    return pcap_compile(p, program, buf, optimize, mask);
+    return ppcap_compile(p, program, buf, optimize, mask);
 }
 
 int CDECL wine_pcap_datalink(pcap_t *p)
 {
     TRACE("(%p)\n", p);
-    return pcap_datalink(p);
+    return ppcap_datalink(p);
 }
 
 int CDECL wine_pcap_datalink_name_to_val(const char *name)
 {
     TRACE("(%s)\n", debugstr_a(name));
-    return pcap_datalink_name_to_val(name);
+    return ppcap_datalink_name_to_val(name);
 }
 
 const char* CDECL wine_pcap_datalink_val_to_description(int dlt)
 {
     TRACE("(%i)\n", dlt);
-    return pcap_datalink_val_to_description(dlt);
+    return ppcap_datalink_val_to_description(dlt);
 }
 
 const char* CDECL wine_pcap_datalink_val_to_name(int dlt)
 {
     TRACE("(%i)\n", dlt);
-    return pcap_datalink_val_to_name(dlt);
+    return ppcap_datalink_val_to_name(dlt);
 }
 
 typedef struct
@@ -112,12 +196,12 @@ int CDECL wine_pcap_dispatch(pcap_t *p, int cnt,
         pcb = HeapAlloc(GetProcessHeap(), 0, sizeof(PCAP_HANDLER_CALLBACK));
         pcb->pfn_cb = callback;
         pcb->user_data = user;
-        res = pcap_dispatch(p, cnt, pcap_handler_callback, (unsigned char *)pcb);
+        res = ppcap_dispatch(p, cnt, pcap_handler_callback, (unsigned char *)pcb);
         HeapFree(GetProcessHeap(), 0, pcb);
         return res;
     }
 
-    return pcap_dispatch(p, cnt, NULL, user);
+    return ppcap_dispatch(p, cnt, NULL, user);
 }
 
 int CDECL wine_pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
@@ -125,7 +209,7 @@ int CDECL wine_pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
     int ret;
 
     TRACE("(%p %p)\n", alldevsp, errbuf);
-    ret = pcap_findalldevs(alldevsp, errbuf);
+    ret = ppcap_findalldevs(alldevsp, errbuf);
     if(alldevsp && !*alldevsp)
         ERR_(winediag)("Failed to access raw network (pcap), this requires special permissions.\n");
 
@@ -141,13 +225,13 @@ int CDECL wine_pcap_findalldevs_ex(char *source, void *auth, pcap_if_t **alldevs
 void CDECL wine_pcap_freealldevs(pcap_if_t *alldevs)
 {
     TRACE("(%p)\n", alldevs);
-    pcap_freealldevs(alldevs);
+    ppcap_freealldevs(alldevs);
 }
 
 void CDECL wine_pcap_freecode(struct bpf_program *fp)
 {
     TRACE("(%p)\n", fp);
-    return pcap_freecode(fp);
+    return ppcap_freecode(fp);
 }
 
 typedef struct _AirpcapHandle *PAirpcapHandle;
@@ -160,18 +244,18 @@ PAirpcapHandle CDECL wine_pcap_get_airpcap_handle(pcap_t *p)
 char* CDECL wine_pcap_geterr(pcap_t *p)
 {
     TRACE("(%p)\n", p);
-    return pcap_geterr(p);
+    return ppcap_geterr(p);
 }
 
 int CDECL wine_pcap_getnonblock(pcap_t *p, char *errbuf)
 {
     TRACE("(%p %p)\n", p, errbuf);
-    return pcap_getnonblock(p, errbuf);
+    return ppcap_getnonblock(p, errbuf);
 }
 
 const char* CDECL wine_pcap_lib_version(void)
 {
-    const char* ret = pcap_lib_version();
+    const char* ret = ppcap_lib_version();
     TRACE("%s\n", debugstr_a(ret));
     return ret;
 }
@@ -179,20 +263,20 @@ const char* CDECL wine_pcap_lib_version(void)
 int CDECL wine_pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
 {
     TRACE("(%p %p)\n", p, dlt_buffer);
-    return pcap_list_datalinks(p, dlt_buffer);
+    return ppcap_list_datalinks(p, dlt_buffer);
 }
 
 char* CDECL wine_pcap_lookupdev(char *errbuf)
 {
     TRACE("(%p)\n", errbuf);
-    return pcap_lookupdev(errbuf);
+    return ppcap_lookupdev(errbuf);
 }
 
 int CDECL wine_pcap_lookupnet(const char *device, unsigned int *netp, unsigned int *maskp,
                               char *errbuf)
 {
     TRACE("(%s %p %p %p)\n", debugstr_a(device), netp, maskp, errbuf);
-    return pcap_lookupnet(device, netp, maskp, errbuf);
+    return ppcap_lookupnet(device, netp, maskp, errbuf);
 }
 
 int CDECL wine_pcap_loop(pcap_t *p, int cnt,
@@ -209,36 +293,36 @@ int CDECL wine_pcap_loop(pcap_t *p, int cnt,
         pcb = HeapAlloc(GetProcessHeap(), 0, sizeof(PCAP_HANDLER_CALLBACK));
         pcb->pfn_cb = callback;
         pcb->user_data = user;
-        res =  pcap_loop(p, cnt, pcap_handler_callback, (unsigned char *)pcb);
+        res =  ppcap_loop(p, cnt, pcap_handler_callback, (unsigned char *)pcb);
         HeapFree(GetProcessHeap(), 0, pcb);
         return res;
     }
 
-    return pcap_loop(p, cnt, NULL, user);
+    return ppcap_loop(p, cnt, NULL, user);
 }
 
 int CDECL wine_pcap_major_version(pcap_t *p)
 {
     TRACE("(%p)\n", p);
-    return pcap_major_version(p);
+    return ppcap_major_version(p);
 }
 
 int CDECL wine_pcap_minor_version(pcap_t *p)
 {
     TRACE("(%p)\n", p);
-    return pcap_minor_version(p);
+    return ppcap_minor_version(p);
 }
 
 const unsigned char* CDECL wine_pcap_next(pcap_t *p, struct pcap_pkthdr *h)
 {
     TRACE("(%p %p)\n", p, h);
-    return pcap_next(p, h);
+    return ppcap_next(p, h);
 }
 
 int CDECL wine_pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, const unsigned char **pkt_data)
 {
     TRACE("(%p %p %p)\n", p, pkt_header, pkt_data);
-    return pcap_next_ex(p, pkt_header, pkt_data);
+    return ppcap_next_ex(p, pkt_header, pkt_data);
 }
 
 #define PCAP_OPENFLAG_PROMISCUOUS 1
@@ -249,14 +333,14 @@ pcap_t* CDECL wine_pcap_open(const char *source, int snaplen, int flags, int rea
     int promisc = flags & PCAP_OPENFLAG_PROMISCUOUS;
     FIXME("(%s %i %i %i %p %p): partial stub\n", debugstr_a(source), snaplen, flags, read_timeout,
                                                  auth, errbuf);
-    return pcap_open_live(source, snaplen, promisc, read_timeout, errbuf);
+    return ppcap_open_live(source, snaplen, promisc, read_timeout, errbuf);
 }
 
 pcap_t* CDECL wine_pcap_open_live(const char *source, int snaplen, int promisc, int to_ms,
                                   char *errbuf)
 {
     TRACE("(%s %i %i %i %p)\n", debugstr_a(source), snaplen, promisc, to_ms, errbuf);
-    return pcap_open_live(source, snaplen, promisc, to_ms, errbuf);
+    return ppcap_open_live(source, snaplen, promisc, to_ms, errbuf);
 }
 
 int CDECL wine_pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf)
@@ -300,13 +384,13 @@ int CDECL wine_pcap_parsesrcstr(const char *source, int *type, char *host, char
 int CDECL wine_pcap_sendpacket(pcap_t *p, const unsigned char *buf, int size)
 {
     TRACE("(%p %p %i)\n", p, buf, size);
-    return pcap_sendpacket(p, buf, size);
+    return ppcap_sendpacket(p, buf, size);
 }
 
 int CDECL wine_pcap_set_datalink(pcap_t *p, int dlt)
 {
     TRACE("(%p %i)\n", p, dlt);
-    return pcap_set_datalink(p, dlt);
+    return ppcap_set_datalink(p, dlt);
 }
 
 int CDECL wine_pcap_setbuff(pcap_t * p, int dim)
@@ -318,25 +402,25 @@ int CDECL wine_pcap_setbuff(pcap_t * p, int dim)
 int CDECL wine_pcap_setfilter(pcap_t *p, struct bpf_program *fp)
 {
     TRACE("(%p %p)\n", p, fp);
-    return pcap_setfilter(p, fp);
+    return ppcap_setfilter(p, fp);
 }
 
 int CDECL wine_pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
 {
     TRACE("(%p %i %p)\n", p, nonblock, errbuf);
-    return pcap_setnonblock(p, nonblock, errbuf);
+    return ppcap_setnonblock(p, nonblock, errbuf);
 }
 
 int CDECL wine_pcap_snapshot(pcap_t *p)
 {
     TRACE("(%p)\n", p);
-    return pcap_snapshot(p);
+    return ppcap_snapshot(p);
 }
 
 int CDECL wine_pcap_stats(pcap_t *p, struct pcap_stat *ps)
 {
     TRACE("(%p %p)\n", p, ps);
-    return pcap_stats(p, ps);
+    return ppcap_stats(p, ps);
 }
 
 int CDECL wine_wsockinit(void)
@@ -349,10 +433,29 @@ int CDECL wine_wsockinit(void)
 
 pcap_dumper_t* CDECL wine_pcap_dump_open(pcap_t *p, const char *fname)
 {
-    return pcap_dump_open(p, fname);
+    return ppcap_dump_open(p, fname);
 }
 
 void CDECL wine_pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
 {
-    return pcap_dump(user, h, sp);
+    return ppcap_dump(user, h, sp);
+}
+
+BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+    TRACE("%p,%x,%p\n", hinstDLL, fdwReason, lpvReserved);
+
+    switch (fdwReason)
+    {
+        case DLL_PROCESS_ATTACH:
+            DisableThreadLibraryCalls(hinstDLL);
+            if (!load_functions()) return FALSE;
+            break;
+        case DLL_PROCESS_DETACH:
+            if (lpvReserved) break;
+            if (pcap_handle) wine_dlclose(pcap_handle, NULL, 0);
+            break;
+    }
+
+    return TRUE;
 }
-- 
2.6.4

