//Cmpnt1.cpp -- Component1
#include <iostream.h>
#include <objbase.h>
#include "Iface.h"
#include "Registry.h"
void trace(const char* msg){cout<<"Component1; \t "<<msg<<endl;}
static HMODULE g_hModule = NULL;
static long g_cComponents = 0;
static long g_cServerLocks = 0;
const char g_szFriendlyName[] = "Inside COM,Component1";
const char g_szProgID[] = "InsideCOM.Cmpnt1_1";
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CA : public IX{
public:
virtual HRESULT __stdcall QueryInterface(const IID& iid,void** ppv);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
virtual void __stdcall Fx(){cout<<"Fx"<<endl;}
virtual void __stdcall Fy(){m_pIY->Fy();}
CA();
~CA();
HRESULT __stdcall Init();
private:
long m_cRef;
IY* m_pIY;
};
CA::CA():m_cRef(1),m_pUnkNownInner(NULL){
InterlockedIncrement(&m_cComponents);
}
CA::~CA(){
InterlockedDecrement(&g_cComponents);
trace("Destroy self.");
m_cRef = 1;
IUnkNown* pUnkNownOuter = this;
pUnkNownOuter->AddRef();
m_pIY->Release();
if(m_pUnkNownInner != NULL){
m_pUnkNownInner->Release();
}
HRESULT __stdcall CA::Init(){
IUnkNown* pUnkNownOuter = this;
trace("Create inner component.");
HRESULT hr = ::CoCreateInstance(CLSID_Component2,pUnkNownOuter,CLSCTX_INPROC_SERVER,IID_IUnkNown,(void**)&m_pUnkNownInner);
if(Failed(hr)){
trace("Could not create contained component.");
return E_FAIL;
}
hr = m_pUnkNownInner->QueryInterface(IID_IY,(void**)&m_pIY);
if(Failed(hr)){
trace("Inner component does not support interface IY.");
m_pUnkNowInner->Release();
return E_FAIL;
}
pUnkNownOuter->Release();
return S_OK;
}
HRESULT __stdcall CA::QueryInterface(const IID& iid,void** ppv){
if(iid == IID_IUnkNown){
*ppv = static_cast<IUnkNown*>(this);
}
else if(iid == IID_IX){
*ppv = static_cast<IX*>(this);
}
else if(iid == IID_IY){
trace("Return inner component's IY interface.");
return m_pUnkNownInner->QueryInterface(iid,ppv);
//or *ppv = m_pIY;
}
else{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnkNown*>(*ppv)->AddRef();
return S_OK;
}
ULONG __stdcall CA::AddRef(){
return InnerlockedIncrement(&m_cRef);
}
ULONG __stdcall CA::Release(){
id(InterlockedDecrement(&m_cRef) == 0){
delete this;
return 0;
}
return m_cRef;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CFactory : public IClassFactory{
public:
virtual HRESULT __stdcall QueryInterface(const IID& iid,void** ppv);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
virtual HRESULT __stdcall CreateInstance(IUnkNown* pUnkNownOuter,const IID& iid,void** ppv);
virtual HRESULT __stdcall Lockserver(BOOL bLock);
CFactory() : m_cRef(1){}
~CFactory(){}
private:
long m_cRef;
};
HRESULT __stdcall CFactory::QueryInterface(const IID& iid,void** ppv){
IUnkNown* pI;
if((iid == IID_IUnkNown) || (iid == IID_IClassFactory)){
pI = static_cast<IClassFactory*>(this);
}
else{
*ppv = NULL;
return E_NOINTERFACE;
}
pI->AddRef();
*ppv = pI;
return S_OK;
}
ULONG CFactory::AddRef(){
return InterlockedIncrement(&m_cRef);
}
ULONG CFactory::Release(){
if(InterlockedDecrement(&m_cRef) == 0){
delete this;
return 0;
}
return m_cRef;
}
HRESULT __stdcall CFactory::CreateInstance(IUnkNown* pUnkNownOuter,void** ppv){
HRESULT hr = E_FAIL;
if(pUnkNownOuter != NULL){
return CLASS_E_NOAGGREGATION;
}
CA* pA = new CA;
if(pA == NULL){
return E_OUTOFMEMORY;
}
hr = pA->Init(); //创建组件2,并请求IY接口
if(Failed(hr)){
pA->Release();
return hr;
}
hr = pA->QueryInterface(iid,ppv);
pA->Release();
return hr;
}
HRESULT __stdcall CFactory::LockServer(BOOL bLock){
if(bLock){
InterlockedIncrement(&g_cServerLocks);
}
else{
InterlockedDecrement(&g_cServerLocks);
}
return S_OK;
}
STDAPI DllCanUnloadNow(){
if((g_cComponents == 0) && (g_cServerLocks == 0)){
return S_OK;
}
else{
return S_FALSE;
}
}
//Get class factory
STDAPI DllGetClassObject(const CLSID& clsid,void** ppv){
if(clsid != CLSID_Component1){
return CLASS_E_CLASSNOTAVAILABLE;
}
CFactory* pFactory = new CFactory;
if(pFactory == NULL){
return E_OUTOFMEMORY;
}
HRESULT hr = pFactory->QueryInterface(iid,ppv);
pFactory->Release();
return hr;
}
STDAPI DllRegisterServer(){
return RegisterServer(g_hModule,CLSID_Component1,g_szFriendlyName,g_szVerIndProgID,g_szProgID);
}
STDAPI DllUnregisterServer(){
return UnregisterServer(CLSID_Component1,g_szProgID);
}
BOOL APIENTRY DllMain(HANDLE hModule,DWORD dwReason,void* lpReserved){
if(dwReason == DLL_PROCESS_ATTACH){
g_hModule = hModule;
}
return TRUE;
}
//****************************************************************************************************************************************
//Cmpnt2.cpp -- Component2
#include <iostream.h>
#include <objbase.h>
#include "Iface.h"
#include "Registry.h"
void trace(const char* msg){cout<<"Component2: \t"<<msg<<endl;}
static HMODULE g_hModule = NULL;
static long g_cComponents = 0;
static long g_cServerLocks = 0;
const char g_szFriendlyName[]="Inside COM.Component2";
const char g_szVerIndProgID[] = "InsideCOM.Cmpnt2";
const char g_szProgID[] = "InsideCOM.Cmpnt2._1";
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CB : public IY,public INondelegatingUnkNown{
public:
virtual HRESULT __stdcall QueryInterface(const IID& iid,void** ppv){
trace("Delegate QueryInterface.");
return m_pUnkNownOuter->QueryInterface(iid,ppv);
}
virtual ULONG __stdcall AddRef(){
trace("Delegate AddRef.");
return m_pUnkNownOuter->AddRef();
}
virtual ULONG __stdcall Release()
{
trace("Delegate Release");
return m_pUnkNownOuter->Release();
}
virtual HRESULT __stdcall NondelegatingQueryInterface(const IID& iid,void** ppv);
virtual ULONG __stdcall NondelegatingAddRef();
virtual ULONG __stdcall Nondelegatingrelease();
virtual void __stdcall Fy(){cout<<"Fy"<<endl;}
CB(IUnkNown* m_pUnkNownOuter);
~CB();
private:
long m_cRef;
};
HRESULT __stdcall CB::NondelegatingQueryInterface(const IID& iid,void** ppv){
if(iid == IID_IUnkNown){
*ppv = static_cast<INondelegatingUnkNown*>(this); //very important !!!
}
else if(iid == IID_IY){
*ppv = static_cast<IY*>(this);
}
else{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnkNown*>(*ppv)->AddRef();
return S_OK;
}
ULONG __stdcall CB::NondelegatingAddRef(){
return InterlockedIncrement(&m_cRef);
}
ULONG __stdcall CB::Nondelegatingrelease(){
if(InterlockedDecrement(&m_cRef = 0)){
delete this;
return 0;
}
return m_cRef;
}
CB::CB(IUnkNown* pUnkNownOuter) : m_cRef(1){
::InterlockedIncrement(&g_cComponents);
if(pUnkNownOuter == NULL){
trace("不是代理未知接口;让我们委托给非代理未知接口吧");
m_pUnkNownOuter = reinterpret_cast<IUnkNown*>(static_cast<INondelegatingUnkNown*>(this));
}
else{
trace("Aggregating; delegate to outer IUnkNown.");
m_pUnkNownOuter = pUnkNownOuter;
}
}
CB::~CB(){
InterlockedDecrement(&g_cComponents);
trace("Destroy self");
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CFactory : public IClassFactory{
public:
virtual HRESULT __stdcall QueryInterface(const IID& iid,void** ppv );
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
virtual HRESULT __stdcall CreateInstance(IUnkNown* pUnkNownOuter,void** ppv);
virtual HRESULT __stdcall LockServer(BOOL bLock);
CFactory() : m_cRef(1){}
~CFactory(){}
private:
long m_cRef;
};
HRESULT CFactory::QueryInterface(const IID& iid,void** ppv){
if((iid == IID_IUnkNown) || (iid == IID_IClassFactory)){
*ppv = static_cast<IClassFactory*>(this);
}
else{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnkNown*>(*ppv)->AddRef();
return S_OK;
}
ULONG _stdcall CFactory::AddRef(){
return InterlockedIncrement(&m_cRef);
}
ULONG _stdcall CFactory::Release(){
if(InterlockedDecrement(&m_cRef) == 0){
delete this;
return 0;
}
return m_cRef;
}
HRESULT __stdcall CFactory::CreateInstance(IUnkNown* pUnkNownOuter,void** ppv){
if((pUnkNownOuter != NULL) && (iid != IID_IUnkNown)){
return CLASS_E_NOAGGREGATION;
}
CB* pB = new CB(pUnkNownOuter);
if(pB == NULL){
return E_OUTOFMEMORY;
}
HRESULT hr = pB->NondelegatingQueryInterface(iid,ppv);
pB->Nondelegatingrelease();
return hr;
}
HRESULT CFactory::LockServer(BOOL bLock){
if(bLock){
InterlockedIncrement(&g_cServerLocks);
}
else{
InterlockedDecrement(&g_cServerLocks);
}
return S_OK;
}
STDAPI DllCanUnloadNow(){
if((g_cComponents == 0) && (g_cServerLocks == 0)){
return S_OK;
}
else{
return S_FALSE;
}
}
STDAPI DllGetClassObject(const CLSID& clsid,void** ppv){
if(clsid != CLSID_Component2){
return CLASS_E_CLASSNOTAVAILABLE;
}
CFactory* pFactory = new CFactory;
if(pFactory == NULL){
return E_OUTOFMEMORY;
}
HRESULT hr = pFactory ->QueryInterface(iid,ppv);
pFactory->Release();
return hr;
}
STDAPI DllRegisterServer(){
return RegisterServer(g_hModule,CLSID_Component2,g_szProgID);
}
STDAPI DllUnregisterServer(){
return UnregisterServer(CLSID_Component2,g_szProgID);
}
BOOL API ENTRY DllMain(HANDLE hModule,void* lpReserved){
if(dwReason == DLL_PROCESS_ATTACH){
g_hModule = hModule;
}
return TRUE;
}
此例中,外部组件只是聚合了内部组件实现的一个接口,客户能够访问的内部组件将只有IY。
当外部组件需要聚合内部组件实现的多个接口时:
避免使用盲目聚合,为避免冲突,有两种方法:其一,元接口。其二,将外部组件和客户或外部组件和内部组件作为匹配对来实现。
组件的内部状态信息:
COM中的所有功能都是通过借口来实现的。因此,为提供内部状态信息,可以加上一个新的接口。此接口可以给外部组件提供一些状态信息,帮助开发人员实现对组件的定制