Skip to content

Instantly share code, notes, and snippets.

@clarkezone
Created September 17, 2018 02:28
Show Gist options
  • Save clarkezone/43e984fb9bdcd2cfcd9a4f41c208a02f to your computer and use it in GitHub Desktop.
Save clarkezone/43e984fb9bdcd2cfcd9a4f41c208a02f to your computer and use it in GitHub Desktop.
Dynamically using WinRT avoiding statically linking windowsapp.lib and thus breaking compatibility with win7
class RoHelper
{
public:
RoHelper() : mWinRtAvailable(false)
{
if (!IsWindows10OrGreater())
{
return;
}
mComBaseModule = LoadLibraryA("ComBase.dll");
if (mComBaseModule == nullptr)
{
return;
}
auto temp = GetProcAddress(mComBaseModule, "WindowsCreateStringReference");
if (temp != nullptr)
{
mFpWindowsCreateStringReference =
reinterpret_cast<_WindowsCreateStringReference *>(temp);
temp = GetProcAddress(mComBaseModule, "RoGetActivationFactory");
if (temp != nullptr)
{
mFpGetActivationFactory = reinterpret_cast<_GetActivationFactory *>(temp);
temp = GetProcAddress(mComBaseModule, "WindowsCompareStringOrdinal");
if (temp != nullptr)
{
mFpWindowsCompareStringOrdinal =
reinterpret_cast<_WindowsCompareStringOrginal *>(temp);
temp = GetProcAddress(mComBaseModule, "WindowsDeleteString");
if (temp != nullptr)
{
mFpWindowsDeleteString = reinterpret_cast<_WindowsDeleteString *>(temp);
temp = GetProcAddress(mComBaseModule, "RoInitialize");
if (temp != nullptr)
{
mFpRoInitialize = reinterpret_cast<_RoInitialize *>(temp);
temp = GetProcAddress(mComBaseModule, "RoUninitialize");
if (temp != nullptr)
{
mFpRoUninitialize = reinterpret_cast<_RoUninitialize *>(temp);
mCoreMessagingModule = LoadLibraryA("coremessaging.dll");
if (mCoreMessagingModule == nullptr)
{
return;
}
temp = GetProcAddress(mCoreMessagingModule,
"CreateDispatcherQueueController");
if (temp != nullptr)
{
mFpCreateDispatcherQueueController =
reinterpret_cast<_CreateDispatcherQueueController *>(temp);
if (SUCCEEDED(RoInitialize(RO_INIT_MULTITHREADED)))
{
mWinRtAvailable = true;
}
}
}
}
}
}
}
}
}
~RoHelper()
{
RoUninitialize();
if (mCoreMessagingModule != nullptr)
{
FreeLibrary(mCoreMessagingModule);
mCoreMessagingModule = nullptr;
}
if (mComBaseModule != nullptr)
{
FreeLibrary(mComBaseModule);
mComBaseModule = nullptr;
}
}
bool WinRtAvailable() const { return mWinRtAvailable; }
bool SupportedWindowsRelease()
{
if (!mWinRtAvailable)
{
return false;
}
HSTRING className, contractName;
HSTRING_HEADER classNameHeader, contractNameHeader;
boolean isSupported = false;
HRESULT hr = GetStringReference(RuntimeClass_Windows_Foundation_Metadata_ApiInformation,
&className, &classNameHeader);
if (FAILED(hr))
{
return isSupported;
}
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Metadata::IApiInformationStatics> api;
hr = GetActivationFactory(
className, __uuidof(ABI::Windows::Foundation::Metadata::IApiInformationStatics), &api);
if (FAILED(hr))
{
return isSupported;
}
hr = GetStringReference(L"Windows.Foundation.UniversalApiContract", &contractName,
&contractNameHeader);
if (FAILED(hr))
{
return isSupported;
}
api->IsApiContractPresentByMajor(contractName, 6, &isSupported);
return isSupported;
}
HRESULT GetStringReference(PCWSTR source, HSTRING *act, HSTRING_HEADER *header)
{
if (!mWinRtAvailable)
{
return E_FAIL;
}
const wchar_t *str = static_cast<const wchar_t *>(source);
unsigned int length;
HRESULT hr = SizeTToUInt32(::wcslen(str), &length);
if (FAILED(hr))
{
return hr;
}
return mFpWindowsCreateStringReference(source, length, header, act);
}
Microsoft::WRL::ComPtr<IActivationFactory> ActivateInstance(PCWSTR source)
{
if (!mWinRtAvailable)
{
return nullptr;
}
HSTRING act;
HSTRING_HEADER header;
auto hr = GetStringReference(source, &act, &header);
if (FAILED(hr))
{
ANGLE_CRASH();
}
void *fac = nullptr;
hr = mFpGetActivationFactory(act, __uuidof(IActivationFactory), &fac);
if (FAILED(hr))
{
ANGLE_CRASH();
}
Microsoft::WRL::ComPtr<IActivationFactory> compositorFactory(static_cast<IActivationFactory *>(fac));
return compositorFactory;
}
HRESULT GetActivationFactory(const HSTRING act, const IID &interfaceId, void **fac)
{
if (!mWinRtAvailable)
{
return E_FAIL;
}
auto hr = mFpGetActivationFactory(act, interfaceId, fac);
return hr;
}
HRESULT WindowsCompareStringOrdinal(HSTRING one, HSTRING two, int *result)
{
if (!mWinRtAvailable)
{
return E_FAIL;
}
return mFpWindowsCompareStringOrdinal(one, two, result);
}
HRESULT CreateDispatcherQueueController(
DispatcherQueueOptions options,
ABI::Windows::System::IDispatcherQueueController **dispatcherQueueController)
{
if (!mWinRtAvailable)
{
return E_FAIL;
}
return mFpCreateDispatcherQueueController(options, dispatcherQueueController);
}
HRESULT WindowsDeleteString(HSTRING one)
{
if (!mWinRtAvailable)
{
return E_FAIL;
}
return mFpWindowsDeleteString(one);
}
HRESULT RoInitialize(RO_INIT_TYPE type) { return mFpRoInitialize(type); }
void RoUninitialize() { mFpRoUninitialize(); }
private:
using _WindowsCreateStringReference = HRESULT __stdcall(PCWSTR,
UINT32,
HSTRING_HEADER *,
HSTRING *);
using _GetActivationFactory = HRESULT __stdcall(HSTRING, REFIID, void **);
using _WindowsCompareStringOrginal = HRESULT __stdcall(HSTRING, HSTRING, int *);
using _WindowsDeleteString = HRESULT __stdcall(HSTRING);
using _CreateDispatcherQueueController =
HRESULT __stdcall(DispatcherQueueOptions,
ABI::Windows::System::IDispatcherQueueController **);
using _RoInitialize = HRESULT __stdcall(RO_INIT_TYPE);
using _RoUninitialize = void __stdcall();
_WindowsCreateStringReference *mFpWindowsCreateStringReference;
_GetActivationFactory *mFpGetActivationFactory;
_WindowsCompareStringOrginal *mFpWindowsCompareStringOrdinal;
_CreateDispatcherQueueController *mFpCreateDispatcherQueueController;
_WindowsDeleteString *mFpWindowsDeleteString;
_RoInitialize *mFpRoInitialize;
_RoUninitialize *mFpRoUninitialize;
bool mWinRtAvailable;
HMODULE mComBaseModule;
HMODULE mCoreMessagingModule;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment