第八章 组件复用:包容与聚合

8.4 一个完整的例子

下面我们将实现一个聚合了一个接口的组件。在这个例子中,组件1支持两个接口IX和IY。但它只实现了接口XX,而没有实现接口IY,并且也并没有将此接口调用转发给组件2的实现。相反,当客户向组件1查询接口IY时,组件1将返回内部组件即组件2所实现的IY接口的指针。程序清单8-3给出的是外部组件的实现,程序清单8-4则是内部组件的实现。客户基本上没有什么变化,因它并不关心我们使用的是包容还是聚合。

// 程序清单8-3 外部组件(聚合组件)的实现。
//
// Cmpnt1.cpp - Component1
//
//
#include <iostream>
#include "Iface.h"
#include "Registry.h"

using namespace std;

void trace(const char* msg) { cout << "Component 1:\t" << msg << endl; }

///
//
// Global variables
//
// Static variables
static HMODULE g_hModule = NULL;            // DLL module handle
static long g_cComponents = 0;              // Count of active components
static long g_cServerLocks = 0;             // Count of locks

// Friendly name of component
const char g_szFriendlyName[]
= "Inside COM, Chapter 8 Example 2, Component 1";

// Version-independent ProgID
const char g_szVerIndProgID[] = "InsideCOM.Chap08.Ex2.Cmpnt1";

// ProgID
const char g_szProgID[] = "InsideCOM.Chap08.Ex2.Cmpnt1.1";

///
//
// Component A
// 
class CA : public IX
    // public IY
{
public:
    // IUnknown
    virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
    virtual ULONG   __stdcall AddRef();
    virtual ULONG   __stdcall Release();

    // Interface IX
    virtual void __stdcall Fx() { cout << "Fx" << endl; }

    /* Component aggregates instead of implementation interface IY.
    // Interface IY
    virtual void __stdcall Fy() { m_pIY->Fy(); }
    */

    // Constructor
    CA();

    // Destructor
    ~CA();

    // Initialization function called by the class factory
    // to create contained component
    HRESULT __stdcall Init();

private:
    // Reference count
    long m_cRef;

    // Pointer to the aggregated component's IY Interface
    // (We do not have to retain an IY pointer. However, we
    // can use it in QueryInterface.)
    IY* m_pIY;

    // Pointer to inner component's IUnknown
    IUnknown* m_pUnknownInner;
}

//
// Constructor
//
CA::CA()
    : m_cRef(1),
    m_pUnknownInner(NULL)
{
    InterlockedIncrement(&g_cComponents);
}

//
// Destructor
//
CA::~CA()
{
    InterlockedDecrement(&g_cComponents);
    trace("Destroy self.");

    // Prevent recursive destruction on next AddRef/Release pair.
    m_cRef = 1;

    // Counter the pUnknownOuter->Release in the Init method.
    IUnknown* pUnknownOuter = this;
    pUnknownOuter->AddRef();

    // Properly release the pointer: there may be per-interface
    // reference counts.
    m_pIY->Release();

    // Release contained component
    if (m_pUnknownInnter != NULL) {
        m_pUnknownInnter->Release();
    }
}

// Initailize the component by creating the contained component.
HRESULT __stdcall CA::Init()
{
    // Get the pointer to the outer unknown.
    // Since this component is not aggregated. the outer unknown
    // is the same as the this pointer.
    IUnknown* pUnknownOuter = this;
    trace("Create inner component.");
    HRESULT hr =
        ::CoCreateInstance(CLSID_Component2,
            pUnknownOuter,   // Outer component's IUnknown
            CLSCTX_INPROC_SERVER,
            IID_IUnknown,    // IUnknown when aggregating
            (void**)&m_pUnknownInner);
    if (FAILED(hr)) {
        trace("Could not create contained component.");
        return E_FAIL;
    }

    // This call will increment the reference count on the outer component.
    trace("Get the IY interface from the inner component.");
    hr = m_pUnknownInner->QueryInterface(IID_IY, (void**)&m_pIY);
    if (FAILED(hr)) {
        trace("Inner component does not support interface IY.");
        m_pUnknownInner->Release();
        return E_FAIL;
    }

    // We need to release the reference count added to the
    // outer component in the above call. So call Release
    // on the pointer you passed to CoCreateInstance.
    pUnknownOuter->Release();
    return S_OK;
}

//
// IUnknown implementation
//
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.");
#if 1
        // You can query for the interface.
        return m_pUnknownInner->QueryInterface(iid, ppv);
#else 
        // Or you can return a cached pointer.
        * ppv = m_pIY;
        // Fall through so it will get AddRef'ed
#endif
    }
    else {
        *ppv = NULL;
        return E_NOINTERFACE;
    }
    reinterpret_cast<IUnknown*>(*ppv)->AddRef();
    return S_OK;
}

ULONG __stdcall CA::AddRef()
{
    retrun InterlockedIncrement(&m_cRef);
}

ULONG __stdcall CA::Release()
{
    if (InterlockedDecrement(&m_cRef) == 0) {
        delete this;
        return 0;
    }
    return m_cRef;
}

///
// 
// Class Factory
//
class CFactory : public IClassFactory
{
public:
    // IUnknown
    virtual HRESULT __stdcall QueryInterface(cosnt IID& iid, void** ppv);
    virtual ULONG   __stdcall AddRef();
    virtual ULONG   __stdcall Release();

    // Interface IClassFactory
    virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter,
        const IID& iid,
        void** ppv);
    virtual HRESULT __stdcall LockServer(BOOL bLock);

    // Constructor
    CFactory() : m_cRef(1) {}

    // Destructor
    ~CFactory() {}

private:
    long m_cRef;
}

// 
// Class factory IUnknown implemenation
//
HRESULT __stdcall CFactory::QueryInstance(REFIID 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)) {
        delete this;
        return 0;
    }
    return m_cRef;
}

// 
// IClassFactory implementation
//
HRESULT __stdcall CFactory::CreateInstance(IUnknown* pUnknownOuter,
    const IID& iid,
    void** ppv)
{
    HRESULT hr = E_FAIL;
    // Cannot aggregate
    if (pUnknownOuter != NULL) {
        return CLASS_E_NOAGGREGATION;
    }

    // Create component.
    CA* pA = new CA;
    if (pA == NULL) {
        return E_OUTOFMEMORY;
    }

    // Initialize the component.
    hr = pA->Init();
    if (FAILED(hr)) {
        // Initialization failed. Delete component.
        pA->Release();
        return hr;
    }

    // Get the requested interface.
    hr = pA->QuerInterface(iid, ppv);
    pA->Release();
    return hr;
}

// LockServer
HRESULT __stdcall CFactory::LockServer(BOOL bLock)
{
    if (bLock) {
        InterlockedIncrement(&g_cServerLocks);
    }
    else {
        InterlockedDecrement(&g_cServerLocks);
    }
    return S_OK;
}

///
// 
// Exported functions
//
STDAPI DllCanUnloadNow()
{
    if (g_cComponents == 0) && (g_cServerLocks == 0)) {
    return S_OK;
    }
    else {
        return S_FALSE;
    }
}

// 
// Get class factory.
//
STDAPI DllGetClassObject(const CLSID& clsid,
    const IID& iid,
    void** ppv)
{
    // Can we create this component?
    if (clsid != CLSID_Component1) {
        return CLASS_E_CLASSNOTAVAILABLE;
    }

    // Create class factory.
    CFactory* pFactory = new CFactory;  // No AddRef in constructor
    if (pFactory == NULL) {
        return E_OUTOFMEMORY;
    }

    // Get requested interface.
    HRESULT hr = pFactory->QueryInterface(iid, ppv);
    pFactory->Release();

    return hr;
}

// 
// Server registration
//
STDAPI DllRegisterServer()
{
    return RegisterServer(g_hModule,
        CLSID_Component1,
        g_szFriendlyName,
        g_szVerIndProgID,
        g_szProgID);
}

STDAPI DllUnregisterServer()
{
    return UnregisterServer(CLSID_Component1,
        g_szVerIndProgID,
        g_szProgID);
}

///
// 
// DLL module information
//
BOOL APIENTRY DllMain(HANDLE hModule,
    DWORD dwReason,
    void* lpReserved)
{
    if (dwReason == DLL_PROCESS_ATTACH) {
        g_hModule = hModule;
    }
    return TRUE;
}
// 程序清单8-4 内部组件(被聚合组件)的实现。
//
// Cmpnt2.cpp - Component 2
// Note the changes in the class factory marked with
//
#include <iostream>
#include <objbase.h>

#include "Iface.h"
#include "Registry.h"

using namespace std;

void trace(const char* msg) { cout << "Component2:\t" << msg << endl; }

///
//
// Global variables
//

// Static variables
static HMODULE g_hModule = NULL;        // DLL module handle
static long g_cComponents = 0;          // Count of active components
static long g_cServerLocks = 0;         // Count of locks

// Friendly name of component
const char g_szFriendlyName[]
= "Inside COM, Chapter 8 Example 2, Component 2";

// Version-independent ProgID
const char g_szVerIndProgID[] = "InsideCOM.Chap08.Ex2.Cmpnt2";

// ProgID
const char g_szProgID[] = "InsideCOM.Chap08.Ex2.Cmpnt2.1";

///
//
// Nondelegating IUnknown interface
//
struct INondelegatingUnknown
{
    virtual HRESULT __stdcall
        NondelegatingQueryInterface(const IID&, void**) = 0;
    virtual ULONG __stdcall NondelegatingAddRef() = 0;
    virtual ULONG __stdcall NondelegatingRelease() = 0;
};

///
//
// Component
//
class CB : public IY,
    INondelegatingUnknown
{
public:
    // Delegating IUnknown
    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();
    }

    // Nondelegating IUnknown
    virtual HRESULT __stdcall
        NondelegatingQueryInterface(const IID& iid, void** ppv);
    virtual ULONG __stdcall NondelegatingAddRef();
    virtual ULONG __stdcall NondelegatingRelease();

    // Interface IY
    virtual void __stdcall Fy() { cout << "Fy" << endl; }

    // Constructor
    CB(IUnknown* m_pUnknownOuter);

    // Destructor
    ~CB();

private:
    long m_cRef;
    IUnknown* m_pUnknownOuter;
}

//
// IUnknown implementation
//
HRESULT __stdcall CB::NondelegatingQueryInterface(const IID& iid, void** ppv)
{
    if (iid == IID_IUnknown) {
        // !!! CAST IS VERY IMPORTANT!!!
        *ppv = static_cast<INondelegatingUnknown*>(this);
    }
    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::NondelegateRelease()
{
    if (InterlockedDecrement(&m_cRef) == 0) {
        delete this;
        return 0;
    }
    return m_cRef;
}

//
// Constructor
//
CB::CB(IUnknown* pUnknownOuter)
    : m_cRef(1)
{
    ::InterlockedIncrement(&g_cComponents);

    if (pUnknownOuter == NULL) {
        trace("Not aggregating: delegate to nondelegating IUnknown.");
        m_pUnknownOuter = reinterpret_cast<IUnknown*>
            (static_cast<INondelegatingUnknown*>
                (this));
    }
    else {
        trace("Aggregating: delegate to outer IUnknown.");
        m_pUnknownOuter = pUnknownOuter;
    }
}

// 
// Destructor
//
CB::~CB()
{
    InterlockedDecrement(&g_cComponents);
    trace("Destroy self.");
}

///
//
// Class factory
//
class CFactory : pubic IClassFactory
{
public:
    // IUnknown
    virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv);
    virtual ULONG   __stdcall AddRef();
    virtual ULONG   __stdcall Release();

    // Interface IClassFactory
    virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter,
        const IID& iid,
        void** ppv);
    virtual HRESULT __stdcall LockServer(BOOL bLock);

    // Constructor
    CFactory() : m_cRef(1) {}

    // Destructor
    ~CFactory() {}

private:
    long m_cRef;
}

// 
// Class factory IUnknown implementation
//
HRESULT CFactory::QueryInstance(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 InterlockedIncremetn(&m_cRef);
}

ULONG __stdcall CFactory::Release()
{
    if (InterlockedDecrement(&m_cRef) == 0) {
        delete this;
        return 0;
    }
    return m_cRef;
}

//
// IClassFactory implementation
//
HRESULT __stdcall CFactory::CreateInstance(IUnknown* pUnknownOuter,
    const IID& iid,
    void** ppv)
{
    // Aggregate only if the requested iid is IID_IUnknown.
    if ((pUnknownOuter != NULL) && (iid != IID_IUnknown)) {
        return CLASS_E_NOAGGREGATION;
    }

    // Create component.
    CB* pB = new CB(pUnknownOuter);
    if (pB == NULL) {
        return E_OUTOFMEMORY;
    }

    // Get the requested interface.
    HRESULT hr = pB->NondelegatingQueryInterface(iid, ppv);
    pB->NondelegatingRelease();
    return hr;
}

// LockServer
HRESULT CFactory::LockServer(BOOL bLock)
{
    if (bLock) {
        InterlockedIncrement(&g_cServerLocks);
    }
    else {
        InterlockedDecrement(&g_cServerLocks);
    }
    return S_OK;
}

///
//
// Exported functions
//
STDAPI DllCanUnloadNow()
{
    if ((g_cComponents == 0) && (g_cServerLocks == 0)) {
        return S_OK;
    }
    else {
        return S_FALSE;
    }
}

//
// Get class factory.
// 
STDAPI DllGetClassObject(const CLSID& clsid,
    const IID& iid,
    void** ppv)
{
    // Can we create this component?
    if (clsid != CLSID_Component2) {
        return CLASS_E_CLASSNOTAVAILABLE;
    }

    // Create class factory.
    CFactory* pFactory = new CFactory;  // No AddRef in constructor
    if (pFactory == NULL) {
        return E_OUTOFMEMORY;
    }

    // Get requested interface.
    HRESULT hr = pFactory->QueryInterface(iid, ppv);
    pFactory->Release();

    return hr;
}

//
// Server registraton
//
STDAPI DllRegisterServer()
{
    return RegisterServer(g_hModule,
        CLSID_Components2,
        g_szFriendlyName,
        g_szVerIndProgID,
        g_szProgID);
}

STDAPI DllUnregisterServer()
{
    return UnregisterServer(CLSID_Components2,
        g_szVerIndProgID,
        g_szProgID);
}

///
// 
// DLL module information
//
BOOL APIENTRY DllMain(HANDLE hModule,
    DWORD dwReason,
    void* lpReserved)
{
    if (dwReason == DLL_PROCESS_ATTACH) {
        g_hModule = hModule;
    }
    return TRUE;
}

在第五章的动态链接过后吗,就正式进入了COM组件的学习,因个人原因,并未详对学习过程进行详细记录
COM技术内幕所有学习笔记暂时完结
这是github中有前辈整理的COM技术内幕项目源码

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值