#include <windows.h>
#include <pcap_wrapper.h>
#include <assert.h>
#include <stdio.h>
int	(*pcap_loop )(pcap_t *, int, pcap_handler, u_char *);
int	(*pcap_breakloop )(pcap_t *);

pcap_t* (*pcap_create)(const char *, char *);

int	(*pcap_set_snaplen) (pcap_t *, int)=0;
int	(*pcap_set_promisc) (pcap_t *, int)=0;
int	(*pcap_can_set_rfmon) (pcap_t *)=0;
int	(*pcap_set_rfmon )(pcap_t *, int)=0;
int	(*pcap_set_timeout)(pcap_t *, int)=0;
int	(*pcap_set_buffer_size)(pcap_t *, int)=0;
int	(*pcap_activate)(pcap_t *)=0;

int	(*pcap_setfilter)(pcap_t *, struct bpf_program *)=0;
int 	(*pcap_setdirection)(pcap_t *, pcap_direction_t)=0;

int	(*pcap_datalink)(pcap_t *)=0;

void	(*pcap_freecode)(struct bpf_program *)=0;

int	(*pcap_compile)(pcap_t *, struct bpf_program *, const char *, int,
     bpf_u_int32)=0;

char*   (*pcap_geterr)(pcap_t *)=0;
int	(*pcap_sendpacket)(pcap_t *, const u_char *, int)=0;

char* (*pcap_lookupdev)(char *)=0;

int	(*pcap_findalldevs)(pcap_if_t **, char *)=0;

struct init_pcap_t
{
	init_pcap_t()
	{
		init_pcap();
	}
	
}do_it;

static void init_npcap_dll_path()
{
	BOOL(WINAPI *SetDllDirectory)(LPCTSTR);
	char sysdir_name[512];
	int len;

	SetDllDirectory = (BOOL(WINAPI *)(LPCTSTR)) GetProcAddress(GetModuleHandle("kernel32.dll"), "SetDllDirectoryA");
	if (SetDllDirectory == NULL) {
		printf("Error in SetDllDirectory\n");
	}
	else {
		len = GetSystemDirectory(sysdir_name, 480);	//	be safe
		if (!len)
			printf("Error in GetSystemDirectory (%d)\n", (int)GetLastError());
		strcat(sysdir_name, "\\Npcap");
		if (SetDllDirectory(sysdir_name) == 0)
			printf("Error in SetDllDirectory(\"System32\\Npcap\")\n");
	}
}

#define EXPORT_FUN(XXX) do{ XXX= (__typeof__(XXX)) GetProcAddress(wpcap, #XXX); }while(0)
int init_pcap()
{
	HMODULE wpcap=LoadLibrary("wpcap.dll");
	if(wpcap!=0)
	{
		printf("using system32/wpcap.dll\n");
	}
	else
	{
		init_npcap_dll_path();
		//SetDllDirectory("C:\\Windows\\System32\\Npcap\\");
		wpcap=LoadLibrary("wpcap.dll");
		if(wpcap!=0)
			printf("using system32/npcap/wpcap.dll\n");
	}
	if(wpcap==0)
	{
		printf("cant not open wpcap.dll, make sure winpcap/npcap is installed\n");
		exit(-1);
	}
	assert(wpcap!=0);

	EXPORT_FUN(pcap_loop);
	EXPORT_FUN(pcap_breakloop);
	EXPORT_FUN(pcap_create);
	EXPORT_FUN(pcap_set_snaplen);
	EXPORT_FUN(pcap_set_promisc);
	EXPORT_FUN(pcap_set_timeout);
	EXPORT_FUN(pcap_activate);
	EXPORT_FUN(pcap_setfilter);
	EXPORT_FUN(pcap_setdirection);
	EXPORT_FUN(pcap_datalink);
	EXPORT_FUN(pcap_freecode);
	EXPORT_FUN(pcap_compile);
	EXPORT_FUN(pcap_geterr);
	EXPORT_FUN(pcap_sendpacket);
	EXPORT_FUN(pcap_lookupdev);
	EXPORT_FUN(pcap_findalldevs);
	/*
	pcap_loop = (__typeof__(pcap_loop))GetProcAddress(wpcap, "pcap_loop");
	pcap_create = (__typeof__(pcap_create))GetProcAddress(wpcap, "pcap_create");
	pcap_set_snaplen = (__typeof__(pcap_set_snaplen))GetProcAddress(wpcap, "pcap_set_snaplen");
	pcap_set_promisc = (__typeof__(pcap_set_promisc))GetProcAddress(wpcap, "pcap_set_promisc");
	pcap_set_timeout = (__typeof__(pcap_set_timeout))GetProcAddress(wpcap, "pcap_set_timeout");
	pcap_activate = (__typeof__(pcap_activate))GetProcAddress(wpcap, "pcap_activate");
	pcap_setfilter = (__typeof__(pcap_setfilter))GetProcAddress(wpcap, "pcap_setfilter");
	pcap_setdirection = (__typeof__(pcap_setdirection))GetProcAddress(wpcap, "pcap_setdirection");
	pcap_datalink = (__typeof__(pcap_datalink))GetProcAddress(wpcap, "pcap_datalink");
	pcap_freecode = (__typeof__(pcap_freecode))GetProcAddress(wpcap, "pcap_freecode");
	pcap_compile = (__typeof__(pcap_compile))GetProcAddress(wpcap, "pcap_compile");
	pcap_geterr = (__typeof__(pcap_geterr))GetProcAddress(wpcap, "pcap_geterr");
	pcap_sendpacket = (__typeof__(pcap_sendpacket))GetProcAddress(wpcap, "pcap_sendpacket");
	pcap_lookupdev = (__typeof__(pcap_lookupdev))GetProcAddress(wpcap, "pcap_lookupdev");
	pcap_findalldevs = (__typeof__(pcap_findalldevs))GetProcAddress(wpcap, "pcap_findalldevs");
	//pcap_loop = (__typeof__(pcap_loop))GetProcAddress(wpcap, "pcap_loop");
	//pcap_loop = (__typeof__(pcap_loop))GetProcAddress(wpcap, "pcap_loop");
	//pcap_loop = (__typeof__(pcap_loop))GetProcAddress(wpcap, "pcap_loop");
	*/
	return 0;

}