#ifdef _WIN32

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

/**
 * Win32 error code from last failure.
 */

static DWORD lastError = 0;

#ifdef __cplusplus
extern "C"
{
#endif

	/**
	 * Convert UTF-8 string to Windows UNICODE (UCS-2 LE).
	 *
	 * Caller must free() the returned string.
	 */

	static WCHAR *
	UTF8toWCHAR(
			const char *inputString /** UTF-8 string. */
	)
	{
		int outputSize;
		WCHAR *outputString;

		outputSize = MultiByteToWideChar(CP_UTF8, 0, inputString, -1, NULL, 0);

		if (outputSize == 0)
			return NULL;

		outputString = (WCHAR *)malloc(outputSize * sizeof(WCHAR));

		if (outputString == NULL)
		{
			SetLastError(ERROR_OUTOFMEMORY);
			return NULL;
		}

		if (MultiByteToWideChar(CP_UTF8, 0, inputString, -1, outputString, outputSize) != outputSize)
		{
			free(outputString);
			return NULL;
		}

		return outputString;
	}

	/**
	 * Open DLL, returning a handle.
	 */

	void *
	dlopen(
			const char *file, /** DLL filename (UTF-8). */
			int mode					/** mode flags (ignored). */
	)
	{
		WCHAR *unicodeFilename;
		UINT errorMode;
		void *handle;

		UNREFERENCED_PARAMETER(mode);

		if (file == NULL)
			return (void *)GetModuleHandle(NULL);

		unicodeFilename = UTF8toWCHAR(file);

		if (unicodeFilename == NULL)
		{
			lastError = GetLastError();
			return NULL;
		}

		errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);

		/* Have LoadLibrary return NULL on failure; prevent GUI error message. */
		SetErrorMode(errorMode | SEM_FAILCRITICALERRORS);

		handle = (void *)LoadLibraryW(unicodeFilename);

		if (handle == NULL)
			lastError = GetLastError();

		SetErrorMode(errorMode);

		free(unicodeFilename);

		return handle;
	}

	/**
	 * Close DLL.
	 */

	int dlclose(
			void *handle /** Handle from dlopen(). */
	)
	{
		int rc = 0;

		if (handle != (void *)GetModuleHandle(NULL))
			rc = !FreeLibrary((HMODULE)handle);

		if (rc)
			lastError = GetLastError();

		return rc;
	}

	/**
	 * Look up symbol exported by DLL.
	 */

	void *
	dlsym(
			void *handle,		 /** Handle from dlopen(). */
			const char *name /** Name of exported symbol (ASCII). */
	)
	{
		void *address = (void *)GetProcAddress((HMODULE)handle, name);

		if (address == NULL)
			lastError = GetLastError();

		return address;
	}

	/**
	 * Return message describing last error.
	 */

	char *
	dlerror(void)
	{
		static char errorMessage[64];

		if (lastError != 0)
		{
			sprintf(errorMessage, "Win32 error %lu", lastError);
			lastError = 0;
			return errorMessage;
		}
		else
		{
			return NULL;
		}
	}
#ifdef __cplusplus
}
#endif

#else
#include <dlfcn.h>
#endif // _WIN32