#ifndef main_H
#define main_H

#ifdef _DEBUG
#ifndef _LTMDB
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)
#define new DEBUG_CLIENTBLOCK
#define _LTMDB
#endif
#endif
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#pragma warning( push )
#pragma warning( disable : 4091 )
#include <DbgHelp.h>
#pragma warning( pop )

#define KSGStart __stdcall

namespace Framework
{
    // Speichert die dem Programm vom Betriebssystem beim Start �bergebenen Parameter
    struct Startparam
    {
        HINSTANCE hinst, hpinst;
        LPSTR cmd;
        int show;
    };

    // �berschreibe diese Funktion. Sie wird vom Framework automatisch beim Start des Programmes aufgerufen
    //  p: Die Parameter, die dem Programm beim Start vom Betriebssystem �bergeben wurden
    int KSGStart Start( Startparam p );
    // Initialisiert das Framework
    // Wird in der (WinMain) des Frameworks automatisch aufgerufen
    __declspec( dllexport ) void initFramework();
    // Gibt den duch (initFramework) benutzten Arbeitsspeicher wieder frei
    // Wird in der (WinMain) des Frameworks automatisch aufgerufen
    __declspec( dllexport ) void releaseFramework();
}

typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType, CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);

void createMinidump(struct _EXCEPTION_POINTERS* apExceptionInfo)
{
	HMODULE mhLib = ::LoadLibrary("dbghelp.dll");
	MINIDUMPWRITEDUMP pDump = (MINIDUMPWRITEDUMP)::GetProcAddress(mhLib, "MiniDumpWriteDump");

	HANDLE  hFile = ::CreateFile("error_core_memory_dump.dmp", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL, NULL);

	_MINIDUMP_EXCEPTION_INFORMATION ExInfo;
	ExInfo.ThreadId = ::GetCurrentThreadId();
	ExInfo.ExceptionPointers = apExceptionInfo;
	ExInfo.ClientPointers = FALSE;

	pDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, MiniDumpNormal, &ExInfo, NULL, NULL);
	::CloseHandle(hFile);
}

LONG WINAPI unhandledHandler(struct _EXCEPTION_POINTERS* apExceptionInfo)
{
	createMinidump(apExceptionInfo);
	return EXCEPTION_CONTINUE_SEARCH;
}


int WINAPI WinMain( _In_ HINSTANCE hinst, _In_opt_ HINSTANCE hpinst, _In_ LPSTR cmd, int _In_ show )
{
#ifdef _DEBUG
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#else
	SetUnhandledExceptionFilter(unhandledHandler);
#endif
    Framework::initFramework();
    Framework::Startparam stp;
    stp.hinst = hinst;
    stp.hpinst = hpinst;
    stp.cmd = cmd;
    stp.show = show;
    int ret = Framework::Start( stp );
    Framework::releaseFramework();
    return ret;
}

#endif