Skip to content

Instantly share code, notes, and snippets.

@urasandesu
Last active August 29, 2015 14:00
Show Gist options
  • Save urasandesu/40452858391914014b88 to your computer and use it in GitHub Desktop.
Save urasandesu/40452858391914014b88 to your computer and use it in GitHub Desktop.
Code snippet for same work as CoCreateInstance without CoInitialize. See also the reference [Registration-free COM - Mikhail Arkhipov (MSFT)'s WebLog - Site Home - MSDN Blogs](http://blogs.msdn.com/b/mikhailarkhipov/archive/2005/04/01/404433.aspx). In Profiling API, timing to call CoInitialize is basically unknown. This hack will enable that you…
#include "stdafx.h"
#ifndef URASANDESU_CPPANONYM_CPPANONYMNOTIMPLEMENTEDEXCEPTION_H
#include <Urasandesu/CppAnonym/CppAnonymNotImplementedException.h>
#endif
#ifndef URASANDESU_CPPANONYM_CPPANONYMCOMEXCEPTION_H
#include <Urasandesu/CppAnonym/CppAnonymCOMException.h>
#endif
#ifndef URASANDESU_CPPANONYM_CPPANONYMSYSTEMEXCEPTION_H
#include <Urasandesu/CppAnonym/CppAnonymSystemException.h>
#endif
#ifndef URASANDESU_CPPANONYM_UTILITIES_CCOMOBJECTSLIM_HPP
#include <Urasandesu/CppAnonym/Utilities/CComObjectSlim.hpp>
#endif
#include <cor.h>
#include <corprof.h>
namespace Urasandesu { namespace CppAnonym { namespace Utilities {
namespace CComClassFactorySlimDetail {
using ATL::CComObjectRootEx;
using ATL::CComGlobalsThreadModel;
using ATL::CComPtr;
using boost::shared_ptr;
class CComClassFactorySlim :
public IClassFactory,
public CComObjectRootEx<CComGlobalsThreadModel>
{
public:
CComClassFactorySlim() { }
virtual ~CComClassFactorySlim() { }
BEGIN_COM_MAP(CComClassFactorySlim)
COM_INTERFACE_ENTRY(IClassFactory)
END_COM_MAP()
HRESULT Initialize(REFCLSID rclsid)
{
using boost::array;
using std::vector;
using std::wstring;
auto strClsid = array<OLECHAR, 128>();
::StringFromGUID2(rclsid, strClsid.c_array(), strClsid.size());
auto key = boost::str(boost::wformat(L"CLSID\\%|1$s|\\InprocServer32") % strClsid.data());
auto hKeyClassesRoot = HKEY();
BOOST_SCOPE_EXIT((&hKeyClassesRoot))
{
if (hKeyClassesRoot)
::RegCloseKey(hKeyClassesRoot);
}
BOOST_SCOPE_EXIT_END
{
auto result = ::RegOpenKeyExW(HKEY_CLASSES_ROOT, key.c_str(), 0, KEY_READ, &hKeyClassesRoot);
if (result != ERROR_SUCCESS)
return HRESULT_FROM_WIN32(result);
}
auto comDllName = wstring();
{
auto length = 0ul;
auto type = 0ul;
auto result = ERROR_SUCCESS;
result = ::RegQueryValueExW(hKeyClassesRoot, nullptr, nullptr, &type, nullptr, &length);
if (result != ERROR_SUCCESS)
return HRESULT_FROM_WIN32(result);
if (type != REG_SZ && type != REG_EXPAND_SZ)
return ERROR_FILE_NOT_FOUND;
auto _comDllName = vector<WCHAR>();
_comDllName.resize(length / sizeof(WCHAR));
result = ::RegQueryValueExW(hKeyClassesRoot, nullptr, nullptr, &type, reinterpret_cast<BYTE *>(&_comDllName[0]), &length);
if (result != ERROR_SUCCESS)
return HRESULT_FROM_WIN32(result);
comDllName = &_comDllName[0];
}
{
m_hmodComDll = shared_ptr<HINSTANCE__>(::LoadLibraryExW(comDllName.c_str(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH), &::FreeLibrary);
if (!m_hmodComDll)
return HRESULT_FROM_WIN32(::GetLastError());
typedef HRESULT (__stdcall *DllGetClassObjectPtr)(REFCLSID rclsid, REFIID riid, void **ppv);
auto *pfnDllGetClassObject = reinterpret_cast<DllGetClassObjectPtr>(::GetProcAddress(m_hmodComDll.get(), "DllGetClassObject"));
if (!pfnDllGetClassObject)
return HRESULT_FROM_WIN32(::GetLastError());
auto hr = pfnDllGetClassObject(rclsid, IID_IClassFactory, reinterpret_cast<void **>(&m_pComClassFactory));
if (FAILED(hr))
return hr;
}
return S_OK;
}
STDMETHOD(CreateInstance)(IUnknown *pUnkOuter, REFIID riid, void **ppvObject)
{
return m_pComClassFactory->CreateInstance(pUnkOuter, riid, ppvObject);
}
STDMETHOD(LockServer)(BOOL fLock)
{
return m_pComClassFactory->LockServer(fLock);
}
private:
shared_ptr<HINSTANCE__> m_hmodComDll;
CComPtr<IClassFactory> m_pComClassFactory;
};
template<REFCLSID RCLSID>
class CComClassFactorySlimT :
public CComClassFactorySlim
{
public:
CComClassFactorySlimT() { }
virtual ~CComClassFactorySlimT() { }
HRESULT FinalConstruct()
{
return CComClassFactorySlim::Initialize(RCLSID);
}
};
} // namespace CComClassFactorySlimDetail {
using CComClassFactorySlimDetail::CComClassFactorySlim;
using CComClassFactorySlimDetail::CComClassFactorySlimT;
}}} // namespace Urasandesu { namespace CppAnonym { namespace Utilities {
// Test.Urasandesu.CppAnonym.exe --gtest_filter=Urasandesu_CppAnonym_Test.*
namespace {
CPPANONYM_TEST(Urasandesu_CppAnonym_Test, Test_01)
{
using namespace Urasandesu::CppAnonym::Utilities;
using ATL::CComPtr;
using std::wstring;
using Urasandesu::CppAnonym::CppAnonymCOMException;
{
typedef CComClassFactorySlimT<CLSID_CorMetaDataDispenser> MetaDataDispenserClassFactory;
typedef CComObjectSlim<MetaDataDispenserClassFactory> MetaDataDispenserClassFactoryObject;
auto *pComMetaDispFactory = static_cast<MetaDataDispenserClassFactoryObject *>(nullptr);
ASSERT_HRESULT_SUCCEEDED(MetaDataDispenserClassFactoryObject::CreateInstance(&pComMetaDispFactory));
auto m_pComMetaDispFactory = CComPtr<IClassFactory>(pComMetaDispFactory);
auto pComMetaDisp = CComPtr<IMetaDataDispenserEx>();
ASSERT_HRESULT_SUCCEEDED(m_pComMetaDispFactory->CreateInstance(nullptr, IID_IMetaDataDispenserEx, reinterpret_cast<void **>(&pComMetaDisp)));
// S_OK
}
{
auto strExtProf = wstring(L"{532C1F05-F8F3-4FBA-8724-699A31756ABD}"); // https://github.com/urasandesu/Prig/blob/master/Urasandesu.Prig/UrasandesuPrig.idl
auto extProf = IID();
::IIDFromString(strExtProf.c_str(), &extProf);
typedef CComObjectSlim<CComClassFactorySlim> ExternalProfilerClassFactoryObject;
auto *pComExtProfFactory = static_cast<ExternalProfilerClassFactoryObject *>(nullptr);
ASSERT_HRESULT_SUCCEEDED(ExternalProfilerClassFactoryObject::CreateInstance(&pComExtProfFactory));
ASSERT_HRESULT_SUCCEEDED(pComExtProfFactory->Initialize(extProf));
auto m_pComExtProfFactory = CComPtr<IClassFactory>(pComExtProfFactory);
auto pComProfExtCallback = CComPtr<ICorProfilerCallback>();
ASSERT_HRESULT_SUCCEEDED(m_pComExtProfFactory->CreateInstance(nullptr, IID_ICorProfilerCallback, reinterpret_cast<void **>(&pComProfExtCallback)));
// S_OK
}
{
auto pComMetaDisp = CComPtr<IMetaDataDispenserEx>();
ASSERT_HRESULT_SUCCEEDED(::CoCreateInstance(CLSID_CorMetaDataDispenser, NULL, CLSCTX_INPROC_SERVER, IID_IMetaDataDispenserEx, reinterpret_cast<void **>(&pComMetaDisp)));
// CO_E_NOTINITIALIZED: CoInitialize は呼び出されていません。
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment