com技术内幕--读书笔记(8_2)

聚合

聚合的情况下,外部组件直接把内部组件的接口指针返回给客户,因此无法对接口的实现进行修改

示意图如下



聚合的实现

客户向外部组件请求接口IY,外部组件只是向内部组件查询此接口并将此接口指针返回给客户。

若内部组件直接返回接口指针给客户,客户可以直接得到两个不同的IUnknown接口,即外部组件和内部组件的。因此内部组将应该使用外部组件所实现的IUnknown接口(外部未知接口),为此,内部组件需要一个指向外部未知接口的指针,将调用请求转发给外部未知接口,


代理和非代理未知接口

内部组件要使用外部未知接口,需要实现两个IUnknown接口,一个是非代理未知接口,一个是代理未知接口。非代理外部接口按照之前的方式实现内部组件的IUnknown接口,代理未知接口在内部调用外部IUnknown接口(被聚合的情况下)或者非代理IUnknown接口(没有被聚合的情况下)。

事实上,对内部组件来说,需要保存一个外部组件的IUnknown接口,当组件使用者调用时,用外部组件的IUnknown来响应用户的调用请求,以及一个未被聚合时的自己内部的IUnknown接口,为了区分,起名字叫非代理IUnknown接口和代理IUnknown接口,代理IUnknown接口还有一个作用,可以实现响应的分发,是决定在聚合时使用外部IUnknown接口还是内部的IUnknown接口。


对聚合组件的客户来说,将调用代理未知接口就是外部组件的IUnknown接口。对外部组件来说,需要保存一个内部组件的IUnknown接口就是非代理外部接口来操作内部组件。如下图所示

com技术内幕--读书笔记(8_2)_第1张图片



代码如下

组件CB,被聚合的组件,即内部组件

cb.cpp

//cb.cpp
//
#include <ObjBase.h>
#include "iface.h"
#include "registry.h"
#include <iostream>
using namespace std;

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

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";

struct INonDelegateUnknown
{
	virtual HRESULT __stdcall NonDelegateQueryInterface(const IID &iid, void **ppv) = 0;
	virtual ULONG   __stdcall NonDelegateAddRef() = 0;
	virtual ULONG   __stdcall NonDelegateRelease() = 0;
};

class CB : public IY, public INonDelegateUnknown
{
public :
	virtual HRESULT __stdcall NonDelegateQueryInterface(const IID &iid, void **ppv);
	virtual ULONG   __stdcall NonDelegateAddRef();
	virtual ULONG   __stdcall NonDelegateRelease();

	virtual HRESULT __stdcall QueryInterface(const IID &iid, void **ppv);
	virtual ULONG   __stdcall AddRef();
	virtual ULONG   __stdcall Release();
	virtual void    __stdcall Fy();

	CB(IUnknown *pIUnkownOuter);
	~CB();
protected:
	long m_cRef;
	IUnknown *m_pIUnknownOuter;
};

HRESULT __stdcall CB::QueryInterface(const IID &iid, void **ppv)
{
	return m_pIUnknownOuter->QueryInterface(iid, ppv);
}

ULONG __stdcall CB::AddRef()
{
	return m_pIUnknownOuter->AddRef();
}

ULONG __stdcall CB::Release()
{
	return m_pIUnknownOuter->Release();
}

ULONG __stdcall CB::NonDelegateAddRef()
{
	return InterlockedIncrement(&m_cRef);
}

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

HRESULT __stdcall CB::NonDelegateQueryInterface(const IID &iid, void **ppv)
{
	if(iid == IID_IUnknown)
	{
		*ppv = static_cast<INonDelegateUnknown*>(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;
}

void __stdcall CB::Fy()
{
	cout<<"CB::Fy()"<<endl;
}

CB::CB(IUnknown *pIUnkownOuter) : m_cRef(1)
{
	InterlockedIncrement(&g_cComponents);
	if(pIUnkownOuter == NULL)
	{
		m_pIUnknownOuter = reinterpret_cast<IUnknown*>(static_cast<INonDelegateUnknown*>(this));
	}
	else
	{
		m_pIUnknownOuter = pIUnkownOuter;
	}
}

CB::~CB()
{
	InterlockedDecrement(&g_cComponents);
}

///////////////////////////////////////////////////////////
class CFactory: public IClassFactory
{
public:
	virtual HRESULT __stdcall CreateInstance(IUnknown *pUnknownOuter, const IID &iid, void **ppv);
	virtual HRESULT __stdcall LockServer(BOOL bLock);

	virtual HRESULT __stdcall QueryInterface(const IID &iid, void **ppv);
	virtual ULONG   __stdcall AddRef();
	virtual ULONG   __stdcall Release();

	CFactory();
	~CFactory();
protected:
	long m_cRef;
};

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

CFactory::~CFactory()
{
}

HRESULT __stdcall CFactory::CreateInstance(IUnknown *pUnknownOuter, const IID &iid, void **ppv)
{
	if(pUnknownOuter != NULL && iid != IID_IUnknown)
	{
		return CLASS_E_NOAGGREGATION;
	}
	CB *pB = new CB(pUnknownOuter);
	HRESULT hr = pB->NonDelegateQueryInterface(iid, ppv);
	pB->NonDelegateRelease();

	return hr;
}

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

HRESULT __stdcall CFactory::QueryInterface(const IID &iid, void **ppv)
{
	if(iid == IID_IClassFactory || iid == IID_IUnknown)
	{
		*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;
}

///////////////////////////////////////////////////////////
//export function

STDAPI  DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv)
{
	if(clsid != CLSID_Component2)
	{
		return CLASS_E_CLASSNOTAVAILABLE;
	}
	IClassFactory *pFactory = new CFactory();
	HRESULT hr = pFactory->QueryInterface(iid, ppv);
	pFactory->Release();
	return hr;
}

STDAPI  DllCanUnloadNow()     
{
	if(g_cServerLocks == 0 && g_cComponents == 0)
	{
		return S_OK;
	}
	return S_FALSE;
}
STDAPI  DllRegisterServer() 
{
	return RegisterServer(g_hModule,
		CLSID_Component2, 
		g_szFriendlyName,
		g_szVerIndProgID,
		g_szProgID);
}

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

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

iface.h

//iface.h
//

#ifndef IFACE_H
#define IFACE_H

interface IX:IUnknown
{
	virtual void __stdcall Fx() = 0;
};

interface IY:IUnknown
{
	virtual void __stdcall Fy() = 0;
};

extern "C" const IID IID_IX;
extern "C" const IID IID_IY;

extern "C" const CLSID CLSID_Component1;

extern "C" const CLSID CLSID_Component2;
#endif //IFACE_H


guids.cpp

#include <ObjBase.h>

// {32bb8320-b41b-11cf-a6bb-0080c7b2d682}
extern "C" const IID IID_IX = 
{0x32bb8320, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};

// {32bb8321-b41b-11cf-a6bb-0080c7b2d682}
extern "C" const IID IID_IY = 
{0x32bb8321, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};


// {0c092c22-882c-11cf-a6bb-0080c7b2d682}
extern "C" const CLSID CLSID_Component1 =
{0x0c092c22, 0x882c, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};

// {0c092c23-882c-11cf-a6bb-0080c7b2d682}
extern "C" const CLSID CLSID_Component2 =
{0x0c092c23, 0x882c, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}};

registry.h

#ifndef _REGISTRY_H_  
#define _REGISTRY_H_  

HRESULT RegisterServer(HMODULE hModule,   
					   const CLSID &clsid,  
					   const char *szFriendlyName,  
					   const char *szVerIndProgID,  
					   const char *szProgID);  
HRESULT UnregisterServer(const CLSID &clsid,  
						 const char *szVerIndProgID,  
						 const char *szProgID);  
 
#endif  //_REGISTRY_H_  

registry.cpp

//  
//registry.cpp  
//  
#include <objbase.h>  
#include <cassert>  
#include "registry.h"  
  
//  
//Internal functions   
  
//Set the key and its value  
BOOL SetKeyAndValue(const char *szKey, const char *szSubKey, const char *szValue);  
  
//Convert a clsid to a char string  
void CLSIDtochar(const CLSID &clsid, char *szClsID, int nLength);  
  
//Delete szKeyChild and all its child  
LONG RecursiveDeleteKey(HKEY hKeyParent, const char *szKeyChild);  
  
const int CLSID_STRING_SIZE = 39 ;  
  
//  
// Register the component in the registry.  
//  
HRESULT RegisterServer(HMODULE hModule,            // DLL module handle  
                       const CLSID& clsid,         // Class ID  
                       const char* szFriendlyName, // Friendly Name  
                       const char* szVerIndProgID, // Programmatic  
                       const char* szProgID)       //   IDs  
{  
    char szModule[512] ;  
    DWORD dwResult =::GetModuleFileName(hModule, szModule, sizeof(szModule)/sizeof(char));  
  
    assert(dwResult != 0) ;  
  
    // Convert the CLSID into a char.  
    char szCLSID[CLSID_STRING_SIZE] ;  
    CLSIDtochar(clsid, szCLSID, sizeof(szCLSID)) ;  
  
    // Build the key CLSID\\{...}  
    char szKey[64] ;  
    strcpy(szKey, "CLSID\\") ;  
    strcat(szKey, szCLSID) ;  
    
    // Add the CLSID to the registry.  
    SetKeyAndValue(szKey, NULL, szFriendlyName) ;  
  
    // Add the server filename subkey under the CLSID key.  
    SetKeyAndValue(szKey, "InprocServer32", szModule) ;  
  
    // Add the ProgID subkey under the CLSID key.  
    SetKeyAndValue(szKey, "ProgID", szProgID) ;  
  
    // Add the version-independent ProgID subkey under CLSID key.  
    SetKeyAndValue(szKey, "VersionIndependentProgID",  
                   szVerIndProgID) ;  
  
    // Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT.  
    SetKeyAndValue(szVerIndProgID, NULL, szFriendlyName) ;   
    SetKeyAndValue(szVerIndProgID, "CLSID", szCLSID) ;  
    SetKeyAndValue(szVerIndProgID, "CurVer", szProgID) ;  
  
    // Add the versioned ProgID subkey under HKEY_CLASSES_ROOT.  
    SetKeyAndValue(szProgID, NULL, szFriendlyName) ;   
    SetKeyAndValue(szProgID, "CLSID", szCLSID) ;  
  
    return S_OK ;  
}  
  
//  
// Remove the component from the registry.  
//  
LONG UnregisterServer(const CLSID& clsid,         // Class ID  
                      const char* szVerIndProgID, // Programmatic  
                      const char* szProgID)       //   IDs  
{  
    // Convert the CLSID into a char.  
    char szCLSID[CLSID_STRING_SIZE] ;  
    CLSIDtochar(clsid, szCLSID, sizeof(szCLSID)) ;  
  
    // Build the key CLSID\\{...}  
    char szKey[64] ;  
    strcpy(szKey, "CLSID\\") ;  
    strcat(szKey, szCLSID) ;  
  
    // Delete the CLSID Key - CLSID\{...}  
    LONG lResult = RecursiveDeleteKey(HKEY_CLASSES_ROOT, szKey) ;  
    assert( (lResult == ERROR_SUCCESS) || (lResult == ERROR_FILE_NOT_FOUND) ) ; // Subkey may not exist.  
  
    // Delete the version-independent ProgID Key.  
    lResult = RecursiveDeleteKey(HKEY_CLASSES_ROOT, szVerIndProgID) ;  
    assert((lResult == ERROR_SUCCESS) ||  
           (lResult == ERROR_FILE_NOT_FOUND)) ; // Subkey may not exist.  
  
    // Delete the ProgID key.  
    lResult = RecursiveDeleteKey(HKEY_CLASSES_ROOT, szProgID) ;  
    assert((lResult == ERROR_SUCCESS) ||  
           (lResult == ERROR_FILE_NOT_FOUND)) ; // Subkey may not exist.  
  
    return S_OK ;  
}  
  
  
BOOL SetKeyAndValue(const char *szKey, const char *szSubKey, const char *szValue)  
{  
    HKEY hKey;  
    char szKeyBuf[1024] ;  
  
    // Copy keyname into buffer.  
    strcpy(szKeyBuf, szKey) ;  
  
    // Add subkey name to buffer.  
    if (szSubKey != NULL)  
    {  
        strcat(szKeyBuf, "\\") ;  
        strcat(szKeyBuf, szSubKey ) ;  
    }  
  
    // Create and open key and subkey.  
    long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT ,  
                                  szKeyBuf,   
                                  0, NULL, REG_OPTION_NON_VOLATILE,  
                                  KEY_ALL_ACCESS, NULL,   
                                  &hKey, NULL) ;  
    if (lResult != ERROR_SUCCESS)  
    {  
        return FALSE ;  
    }  
  
    // Set the Value.  
    if (szValue != NULL)  
    {  
        RegSetValueEx(hKey, NULL, 0, REG_SZ,   
                      (BYTE *)szValue,   
                      strlen(szValue)+1) ;  
    }  
  
    RegCloseKey(hKey) ;  
    return TRUE ;  
      
}  
  
  
LONG RecursiveDeleteKey(HKEY hKeyParent, const char *szKeyChild)  
{  
    // Open the child.  
    HKEY hKeyChild ;  
    LONG lRes = RegOpenKeyEx(hKeyParent, szKeyChild, 0,  
                             KEY_ALL_ACCESS, &hKeyChild) ;  
    if (lRes != ERROR_SUCCESS)  
    {  
        return lRes ;  
    }  
  
    // Enumerate all of the decendents of this child.  
    FILETIME time ;  
    char szBuffer[256] ;  
    DWORD dwSize = 256 ;  
    while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL,  
                        NULL, NULL, &time) == S_OK)  
    {  
        // Delete the decendents of this child.  
        lRes = RecursiveDeleteKey(hKeyChild, szBuffer) ;  
        if (lRes != ERROR_SUCCESS)  
        {  
            // Cleanup before exiting.  
            RegCloseKey(hKeyChild) ;  
            return lRes;  
        }  
        dwSize = 256 ;  
    }  
  
    // Close the child.  
    RegCloseKey(hKeyChild) ;  
  
    // Delete this child.  
    return RegDeleteKey(hKeyParent, szKeyChild) ;  
}  
  
void CLSIDtochar(const CLSID &clsid, char *szClSID, int nLength)  
{  
    assert(nLength >= CLSID_STRING_SIZE) ;  
    // Get CLSID  
    LPOLESTR wszCLSID = NULL ;  
    HRESULT hr = StringFromCLSID(clsid, &wszCLSID) ;  
    assert(SUCCEEDED(hr)) ;  
  
    // Covert from wide characters to non-wide.  
    wcstombs(szClSID, wszCLSID, nLength);  
  
    // Free memory.  
    CoTaskMemFree(wszCLSID) ;  
}  

cb.def

LIBRARY	cb.dll
EXPORTS DllGetClassObject   @2	PRIVATE
	    DllCanUnloadNow     @3	PRIVATE
		DllRegisterServer   @4	PRIVATE
		DllUnregisterServer @5	PRIVATE

组件CA,外部组件

ca.cpp

#include <ObjBase.h>
#include "iface.h"
#include "registry.h"
#include <iostream>
using namespace std;

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";

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();

	CA();
	~CA();
	HRESULT __stdcall Init();

protected:
	long m_cRef;
	IY *m_pIy;
	IUnknown *m_pIUnknownInner;
};

CA::CA():m_cRef(1), m_pIUnknownInner(NULL)
{
	InterlockedIncrement(&g_cComponents);
}

CA::~CA()
{
	InterlockedDecrement(&g_cComponents);



	if (m_pIUnknownInner != NULL)
	{
		m_pIUnknownInner->Release();
	}
}

HRESULT __stdcall CA::Init()
{
	HRESULT hr; 
	IUnknown *pIUnknownOuter = this;
	hr = CoCreateInstance(CLSID_Component2, pIUnknownOuter, CLSCTX_INPROC_SERVER,
						  IID_IUnknown, (void**)&m_pIUnknownInner);
	if (FAILED(hr))
	{
		return E_FAIL;
	}

	hr = m_pIUnknownInner->QueryInterface(IID_IY, (void**)&m_pIy); 
	if (FAILED(hr))
	{
		m_pIUnknownInner->Release();
		return E_FAIL;
	}

	pIUnknownOuter->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)
	{
		return m_pIUnknownInner->QueryInterface(iid, ppv);
	}
	else
	{
		*ppv = NULL;
		return E_NOINTERFACE;
	}
	reinterpret_cast<IUnknown*>(*ppv)->AddRef();
	return S_OK;
}

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

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

void __stdcall CA::Fx()
{
	cout<<"CA::Fx()"<<endl;
}

////////////////////////////////////////////////////////
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();

	~CFactory();

private:
	long m_cRef;
};

CFactory::CFactory() : m_cRef(1) 
{

}

CFactory::~CFactory() 
{

}

HRESULT __stdcall CFactory::QueryInterface(REFIID 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, const IID& iid, void** ppv) 
{
	if (pUnknownOuter != NULL)
	{
		return CLASS_E_NOAGGREGATION;
	}

	CA* pA = new CA;
	if (pA == NULL)
	{
		return E_OUTOFMEMORY;
	}

	HRESULT hr = pA->Init();
	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;
}



///////////////////////////////////////////////////////////
// Export functions

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

STDAPI DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv) 
{
	if (clsid != CLSID_Component1)
	{
		return CLASS_E_CLASSNOTAVAILABLE;
	}

	CFactory* pFactory = new CFactory;

	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_szVerIndProgID,
		g_szProgID);
}


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


ca.def
LIBRARY	ca.dll
EXPORTS DllGetClassObject   @2	PRIVATE
        DllCanUnloadNow     @3	PRIVATE
        DllRegisterServer   @4	PRIVATE
        DllUnregisterServer @5	PRIVATE

组件ca的iface.h,guids.cpp,registry.h,registry.cpp同组件cb


客户端

client.cpp

#include <objbase.h>
#include "Iface.h"
#include <iostream>
using namespace std;

int main(void)
{
	CoInitialize(NULL);
	IX* pIX = NULL; 
	HRESULT hr = CoCreateInstance(CLSID_Component1, NULL, CLSCTX_INPROC_SERVER,
		                            IID_IX, (void**)&pIX);

	if (SUCCEEDED(hr))
	{
		IY* pIY = NULL;
		hr = pIX->QueryInterface(IID_IY, (void**)&pIY);
		if (SUCCEEDED(hr))
		{
			pIY->Fy();
			pIY->Release();
		}
		pIX->Release();
	}
	

	CoUninitialize();

	return 0;
}

客户端的iface.h,guids.cpp同组件cb


聚合组件的一些问题

一.对组件cb来说,有两个未知接口,一个是自身的未知接口,一个是外部组件的未知接口

   对组件ca来说,需要在组件创建的时候Init()的时候,创建组件cb,获取一个内部组件的非代理未知接口,方便对组件cb读取控制


二. 组件cb中的

HRESULT __stdcall CFactory::CreateInstance(IUnknown *pUnknownOuter, const IID &iid, void **ppv)

创建组件cb的时候

HRESULT hr = pB->NonDelegateQueryInterface(iid, ppv);
pB->NonDelegateRelease();

如果组件cb被聚合,返回的是非代理未知接口,由外部组件ca获取。


HRESULT __stdcall CB::NonDelegateQueryInterface(const IID &iid, void **ppv)
函数中的

reinterpret_cast<IUnknown*>(*ppv)->AddRef();
的作用,当组件cb被聚合的情况下,iid == IID_IY时,*ppv指向的是接口IY,对它AddRef(),实际是上增加外部组件的引用计数





你可能感兴趣的:(读书)