/*
  Content-0C458F.cpp - Catch exceptions at this address.

  Jason Hood, 28 October, 2010.

  Build (VC6):
	cl /nologo /W3 /Ox /GfX /MD /LD Content-0C458F.cpp
*/

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <time.h>
#include <sys/timeb.h>
#include <stdio.h>
#include <string.h>
#include <vector>

#define NAKED	__declspec(naked)
#define STDCALL __stdcall
#define EXPORT	__declspec(dllexport)


#define ADDR_CONTENT (content+0xC458F)


DWORD dummy;
#define ProtectX( addr, size ) \
  VirtualProtect( addr, size, PAGE_EXECUTE_READWRITE, &dummy );

#define RELOFS( from, to ) \
  (DWORD)(to) - (DWORD)(from) - 4;

#define CALL( from, to ) \
  *(PBYTE)(from) = 0xe8; \
  *(PDWORD)((DWORD)from+1) = RELOFS( (DWORD)from+1, to )

#define CALL1( from, to ) \
  CALL( from, to ); \
  *((PBYTE)(from)+5) = 0x90


struct IDLL
{
  virtual void whatever( int, LPVOID ) { }
};


const char content_log[] = "Content-0C458F-bad.txt";

struct Docks
{
  UINT id;
  std::vector<int> property;
};

struct Paths
{
  std::vector<Docks> docks;
  UINT id;
};


int STDCALL Content_Log( int* data, int idx, int cnt, const Paths& path )
{
  FILE*  file;
  struct tm* tim;
  struct _timeb t;

  __try
  {
    return data[idx];
  }
  __except( EXCEPTION_EXECUTE_HANDLER )
  {
    _ftime( &t );
    tim = localtime( &t.time );
    file = fopen( content_log, "a" );
    fprintf( file, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d.%.3d: addr = %p, index = %d, count = %d\n",
		   tim->tm_year + 1900, tim->tm_mon + 1, tim->tm_mday,
		   tim->tm_hour, tim->tm_min, tim->tm_sec, t.millitm,
		   data, idx, cnt );
    fprintf( file, "\tpath = %u\n", path.id );
    std::vector<Docks>::const_iterator iter, end = path.docks.end();
    for (iter = path.docks.begin(); iter != end; ++iter)
      fprintf( file, "\tdock = %u\n", iter->id );
    putc( '\n', file );
    fclose( file );
    return 0;
  }
}


NAKED
void Content_Hook()
{
  __asm {
	push	ecx

	push	edi
	push	ebx
	push	eax
	push	edx
	call	Content_Log

	pop	ecx
	mov	[ecx+0x2C], eax
	ret
  }
}


extern "C" EXPORT
LPVOID CreateInstance( LPVOID, LPCSTR, LPVOID )
{
  PBYTE content = (PBYTE)GetModuleHandle( "content.dll" );
  ProtectX( ADDR_CONTENT, 6 );
  CALL1( ADDR_CONTENT, Content_Hook );

  return new IDLL;
}


extern "C" EXPORT
void DestroyInstance( IDLL& )
{
  return;
}


BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
{
  return TRUE;
}
