/* --- Copyright University of Sussex 1997. All rights reserved. ----------
 * File:			C.win32/extern/src/external.c
 * Purpose:			Suppport for external load, callback, etc.
 * Author:			Robert John Duncan, Jun 14 1994 (see revisions)
 * Documentation:
 * Related Files:
 */

#include "popcore.h"
#include "../lib/callback.h"


HINSTANCE pop_load_library(TCHAR *name)
	/*	Map a DLL into Poplog's address space
	*/
{
	return LoadLibrary(name);
}

BOOL pop_free_library(HINSTANCE handle)
	/*	Unmap a previously-mapped DLL
	*/
{
	return FreeLibrary(handle);
}

FARPROC pop_get_proc_address(HINSTANCE handle, LPCSTR symbol)
	/*	Get the address of a function exported from a DLL
	*/
{
	return GetProcAddress(handle, symbol);
}

int _pop_external_callback(void *args)
	/*	Callback wrapper: resets Poplog exception handling before making
		the call
	*/
{
	int status;

	__try {
		/* 	make sure the callback returns, so as not to screw up any
			exception handlers */
		*pop_external_flags |= PEF_RETURN_ABEXIT_NEXT;
		status = _WEAK_pop_external_callback(args);
	}
	__except(pop_exception_filter(GetExceptionInformation()))
	{
		/* shouldn't get here */
		status = -1;
	}

	return status;
}


/***************************************************************************
*                                                                          *
*	External function closures                                             *
*	(adapted from code in "c_core.c")                                      *
*                                                                          *
***************************************************************************/

#include <stdarg.h>

#define MAX_N_ARGS 10

POPOBJ pop_exfunc_arg;

DWORD _pop_exfunc_callback(DWORD arg, ...)
{
	struct efdata { int *flags; POPOBJ proc; };
	struct efdata *efdata = (struct efdata *)pop_exfunc_arg;
	struct { unsigned func; POPOBJ obj; DWORD *argp; } args;
	DWORD tmp[MAX_N_ARGS];
	va_list argp;
	int i;

	tmp[0] = arg;
	va_start(argp, arg);
	for (i = 1; i < MAX_N_ARGS; i++)
		tmp[i] = va_arg(argp, DWORD);
	va_end(argp);
	*pop_external_flags |= *(efdata->flags);
	args.func	= PEC_FUNC_CALL;
	args.obj	= efdata->proc;
	args.argp	= tmp;
	(void)_pop_external_callback(&args);
	return(tmp[0]);
}


/* --- Revision History ---------------------------------------------------
--- Robert Duncan, Jan 24 1997
		Corrections for UNICODE compilation
--- Robert John Duncan, Sep 13 1995
		Deleted definition of _pop_in_u*ser_extern, now in initial.p
 */
