Both the com interface and d3d interfaces use the _ stdcall call protocol to declare member functions. Such a declaration allows an additional push in the passing parameters of compiled assembly code,
After all parameters are pushed to the stack, the object peer address is also pushed to the stack;
In this way, the function in vtable can be replaced by the c function of _ stdcall. The first parameter must be an object pointer. Other parameters are the same as those of the corresponding member function;
Com is designed to support CINTERFACE.
# Include "objbase. h"
_ Declspec (novtable) interface AA: public IUnknown
{
Public:
Virtual hresult stdmethodcalltype QueryInterface (
/* [In] */REFIID riid,
/* [Iid_is] [out] */_ RPC _ deref_out void _ RPC_FAR * ppvObject)
{
Return S_ OK;
}
Virtual ulong stdmethodcalltype AddRef (void)
{
Return 0;
}
Virtual ulong stdmethodcalltype Release (void)
{
Return 0;
}
// The member function uses _ stdcall.
Virtual void _ stdcall v1 (void * p)
{
}
Virtual void _ stdcall v2 (void * p)
{
}
Virtual void _ stdcall v3 (void * p)
{
}
};
// C function Declaration requires an AA * pthis parameter more than AA: v1
Void _ stdcall fpv1 (AA * pthis, void * p)
{
Pthis-> v2 (p );
}
Int _ tmain (int argc, _ TCHAR * argv [])
{
AA aa1, aa2;
Unsigned int p1 = * (unsigned int *) & aa1;
Unsigned int p2 = * (unsigned int *) & aa2;
Unsigned int * v = (unsigned int *) p1;
DWORD dwProtected = 0;
VirtualProtect (v, 256, PAGE_EXECUTE_READWRITE, & dwProtected); // remove the write protection of executable code
V [3] = (unsigned int) & fpv1; // Replace the vtable entry of v1
AA * pp1 = & aa1;
Pp1-> v1 (NULL); // It will jump to fpv1. After you view the assembly code, you will see a push pp1 after pushing 0.
Return 0;
}