//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;
IUnknown* m_pUnknownInner;
};
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;
IUnknown* m_pUnknownOuter;
};
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中的所有功能都是通过借口来实现的。因此,为提供内部状态信息,可以加上一个新的接口。此接口可以给外部组件提供一些状态信息,帮助开发人员实现对组件的定制