// traps.hpp
/*
(c) ��������� ������� telepat@inbox.ru
����� ������� ��� ��������� �������.
*/
#pragma once
// ������� ��� ����������� ����� ������� ������� �������
// �������������:
// ���� ��������� �� ����� � ������� ���
// DWORD* pFunc = mf_cast<DWORD*>(&Class::Method);
// ���� �������� ���� � ��������� �� �����
// int(Class::*pMemFunc)(int, int) = mf_cast<int(Class::*)(int, int)>(ptr);
template<typename T, typename K>
__forceinline static T mf_cast(const K& ptr)
{
return *reinterpret_cast<T*>(&const_cast<K&>(ptr));
}
// ����� ��� ������� ������ � ������� ����������� �������
class CTrapVirtual
{
public:
//CTrapVirtual(): m_pVtable(NULL), m_dwRealAdress(0){}
//~CTrapVirtual(){UnTrap();}
// ��������� ���������.
// �� ���� ������ ��������� �� ������, ����������� ������� �������� ����� ����������,
// ����� ������� � �������, � ����� ����� �������.
// ����������� ������� ���� �� �����. �������� ��������� �� ��� ������� ����� ������.
template<typename T>
void SetTrap(void* pObject, int offset, T pFunc)
{
_SetTrap(pObject, offset, *reinterpret_cast<DWORD*>(&pFunc));
}
template<typename T>
void GetAddress(T& t){t=*reinterpret_cast<T*>(&m_dwRealAdress);}
// ������ ���������.
void UnTrap()
{
if(m_pVtable)
{
*m_pVtable=m_dwRealAdress;
m_pVtable=NULL;
}
}
void _SetTrap(void* pObject, int offset, DWORD dwFunction)
{
m_pVtable =*reinterpret_cast<DWORD**>(pObject);
m_pVtable+=offset;
DWORD old;
VirtualProtect(m_pVtable,4,PAGE_EXECUTE_READWRITE,&old);
m_dwRealAdress=*m_pVtable;
*m_pVtable=dwFunction;
}
DWORD* m_pVtable;
DWORD m_dwRealAdress;
};
typedef unsigned __int64 ui64;
// ����� ��� ��������� ������� ����� ��������� ����������� � ������ �������.
class CTrapSwap
{
public:
//CTrapSwap():m_pFunc(NULL), m_SwapBuf(0){}
template<typename T>
void SetTrapByName(HINSTANCE hDll, LPCSTR strFuncName, T newFunc)
{
DWORD* pFunc=reinterpret_cast<DWORD*>(GetProcAddress(hDll, strFuncName));
DWORD pNewFunc=*reinterpret_cast<DWORD*>(&newFunc);
_SetTrap(pFunc, pNewFunc);
}
template<typename T>
void SetTrapByName(LPCSTR strDll, LPCSTR strFuncName, T newFunc)
{
SetTrapByName(GetModuleHandle(strDll), strFuncName, newFunc);
}
template<typename T>
void SetTrapByAddress(DWORD* pFuncAddress, T newFunc)
{
DWORD* pFunc = pFuncAddress;
DWORD pNewFunc=*reinterpret_cast<DWORD*>(&newFunc);
_SetTrap(pFunc, pNewFunc);
}
template<typename T, typename M>
void SetTrapOnImportFunc(T oldFunc, M newFunc)
{
BYTE* ptr=*reinterpret_cast<BYTE**>(&oldFunc);
ptr+=2;
DWORD* pFunc=**reinterpret_cast<DWORD***>(ptr);
DWORD pNewFunc=*reinterpret_cast<DWORD*>(&newFunc);
_SetTrap(pFunc, pNewFunc);
}
template<typename T, typename M>
void SetTrapOnDeclImportFunc(T oldFunc, M newFunc)
{
DWORD* pFunc=*reinterpret_cast<DWORD**>(&oldFunc);
DWORD pNewFunc=*reinterpret_cast<DWORD*>(&newFunc);
_SetTrap(pFunc, pNewFunc);
}
void Swap()
{
ui64 t=*m_pFunc;
*m_pFunc=m_SwapBuf;
m_SwapBuf=t;
}
void _SetTrap(DWORD* pFunc, DWORD pNewFunc)
{
m_pFunc=reinterpret_cast<ui64*>(pFunc);
DWORD old;
VirtualProtect(pFunc, 8, PAGE_EXECUTE_READWRITE, &old);
// ��������� ����� �� ����� ����� �������
m_SwapBuf = (static_cast<ui64>(pNewFunc - reinterpret_cast<DWORD>(pFunc)-5)<<8) | 0xE9;
// � ��������� � ������ ������� �������������� �����
Swap();
FlushInstructionCache(GetCurrentProcess(), m_pFunc, 8);
}
ui64* m_pFunc;
ui64 m_SwapBuf;
};
struct trapswaper
{
CTrapSwap& trap;
trapswaper(CTrapSwap& t):trap(t){trap.Swap();}
~trapswaper(){trap.Swap();}
};
//Window subclassing
struct WndSubclasser
{
#pragma pack(push,1)
struct _Thunk
{
DWORD m_mov; // mov dword ptr [esp+0x4], pThis (esp+0x4 is hWnd)
DWORD m_this; //
BYTE m_jmp; // jmp WndProc
DWORD m_relproc; // relative jmp
} thunk;
#pragma pack(pop)
HWND m_hWnd;
WNDPROC m_pfWndProc;
template<typename T>
WndSubclasser(T* ptr, LRESULT (CALLBACK *pFunc)(T*,UINT,WPARAM,LPARAM), HWND hWindow)
{
thunk.m_mov = 0x042444C7; //C7 44 24 0C
thunk.m_this = reinterpret_cast<DWORD>(ptr);
thunk.m_jmp = 0xE9;
thunk.m_relproc = (int)pFunc - ((int)&thunk+sizeof(thunk));
m_hWnd = hWindow;
m_pfWndProc = (WNDPROC) SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)this);
}
template<typename T>
struct jumper
{
static LRESULT CALLBACK WndProc(T* pThis, UINT msg, WPARAM w, LPARAM l)
{
return pThis->WndProc(msg, w, l);
}
};
template<typename T>
WndSubclasser(T* ptr, HWND hWindow)
{
thunk.m_mov = 0x042444C7; //C7 44 24 0C
thunk.m_this = reinterpret_cast<DWORD>(ptr);
thunk.m_jmp = 0xE9;
thunk.m_relproc = (int)&jumper<T>::WndProc - ((int)&thunk+sizeof(thunk));
m_hWnd = hWindow;
m_pfWndProc = (WNDPROC) SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)this);
}
static LRESULT CALLBACK MyWndProc(WndSubclasser* pThis, UINT nMessage, WPARAM w, LPARAM l)
{
LRESULT res = CallWindowProc(pThis->m_pfWndProc, pThis->m_hWnd, nMessage, w, l);
if(nMessage==WM_NCDESTROY)
delete pThis;
return res;
}
void Detach()
{
if ((LONG) this == GetWindowLong(m_hWnd, GWL_WNDPROC))
{
SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)m_pfWndProc);
delete this;
}
else
{
thunk.m_this = reinterpret_cast<DWORD>(this);
thunk.m_relproc = (int)MyWndProc - ((int)&thunk+sizeof(thunk));
}
}
};
/* USING WndSubclasser
struct WS_Client
{
WS_Client() : pWndSubclassInfo(NULL){}
~WS_Client()
{
if(pWndSubclassInfo)
pWndSubclassInfo->Detach();
}
WndSubclasser* pWndSubclassInfo;
void AttachToWnd(HWND hWnd)
{
if(pWndSubclassInfo)
pWndSubclassInfo->Detach();
pWndSubclassInfo = new WndSubclasser(this, &WS_Client::MyWndProc, hWnd);
}
LRESULT ClassWndProc(UINT msg, WPARAM w, LPARAM l)
{
return CallWindowProc(pWndSubclassInfo->m_pfWndProc, pWndSubclassInfo->m_hWnd, msg, w, l);
}
static LRESULT CALLBACK MyWndProc(WS_Client* ptr, UINT msg, WPARAM w, LPARAM l)
{
return ptr->ClassWndProc(msg, w, l);
}
};
*/
/*
�������� msgmap ���� ���� ������ ������.
��� ����� ������� ����� ��������� ����, ���� �����, � ����������
� ��� lpEntries. ����� pfnGetBaseMap �� ����� ��������� ����
��������� � ���� �����, � � �������� ���� ������ ��� �������� �����
�������, ����������� ���� �����.
*/
class CMsgMapTrapBase // ������� ����� ��� ��������� �������
{
protected:
static void _SetTrap(AFX_MSGMAP* pTrapMap, AFX_MSGMAP* pNewMap, const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)())
{
DWORD old;
VirtualProtect(pTrapMap, sizeof(AFX_MSGMAP), PAGE_EXECUTE_READWRITE, &old);
VirtualProtect(pNewMap, sizeof(AFX_MSGMAP), PAGE_EXECUTE_READWRITE, &old);
AFX_MSGMAP_ENTRY* pTemp = (AFX_MSGMAP_ENTRY*) pTrapMap->lpEntries;
pTrapMap->lpEntries = pNewMap->lpEntries;
pNewMap->lpEntries = pTemp;
pNewMap->pfnGetBaseMap = pTrapMap->pfnGetBaseMap;
pTrapMap->pfnGetBaseMap = pfnGetBaseMap;
}
static AFX_PMSG FindRealHandler(UINT nMessage, AFX_MSGMAP* pMap)
{
AFX_MSGMAP_ENTRY* pEntry;
while(pMap)
{
pEntry=(AFX_MSGMAP_ENTRY*)pMap->lpEntries;
while(pEntry->nMessage)
{
if(pEntry->nMessage==nMessage)
return pEntry->pfn;
pEntry++;
}
pMap=(AFX_MSGMAP*)pMap->pfnGetBaseMap();
}
return NULL;
}
static AFX_PMSG FindRealHandler(UINT nMessage, UINT nCode, UINT nID, UINT nLastID, AFX_MSGMAP* pMap)
{
AFX_MSGMAP_ENTRY* pEntry;
while(pMap)
{
pEntry=(AFX_MSGMAP_ENTRY*)pMap->lpEntries;
while(pEntry->nMessage)
{
if(pEntry->nMessage==nMessage && pEntry->nCode == nCode
&& pEntry->nID >= nID && pEntry->nLastID <= nLastID)
return pEntry->pfn;
pEntry++;
}
pMap=(AFX_MSGMAP*)pMap->pfnGetBaseMap();
}
}
};
template<typename T>
class CMsgMapTrap : public CMsgMapTrapBase
{
protected:
struct wnd_get_map : public T
{
AFX_MSGMAP* GetMap() {return const_cast<AFX_MSGMAP*>(GetMessageMap());}
static AFX_MSGMAP* GetTMap(){return const_cast<AFX_MSGMAP*>(&T::messageMap);}
};
static const AFX_MSGMAP* PASCAL GetBase() { return wnd_get_map::GetTMap(); }
public:
static void SetTrap(CWnd* pWnd)
{
_SetTrap(static_cast<wnd_get_map*>(pWnd)->GetMap(), wnd_get_map::GetTMap(),
&CMsgMapTrap<T>::GetBase);
}
template<typename K>
static void FindHandler(UINT nMessage, K& pHandler)
{
AFX_PMSG pMsg = FindRealHandler(nMessage, wnd_get_map::GetTMap());
pHandler = *reinterpret_cast<K*>(&pMsg);
}
template<typename K>
static void FindHandler(UINT nMessage, UINT nCode, UINT nID, UINT nLastID, K& pHandler)
{
pHandler = *reinterpret_cast<K*>(FindRealHandler(nMessage, nCode, nID, nLastID, wnd_get_map::GetTMap()));
}
};
/*
//////////////////////////////////////////////////////////////////
TRAP_HEADER(CSheetView_OnLButtonDblClk, CV7TableDocManager, CSheetDoc, "moxel.dll", "?OnLButtonDblClk@CSheetView@@IAEXIVCPoint@@@Z", void)(UINT, CPoint);
// ������ � ������������ � ��
CSheetViewOnLButtonDown::trapper()
CSheetViewOnLButtonDown::mapper()
CSheetViewOnLButtonDown::isTrap()
*/
#define TRAP_HEADER(funcName, ThisType_mapKEY, mapVAL, dllName, decorName, retType)\
struct funcName{\
typedef CMap<ThisType_mapKEY*, ThisType_mapKEY*, mapVAL*, mapVAL*> trapmap;\
static CTrapSwap& trapper(){static CTrapSwap tr; return tr;}\
static trapmap& mapper(){static trapmap m;return m;}\
static BOOL& isTrap(){static BOOL f;return f;}\
static void Wrap(ThisType_mapKEY* pKey, mapVAL* pVal){\
if(!isTrap()){\
trapper().SetTrapByName(dllName, decorName, &ThisType_mapKEY::##funcName);\
isTrap() = TRUE;}\
mapper()[pKey] = pVal;}\
static void UnWrap(ThisType_mapKEY* pKey){mapper().RemoveKey(pKey);};\
};\
friend struct funcName;\
retType funcName