Windows NT Systems Programming: Spring 2000

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


Implementing the Component ISum

Could use any language - Let's use C++ first

Remember that the ISum interface object is an abstract class because its four functions are pure virtual.

(What are the four functions?)

Therefore we need to derive a implementation class from it.

rainbow.gif (2243 bytes)

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

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

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

private:
   ULONG m_cRef;
};

 

rainbow.gif (2243 bytes)


Implementing IUnknown Functions

ULONG CInsideDCOM::AddRef()
{
   return ++m_cRef;
}

ULONG CInsideDCOM::Release()
{
   if(--m_cRef != 0) // test if last reference
      return m_cRef;
   delete this; // "calls" destructor
   return 0;
}

HRESULT CInsideDCOM::QueryInterface(REFIID iid, void** ppv)
{
   if(iid == IID_IUnknown) {
      *ppv = (IUnknown*)this;
   }
   else if(iid == IID_ISum) {
      *ppv = (ISum*)this;
   }
   else {
      *ppv = NULL;
      return E_NOINTERFACE;
   }
   AddRef();
   return S_OK;
}
rainbow.gif (2243 bytes)

QueryInterface Rules

QueryInterface on any interface of a component, must produce the same results.
You can query ISum for IUnknown for instance.


SUM implementation

HRESULT CInsideDCOM::Sum(int x, int y, int* retval)
{
   *retval = x + y;
   return S_OK;
}

Creating a  "Location Transparent"  to IUnknown

IClassFactory:
A COM object for creating other COM objects of a given type.

Used by CoCreateInstance, calls CreateInstance.

rainbow.gif (2243 bytes)

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

	// IClassFactory
	HRESULT __stdcall CreateInstance(IUnknown *pUnknownOuter, REFIID iid, void** ppv);
	HRESULT __stdcall LockServer(BOOL bLock);

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

private:
	ULONG m_cRef;
};

rainbow.gif (2243 bytes)

HRESULT CFactory::CreateInstance(IUnknown *pUnknownOuter, REFIID iid, void** ppv)
{
	if(pUnknownOuter != NULL)
		return CLASS_E_NOAGGREGATION;

	CInsideDCOM *pInsideDCOM = new CInsideDCOM;
	cout << "Component: CFactory::CreateInstance() " << pInsideDCOM << endl;

	if(pInsideDCOM == NULL)
		return E_OUTOFMEMORY;

	// QueryInterface probably for IID_IUNKNOWN
	HRESULT hr = pInsideDCOM->QueryInterface(iid, ppv);
	pInsideDCOM->Release();
	return hr;
}

 

rainbow.gif (2243 bytes)

HRESULT CFactory::LockServer(BOOL bLock)
{
	if(bLock)
		g_cServerLocks++;
	else
		g_cServerLocks--;
	return S_OK;
}

HRESULT __stdcall DllCanUnloadNow()
{
	cout << "Component: DllCanUnloadNow() " << (g_cServerLocks == 0 && g_cComponents == 0 ? "Yes" : "No") << endl;
	if(g_cServerLocks == 0 && g_cComponents == 0)
		return S_OK;
	else
		return S_FALSE;
}

HRESULT __stdcall DllGetClassObject(REFCLSID clsid, REFIID iid, void** ppv)
{
	cout << "Component: DllGetClassObject" << endl;
	
	if(clsid != CLSID_InsideDCOM)
		return CLASS_E_CLASSNOTAVAILABLE;

	CFactory* pFactory = new CFactory;
	if(pFactory == NULL)
		return E_OUTOFMEMORY;

	// QueryInterface probably for IClassFactory
	HRESULT hr = pFactory->QueryInterface(iid, ppv);
	pFactory->Release();
	return hr;
}

rainbow.gif (2243 bytes)

 


dll2.gif (20140 bytes)



Copyright chris wild 1999/2000.
For problems or questions regarding this web contact [Dr. Wild].
Last updated: March 14, 2000.