2013年7月18日 星期四

Component Object Model Aggregation Example

CA為outer object, CX為inner object


將CA聚合CX成為單一物件使用

或是直接使用CX物件


//CA.h
#include “CX.h”


class CA:public IA{
private:
   int m_ref;
   CX* m_cx;
public:
   static NTSTATUS CreateInstance(IUnknown** Unknown);
   CA();
void *operator new(size_t s){
       CA  *p = reinterpret_cast<CA*>(ExAllocatePoolWithTag(NonPagedPool, s, 'cdev'));
       if(p) RtlZeroMemory(p, s);
       return p;
   }
   void operator delete(void *p){
       if(p) ExFreePool(p);
       p = NULL;
   }
   NTSTATUS QueryInterface(REFIID iid, void** ppv);
   ULONG AddRef();
   ULONG Release();
};
//------------------------------------------------------------------------

//CA.cpp
#include "CA.h"


NTSTATUS CA::CreateInstance(IUnknown** Unknown){
   CA *p = new CA();
   p->AddRef();
   *Unknown = (IUnknown*)(IA*)p;
   return STATUS_SUCCESS;
}

CA::CA(){
   m_ref = 0;
   m_cx = new CX(this);
}


NTSTATUS CA::QueryInterface(REFIID iid, void** ppv){
   if ((iid==IID_IX) || (iid==IID_IY)){
       m_cx->NonDelegatingQueryInterface(iid,ppv);
return STATUS_SUCCESS;
   }else if (iid == IID_IA){
       *ppv = (IA*)(this);
   }else if (iid == IID_IUnknown){
       *ppv = (IUnknown*)(this);
   }else{
       *ppv = NULL;
       return STATUS_INVALID_PARAMETER;
   }
   ((IUnknown*)*ppv)->AddRef();
   return STATUS_SUCCESS;
}


ULONG CA::AddRef(){
   m_ref++;
   return m_ref;
}


ULONG CA::Release(){
   --m_ref;
   if(m_ref==0)
       delete this;
   return m_ref;
}
//------------------------------------------------------------------------

CX是inner object,也就是被聚合的物件,因此需要實作兩組IUnknown interface:
1組是被聚合時使用的IUnknown
另1組則是未被聚合使用的INonDelegatingUnknown

//CX.h
class CX : public IX, public IY, public IZ, public INonDelegatingUnknown{
private:
PUNKNOWN m_pUnknownOuter; int m_ref;
public:
   static NTSTATUS CreateInstance(IUnknown** Unknown);
CX(IUnknown* pUnknownOuter);
   void *operator new(size_t s){
       CA  *p = reinterpret_cast<CA*>(ExAllocatePoolWithTag(NonPagedPool, s, 'cdev'));
       if(p) RtlZeroMemory(p, s);
       return p;
   }
   void operator delete(void *p){
       if(p) ExFreePool(p);
       p = NULL;
   }

NTSTATUS QueryInterface(REFIID iid, void** ppv); ULONG AddRef(); ULONG Release(); NTSTATUS NonDelegatingQueryInterface(REFIID iid, void** ppv);
ULONG NonDelegatingAddRef(); ULONG NonDelegatingRelease();
}

//------------------------------------------------------------------------

//CX.cpp
#include "CX.h"


NTSTATUS CX::CreateInstance(IUnknown** Unknown, IUnknown* pUnknownOuter){
   CX *p = new CX(pUnknownOuter);
   p->AddRef();
   *Unknown = (IUnknown*)(IX*)p;
   return STATUS_SUCCESS;
}

CX::CX(IUnknown* pUnknownOuter){
m_ref = 0;
if(pUnknownOuter)
m_pUnknownOuter = pUnknownOuter;
else
m_pUnknownOuter = reinterpret_cast<IUnknown*>(static_cast<INonDelegatingUnknown*>(this));
}
//------------------------------------------- // IUnknown //-------------------------------------------
NTSTATUS CX::QueryInterface(REFIID iid, void** ppv){ m_pUnknownOuter ->QueryInterface(iid,ppv); return STATUS_SUCCESS; } ULONG CX::AddRef(){ return m_pUnknownOuter ->AddRef(); } ULONG CX::Release(){ return m_pUnknownOuter ->Release(); }
//------------------------------------------- // INonDelegatingUnknown //------------------------------------------- // ULONG CX::NonDelegatingAddRef(){ m_ref++; return m_ref; } ULONG CX::NonDelegatingRelease(){ m_ref--; if(m_ref==0) delete this; return m_ref; } NTSTATUS CX::NonDelegatingQueryInterface(REFIID iid, void** ppv){ if (iid==IID_IUnknown){ *ppv = (IUnknown*)this; } else if (iid==IX){ *ppv = (IUnknown*)(IX*)this; } else if (iid==IY){ *ppv = (IUnknown*)(IY*)this; }
else if (iid==IZ){ *ppv = (IUnknown*)(IZ*)this; } else{ *ppv= NULL; return STATUS_INVALID_PARAMETER; } ((IUnknown*)*ppv)->AddRef(); return STATUS_SUCCESS; }


//------------------------------------------------------------------------

當需要使用CA聚合CX成為單一物件使用時:
IUnknown* caInf;
IUnknown* ixInf;
IUnknown* iaInf;
IUnknown* izInf;
CA::CreateInstance(&caInf);
caInf->QueryInterface(IID_IX, (void**)&ixInf);//using IX interface(inner object)
ixInf->QueryInterface(IID_IA, (void**)&iaInf);//using IA interface(outer object)
iaInf->QueryInterface(IID_IZ, (void**)&izInf);//cannot using IZ interface(inner object)

直接使用CX物件:
IUnknown* cxInf;
IUnknown* ixInf;
CX::CreateInstance(&cxInf, NULL);
cxInf->QueryInterface(IID_IX, (void**)&ixInf);//using IX interface

沒有留言:

張貼留言