コード全体をコピーしたい場合は、著作権表示といちごパックへのリンクを残した形でコピーしてください。
サンプルコードとしてその一部を利用、参照いただくぶんには問題ありません。
//
// Copyright (c) 2016 The Ichigopack Project (http://ichigopack.net/).
//
#include "ichigocomhelper.h"
#include <olectl.h>
#include <iostream>
#include <new>
#include <exception>
#include <vector>
#define LOGFILENAME L"c:\\tmp\\ichigo3.txt"
#define PROGID_Ichigo3 L"Ichigo3.Logwriter"
#define DISPID_Ichigo3_Write 1
#define ICHIGO_LOGLINE_MAX 80
HINSTANCE g_hinstDLL = NULL;
LONG g_nLockDLL = 0;
// {316E547D-CBB4-495F-A839-DC4414842C8F}
const CLSID CLSID_Ichigo3 =
{ 0x316e547d, 0xcbb4, 0x495f, { 0xa8, 0x39, 0xdc, 0x44, 0x14, 0x84, 0x2c, 0x8f } };
#define AppID_Ichigo3 CLSID_Ichigo3
class CIchigo3Factory : public IClassFactory
{
public:
CIchigo3Factory();
~CIchigo3Factory();
// 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 );
private:
LONG m_nRef;
};
class CIchigo3 : public IDispatch
{
public:
CIchigo3();
~CIchigo3();
// 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);
private:
HRESULT Write( BSTR bstrWrite );
private:
LONG m_nRef;
};
/***********************************************************************/
EXTERN_C BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason,
LPVOID pvReserved )
{
if ( dwReason == DLL_PROCESS_ATTACH ) {
g_hinstDLL = hinstDLL;
}
return TRUE;
}
EXTERN_C HRESULT STDAPICALLTYPE DllInstall( BOOL bInstall,
LPCWSTR pwszCmdline )
{
const bool per_user_flag = suppIsPerUserRequest( pwszCmdline );
try {
HKEY hkeyRoot;
std::wstring wstrSubkey;
LONG regerr;
if ( bInstall ) {
std::wstring wstrName = suppGetModuleFileName( g_hinstDLL );
std::wstring wstrValue;
// Coclass
wstrSubkey = suppGetRegKeyCLSID( &hkeyRoot, per_user_flag, CLSID_Ichigo3,
L"InprocServer32" );
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_Ichigo3,
L"ProgID" );
if ( wstrSubkey.empty() ) {
return E_FAIL;
}
regerr = suppRegSetStringW(hkeyRoot, wstrSubkey.c_str(), NULL,
PROGID_Ichigo3 );
if ( regerr != ERROR_SUCCESS ) {
return SELFREG_E_CLASS;
}
wstrSubkey = suppGetRegKeyProgID( &hkeyRoot, per_user_flag,
PROGID_Ichigo3, L"CLSID" );
wstrValue = suppGuidToString( CLSID_Ichigo3, 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;
}
// AppID
wstrSubkey = suppGetRegKeyCLSID( &hkeyRoot, per_user_flag, CLSID_Ichigo3,
NULL );
wstrValue = suppGuidToString( AppID_Ichigo3, true );
if ( wstrSubkey.empty() || wstrValue.empty() ) {
return E_FAIL;
}
regerr = suppRegSetStringW(hkeyRoot, wstrSubkey.c_str(), L"AppID",
wstrValue.c_str() );
if ( regerr != ERROR_SUCCESS ) {
return SELFREG_E_CLASS;
}
wstrSubkey = suppGetRegKeyAppID( &hkeyRoot, per_user_flag, AppID_Ichigo3,
NULL );
if ( wstrSubkey.empty() ) {
return E_FAIL;
}
regerr = suppRegSetStringW(hkeyRoot, wstrSubkey.c_str(), L"DllSurrogate",
L"" );
if ( regerr != ERROR_SUCCESS ) {
return SELFREG_E_CLASS;
}
} else {
wstrSubkey = suppGetRegKeyCLSID( &hkeyRoot, per_user_flag, CLSID_Ichigo3,
NULL );
if ( wstrSubkey.empty() ) {
return E_FAIL;
}
regerr = suppRegRemoveKeyW(hkeyRoot, wstrSubkey.c_str());
if ( regerr != ERROR_SUCCESS ) {
return SELFREG_E_CLASS;
}
wstrSubkey = suppGetRegKeyProgID( &hkeyRoot, per_user_flag,
PROGID_Ichigo3, NULL );
if ( wstrSubkey.empty() ) {
return E_FAIL;
}
regerr = suppRegRemoveKeyW(hkeyRoot, wstrSubkey.c_str());
if ( regerr != ERROR_SUCCESS ) {
return SELFREG_E_CLASS;
}
wstrSubkey = suppGetRegKeyAppID( &hkeyRoot, per_user_flag, AppID_Ichigo3,
NULL );
if ( wstrSubkey.empty() ) {
return E_FAIL;
}
regerr = suppRegRemoveKeyW(hkeyRoot, wstrSubkey.c_str());
if ( regerr != ERROR_SUCCESS ) {
return SELFREG_E_CLASS;
}
}
} catch ( const std::exception& ) {
return E_FAIL;
}
return S_OK;
}
EXTERN_C HRESULT STDAPICALLTYPE DllRegisterServer()
{
return DllInstall( TRUE, NULL );
}
EXTERN_C HRESULT STDAPICALLTYPE DllUnregisterServer()
{
return DllInstall( FALSE, NULL );
}
EXTERN_C HRESULT STDAPICALLTYPE DllCanUnloadNow()
{
return (g_nLockDLL <= 0) ? S_OK : S_FALSE;
}
EXTERN_C HRESULT STDAPICALLTYPE DllGetClassObject( REFCLSID rclsid,
REFIID riid, LPVOID* ppv )
{
static CIchigo3Factory g_factory;
*ppv = NULL;
if ( rclsid == CLSID_Ichigo3 ) {
return g_factory.QueryInterface( riid, ppv );
}
return CLASS_E_CLASSNOTAVAILABLE;
}
/***********************************************************************/
CIchigo3Factory::CIchigo3Factory() : m_nRef(0)
{
}
CIchigo3Factory::~CIchigo3Factory()
{
}
HRESULT STDMETHODCALLTYPE CIchigo3Factory::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 CIchigo3Factory::AddRef()
{
if (m_nRef++ == 0) {
++g_nLockDLL;
}
return m_nRef;
}
ULONG STDMETHODCALLTYPE CIchigo3Factory::Release()
{
if (--m_nRef == 0) {
--g_nLockDLL;
}
return m_nRef;
}
HRESULT STDMETHODCALLTYPE CIchigo3Factory::CreateInstance(
IUnknown* pUnkOuter, REFIID riid, LPVOID* ppv )
{
*ppv = NULL;
if ( pUnkOuter != NULL ) {
return CLASS_E_NOAGGREGATION;
}
CIchigo3* pObj = new (std::nothrow) CIchigo3();
if ( pObj == NULL ) {
return E_OUTOFMEMORY;
}
HRESULT hr = pObj->QueryInterface( riid, ppv );
pObj->Release();
return hr;
}
HRESULT STDMETHODCALLTYPE CIchigo3Factory::LockServer( BOOL fLock )
{
if ( fLock ) {
++g_nLockDLL;
} else {
--g_nLockDLL;
}
return S_OK;
}
/***********************************************************************/
CIchigo3::CIchigo3() : m_nRef(1)
{
++g_nLockDLL;
}
CIchigo3::~CIchigo3()
{
--g_nLockDLL;
}
HRESULT STDMETHODCALLTYPE CIchigo3::QueryInterface( REFIID riid,
LPVOID* ppv )
{
*ppv = NULL;
if ( riid == IID_IUnknown || riid == IID_IDispatch ) {
*ppv = static_cast<IDispatch*>( this );
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE CIchigo3::AddRef()
{
return ++m_nRef;
}
ULONG STDMETHODCALLTYPE CIchigo3::Release()
{
if ( --m_nRef == 0 ) {
delete this;
return 0;
}
return m_nRef;
}
HRESULT STDMETHODCALLTYPE CIchigo3::GetTypeInfoCount(UINT* pcTInfo)
{
*pcTInfo = 0;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CIchigo3::GetTypeInfo(UINT iTInfo, LCID lcid,
ITypeInfo** ppTInfo)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CIchigo3::GetIDsOfNames(
REFIID riidNull, LPOLESTR* rgszNames, UINT cNames,
LCID lcid, DISPID* rgDispId)
{
UINT iName;
HRESULT hr = S_OK;
if ( riidNull != IID_NULL ) {
return DISP_E_UNKNOWNINTERFACE;
}
for ( iName = 0; iName < cNames; ++iName ) {
DISPID id = DISPID_UNKNOWN;
if ( lstrcmpW( rgszNames[iName], L"Write" ) == 0 ) {
id = DISPID_Ichigo3_Write;
}
rgDispId[iName] = id;
if ( id == DISPID_UNKNOWN ) {
hr = DISP_E_UNKNOWNNAME;
}
}
return hr;
}
HRESULT STDMETHODCALLTYPE CIchigo3::Invoke(
DISPID dispIdMember, REFIID riidNull, LCID lcid,
WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
EXCEPINFO* pExcepInfo, UINT* puArgErr)
{
UINT uArgErrTemp;
if ( puArgErr == NULL ) {
puArgErr = &uArgErrTemp;
}
if ( riidNull != IID_NULL ) {
return DISP_E_UNKNOWNINTERFACE;
}
HRESULT hr;
if ( (wFlags & DISPATCH_METHOD) != 0 &&
dispIdMember == DISPID_Ichigo3_Write ) {
if ( pDispParams->cArgs != 1 ) {
return DISP_E_BADPARAMCOUNT;
}
// rgvarg: reverse order
if ( pDispParams->rgvarg[0].vt != VT_BSTR ) {
*puArgErr = 0;
return DISP_E_TYPEMISMATCH;
}
hr = Write( pDispParams->rgvarg[0].bstrVal );
} else {
return DISP_E_MEMBERNOTFOUND;
}
if ( FAILED(hr) ) {
if ( pExcepInfo != NULL ) {
pExcepInfo->scode = hr;
pExcepInfo->wCode = 0;
pExcepInfo->wReserved = 0;
pExcepInfo->bstrSource = NULL;
pExcepInfo->bstrDescription = NULL;
pExcepInfo->bstrHelpFile = NULL;
pExcepInfo->dwHelpContext = 0;
pExcepInfo->pvReserved = NULL;
pExcepInfo->pfnDeferredFillIn = NULL;
}
IErrorInfo* pei = NULL;
if ( S_OK == GetErrorInfo(0, &pei) ) {
if ( pExcepInfo != NULL ) {
if ( FAILED(pei->GetSource( &pExcepInfo->bstrSource )) )
pExcepInfo->bstrSource = NULL;
if ( FAILED(pei->GetDescription( &pExcepInfo->bstrDescription )) )
pExcepInfo->bstrDescription = NULL;
if ( FAILED(pei->GetHelpFile( &pExcepInfo->bstrHelpFile )) )
pExcepInfo->bstrHelpFile = NULL;
if ( FAILED(pei->GetHelpContext( &pExcepInfo->dwHelpContext )) )
pExcepInfo->dwHelpContext = 0;
}
pei->Release();
}
if ( pExcepInfo != NULL && pExcepInfo->bstrSource == NULL )
pExcepInfo->bstrSource = SysAllocString( PROGID_Ichigo3 );
return DISP_E_EXCEPTION;
}
return hr;
}
HRESULT CIchigo3::Write( BSTR bstrWrite )
{
try {
UINT cLen = SysStringLen(bstrWrite);
if ( cLen >= ICHIGO_LOGLINE_MAX ) {
HRESULT hr;
ICreateErrorInfo* pcreateei = NULL;
IErrorInfo* pei = NULL;
hr = CreateErrorInfo(&pcreateei);
if ( SUCCEEDED(hr) ) {
pcreateei->SetSource( PROGID_Ichigo3 );
pcreateei->SetDescription(
L"SysStringLen(bstrWrite) >= ICHIGO_LOGLINE_MAX" );
hr = pcreateei->QueryInterface(
IID_IErrorInfo, (LPVOID*)&pei );
if ( SUCCEEDED(hr) ) {
SetErrorInfo(0, pei);
pei->Release();
}
pcreateei->Release();
}
return E_INVALIDARG;
}
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;
}
}