/* $PostgreSQL: pgsql/src/backend/port/dynloader/win32.c,v 1.6 2005/08/12 21:23:10 momjian Exp $ */

#include <windows.h>
#include <stdio.h>

char *dlerror(void);
int dlclose(void *handle);
void *dlsym(void *handle, const char *symbol);
void *dlopen(const char *path, int mode);

static char last_dyn_error[512];

static void set_dl_error(void)
{
	DWORD err = GetLastError();

	if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
				FORMAT_MESSAGE_FROM_SYSTEM,
				NULL,
				err,
				MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
				last_dyn_error,
				sizeof(last_dyn_error)-1,
				NULL) == 0)
	{
		snprintf(last_dyn_error, sizeof(last_dyn_error)-1,
				"unknown error %lu", err);
	}	
}

char *
dlerror(void)
{
	if (last_dyn_error[0])
		return last_dyn_error;
	else
		return NULL;
}

int
dlclose(void *handle)
{
	if (!FreeLibrary((HMODULE) handle))
	{
		set_dl_error();
		return 1;
	}
	last_dyn_error[0] = 0;
	return 0;
}

void *
dlsym(void *handle, const char *symbol)
{
	void *ptr;
	ptr = GetProcAddress((HMODULE) handle, symbol);
	if (!ptr) 
	{
		set_dl_error();
		return NULL;
	}
	last_dyn_error[0] = 0;
	return ptr;
}

void *
dlopen(const char *path, int mode)
{
	HMODULE h;
	int prevmode;

	/* Disable popup error messages when loading DLLs */
	prevmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
	h = LoadLibrary(path);
	SetErrorMode(prevmode);
	
	if (!h) 
	{
		set_dl_error();
		return NULL;
	}
	last_dyn_error[0] = 0;
	return (void *) h;
}
