C++手动实现 com

#pragma once
#include "unknwn.h"
class SCPIFactory :public IClassFactory
{
public:
 SCPIFactory(void);
 ~SCPIFactory(void);
public:
 //IUnknow Method
 STDMETHODIMP QueryInterface(REFIID,void**);
 STDMETHODIMP_(ULONG) AddRef();
 STDMETHODIMP_(ULONG) Release();
 //IClassFactory Method
 STDMETHODIMP CreateInstance(IUnknown * ,REFIID ,void **);
 STDMETHODIMP LockServer(BOOL fLock);
private:
 LONG m_cRef;
};

import "oaidl.idl";import "ocidl.idl";[uuid(011E50FF-873E-4FB2-86D5-296BFFCB47C4),object, dual,//这个标识说明定义的是双接口pointer_default(unique)]interface ISCPI : IDispatch//必须从IDispatch接口派生{[id(1)]HRESULT add([in]int a, [in]int b, [out]int* c);};[uuid(681B4072-519F-43B2-A356-055CD5B9FFC1),version(1.0),]library SCPILib{importlib("stdole32.tlb");importlib("stdole2.tlb");[uuid(050779DB-3DF0-49C4-9CCF-C92BD363DB82)]coclass SCPIImp//com类{[default] interface ISCPI;};};

SCPIX.idl

SCPIImp.h

#pragma once
#include "SCPI_h.h"

class SCPIImp :public ISCPI
{
public:
	SCPIImp(void);
	~SCPIImp(void);

public:

	//IUnknown接口
	STDMETHOD(QueryInterface)(REFIID riid, void **ppv);//接口查询
	STDMETHOD_(ULONG, AddRef)();//增加一个引用
	STDMETHOD_(ULONG, Release)();//减少一个引用

	// IDispatch
	STDMETHOD(GetTypeInfoCount)(UINT * pit);
	STDMETHOD(GetTypeInfo)(UINT it,LCID lcid,ITypeInfo **ppti);
	STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR ** pNames, UINT nNames, LCID lcid, DISPID * pdispids);
	STDMETHOD(Invoke)(DISPID id, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pd, VARIANT * pVarResult, EXCEPINFO * pe, UINT *pu);

	//ISCPI
	STDMETHOD(add)(int a, int b, int *c);

private:
	ULONG m_cRef; //引用计数
};

SCPImp.cpp
#include "SCPIImp.h"


SCPIImp::SCPIImp(void)
{
	m_cRef = 0;
}


SCPIImp::~SCPIImp(void)
{
}

//IUnknown接口
STDMETHODIMP SCPIImp::QueryInterface(REFIID riid, void **ppv)
{
	if(riid == IID_ISCPI)
		*ppv = static_cast<ISCPI *>(this);
	else if(riid == IID_IUnknown)
		*ppv = static_cast<ISCPI *>(this);
	else if(riid == IID_IDispatch)
		*ppv = reinterpret_cast<IDispatch *>(this);
	else {
		*ppv = 0;
		return E_NOINTERFACE;
	}

	reinterpret_cast<IUnknown *>(*ppv)->AddRef();
	return S_OK;
}

STDMETHODIMP_(ULONG) SCPIImp::AddRef()
{
	return ++m_cRef;
}

STDMETHODIMP_(ULONG) SCPIImp::Release()
{
	ULONG res = --m_cRef; 
	if(res == 0)
		delete this;
	return res;
}

// IDispatch
STDMETHODIMP SCPIImp::Invoke(DISPID id, REFIID riid, LCID lcid, 
	WORD wFlags, DISPPARAMS *pd, 
	VARIANT * pVarResult, EXCEPINFO * pe, UINT *pu)
{
	if(riid == IID_ISCPI)
	{  
		if(1 == id)
			return add(pd->rgvarg->iVal, pd->rgvarg->iVal , &pVarResult->intVal);
		else 
			return E_FAIL;
	}
	else 
		return E_NOINTERFACE;
}


STDMETHODIMP SCPIImp::GetIDsOfNames(REFIID riid, OLECHAR ** pNames, 
	UINT nNames, LCID lcid, DISPID * pdispids)
{
	return E_NOTIMPL;
}

STDMETHODIMP SCPIImp::GetTypeInfo(UINT it,LCID lcid,ITypeInfo **ppti)
{
	return E_NOTIMPL;
}

STDMETHODIMP SCPIImp::GetTypeInfoCount(UINT * pit)
{
	return E_NOTIMPL;
}

STDMETHODIMP SCPIImp::add(int a, int b, int *c)
{
	*c = a + b;
	return S_OK;
}
#pragma once
#include "unknwn.h"
class SCPIFactory :public IClassFactory
{
public:
 SCPIFactory(void);
 ~SCPIFactory(void);
public:
 //IUnknow Method
 STDMETHODIMP QueryInterface(REFIID,void**);
 STDMETHODIMP_(ULONG) AddRef();
 STDMETHODIMP_(ULONG) Release();
 //IClassFactory Method
 STDMETHODIMP CreateInstance(IUnknown * ,REFIID ,void **);
 STDMETHODIMP LockServer(BOOL fLock);
private:
 LONG m_cRef;
};

#include "SCPIFactory.h"
#include "SCPIImp.h"
#include "SCPI_h.h"
extern LONG g_cObjectAndLocks;
SCPIFactory::SCPIFactory(void)
{
 m_cRef = 0;
}
SCPIFactory::~SCPIFactory(void)
{
 
}
STDMETHODIMP_(ULONG) SCPIFactory::AddRef(void)
{
 return InterlockedIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG) SCPIFactory::Release(void)
{
 return ::InterlockedDecrement(&m_cRef);
}
STDMETHODIMP SCPIFactory::QueryInterface(REFIID riid,void ** ppv)
{
 *ppv = NULL;
 if(riid == IID_IUnknown || riid == IID_IClassFactory || riid == IID_IDispatch)
 {
  *ppv = static_cast<IClassFactory *>(this);
  reinterpret_cast<IUnknown*>(*ppv)->AddRef();
  return S_OK;
 }
 else
  return (*ppv=0),E_NOINTERFACE;
}
STDMETHODIMP SCPIFactory::CreateInstance(IUnknown * pUnkOuter,REFIID riid,void ** ppv)
{
 *ppv=NULL;
 if(pUnkOuter != NULL)
  return CLASS_E_NOAGGREGATION;
 SCPIImp * pSCPIImp = new SCPIImp();
 if(pSCPIImp == NULL)
  return E_OUTOFMEMORY;
 HRESULT hr = pSCPIImp->QueryInterface(riid,ppv);
 if(FAILED(hr))
  delete pSCPIImp;
 return hr;
}
STDMETHODIMP SCPIFactory::LockServer(BOOL fLock)
{
 if(fLock)
  ::InterlockedIncrement(&g_cObjectAndLocks);
 else
  ::InterlockedDecrement(&g_cObjectAndLocks);
 return NOERROR;
}
#include "SCPIImp.h"
#include "SCPIFactory.h"
#include "SCPI_h.h"
#include "SCPI_i.c"


LONG g_cObjectAndLocks=0;

const char * g_RegTable[][3]={
	{"CLSID//{050779DB-3DF0-49C4-9CCF-C92BD363DB82}",
	0,
	"SCPIX"},
	{"CLSID//{050779DB-3DF0-49C4-9CCF-C92BD363DB82}//InprocServer32",
	0,
	(const char * )-1},
	{"CLSID//{050779DB-3DF0-49C4-9CCF-C92BD363DB82}//ProgID",
	0,
	"SCPIX.2"},
	{"SCPIX.SCPI.2",
	0,
	"SCPI"},
	{"SCPIX.SCPI.2//CLSID",
	0,
	"{050779DB-3DF0-49C4-9CCF-C92BD363DB82}"},
};

HINSTANCE  g_hinstDll;
BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
	g_hinstDll = (HINSTANCE)hModule;
	return TRUE;
}

STDAPI DllUnregisterServer(void)//从注册表中注销
{
	HRESULT hr = S_OK;
	char szFileName [MAX_PATH];
	::GetModuleFileName(g_hinstDll,szFileName,MAX_PATH);

	int nEntries = sizeof(g_RegTable) / sizeof(*g_RegTable);

	for(int i = 0; SUCCEEDED(hr) && i < nEntries; i ++)
	{
		const char * pszKeyName = g_RegTable[i][0];
		long err = ::RegDeleteKey(HKEY_CLASSES_ROOT, pszKeyName);
		if( err != ERROR_SUCCESS)
			hr = S_FALSE;
	}

	return hr;
}

STDAPI DllRegisterServer(void)//注册服务器
{
	HRESULT hr = S_OK;
	char szFileName [MAX_PATH];
	::GetModuleFileName(g_hinstDll, szFileName, MAX_PATH);

	int nEntries = sizeof(g_RegTable) / sizeof(*g_RegTable);
	for(int i = 0 ; SUCCEEDED(hr) && i < nEntries; i ++)
	{
		const char * pszKeyName = g_RegTable[i][0];
		const char * pszValueName = g_RegTable[i][1];
		const char * pszValue = g_RegTable[i][2];

		if(pszValue == (const char *) - 1)
		{
			pszValue = szFileName;
		}

		HKEY hkey;
		long err = ::RegCreateKey(HKEY_CLASSES_ROOT, pszKeyName, &hkey);
		if(err == ERROR_SUCCESS)
		{
			err = ::RegSetValueEx( hkey,
				pszValueName,
				0,
				REG_SZ,
				( const BYTE*)pszValue,
				( strlen(pszValue)+1 ) );
			::RegCloseKey(hkey);
		}
		if( err != ERROR_SUCCESS)
		{
			::DllUnregisterServer();
			hr = E_FAIL;
		}

	}
	return hr;
}

STDAPI DllGetClassObject(REFCLSID rclsid ,REFIID riid,void **ppv)
{
	if(rclsid == CLSID_SCPIImp)
	{
		SCPIFactory *pFactory = new SCPIFactory;
		if(pFactory == NULL)
			return E_OUTOFMEMORY;
		HRESULT hr = pFactory->QueryInterface(riid, ppv);
		return hr;
	}

	return CLASS_E_CLASSNOTAVAILABLE;
}

STDAPI DllCanUnloadNow(void)
{
	return ( g_cObjectAndLocks == 0 ) 
		? S_OK : E_FAIL;
}
#include "SCPIFactory.h"
#include "SCPIImp.h"
#include "SCPI_h.h"

extern LONG g_cObjectAndLocks;

SCPIFactory::SCPIFactory(void)
{
	m_cRef = 0;
}

SCPIFactory::~SCPIFactory(void)
{
	
}

STDMETHODIMP_(ULONG) SCPIFactory::AddRef(void)
{
	return InterlockedIncrement(&m_cRef);
}

STDMETHODIMP_(ULONG) SCPIFactory::Release(void)
{
	return ::InterlockedDecrement(&m_cRef);
}

STDMETHODIMP SCPIFactory::QueryInterface(REFIID riid,void ** ppv)
{
	*ppv = NULL;
	if(riid == IID_IUnknown || riid == IID_IClassFactory || riid == IID_IDispatch)
	{
		*ppv = static_cast<IClassFactory *>(this);
		reinterpret_cast<IUnknown*>(*ppv)->AddRef();
		return S_OK;
	}
	else
		return (*ppv=0),E_NOINTERFACE;
}

STDMETHODIMP SCPIFactory::CreateInstance(IUnknown * pUnkOuter,REFIID riid,void ** ppv)
{
	*ppv=NULL;

	if(pUnkOuter != NULL)
		return CLASS_E_NOAGGREGATION;

	SCPIImp * pSCPIImp = new SCPIImp();
	if(pSCPIImp == NULL)
		return E_OUTOFMEMORY;

	HRESULT hr = pSCPIImp->QueryInterface(riid,ppv);

	if(FAILED(hr))
		delete pSCPIImp;

	return hr;
}

STDMETHODIMP SCPIFactory::LockServer(BOOL fLock)
{
	if(fLock)
		::InterlockedIncrement(&g_cObjectAndLocks);
	else 
		::InterlockedDecrement(&g_cObjectAndLocks);
	return NOERROR;

}



猜你喜欢

转载自blog.csdn.net/max2009verygood/article/details/80653537
今日推荐