Windows NT Systems Programming: Spring 1999

[ Home | Syllabus | Course Notes | Assignments | Search]


DCOMin.gif (6548 bytes)

 


DCOMout.gif (9922 bytes)


Connectable Objects

Motivation:

Example: NOMS: sharing message folders - how to inform of deleted or added messages?

SOLUTION: Connectable Objects (that is objects which can call the client)

Connect1.gif (3178 bytes)

conn.bmp (79382 bytes)

 


Client Code

Client has to provide an interface to the sink to be used by the connectable object

// client.cpp
#define _WIN32_DCOM
#include <olectl.h>
#include <conio.h>
#include <iostream.h>
#include "Component\component.h"

class CSink : public IOutGoing
{
public:
	// IUnknown
	ULONG __stdcall AddRef();
	ULONG __stdcall Release();
	HRESULT __stdcall QueryInterface(REFIID iid, void** ppv);

	// IOutGoing
	HRESULT __stdcall GotMessage(int Message);

	CSink() : m_cRef(0) { }
	~CSink() { }

private:
	long m_cRef;
};

//......

HRESULT CSink::GotMessage(int Message)
{
	if(Message == (int)'b' || Message == (int)'B')
		PlaySound("BrockschmidtQuack", NULL, SND_RESOURCE|SND_ASYNC);
	cout << "CSink::GotMessage is " << (char)Message << endl;
	return S_OK;
}
rainbow.gif (2243 bytes)
rainbow.gif (2243 bytes)

void main()
{
	cout << "Client: Calling CoInitialize()" << endl;
	CoInitializeEx(NULL, COINIT_MULTITHREADED); // why multi-threaded?
	
	IUnknown* pUnknown;
	cout << "Client: Calling CoCreateInstance()" << endl;
	CoCreateInstance(CLSID_InsideDCOM, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&pUnknown);

	ISum* pSum;
	cout << "Client: Calling QueryInterface() for ISum on " << pUnknown << endl;
	HRESULT hr = pUnknown->QueryInterface(IID_ISum, (void**)&pSum);
	if(FAILED(hr))
		cout << "QueryInterface FAILED" << endl;

	int sum;
	pSum->Sum(17, 2, &sum);
	cout << "pSum->Sum(17, 2) = " << sum << endl;

	IConnectionPointContainer* pConnectionPointContainer;
	hr = pUnknown->QueryInterface(IID_IConnectionPointContainer, (void**)&pConnectionPointContainer);
	if(SUCCEEDED(hr))
	{
		IConnectionPoint* pConnectionPoint;
		hr = pConnectionPointContainer->FindConnectionPoint(IID_IOutGoing, &pConnectionPoint);
		cout << "FindConnectionPoint returns " << hr << " pConnectionPoint = " << pConnectionPoint << endl;

		CSink* mySink = new CSink;
		DWORD dwCookie;
		pConnectionPoint->Advise((IUnknown*)mySink, &dwCookie);

		cout << "Press any key to exit" << endl;
		_getch(); // wait until user wants client to stop

		pConnectionPoint->Unadvise(dwCookie);
		pConnectionPoint->Release();
		pConnectionPointContainer->Release();
	}

	cout << "Client: Calling Release() for pSum" << endl;
	hr = pSum->Release();

	cout << "Client: Calling Release() for pUnknown" << endl;
	hr = pUnknown->Release();

	cout << "Client: Calling CoUninitialize()" << endl;
	CoUninitialize();
}
rainbow.gif (2243 bytes)

Component needs to also support IConnectionPointContainer

class CInsideDCOM : public ISum, IConnectionPointContainer, IConnectionPoint
// NOTICE multiple inheritance of interfaces
{
public:
	// IUnknown
	ULONG __stdcall AddRef();
	ULONG __stdcall Release();
	HRESULT __stdcall QueryInterface(REFIID iid, void** ppv);

	// IConnectionPointContainer
	HRESULT __stdcall EnumConnectionPoints(IEnumConnectionPoints** ppEnum);
	HRESULT __stdcall FindConnectionPoint(REFIID riid, IConnectionPoint** ppCP);

	// IConnectionPoint
	HRESULT __stdcall GetConnectionInterface(IID* pIID);
	HRESULT __stdcall GetConnectionPointContainer(IConnectionPointContainer** ppCPC);
	HRESULT __stdcall Advise(IUnknown* pUnknown, DWORD* pdwCookie);
	HRESULT __stdcall Unadvise(DWORD dwCookie);
	HRESULT __stdcall EnumConnections(IEnumConnections** ppEnum);

	// ISum
	HRESULT __stdcall Sum(int x, int y, int* retval);

	CInsideDCOM() : m_cRef(0) { g_cComponents++; }
	~CInsideDCOM() { cout << "Component: CInsideDCOM::~CInsideDCOM()" << endl, g_cComponents--; }

private:
	long m_cRef;
};



HRESULT CInsideDCOM::Advise(IUnknown* pUnknown, DWORD* pdwCookie)
{
	cout << "Advise" << endl;
	*pdwCookie = 1;
	return pUnknown->QueryInterface(IID_IOutGoing, (void**)&g_pOutGoing);
}

HRESULT CInsideDCOM::Unadvise(DWORD dwCookie)
{
	cout << "Unadvise" << endl;
	g_pOutGoing->Release();
	return NOERROR;
}


HRESULT CInsideDCOM::FindConnectionPoint(REFIID riid, IConnectionPoint** ppCP)
{
	if(riid == IID_IOutGoing)
	{
		cout << "Component: CInsideDCOM::FindConnectionPoint() for IID_IOutGoing" << endl;
		return QueryInterface(IID_IConnectionPoint, (void**)ppCP);
	}
	return E_NOINTERFACE;
}
rainbow.gif (2243 bytes)

IDL file

// component.idl
import "unknwn.idl";

[ object, uuid(10000001-0000-0000-0000-000000000001),
  oleautomation ]
interface ISum : IUnknown
{
	HRESULT Sum(int x, int y, [out, retval] int* retval);
}

[ object, uuid(10000005-0000-0000-0000-000000000001),
  oleautomation ]
interface IOutGoing : IUnknown
{
	HRESULT GotMessage(int Message);
}

[ uuid(10000003-0000-0000-0000-000000000001),
  helpstring("Inside DCOM Component Type Library"),
  version(1.0) ]
library Component
{
	importlib("stdole32.tlb");

	interface ISum;
	interface IOutGoing;

	[ uuid(10000002-0000-0000-0000-000000000001) ]
	coclass InsideDCOM
	{
		interface ISum;
		[source] interface IOutGoing;
	}
};


Copyright chris wild 1999.
For problems or questions regarding this web contact [Dr. Wild].
Last updated: April 06, 1999.