#pragma once #include #include #include #include "wil/result_macros.h" #ifdef _CPPRTTI #include #include #endif #ifndef CINTERFACE struct IUnknownVtbl { HRESULT(*QueryInterface)(IUnknown *, REFIID riid, void **ppvObject); ULONG(*AddRef)(IUnknown *); ULONG(*Release)(IUnknown *); }; #endif struct abi_t { uint32_t Major = 0; uint32_t Minor = 0; uint32_t Build = 0; uint32_t Revision = 0; auto operator<=>(abi_t const &other) const noexcept = default; bool operator==(abi_t const &other) const noexcept = default; }; // {7E93844E-159A-4D07-9910-87E9D65ECE00} static const GUID GUID_UnwrapInterface = { 0x7E93844E, 0x159A, 0x4D07, { 0x99, 0x10, 0x87, 0xE9, 0xD6, 0x5E, 0xCE, 0x00 } }; template using reg_return_t = std::conditional_t<(std::is_class_v || std::is_union_v) && (sizeof(T) <= sizeof(std::uintptr_t)), std::uintptr_t, T>; template FORCEINLINE reg_return_t to_reg_return(T value) { if constexpr (std::is_same_v>) return value; reg_return_t reg = {}; memcpy(®, &value, sizeof(T)); return reg; } namespace xcom { namespace impl { template inline constexpr GUID guid_v = __uuidof(T); } template inline constexpr GUID guid_of() { return impl::guid_v; } template typename T> inline constexpr GUID guid_of() { return guid_of>(); } inline void StubHandler(char const *name, void *object) { #ifdef _CPPRTTI char const *type = object ? ((type_info const *)__RTtypeid(object))->name() : "STUB"; #else char const *type = "STUB"; #endif MessageBoxA(nullptr, name, type, MB_ICONERROR); #ifdef _DEBUG DebugBreak(); #endif ExitProcess(0); } inline void TodoHandler(char const *name, void *object) { #ifdef _CPPRTTI char const *type = object ? ((type_info const *)__RTtypeid(object))->name() : nullptr; #else char const *type = nullptr; #endif OutputDebugStringA("TODO: "); OutputDebugStringA(name); if (type != nullptr) { OutputDebugStringA("(from "); OutputDebugStringA(type); OutputDebugStringA(")"); } OutputDebugStringA("\n"); } inline HRESULT UnwrapInterface(_In_opt_ IUnknown *pUnknown, _Outptr_ void **ppvObject) { HRESULT hr; if (ppvObject == nullptr) RETURN_HR(E_POINTER); if (pUnknown == nullptr) { *ppvObject = nullptr; return S_FALSE; } if (SUCCEEDED(hr = pUnknown->QueryInterface(GUID_UnwrapInterface, ppvObject))) return hr; *ppvObject = nullptr; return hr; } } #ifndef DECLARE_UUIDOF_HELPER #define DECLARE_UUIDOF_HELPER(type, a, b, c, d, e, f, g, h, i, j, k) template<> inline constexpr GUID (::xcom::impl::guid_v){a,b,c,{d,e,f,g,h,i,j,k}}; #endif #define DECLARE_ABI_UUIDOF_HELPER(type, a, b, c, d, e, f, g, h, i, j, k) template<> inline constexpr GUID (::xcom::impl::guid_v>){a,b,c,{d,e,f,g,h,i,j,k}}; #define IMPLEMENT_STUB() ::xcom::StubHandler(__func__, __if_exists(this) { this } __if_not_exists(this) { nullptr }) #define IMPLEMENT_TODO() ::xcom::TodoHandler(__func__, __if_exists(this) { this } __if_not_exists(this) { nullptr })