Click here to Skip to main content
15,894,630 members
Articles / Programming Languages / C++

COM in plain C, Part 6

Rate me:
Please Sign up or sign in to vote.
4.89/5 (32 votes)
22 Jul 2006CPOL25 min read 103.2K   2.4K   102  
How to write an ActiveX Script Host in C.
// Registers our IExample.DLL as a COM component.

#include <windows.h>
#include <tchar.h>
#include <initguid.h>
#include "../IExample/IExample.h"


// These first 3 strings will change if you create your own object
static const TCHAR	OurDllName[] = _T("IExample.dll");
static const TCHAR	ObjectDescription[] = _T("IExample COM component");
static const TCHAR	FileDlgTitle[] = _T("Locate IExample.dll to register it");

static const TCHAR	FileDlgExt[] = _T("DLL files\000*.dll\000\000");
static const TCHAR	ClassKeyName[] = _T("Software\\Classes");
static const TCHAR	CLSID_Str[] = _T("CLSID");
static const TCHAR	InprocServer32Name[] = _T("InprocServer32");
static const TCHAR	ThreadingModel[] = _T("ThreadingModel");
static const TCHAR	BothStr[] = _T("both");
static const TCHAR	GUID_Format[] = _T("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}");





/************************ stringFromCLSID() ***********************
 * Converts an object's GUID (array) to an ascii string (in a special
 * format where there are groups of ascii digits separated by a dash).
 * NOTE: Using wsprintf() avoids needing to load ole32.dll just to
 * call StringFromCLSID(). We're just doing the same thing it would do.
 */

static void stringFromCLSID(LPTSTR buffer, REFCLSID ri)
{
	wsprintf(buffer, &GUID_Format[0],
		((REFCLSID)ri)->Data1, ((REFCLSID)ri)->Data2, ((REFCLSID)ri)->Data3, ((REFCLSID)ri)->Data4[0],
		((REFCLSID)ri)->Data4[1], ((REFCLSID)ri)->Data4[2], ((REFCLSID)ri)->Data4[3],
		((REFCLSID)ri)->Data4[4], ((REFCLSID)ri)->Data4[5], ((REFCLSID)ri)->Data4[6],
		((REFCLSID)ri)->Data4[7]);
}





/************************ cleanup() ***********************
 * Removes all of the registry entries we create in WinMain.
 * This is called to do cleanup if there's an error
 * installing our DLL as a COM component.
 */

static void cleanup(void)
{
	HKEY		rootKey;
	HKEY		hKey;
	HKEY		hKey2;
	TCHAR		buffer[39];

	stringFromCLSID(&buffer[0], (REFCLSID)(&CLSID_IExample));

	// Open "HKEY_LOCAL_MACHINE\Software\Classes"
	if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, &ClassKeyName[0], 0, KEY_WRITE, &rootKey))
	{
		// Delete our CLSID key and everything under it
		if (!RegOpenKeyEx(rootKey, &CLSID_Str[0], 0, KEY_ALL_ACCESS, &hKey))
		{
			if (!RegOpenKeyEx(hKey, &buffer[0], 0, KEY_ALL_ACCESS, &hKey2))
			{
				RegDeleteKey(hKey2, &InprocServer32Name[0]);

				RegCloseKey(hKey2);
				RegDeleteKey(hKey, &buffer[0]);
			}

			RegCloseKey(hKey);
		}

		RegCloseKey(rootKey);
	}
}





/************************** WinMain() ************************
 * Program Entry point
 */

int WINAPI WinMain(HINSTANCE hinstExe, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow)
{
	int				result;
	TCHAR			filename[MAX_PATH];

	{
	OPENFILENAME	ofn;

	// Pick out where our DLL is located. We need to know its location in
	// order to register it as a COM component
	lstrcpy(&filename[0], &OurDllName[0]);
	ZeroMemory(&ofn, sizeof(OPENFILENAME));
	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.lpstrFilter = &FileDlgExt[0];
	ofn.lpstrFile = &filename[0];
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrTitle = &FileDlgTitle[0];
	ofn.Flags = OFN_FILEMUSTEXIST|OFN_EXPLORER|OFN_PATHMUSTEXIST;
	result = GetOpenFileName(&ofn);
	}

	if (result > 0)
	{
		HKEY		rootKey;
		HKEY		hKey;
		HKEY		hKey2;
		HKEY		hkExtra;
		TCHAR		buffer[39];
		DWORD		disposition;

		// Assume an error
		result = 1;

		// Open "HKEY_LOCAL_MACHINE\Software\Classes"
		if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, &ClassKeyName[0], 0, KEY_WRITE, &rootKey))
		{
			// Open "HKEY_LOCAL_MACHINE\Software\Classes\CLSID"
			if (!RegOpenKeyEx(rootKey, &CLSID_Str[0], 0, KEY_ALL_ACCESS, &hKey))
			{
				// Create a subkey whose name is the ascii string that represents
				// our IExample2 object's GUID
				stringFromCLSID(&buffer[0], (REFCLSID)(&CLSID_IExample));
				if (!RegCreateKeyEx(hKey, &buffer[0], 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &hKey2, &disposition))
				{
					// Set its default value to some "friendly" string that helps
					// a user identify what this COM DLL is for. Setting this value
					// is optional. You don't need to do it
					RegSetValueEx(hKey2, 0, 0, REG_SZ, (const BYTE *)&ObjectDescription[0], sizeof(ObjectDescription));

					// Create an "InprocServer32" key whose default value is the path of this DLL
					if (!RegCreateKeyEx(hKey2, &InprocServer32Name[0], 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &hkExtra, &disposition))
					{
						if (!RegSetValueEx(hkExtra, 0, 0, REG_SZ, (const BYTE *)&filename[0], lstrlen(&filename[0]) + 1))
						{
							// Create a "ThreadingModel" value set to the string "both" (ie, we don't need to restrict an
							// application to calling this DLL's functions only from a single thread. We don't use global
							// data in our IExample functions, so we're thread-safe)
							if (!RegSetValueEx(hkExtra, &ThreadingModel[0], 0, REG_SZ, (const BYTE *)&BothStr[0], sizeof(BothStr)))
							{
								result = 0;
								MessageBox(0, "Successfully registered IExample.DLL as a COM component.", &ObjectDescription[0], MB_OK);
							}
						}

			// Close all keys we opened/created.

						RegCloseKey(hkExtra);
					}

					RegCloseKey(hKey2);
				}

				RegCloseKey(hKey);
			}

			RegCloseKey(rootKey);
		}

		// If an error, make sure we clean everything up
		if (result)
		{
			cleanup();
			MessageBox(0, "Failed to register IExample.DLL as a COM component.", &ObjectDescription[0], MB_OK|MB_ICONEXCLAMATION);
		}
	}

	return(0);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions