CUnknown和INonDelegatingUnknown
2022-08-23
51
0
CUnknown继承于INonDelegatingUnknown,并且CUnknown是所有COM的基类。
class CUnknown : public INonDelegatingUnknown
而INonDelegatingUnknown是一个虚基结构体。
INonDelegatingUnknown
basetype.h
DECLARE_INTERFACE(INonDelegatingUnknown)
{
STDMETHOD_(NTSTATUS,NonDelegatingQueryInterface)
( THIS_
_In_ REFIID,
_COM_Outptr_ PVOID *
) PURE;
STDMETHOD_(ULONG,NonDelegatingAddRef)
( THIS
) PURE;
STDMETHOD_(ULONG,NonDelegatingRelease)
( THIS
) PURE;
};
typedef INonDelegatingUnknown *PNONDELEGATINGUNKNOWN;
以上的宏:
#define __STRUCT__ struct
#define interface __STRUCT__
#define DECLSPEC_NOVTABLE __declspec(novtable)
#define DECLARE_INTERFACE(iface) interface DECLSPEC_NOVTABLE iface
故DECLARE_INTERFACE(INonDelegatingUnknown)宏展开为:
struct __declspec(novtable) INonDelegatingUnknown
而STDMETHOD_宏定义如下:
#define DECLSPEC_NOTHROW __declspec(nothrow)
#define COM_DECLSPEC_NOTHROW DECLSPEC_NOTHROW
#define STDMETHODCALLTYPE __stdcall
#define PURE = 0
#define STDMETHOD_(type,method) virtual COM_DECLSPEC_NOTHROW type STDMETHODCALLTYPE method
故 STDMETHOD_(NTSTATUS,NonDelegatingQueryInterface)展开如下:
virtual
_declspec(nothrow)
NTSTATUS
__stdcall
NonDelegatingQueryInterface
( THIS_
_In_ REFIID,
_COM_Outptr_ PVOID *
) = 0;
可以看到,其实现的是一个纯虚函数
CUnknown
class CUnknown : public INonDelegatingUnknown
{
private:
LONG m_lRefCount; // Reference count.
PUNKNOWN m_pUnknownOuter; // Outer IUnknown.
public:
/*************************************************************************
* CUnknown methods.
*/
CUnknown(PUNKNOWN pUnknownOuter);
virtual ~CUnknown(void);
PUNKNOWN GetOuterUnknown(void)
{
return m_pUnknownOuter;
}
/*************************************************************************
* INonDelegatingUnknown methods.
*/
STDMETHODIMP_(ULONG) NonDelegatingAddRef
( void
);
STDMETHODIMP_(ULONG) NonDelegatingRelease
( void
);
STDMETHODIMP_(NTSTATUS) NonDelegatingQueryInterface
(
__in REFIID rIID,
__out PVOID * ppVoid
);
};
可以看到,CUnknown重写了INonDelegatingUnknown的三个方法,当然CUnknown也实现了自己的构造函数(带一个参数)和对构造函数指针的引用函数GetOuterUnknown。
CUnkonw的具体实现可参考WDK的stdunk.cpp文件
CUnknown构造和成员函数
/*****************************************************************************
* CUnknown::CUnknown()
*****************************************************************************
* Constructor.
*/
CUnknown::CUnknown(PUNKNOWN pUnknownOuter)
: m_lRefCount(0)
{
if (pUnknownOuter)
{
m_pUnknownOuter = pUnknownOuter;
}
else
{
m_pUnknownOuter = PUNKNOWN(dynamic_cast<PNONDELEGATINGUNKNOWN>(this));
}
}
/*****************************************************************************
* CUnknown::~CUnknown()
*****************************************************************************
* Destructor.
*/
CUnknown::~CUnknown(void)
{
}
CUnknown继承的三个虚函数实现
- NonDelegatingAddRef:增加引用计数
- NonDelegatingQueryInterface:减少引用计数
- NonDelegatingQueryInterface:通过接口GUID返回接口
/*****************************************************************************
* CUnknown::NonDelegatingAddRef()
*****************************************************************************
* Register a new reference to the object without delegating to the outer
* unknown.
*/
STDMETHODIMP_(ULONG) CUnknown::NonDelegatingAddRef(void)
{
ASSERT(m_lRefCount >= 0);
InterlockedIncrement(&m_lRefCount);
return ULONG(m_lRefCount);
}
/*****************************************************************************
* CUnknown::NonDelegatingRelease()
*****************************************************************************
* Release a reference to the object without delegating to the outer unknown.
*/
STDMETHODIMP_(ULONG) CUnknown::NonDelegatingRelease(void)
{
ASSERT(m_lRefCount > 0);
if (InterlockedDecrement(&m_lRefCount) == 0)
{
m_lRefCount++;
delete this;
return 0;
}
return ULONG(m_lRefCount);
}
/*****************************************************************************
* CUnknown::NonDelegatingQueryInterface()
*****************************************************************************
* Obtains an interface.
*/
STDMETHODIMP_(NTSTATUS) CUnknown::NonDelegatingQueryInterface
(
REFIID rIID,
PVOID * ppVoid
)
{
ASSERT(ppVoid);
if (IsEqualGUIDAligned(rIID,IID_IUnknown))
{
*ppVoid = PVOID(PUNKNOWN(this));
}
else
{
*ppVoid = NULL;
}
if (*ppVoid)
{
PUNKNOWN(*ppVoid)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_INVALID_PARAMETER;
}