で作成した.idlファイルも必要になります。
このソースコードでは、.idlファイルの名前をichigocom4_if.idlとし、
自動生成されるichigocom4_if.hとichigocom4_if_i.cを利用しています。
コード全体をコピーしたい場合は、著作権表示といちごパックへのリンクを残した形でコピーしてください。
サンプルコードとしてその一部を利用、参照いただくぶんには問題ありません。
//
// Copyright (c) 2016 The Ichigopack Project (http://ichigopack.net/).
//
#include "ichigocomhelper.h"
#include <olectl.h>
#include <sstream>
#include <iomanip>
#include <string.h>
#include <new>
#include <exception>
#include <vector>
#include "ichigocom4_if.h"
#define LOGFILENAME L"c:\\tmp\\ichigo4.txt"
#define PROGID_Ichigo4 L"Ichigo4.Logwriter"
// {287AF1C7-7618-4C81-952C-B70238A474CB}
static const GUID CLSID_Ichigo4 =
{ 0x287af1c7, 0x7618, 0x4c81, { 0x95, 0x2c, 0xb7, 0x2, 0x38, 0xa4, 0x74, 0xcb } };
class CIchigo4Factory : public IClassFactory
{
public:
CIchigo4Factory();
~CIchigo4Factory();
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, LPVOID* ppv );
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
// IClassFactory
HRESULT STDMETHODCALLTYPE CreateInstance( IUnknown* pUnkOuter,
REFIID riid, LPVOID* ppv );
HRESULT STDMETHODCALLTYPE LockServer( BOOL fLock );
};
class CIchigo4 : public IIchigo4
{
public:
CIchigo4();
~CIchigo4();
HRESULT Init();
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, LPVOID* ppv );
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
// IDispatch
HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pcTInfo);
HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid,
ITypeInfo** ppTInfo);
HRESULT STDMETHODCALLTYPE GetIDsOfNames(
REFIID riidNull, LPOLESTR* rgszNames, UINT cNames,
LCID lcid, DISPID* rgDispId);
HRESULT STDMETHODCALLTYPE Invoke(
DISPID dispIdMember, REFIID riidNull, LCID lcid,
WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
EXCEPINFO* pExcepInfo, UINT* puArgErr);
// IIchigo4
HRESULT STDMETHODCALLTYPE Write(BSTR bstrWrite);
private:
LONG m_nRef;
ITypeInfo* m_pti;
};
/***********************************************************************/
HRESULT RunRegisterServer( HINSTANCE hinstEXE,
bool per_user_flag ) throw()
{
try {
std::wstring wstrName = suppGetModuleFileName( hinstEXE );
HKEY hkeyRoot;
std::wstring wstrSubkey;
std::wstring wstrValue;
LONG regerr;
// Coclass
wstrSubkey = suppGetRegKeyCLSID( &hkeyRoot, per_user_flag, CLSID_Ichigo4,
L"LocalServer32" );
if ( wstrSubkey.empty() || wstrName.empty() ) {
return E_FAIL;
}
regerr = suppRegSetStringW(hkeyRoot, wstrSubkey.c_str(), NULL,
wstrName.c_str() );
if ( regerr != ERROR_SUCCESS ) {
return SELFREG_E_CLASS;
}
// ProgID
wstrSubkey = suppGetRegKeyCLSID( &hkeyRoot, per_user_flag, CLSID_Ichigo4,
L"ProgID" );
if ( wstrSubkey.empty() ) {
return E_FAIL;
}
regerr = suppRegSetStringW(hkeyRoot, wstrSubkey.c_str(), NULL,
PROGID_Ichigo4 );
if ( regerr != ERROR_SUCCESS ) {
return SELFREG_E_CLASS;
}
wstrSubkey = suppGetRegKeyProgID( &hkeyRoot, per_user_flag,
PROGID_Ichigo4, L"CLSID" );
wstrValue = suppGuidToString( CLSID_Ichigo4, true );
if ( wstrSubkey.empty() || wstrValue.empty() ) {
return E_FAIL;
}
regerr = suppRegSetStringW(hkeyRoot, wstrSubkey.c_str(), NULL,
wstrValue.c_str() );
if ( regerr != ERROR_SUCCESS ) {
return SELFREG_E_CLASS;
}
// TypeLib
ITypeLib* ptl = NULL;
HRESULT hr;
hr = LoadTypeLib( wstrName.c_str(), &ptl );
if ( SUCCEEDED(hr) ) {
if ( per_user_flag ) {
hr = RegisterTypeLibForUser( ptl, (OLECHAR*) wstrName.c_str(), NULL );
} else {
hr = RegisterTypeLib( ptl, wstrName.c_str(), NULL );
}
ptl->Release();
}
if ( FAILED(hr) ) {
return hr;
}
} catch ( const std::exception& ) {
return E_FAIL;
}
return S_OK;
}
HRESULT RunUnregisterServer( bool per_user_flag ) throw()
{
try {
HKEY hkeyRoot;
std::wstring wstrSubkey = suppGetRegKeyCLSID( &hkeyRoot, per_user_flag,
CLSID_Ichigo4, NULL );
LONG regerr;
if ( wstrSubkey.empty() ) {
return E_FAIL;
}
regerr = suppRegRemoveKeyW(hkeyRoot, wstrSubkey.c_str());
if ( regerr != ERROR_SUCCESS ) {
return SELFREG_E_CLASS;
}
HRESULT hr;
#if defined(WIN64) || defined(_WIN64)
const SYSKIND syskind = SYS_WIN64;
#else
const SYSKIND syskind = SYS_WIN32;
#endif
if ( per_user_flag ) {
hr = UnRegisterTypeLibForUser( LIBID_Ichigo4TypeLib, 1, 0, LOCALE_NEUTRAL,
syskind );
} else {
hr = UnRegisterTypeLib( LIBID_Ichigo4TypeLib, 1, 0, LOCALE_NEUTRAL,
syskind );
}
if ( FAILED(hr) ) {
return hr;
}
} catch ( const std::exception& ) {
return E_FAIL;
}
return S_OK;
}
/***********************************************************************/
void LockServerProcess()
{
CoAddRefServerProcess();
}
void UnlockServerProcess()
{
if ( CoReleaseServerProcess() == 0 ) {
PostQuitMessage(0);
}
}
HRESULT RunEmbedding( HINSTANCE hinstEXE )
{
CIchigo4Factory factory;
HRESULT hr;
DWORD dwRegister = 0;
hr = CoRegisterClassObject(
CLSID_Ichigo4, static_cast<IClassFactory*>(&factory),
CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &dwRegister);
if ( FAILED(hr) ) {
return hr;
}
hr = CoResumeClassObjects();
if ( SUCCEEDED(hr) ) {
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
CoRevokeClassObject(dwRegister);
return hr;
}
EXTERN_C int APIENTRY WinMain( HINSTANCE hinstEXE, HINSTANCE hinstNull,
LPSTR lpCmdLine, int nCmdShow )
{
HRESULT hr;
hr = CoInitialize(NULL);
if ( FAILED(hr) ) {
MessageBoxW( NULL, L"CoInitialize()", L"IchigoCom4", MB_OK );
return 1;
}
const char* pcommand;
bool invalid_command = false;
pcommand = strchr(lpCmdLine, '/');
if ( pcommand == NULL ) {
pcommand = strchr(lpCmdLine, '-');
}
if ( pcommand == NULL ) {
invalid_command = true;
}
if ( pcommand != NULL ) {
char* ptoken = _strdup(pcommand + 1);
if ( ptoken == NULL ) {
hr = E_OUTOFMEMORY;
} else {
strtok( ptoken, " \t\r\n" );
if ( _stricmp(ptoken, "embedding") == 0 ) {
hr = RunEmbedding( hinstEXE );
} else if ( _stricmp(ptoken, "regserver") == 0 ) {
hr = RunRegisterServer( hinstEXE, false );
} else if ( _stricmp(ptoken, "regserverperuser") == 0 ) {
hr = RunRegisterServer( hinstEXE, true );
} else if ( _stricmp(ptoken, "unregserver") == 0 ) {
hr = RunUnregisterServer( false );
} else if ( _stricmp(ptoken, "unregserverperuser") == 0 ) {
hr = RunUnregisterServer( true );
} else {
invalid_command = true;
}
free(ptoken);
}
}
CoUninitialize();
if ( invalid_command ) {
MessageBoxW( NULL, L"ichigocom4 /regserver|/unregserver", L"IchigoCom4",
MB_OK );
return 1;
}
if ( FAILED(hr) ) {
std::wostringstream wos;
wos << L"error " << std::hex << std::setfill(L'0') << std::setw(8) << hr;
MessageBoxW( NULL, wos.str().c_str(), L"IchigoCom4", MB_OK );
return 1;
}
return 0;
}
/***********************************************************************/
CIchigo4Factory::CIchigo4Factory()
{
}
CIchigo4Factory::~CIchigo4Factory()
{
}
HRESULT STDMETHODCALLTYPE CIchigo4Factory::QueryInterface( REFIID riid,
LPVOID* ppv )
{
*ppv = NULL;
if ( riid == IID_IUnknown || riid == IID_IClassFactory ) {
*ppv = static_cast<IClassFactory*>( this );
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE CIchigo4Factory::AddRef()
{
return 1;
}
ULONG STDMETHODCALLTYPE CIchigo4Factory::Release()
{
return 1;
}
HRESULT STDMETHODCALLTYPE CIchigo4Factory::CreateInstance(
IUnknown* pUnkOuter, REFIID riid, LPVOID* ppv )
{
*ppv = NULL;
if ( pUnkOuter != NULL ) {
return CLASS_E_NOAGGREGATION;
}
CIchigo4* pObj = new (std::nothrow) CIchigo4();
if ( pObj == NULL ) {
return E_OUTOFMEMORY;
}
HRESULT hr;
hr = pObj->Init();
if ( SUCCEEDED(hr) ) {
hr = pObj->QueryInterface( riid, ppv );
}
pObj->Release();
return hr;
}
HRESULT STDMETHODCALLTYPE CIchigo4Factory::LockServer( BOOL fLock )
{
if ( fLock ) {
LockServerProcess();
} else {
UnlockServerProcess();
}
return S_OK;
}
/***********************************************************************/
CIchigo4::CIchigo4() : m_nRef(1), m_pti(NULL)
{
LockServerProcess();
}
CIchigo4::~CIchigo4()
{
if ( m_pti != NULL ) {
m_pti->Release();
}
UnlockServerProcess();
}
HRESULT CIchigo4::Init()
{
HRESULT hr;
ITypeLib* ptl = NULL;
hr = LoadRegTypeLib( LIBID_Ichigo4TypeLib, 1, 0, LOCALE_NEUTRAL, &ptl );
if ( SUCCEEDED(hr) ) {
hr = ptl->GetTypeInfoOfGuid( IID_IIchigo4, &m_pti );
ptl->Release();
}
return hr;
}
HRESULT STDMETHODCALLTYPE CIchigo4::QueryInterface( REFIID riid,
LPVOID* ppv )
{
*ppv = NULL;
if ( riid == IID_IUnknown || riid == IID_IDispatch ||
riid == IID_IIchigo4 ) {
*ppv = static_cast<IIchigo4*>( this );
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE CIchigo4::AddRef()
{
return ++m_nRef;
}
ULONG STDMETHODCALLTYPE CIchigo4::Release()
{
if ( --m_nRef == 0 ) {
delete this;
return 0;
}
return m_nRef;
}
HRESULT STDMETHODCALLTYPE CIchigo4::GetTypeInfoCount(UINT* pcTInfo)
{
*pcTInfo = (m_pti != NULL) ? 1 : 0;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CIchigo4::GetTypeInfo(UINT iTInfo, LCID lcid,
ITypeInfo** ppTInfo)
{
*ppTInfo = NULL;
if ( iTInfo != 0 ) {
return DISP_E_BADINDEX;
}
*ppTInfo = m_pti;
m_pti->AddRef();
return S_OK;
}
HRESULT STDMETHODCALLTYPE CIchigo4::GetIDsOfNames(
REFIID riidNull, LPOLESTR* rgszNames, UINT cNames,
LCID lcid, DISPID* rgDispId)
{
if ( riidNull != IID_NULL ) {
return DISP_E_UNKNOWNINTERFACE;
}
return DispGetIDsOfNames( m_pti, rgszNames, cNames, rgDispId );
}
HRESULT STDMETHODCALLTYPE CIchigo4::Invoke(
DISPID dispIdMember, REFIID riidNull, LCID lcid,
WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
EXCEPINFO* pExcepInfo, UINT* puArgErr)
{
if ( riidNull != IID_NULL ) {
return DISP_E_UNKNOWNINTERFACE;
}
return DispInvoke(
this, m_pti, dispIdMember, wFlags, pDispParams,
pVarResult, pExcepInfo, puArgErr );
}
HRESULT STDMETHODCALLTYPE CIchigo4::Write( BSTR bstrWrite )
{
try {
UINT cLen = SysStringLen(bstrWrite);
std::vector<char> buf;
int cLenMB;
cLenMB = WideCharToMultiByte( CP_ACP, 0, bstrWrite, cLen, NULL, 0, NULL,
NULL );
if ( cLenMB <= 0 ) {
return E_FAIL;
}
buf.resize( cLenMB );
cLenMB = WideCharToMultiByte( CP_ACP, 0, bstrWrite, cLen, &buf[0],
buf.size(), NULL, NULL );
if ( cLenMB <= 0 ) {
return E_FAIL;
}
return suppLogFileAppendW( LOGFILENAME, &buf[0], cLenMB );
} catch ( const std::exception& ) {
return E_FAIL;
}
}