/*
    Run-time dynamic linking of DLL functions and data

    To use data by run-time linking, *data must be used.

    Emx 0.9c does not understand WINAPI inside a typedef definition (stack).
    The functions save_access and save_stat restores the stack.

    NT09c does not contain this error.
*/

#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include "dlltest.h"

typedef int WINAPI (*DLLACCESS) (const char *);
typedef int WINAPI (*DLLSTAT) (const char *, struct stat *);

int save_access(DLLACCESS func, char *s)
{
    return (*func) (s);
}

int save_stat(DLLSTAT func, const char *s, struct stat *t)
{
    return (*func) (s,t);
}

int main(int argc, char **argv)
{
    HINSTANCE hLib;		/* handle of the DLL */
    DLLACCESS lpfnAccess;	/* address of DLL function */
    DLLSTAT lpfnStat;		/* address of DLL function */
    int *data;			/* address of DLL data */
    struct stat fStat;

    /* --- load the library --- */

    hLib = LoadLibrary("dlltest.dll");
    if (!hLib) {
	DWORD err = GetLastError();
	printf("Cannot load dll fails err=0x%lX = %ld\n", err, err);
	exit(1);
    }

    /* --- get the address of the exported functions --- */

    lpfnAccess = (DLLACCESS) GetProcAddress(hLib, "DllAccess");
    if (!lpfnAccess) {
	printf("Error: GetProcAddress(Maximum)\n");
	exit(1);
    }
    lpfnStat = (DLLSTAT) GetProcAddress(hLib, "DllStat");
    if (!lpfnStat) {
	printf("Error: GetProcAddress(Minimum)\n");
	exit(1);
    }

    /* --- get the address of the exported data --- */

    data = (int *) GetProcAddress(hLib, "VariableDll");
    if (!data) {
	printf("Error: GetProcAddress(data)\n");
	exit(1);
    }

    /* --- access the dll --- */

    printf ("external data is %X\n\n", *data);

    if (argc > 1) {
	if (save_access(lpfnAccess, argv[1]) == 0) {
	    puts("dll access ok");

	    if (save_stat(lpfnStat, argv[1], &fStat) == 0) {
		puts("dll stat ok");
		printf("file mode %d\n", fStat.st_mode);
		printf("file size %lu\n", fStat.st_size);
		printf("file attr %lu\n", fStat.st_attr);
	    } else
		puts("dll stat error");
	} else
	    puts("dll access error");

    } else
	puts("usage: calldll <filename>");

    FreeLibrary(hLib);

    return 0;
}
