Last active
August 29, 2015 14:00
-
-
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…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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