自己根据网上的一篇Thunk技术改写的Thunk通用类

template<typename CallFunctionType,typename ClassFunctionType>class Thunk
{
	//BYTE:unsigned char
	//DWORD:unsigned long
	BYTE*m_thunk=0;
public:
	operator CallFunctionType()
	{
		return (CallFunctionType)m_thunk;
	}
public:
	Thunk(void*_this, ClassFunctionType callBack)
	{
		DWORD FuncAddr;
		DWORD addr1, addr2;
		GetMemberFuncAddr_VC6(FuncAddr, callBack);
		ThunkTemplate(addr1, addr2, 0);
		m_thunk = (BYTE *)VirtualAlloc(NULL, sizeof(BYTE[100]), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
		memcpy(m_thunk, (void*)addr1, addr2 - addr1);
		ReplaceCodeBuf(m_thunk, addr2 - addr1, -1, (DWORD)((void*)_this));
		ReplaceCodeBuf(m_thunk, addr2 - addr1, -2, FuncAddr);
	}
	~Thunk()
	{
		VirtualFree(m_thunk, sizeof(BYTE[100]), MEM_RELEASE);
	}

	template <class ToType, class FromType>void GetMemberFuncAddr_VC6(ToType& addr, FromType f)
	{
		union
		{
			FromType _f;
			ToType   _t;
		}ut;

		ut._f = f;

		addr = ut._t;
	}

	void ThunkTemplate(DWORD& addr1, DWORD& addr2, int calltype = 0)
	{
		int flag = 0;
		DWORD x1, x2;

		if (flag)
		{
			__asm //__thiscall
			{
			thiscall_1:	mov   ecx, -1;   //-1占位符,运行时将被替换为this指针.
				mov   eax, -2;   //-2占位符,运行时将被替换为CTimer::CallBcak的地址.
				jmp   eax;
			thiscall_2:;
			}

			__asm //__stdcall
			{
			stdcall_1:	push  dword ptr[esp]; //保存(复制)返回地址到当前栈中
				mov   dword ptr[esp + 4], -1; //将this指针送入栈中,即原来的返回地址处
				mov   eax, -2;
				jmp   eax; //跳转至目标消息处理函数(类成员函数)
			stdcall_2:;
			}
		}

		if (calltype == 0)//this_call
		{
			__asm
			{
				mov   x1, offset thiscall_1;  //取 Thunk代码段 的地址范围.
				mov   x2, offset thiscall_2;
			}
		}
		else
		{
			__asm
			{
				mov   x1, offset stdcall_1;
				mov   x2, offset stdcall_2;
			}
		}

		addr1 = x1;
		addr2 = x2;
	}

	void ReplaceCodeBuf(BYTE *code, int len, DWORD old, DWORD x)
	{
		int i = 0;

		for (i = 0; i<len - 4; ++i)
		{
			if (*((DWORD *)&code[i]) == old)
			{
				*((DWORD *)&code[i]) = x;

				return;
			}
		}
	}
};

使用例子:

class CTimer
{
private:

	int m_uElapse;
	int m_handle;
	typedef  Thunk<TIMERPROC, void (CTimer::*)(HWND hwnd, UINT uMsg, unsigned int  idEvent, DWORD dwTime)>TimerCallBackThunk;
	TimerCallBackThunk*m_timerCallbackFun = 0;
public:

	CTimer() :m_uElapse(20), m_handle(1), m_timerCallbackFun(new TimerCallBackThunk(this, &CTimer::TimerProc)){}
	~CTimer(){ delete m_timerCallbackFun; }
	void SetInterval(int uElapse)
	{
		m_uElapse = uElapse;
	}

	void Begin()
	{
		m_handle = SetTimer(NULL, 0, m_uElapse, *m_timerCallbackFun);
	}
	void End()
	{
		KillTimer(NULL, m_handle);
	}

	void TimerProc(HWND hwnd, UINT uMsg, unsigned int  idEvent, DWORD dwTime)
	{
		printf("回调转换成功!当前时间计数:dwTime=%d\n",dwTime);
	}
};
int main(int argc, char* argv[])
{
	CTimer timer;
	timer.SetInterval(400);
	timer.Begin();

	MSG msg;
	BOOL bRet;

	while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
	{
		if (bRet == -1)
		{
			break;
		}
		else
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值