This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

 

  COM Tutorial Code
  Submitted by



I recently wrote this very simple/fast COM tutorial, since many wondered how you do multiple implementations of the same interface like for having different renders etc.

Currently browsing [COMTutorial.zip] (184,818 bytes) - [COMTutorial/COMTest/COMTest.cpp] - (1,269 bytes)

// COMTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

// Include com api #include <objbase.h>

// Include interface (That's all we need. COM needs no libs :) #include "..\include\icoolrender.h"

// Create usefull release macro #define COM_SAFE_RELEASE(x) if (x != NULL) x->Release(); x = NULL

// Create cool render pointer ICoolRender * pAnyRender = NULL;

int main(int argc, char* argv[]) { // Initialize COM CoInitialize(NULL); // First try the DirectX8 render if (FAILED(GetDirectX8Render(pAnyRender))) { MessageBox(NULL, "Make sure DirectX8 render component is installed", "ERROR!", MB_ICONERROR|MB_OK); return 1; }

// Run function pAnyRender->DoCool3DGame();

// Relase again. This is important or COM component won't get unloaded! COM_SAFE_RELEASE(pAnyRender);

// Try OpenGL render if (FAILED(GetOpenGLRender(pAnyRender))) { MessageBox(NULL, "Make sure OpenGL render component is installed", "ERROR!", MB_ICONERROR|MB_OK); return 1; }

// Run function pAnyRender->DoCool3DGame();

// Relase again. This is important or COM component won't get unloaded! COM_SAFE_RELEASE(pAnyRender); // Release COM CoUninitialize(); return 0; }

Currently browsing [COMTutorial.zip] (184,818 bytes) - [COMTutorial/COMTest/StdAfx.cpp] - (294 bytes)

// stdafx.cpp : source file that includes just the standard includes
//	COMTest.pch will be the pre-compiled header
//	stdafx.obj will contain the pre-compiled type information

#include "stdafx.h"

// TODO: reference any additional headers you need in STDAFX.H // and not in this file

Currently browsing [COMTutorial.zip] (184,818 bytes) - [COMTutorial/COMTest/StdAfx.h] - (667 bytes)

// stdafx.h : include file for standard system include files,
//  or project specific include files that are used frequently, but
//      are changed infrequently
//

#if !defined(AFX_STDAFX_H__40807C4B_690F_4E33_B669_63E6591DEE83__INCLUDED_)
#define AFX_STDAFX_H__40807C4B_690F_4E33_B669_63E6591DEE83__INCLUDED_

#if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000

// TODO: reference additional headers your program requires here //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_STDAFX_H__40807C4B_690F_4E33_B669_63E6591DEE83__INCLUDED_)

Currently browsing [COMTutorial.zip] (184,818 bytes) - [COMTutorial/DirectX8Render/DirectX8Render.cpp] - (5,920 bytes)

// DirectX8Render1.cpp: implementation of the CDirectX8Render class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "DirectX8Render.h"

// Include shared registry handling #include "..\shared\Registry.h"

/////////////////////////////////////////////////////////// // // Global variables // 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[] = "CoolRender DirectX8 component";

// Version-independent ProgID const char g_szVerIndProgID[] = "CoolRender.DirectX8";

// ProgID const char g_szProgID[] = "CoolRender.DirectX8.1";

////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CDirectX8Render::CDirectX8Render() : m_cRef(1) { // Exclusive increment (COM stuff) InterlockedIncrement(&g_cComponents); }

CDirectX8Render::~CDirectX8Render() { // Exclusive decrement (COM stuff) InterlockedDecrement(&g_cComponents); }

// Our only function void CDirectX8Render::DoCool3DGame() { MessageBox(NULL, "Hello from the DirectX8 render!", "Render", MB_ICONINFORMATION|MB_OK); }

// *** COM Stuff here *** // // IUnknown implementation // HRESULT __stdcall CDirectX8Render::QueryInterface(const IID& iid, void** ppv) { if (iid == IID_IUnknown) { *ppv = static_cast<ICoolRender*>(this) ; } else if (iid == IID_DIRECTX8RENDER) { *ppv = static_cast<ICoolRender*>(this) ; } else { *ppv = NULL ; return E_NOINTERFACE ; } reinterpret_cast<IUnknown*>(*ppv)->AddRef() ; return S_OK ; }

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

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

/////////////////////////////////////////////////////////// // // Class factory // class CFactory : public IClassFactory { public: // IUnknown virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) ; virtual ULONG __stdcall AddRef() ; virtual ULONG __stdcall Release() ;

// Interface IClassFactory virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv) ; virtual HRESULT __stdcall LockServer(BOOL bLock) ;

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

// Destructor ~CFactory() {}

private: long m_cRef ; } ;

// // Class factory IUnknown implementation // HRESULT __stdcall CFactory::QueryInterface(const IID& 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 ; }

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

// Cannot aggregate. if (pUnknownOuter != NULL) { return CLASS_E_NOAGGREGATION ; }

// Create component. CDirectX8Render* pA = new CDirectX8Render ; if (pA == NULL) { return E_OUTOFMEMORY ; }

// Get the requested interface. HRESULT hr = pA->QueryInterface(iid, ppv) ;

// Release the IUnknown pointer. // (If QueryInterface failed, component will delete itself.) pA->Release() ; return hr ; }

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

// * * * Exported functions * * * // // Server registration // STDAPI DllRegisterServer() { return RegisterServer(g_hModule, CLSID_DIRECTX8RENDER, g_szFriendlyName, g_szVerIndProgID, g_szProgID) ; }

// // Server unregistration // STDAPI DllUnregisterServer() { return UnregisterServer(CLSID_DIRECTX8RENDER, g_szVerIndProgID, g_szProgID) ; }

/////////////////////////////////////////////////////////// // // DLL module information // BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) { if (dwReason == DLL_PROCESS_ATTACH) { g_hModule = (struct HINSTANCE__ *)hModule ; } return TRUE; }

// // Can DLL unload now? // STDAPI DllCanUnloadNow() { if ((g_cComponents == 0) && (g_cServerLocks == 0)) { return S_OK ; } else { return S_FALSE ; } }

// // Get class factory // STDAPI DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv) { // Can we create this component? if (clsid != CLSID_DIRECTX8RENDER) { return CLASS_E_CLASSNOTAVAILABLE ; }

// Create class factory. CFactory* pFactory = new CFactory ; // Reference count set to 1 // in constructor if (pFactory == NULL) { return E_OUTOFMEMORY ; }

// Get requested interface. HRESULT hr = pFactory->QueryInterface(iid, ppv) ; pFactory->Release() ;

return hr ; }






Currently browsing [COMTutorial.zip] (184,818 bytes) - [COMTutorial/DirectX8Render/DirectX8Render.h] - (1,107 bytes)

// DirectX8Render.h: interface for the CDirectX8Render class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_DIRECTX8RENDER1_H__CA9AE665_9168_47A1_BCD9_BF258FF535B0__INCLUDED_)
#define AFX_DIRECTX8RENDER1_H__CA9AE665_9168_47A1_BCD9_BF258FF535B0__INCLUDED_

#if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // Include interface #include "..\include\ICoolRender.h"

// Make class that inherits from the cool render interface. // This is the actual implementation class CDirectX8Render : public ICoolRender { public: // Needed to implement IUnknown used by COM to acces your component virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv); virtual ULONG __stdcall AddRef(); virtual ULONG __stdcall Release(); // Constructor CDirectX8Render(); // Destructor virtual ~CDirectX8Render();

// Our only function void DoCool3DGame();

private:

long m_cRef; // Reference count for component };

#endif // !defined(AFX_DIRECTX8RENDER1_H__CA9AE665_9168_47A1_BCD9_BF258FF535B0__INCLUDED_)

Currently browsing [COMTutorial.zip] (184,818 bytes) - [COMTutorial/DirectX8Render/StdAfx.cpp] - (301 bytes)

// stdafx.cpp : source file that includes just the standard includes
//	DirectX8Render.pch will be the pre-compiled header
//	stdafx.obj will contain the pre-compiled type information

#include "stdafx.h"

// TODO: reference any additional headers you need in STDAFX.H // and not in this file

Currently browsing [COMTutorial.zip] (184,818 bytes) - [COMTutorial/DirectX8Render/StdAfx.h] - (802 bytes)

// stdafx.h : include file for standard system include files,
//  or project specific include files that are used frequently, but
//      are changed infrequently
//

#if !defined(AFX_STDAFX_H__1009A526_1E5F_47A9_A98F_9F99904E3B6A__INCLUDED_)
#define AFX_STDAFX_H__1009A526_1E5F_47A9_A98F_9F99904E3B6A__INCLUDED_

#if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000

// Insert your headers here #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include <windows.h>

// TODO: reference additional headers your program requires here //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_STDAFX_H__1009A526_1E5F_47A9_A98F_9F99904E3B6A__INCLUDED_)

Currently browsing [COMTutorial.zip] (184,818 bytes) - [COMTutorial/Include/ICoolRender.h] - (470 bytes)

// Shared interface for the CoolRender (tm) interface
// COM tutorial by odin@nukesoftware.com
// Use as you please :)

// Include com API (IUnknown etc)
#include <objbase.h>

// Include possible render GUIDS + their construction macros #include "RenderGUIDS.h"

// Render interface. Derives from IUnknown. (Don't be scared by interface. It's just a struct :) interface ICoolRender : IUnknown { // Our only function virtual void DoCool3DGame() = 0; };

Currently browsing [COMTutorial.zip] (184,818 bytes) - [COMTutorial/Include/RenderGUIDS.h] - (1,387 bytes)

// Render GUIDS the CoolRender (tm) interface
// COM tutorial by odin@nukesoftware.com
// Use as you please :)
// NOTE : GUIDS are generated with "Microsoft Visual Studio\Common\Tools\GUIDGEN.EXE"

// DirectX8 render
// Interface identifier
// {FDB516F0-2086-402d-9276-79F867925BA4}
static const IID IID_DIRECTX8RENDER = 
{ 0xfdb516f0, 0x2086, 0x402d, { 0x92, 0x76, 0x79, 0xf8, 0x67, 0x92, 0x5b, 0xa4 } };

// Class identifier // {B037CE71-3A01-4cda-8334-FA6096CA1C3D} static const CLSID CLSID_DIRECTX8RENDER = { 0xb037ce71, 0x3a01, 0x4cda, { 0x83, 0x34, 0xfa, 0x60, 0x96, 0xca, 0x1c, 0x3d } };

// OpenGL render // Interface identifier // {FE01952B-8278-48c9-B3EA-7B9187219F9A} static const IID IID_OPENGLRENDER = { 0xfe01952b, 0x8278, 0x48c9, { 0xb3, 0xea, 0x7b, 0x91, 0x87, 0x21, 0x9f, 0x9a } };

// Class identifier // {BD38F132-DEB2-4677-9CD2-570EED2CE5FE} static const CLSID CLSID_OPENGLRENDER = { 0xbd38f132, 0xdeb2, 0x4677, { 0x9c, 0xd2, 0x57, 0xe, 0xed, 0x2c, 0xe5, 0xfe } };

// Macro for easy creation of DirectX Render #define GetDirectX8Render(pRender) ::CoCreateInstance(CLSID_DIRECTX8RENDER, NULL, CLSCTX_INPROC_SERVER, IID_DIRECTX8RENDER, (void**)&pRender)

// Macro for easy creation of OpenGL Render #define GetOpenGLRender(pRender) ::CoCreateInstance(CLSID_OPENGLRENDER, NULL, CLSCTX_INPROC_SERVER, IID_OPENGLRENDER, (void**)&pRender)

Currently browsing [COMTutorial.zip] (184,818 bytes) - [COMTutorial/OpenGLRender/OpenGLRender.cpp] - (5,880 bytes)

// OpenGLRender1.cpp: implementation of the COpenGLRender class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "OpenGLRender.h"

// Include shared registry handling #include "..\shared\Registry.h"

/////////////////////////////////////////////////////////// // // Global variables // 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[] = "CoolRender OpenGL component";

// Version-independent ProgID const char g_szVerIndProgID[] = "CoolRender.OpenGL";

// ProgID const char g_szProgID[] = "CoolRender.OpenGL.1";

// Our only function void COpenGLRender::DoCool3DGame() { MessageBox(NULL, "Hello from the OpenGL render!", "Render", MB_ICONINFORMATION|MB_OK); }

////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// COpenGLRender::COpenGLRender() : m_cRef(1) { // Exclusive increment (COM stuff) InterlockedIncrement(&g_cComponents); }

COpenGLRender::~COpenGLRender() { // Exclusive decrement (COM stuff) InterlockedDecrement(&g_cComponents); }

// *** COM Stuff here *** // // IUnknown implementation // HRESULT __stdcall COpenGLRender::QueryInterface(const IID& iid, void** ppv) { if (iid == IID_IUnknown) { *ppv = static_cast<ICoolRender*>(this) ; } else if (iid == IID_OPENGLRENDER) { *ppv = static_cast<ICoolRender*>(this) ; } else { *ppv = NULL ; return E_NOINTERFACE ; } reinterpret_cast<IUnknown*>(*ppv)->AddRef() ; return S_OK ; }

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

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

/////////////////////////////////////////////////////////// // // Class factory // class CFactory : public IClassFactory { public: // IUnknown virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) ; virtual ULONG __stdcall AddRef() ; virtual ULONG __stdcall Release() ;

// Interface IClassFactory virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv) ; virtual HRESULT __stdcall LockServer(BOOL bLock) ;

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

// Destructor ~CFactory() {}

private: long m_cRef ; } ;

// // Class factory IUnknown implementation // HRESULT __stdcall CFactory::QueryInterface(const IID& 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 ; }

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

// Cannot aggregate. if (pUnknownOuter != NULL) { return CLASS_E_NOAGGREGATION ; }

// Create component. COpenGLRender* pA = new COpenGLRender ; if (pA == NULL) { return E_OUTOFMEMORY ; }

// Get the requested interface. HRESULT hr = pA->QueryInterface(iid, ppv) ;

// Release the IUnknown pointer. // (If QueryInterface failed, component will delete itself.) pA->Release() ; return hr ; }

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

// * * * Exported functions * * * // // Server registration // STDAPI DllRegisterServer() { return RegisterServer(g_hModule, CLSID_OPENGLRENDER, g_szFriendlyName, g_szVerIndProgID, g_szProgID) ; }

// // Server unregistration // STDAPI DllUnregisterServer() { return UnregisterServer(CLSID_OPENGLRENDER, g_szVerIndProgID, g_szProgID) ; }

/////////////////////////////////////////////////////////// // // DLL module information // BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) { if (dwReason == DLL_PROCESS_ATTACH) { g_hModule = (struct HINSTANCE__ *)hModule ; } return TRUE; }

// // Can DLL unload now? // STDAPI DllCanUnloadNow() { if ((g_cComponents == 0) && (g_cServerLocks == 0)) { return S_OK ; } else { return S_FALSE ; } }

// // Get class factory // STDAPI DllGetClassObject(const CLSID& clsid, const IID& iid, void** ppv) { // Can we create this component? if (clsid != CLSID_OPENGLRENDER) { return CLASS_E_CLASSNOTAVAILABLE ; }

// Create class factory. CFactory* pFactory = new CFactory ; // Reference count set to 1 // in constructor if (pFactory == NULL) { return E_OUTOFMEMORY ; }

// Get requested interface. HRESULT hr = pFactory->QueryInterface(iid, ppv) ; pFactory->Release() ;

return hr ; }






Currently browsing [COMTutorial.zip] (184,818 bytes) - [COMTutorial/OpenGLRender/OpenGLRender.h] - (1,079 bytes)

// OpenGLRender.h: interface for the COpenGLRender class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_OPENGLRENDER1_H__EE377BF3_CF74_4A3C_851F_04523308980B__INCLUDED_)
#define AFX_OPENGLRENDER1_H__EE377BF3_CF74_4A3C_851F_04523308980B__INCLUDED_

#if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // Include interface #include "..\include\ICoolRender.h"

// Make class that inherits from the cool render interface. // This is the actual implementation class COpenGLRender : public ICoolRender { public: // Needed to implement IUnknown used by COM to acces your component virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv); virtual ULONG __stdcall AddRef(); virtual ULONG __stdcall Release(); // Constructor COpenGLRender(); // Destructor virtual ~COpenGLRender();

// Our only function void DoCool3DGame();

private:

// Reference counter long m_cRef; };

#endif // !defined(AFX_OPENGLRENDER1_H__EE377BF3_CF74_4A3C_851F_04523308980B__INCLUDED_)

Currently browsing [COMTutorial.zip] (184,818 bytes) - [COMTutorial/OpenGLRender/StdAfx.cpp] - (299 bytes)

// stdafx.cpp : source file that includes just the standard includes
//	OpenGLRender.pch will be the pre-compiled header
//	stdafx.obj will contain the pre-compiled type information

#include "stdafx.h"

// TODO: reference any additional headers you need in STDAFX.H // and not in this file

Currently browsing [COMTutorial.zip] (184,818 bytes) - [COMTutorial/OpenGLRender/StdAfx.h] - (802 bytes)

// stdafx.h : include file for standard system include files,
//  or project specific include files that are used frequently, but
//      are changed infrequently
//

#if !defined(AFX_STDAFX_H__647553AE_49DA_44B1_A8E3_49257E2B5875__INCLUDED_)
#define AFX_STDAFX_H__647553AE_49DA_44B1_A8E3_49257E2B5875__INCLUDED_

#if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000

// Insert your headers here #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include <windows.h>

// TODO: reference additional headers your program requires here //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_STDAFX_H__647553AE_49DA_44B1_A8E3_49257E2B5875__INCLUDED_)

Currently browsing [COMTutorial.zip] (184,818 bytes) - [COMTutorial/Shared/REGISTRY.CPP] - (6,381 bytes)

//
// Registry.cpp
//

#include <objbase.h>
#include <assert.h>

#include "Registry.h"

//////////////////////////////////////////////////////// // // Internal helper functions prototypes // // Set the given key and its value. BOOL setKeyAndValue(const char* pszPath, const char* szSubkey, const char* szValue) ;

// Convert a CLSID into a char string. void CLSIDtochar(const CLSID& clsid, char* szCLSID, int length) ;

// Delete szKeyChild and all of its descendents. LONG recursiveDeleteKey(HKEY hKeyParent, const char* szKeyChild) ;

//////////////////////////////////////////////////////// // // Constants // // Size of a CLSID as a string const int CLSID_STRING_SIZE = 39 ;

///////////////////////////////////////////////////////// // // Public function implementation // // // 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 { // Get server location. 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 ; }

/////////////////////////////////////////////////////////// // // Internal helper functions // // Convert a CLSID to a char string. void CLSIDtochar(const CLSID& clsid, char* szCLSID, int length) { assert(length >= 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, length) ;

// Free memory. CoTaskMemFree(wszCLSID) ; }

// // Delete a key and all of its descendents. // LONG recursiveDeleteKey(HKEY hKeyParent, // Parent of key to delete const char* lpszKeyChild) // Key to delete { // Open the child. HKEY hKeyChild ; LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyChild, 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, lpszKeyChild) ; }

// // Create a key and set its value. // - This helper function was borrowed and modifed from // Kraig Brockschmidt's book Inside OLE. // 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 ; }

Currently browsing [COMTutorial.zip] (184,818 bytes) - [COMTutorial/Shared/REGISTRY.H] - (799 bytes)

#ifndef __Registry_H__
#define __Registry_H__
//
// Registry.h
//   - Helper functions registering and unregistering a component.
//

// This function will register a component in the Registry.
// The component calls this function from its DllRegisterServer function.
HRESULT RegisterServer(HMODULE hModule, 
                       const CLSID& clsid, 
                       const char* szFriendlyName,
                       const char* szVerIndProgID,
                       const char* szProgID) ;

// This function will unregister a component. Components // call this function from their DllUnregisterServer function. HRESULT UnregisterServer(const CLSID& clsid, const char* szVerIndProgID, const char* szProgID) ;

#endif

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

 

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.