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.