/* Test Code (c) 2010 Daniel Stelter-Gliese / Sirius_White */
#include <stdio.h>
#include <windows.h>

typedef void (*PluginMainProc)(void);

char *dll_basename[65536] = { NULL };

void __declspec(dllexport) LogFunction(void) {
	unsigned int retAddr;
	char *source_name;

	__asm {
		push eax			// Save value of eax
		mov	 eax, [ebp+4]	// Get return address
		mov  retAddr, eax	// Write to variable
		pop  eax			// Restore eax
	}

	retAddr &= 0xFFFF0000;	// Align to 64kb
	retAddr >>= 16;			// Divide by 64Kb
	
	if( dll_basename[retAddr] )
		source_name = dll_basename[retAddr];
	else
		source_name = "[Unknown Module]";

	printf("%s says hello!", source_name);
}

void LoadPlugin(char *file) {
	IMAGE_NT_HEADERS *pe;
	IMAGE_DOS_HEADER *dos;
	size_t i, start_base, end_base;
	PluginMainProc mainProc;

	HMODULE hMod = LoadLibrary(file);
	if( !hMod )
		return;

	// LoadLibrary returns a HMODULE variable.
	// This value represents the base address
	// of the Dll and can be used as such
	
	// Locate PE header
	dos = (IMAGE_DOS_HEADER *)hMod;
	pe = (IMAGE_NT_HEADERS *)((char*)hMod + dos->e_lfanew);

	// Determine base address index
	start_base = (size_t)hMod / 65536;
	// Calculate end base address
	end_base = start_base + pe->OptionalHeader.SizeOfImage / 65536;

	// Set values
	for(i = ((int)hMod / 65536); i <= end_base; i++) {
		dll_basename[i] = file; // Direct pointer as this is a test
	}

	printf("Loaded plugin.. Calling main!\n");
	mainProc = (PluginMainProc)GetProcAddress(hMod, "PluginMain");
	if( !mainProc )
		fprintf(stderr, "Failed to locate PluginMain!\n");
	else
		mainProc();
}

int main(int argc, char **argv) {
	LoadPlugin("plugin.dll");
}
