CodeSteps

Python, C, C++, C#, PowerShell, Android, Visual C++, Java ...

COM – Creating a COM Component using C++ – DLL component

In this series of articles on creating a COM Component using C++, in the previous article, we implemented a component using C++. The component implemented the IUnknown standard interface and IHello custom interface. Custom interfaces are the interfaces defined by us. Standard interfaces are the interfaces that are defined by the COM component library.

We need to package this component as either an EXE component or a DLL component.

EXE components required main or WinMain functions. So, if you want to pack this component as an EXE component, you need to provide main or WinMain functions in your component code.

DLL components require two helper functions, DllGetClassObject and DllCanUnloadNow. DllGetClassObject to create an instance of a requested component and return the requested interface. The DllCanUnloadNow function determines whether the DLL can unload from memory or not.

Let’s package our component as a DLL component. So, we need to implement DllGetClassObject and DllCanUnloadNow functions.

The syntax of the DllGetClassObject function is:

HRESULT __stdcall DllGetClassObject(
  REFCLSID rclsid,
  REFIID riid,
  LPVOID *ppv
);

This function takes two input parameters one is the CLSID of the component, and another one is the IID of an interface and returns the pointer to the requested interface object.

We know IID is the GUID of an interface. What about CLSID? CLSID is also a GUID. But this one is an IID of a component. So, we need to provide a GUID to our component. Generate a GUID (you can generate GUID using GUID generator tool. Good thing is this tool generates GUID in different formats.) and add it in HelloComponent.h file. Below is the CLSID for HelloComponent.

// {23893EE4-8514-4BD6-8830-A7EBDDF5C944}
static const GUID CLSID_HelloComponent = { 0x23893ee4, 0x8514, 0x4bd6, { 0x88, 0x30, 0xa7, 0xeb, 0xdd, 0xf5, 0xc9, 0x44 } };

Add the below code into HelloComponent.cpp file.

// DllGetClassObject - Returns the requested interface object pointer
// 
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
	HRESULT hr = S_OK;

	if ( rclsid == CLSID_HelloComponent )
	{
		CHelloComponent *pObj = new CHelloComponent();
		if ( pObj )
		{
			hr = pObj->QueryInterface(riid, ppv);
			if ( FAILED(hr) )
			{
				delete pObj;
				pObj = NULL;
			}
		}
	}

	return hr;
}

Now, look at the DllCanUnloadNow function. This will tell whether to unload the DLL or not. How does it decide whether to unload DLL or not? The answer is simple. We have to add a variable into HelloComponent to keep track number of instances created.

So, add m_cComponents static member into CHelloComponent and increments its value by 1 when an instance is created. Don’t forget to decrement the value by 1 when the component is released.

Now CHelloComponent looks like below:

#include "Hello.h"
#include "Hello_i.c"

#include <iostream>

// {23893EE4-8514-4BD6-8830-A7EBDDF5C944}
static const GUID CLSID_HelloComponent = { 0x23893ee4, 0x8514, 0x4bd6, { 0x88, 0x30, 0xa7, 0xeb, 0xdd, 0xf5, 0xc9, 0x44 } };

class CHelloComponent : public IHello
{
public:
	CHelloComponent() : m_cRef (1)
	{
		m_cComponents++;
	}
	~CHelloComponent()
	{
		m_cComponents--;
	}

	// -- IUnknown Methods
	ULONG STDMETHODCALLTYPE AddRef();
	ULONG STDMETHODCALLTYPE Release();
	HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID *ppv);

	// -- IHello Method
	HRESULT STDMETHODCALLTYPE SayHello(BSTR message);

public:
	static int m_cComponents;

private:
	ULONG m_cRef;
};

// -- Initialize static members of a class here.
int CHelloComponent::m_cComponents = 0;

Now implement the DllCanUnloadNow function. It is simple.

STDAPI DllCanUnloadNow()
{
	return (CHelloComponent::m_cComponents == 0) ? S_OK : S_FALSE;
}

Let’s compile HelloComponent.cpp file and generate the DLL file.

cl HelloComponent.cpp /EHsc /LD /link comsuppw.lib

This will compile HelloComponent.cpp file and generate HelloComponent.dll.

Now DLL file is created. Next, we have to register our component. We will discuss registering the component in our next article.

**

COM – Creating a COM Component using C++ – DLL component

2 thoughts on “COM – Creating a COM Component using C++ – DLL component

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top