|
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.
|