Brew MP 中 IQI 指针的说明

IQI 指针的说明

1. 宏INHERIT_IQI()意思



2. INHERIT_IQIIQI)表示定义了如下函数指针


3. AEEINTERFACE_DEFINE 表示如下



其实就是如下的东东:


那么如上的IQIVtbl 就是IQI的虚表指针,因为这个结构体中就是包含了三个函数指针成员。其他什么都没有。


4. 最后一个宏,

这个要一段一段的分析,(void *)p 是去掉指针类型偏移,避免后面运算和转型造成偏移错误。

然后将这个指针转换成指向虚表指针的指针,然后再对其解引用,将所指向空间最前面4个字节拿出来,作为虚表指针。

我们在看



可以看到IWidget的虚表中,有一个INHERIT_IHandler 这个是什么呢?

5. INHERIT_IHandler 说明


哈哈,很明显,说明了IWidgetVtbl 这个结构体中前面三个成员是


并且紧跟着 handleEvent, 和 SetHandler 两个函数,然后才是widget 自己函数。

那么只要给IWidget 的结构的对象,我们可以IQI 强制指向它,然后直接调用addRef 

Release 那么一定不会出错,因为结构体排列是一样的。

所以就可以IWidget_Release 和 IQI Release 是一样的。

为了验证这个问题,我写了一个Demo,就说用来说明这个问题。

// acd.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>
typedef unsigned UUIDX;
typedef unsigned uint32;


struct IQI
{
	virtual uint32 __cdecl AddRef() = 0;
	virtual uint32 __cdecl Release() = 0;
	virtual int __cdecl QueryInterface(UUIDX idReq, void **ppo) = 0;
};

struct IWidget : public IQI
{
	virtual uint32 __cdecl SetBackColor()  = 0;
};

struct IQIVtbl
{
	uint32 (__cdecl*AddRef)(IQI*);
	uint32 (__cdecl*Release)(IQI*);
	int    (__cdecl*QueryInterface)(IQI *, UUIDX, void **);
};

struct IWidgetVtbl
{
	uint32 (__cdecl*AddRef)(IWidget*);
	uint32 (__cdecl*Release)(IWidget*);
	int    (__cdecl*QueryInterface)(IWidget *, UUIDX, void **);
	uint32  (__cdecl*SetBackColor)(IWidget *Phis);
};



struct C_Widget : public IWidget
{
	C_Widget():m_nRef(0)
	{
		m_pInt = new int;

	}

	virtual ~C_Widget( )
	{
		delete m_pInt;
	}


	virtual uint32 __cdecl AddRef()
	{
		printf("current refcount = %d\n", m_nRef);
		++m_nRef;
		return m_nRef;
	}

	virtual uint32 __cdecl Release()
	{ 
		uint32 uTemp = 0;
		if ( (uTemp = --m_nRef) == 0 )
		{
			delete this;
		}

		printf("Release refcount is %d\n", uTemp );

		return uTemp;
	}

	virtual int __cdecl QueryInterface(UUIDX idReq, void **ppo)
	{
		printf("Enter QueryInterface\n");
		if ( idReq == 1 )
		{
			this->AddRef();
			*ppo = this;
			return 0;
		}
		return -1;
	}

	virtual uint32 __cdecl SetBackColor()
	{
		printf("test in OK\n");
		*m_pInt = 9;
		
		return 0;
	}

private:
	uint32 m_nRef;
	int *m_pInt;
};


//#define AEEGETPVTBL(p,iname)  (*((AEEVTBL(iname) **)((void *)p)))

#define TELGETPVTBL(p,iname)  (*(( iname**)((void *)p)))   /// 替代实现



void Shell_CreateInstance(void **pObject)
{
	C_Widget *pWidgetImp = new C_Widget;
	pWidgetImp->AddRef();

	*pObject = pWidgetImp;
}

void IAny_Release(IQI *pObject)
{
	IQIVtbl *pIQI  = TELGETPVTBL(pObject, IQIVtbl);
	pIQI->Release(pObject);
}


uint32  __cdecl SetBackColorHook(IWidget *Phis)
{
	printf("I am in hook function\n");
	return 0;
}



int _tmain(int argc, _TCHAR* argv[])
{
	size_t uSize = sizeof(IQI);
	C_Widget *pWidgetImp = NULL;
	Shell_CreateInstance( (void**)&pWidgetImp );
	

	IQIVtbl *pIQI  = TELGETPVTBL(pWidgetImp, IQIVtbl);

	IWidgetVtbl *pWidget = TELGETPVTBL(pWidgetImp, IWidgetVtbl);
	DWORD *pWord = (DWORD*)pWidget;

	pIQI->AddRef(pWidgetImp);

	pWidget->AddRef(pWidgetImp);

	pWidget->Release(pWidgetImp);

	pIQI->Release(pWidgetImp);

	void *pV = 0;
	pWidgetImp->QueryInterface(1, &pV);

	pWidget->QueryInterface(pWidgetImp, 1, &pV);

	pIQI->Release(pWidgetImp);

	pIQI->Release(pWidgetImp);
	
	DWORD dwSize = 0;
	BOOL bRet = VirtualProtect(&(pWidget->SetBackColor), 4, PAGE_EXECUTE_READWRITE, &dwSize);

	pWidget->SetBackColor = SetBackColorHook;

	pWidget->SetBackColor( pWidgetImp );
	

	IAny_Release( pWidgetImp );


	C_Widget *pSend = new C_Widget;
	pSend->SetBackColor();
	

	return 0;
}

点击打开链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值