#include <windows.h>
#include <winuser.h>
#include <fcntl.h>
#include <malloc.h>
#include <stdio.h>
#include <io.h>

STARTUPINFO		si;
PROCESS_INFORMATION	pi;
DEBUG_EVENT		de;
CONTEXT			ctx;

double	dig1, dig2;
double  dig3=3;

unsigned char buf[10];

const char *whatis="\nExcel runtime patcher \"2+2=5\" <www.conus.info>\n";

char* find_blk (char* buf, int buf_c, char* pt, int pt_c)
{
	do
		if (memcmp ((char*)(buf+buf_c-pt_c),pt,pt_c)==0)
			return (char*)(buf+buf_c-pt_c);
	while (buf_c--);
	return NULL;
};

void problem (char *m)
{
	MessageBox (NULL, m, "Problem", 0);
	ExitProcess (0);
};

void main ()
{
	unsigned int	adr;
	unsigned int	_edi;
	int		len;
	int		hdl1;
	char		*buf;
	char		*pt;
	unsigned int	_FLD_A, _ANCHOR;


	hdl1=open ("excel.exe", _O_RDONLY | _O_BINARY, 0);
	if (hdl1==-1)
		problem ("Can't find excel.exe");

	if ((buf=malloc (len=lseek (hdl1, 0, SEEK_END)))==NULL)
		problem ("malloc()");

	close (hdl1);

	GetStartupInfo (&si);
	if (CreateProcess ("excel.exe", 0, 0, 0, 0, DEBUG_ONLY_THIS_PROCESS, 0, 0, &si, &pi)==FALSE)
		problem ("CreateProcess()");

	// yes! I know that 0x30000000 is so overbold
#define _IMAGE_BASE 0x30000000
	if (ReadProcessMemory (pi.hProcess, (void*)_IMAGE_BASE, buf, len, NULL)==FALSE)
		problem ("ReadProcessMemory()");

	if ((pt=find_blk (buf, len, "\xDD\x47\xF4\xDC\x47\xE8\x8B\x57\xEC", 9))==NULL)
		problem ("This version of Excel is not so suitable for me, sorry");

	_ANCHOR=(_FLD_A=pt-buf+_IMAGE_BASE)+6;

// ** DEBUG
//	printf ("_FLD_A=%08X _ANCHOR=%08X\n",_FLD_A,_ANCHOR);

	free (buf);

	WriteProcessMemory (pi.hProcess, (void*)_FLD_A, "\xCC", 1, NULL);

	while (WaitForDebugEvent (&de, INFINITE))
	{
		if (de.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT)
			return;
		if (de.u.Exception.ExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT)
		{
			adr=(long int)de.u.Exception.ExceptionRecord.ExceptionAddress;
			if (adr==_FLD_A)
			{
				ctx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
				GetThreadContext (pi.hThread, &ctx);
				ctx.Eip--;
				SetThreadContext (pi.hThread, &ctx);
				WriteProcessMemory (pi.hProcess, (void*)_FLD_A, "\xDD", 1, NULL);
				_edi=ctx.Edi;

				ReadProcessMemory (pi.hProcess, (void*)(_edi-0x0C), &dig1, 8, NULL);
// ** DEBUG
//				printf ("dig1=%f\n",dig1);

				_edi=ctx.Edi;

				ReadProcessMemory (pi.hProcess, (void*)(_edi-0x18), &dig2, 8, NULL);
// ** DEBUG
//				printf ("dig2=%f\n",dig2);

				if (dig1==dig2 && dig1==2)
					WriteProcessMemory (pi.hProcess, (void*)(_edi-0x18), &dig3, 8, NULL);
				WriteProcessMemory (pi.hProcess, (void*)_ANCHOR, "\xCC", 1, NULL);
			};
			if (adr==_ANCHOR)
			{
				ctx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
				GetThreadContext (pi.hThread, &ctx);
				ctx.Eip--;
				SetThreadContext (pi.hThread, &ctx);
				WriteProcessMemory (pi.hProcess, (void*)_ANCHOR, "\x8B", 1, NULL);
				WriteProcessMemory (pi.hProcess, (void*)_FLD_A, "\xCC", 1, NULL);

			};
			ContinueDebugEvent (de.dwProcessId, de.dwThreadId, DBG_CONTINUE);

		} else
			ContinueDebugEvent (de.dwProcessId, de.dwThreadId, DBG_EXCEPTION_NOT_HANDLED);
	};
};
