mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-25 07:09:48 -06:00
update wil to 0b2d6c2d822bb301e7558a14ee66d567c14f5dc7
This commit is contained in:
241
Externals/WIL/include/wil/com.h
vendored
241
Externals/WIL/include/wil/com.h
vendored
@ -16,6 +16,13 @@
|
||||
#include "result.h"
|
||||
#include "resource.h" // last to ensure _COMBASEAPI_H_ protected definitions are available
|
||||
|
||||
#if __has_include(<tuple>)
|
||||
#include <tuple>
|
||||
#endif
|
||||
#if __has_include(<type_traits>)
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
// Forward declaration within WIL (see https://msdn.microsoft.com/en-us/library/br244983.aspx)
|
||||
/// @cond
|
||||
namespace Microsoft
|
||||
@ -46,10 +53,10 @@ namespace wil
|
||||
{
|
||||
};
|
||||
|
||||
typedef wistd::integral_constant<char, 0> tag_com_query;
|
||||
typedef wistd::integral_constant<char, 1> tag_try_com_query;
|
||||
typedef wistd::integral_constant<char, 2> tag_com_copy;
|
||||
typedef wistd::integral_constant<char, 3> tag_try_com_copy;
|
||||
using tag_com_query = wistd::integral_constant<char, 0>;
|
||||
using tag_try_com_query = wistd::integral_constant<char, 1>;
|
||||
using tag_com_copy = wistd::integral_constant<char, 2>;
|
||||
using tag_try_com_copy = wistd::integral_constant<char, 3>;
|
||||
|
||||
class default_query_policy
|
||||
{
|
||||
@ -87,7 +94,7 @@ namespace wil
|
||||
template <typename T>
|
||||
struct query_policy_helper
|
||||
{
|
||||
typedef default_query_policy type;
|
||||
using type = default_query_policy;
|
||||
};
|
||||
|
||||
class weak_query_policy
|
||||
@ -99,7 +106,7 @@ namespace wil
|
||||
*result = nullptr;
|
||||
|
||||
IInspectable* temp;
|
||||
HRESULT hr = ptr->Resolve(__uuidof(IInspectable), reinterpret_cast<IInspectable**>(&temp));
|
||||
HRESULT hr = ptr->Resolve(__uuidof(IInspectable), &temp);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (temp == nullptr)
|
||||
@ -144,7 +151,7 @@ namespace wil
|
||||
template <>
|
||||
struct query_policy_helper<IWeakReference>
|
||||
{
|
||||
typedef weak_query_policy type;
|
||||
using type = weak_query_policy;
|
||||
};
|
||||
|
||||
#if (NTDDI_VERSION >= NTDDI_WINBLUE)
|
||||
@ -170,7 +177,7 @@ namespace wil
|
||||
template <>
|
||||
struct query_policy_helper<IAgileReference>
|
||||
{
|
||||
typedef agile_query_policy type;
|
||||
using type = agile_query_policy;
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -190,15 +197,15 @@ namespace wil
|
||||
class com_ptr_t
|
||||
{
|
||||
private:
|
||||
typedef typename wistd::add_lvalue_reference<T>::type element_type_reference;
|
||||
typedef details::query_policy_t<T> query_policy;
|
||||
using element_type_reference = typename wistd::add_lvalue_reference<T>::type;
|
||||
using query_policy = details::query_policy_t<T>;
|
||||
public:
|
||||
//! The function return result (HRESULT or void) for the given err_policy (see @ref page_errors).
|
||||
typedef typename err_policy::result result;
|
||||
using result = typename err_policy::result;
|
||||
//! The template type `T` being held by the com_ptr_t.
|
||||
typedef T element_type;
|
||||
using element_type = T;
|
||||
//! A pointer to the template type `T` being held by the com_ptr_t (what `get()` returns).
|
||||
typedef T* pointer;
|
||||
using pointer = T*;
|
||||
|
||||
//! @name Constructors
|
||||
//! @{
|
||||
@ -359,8 +366,7 @@ namespace wil
|
||||
m_ptr = other;
|
||||
if (ptr)
|
||||
{
|
||||
ULONG ref;
|
||||
ref = ptr->Release();
|
||||
ULONG ref = ptr->Release();
|
||||
WI_ASSERT_MSG(((other != ptr) || (ref > 0)), "Bug: Attaching the same already assigned, destructed pointer");
|
||||
}
|
||||
}
|
||||
@ -397,9 +403,9 @@ namespace wil
|
||||
|
||||
//! Returns the address of the internal pointer casted to IUnknown** (releases ownership of the pointer BEFORE returning the address).
|
||||
//! @see put
|
||||
IUnknown** put_unknown() WI_NOEXCEPT
|
||||
::IUnknown** put_unknown() WI_NOEXCEPT
|
||||
{
|
||||
return reinterpret_cast<IUnknown**>(put());
|
||||
return reinterpret_cast<::IUnknown**>(put());
|
||||
}
|
||||
|
||||
//! Returns the address of the internal pointer (releases ownership of the pointer BEFORE returning the address).
|
||||
@ -863,7 +869,7 @@ namespace wil
|
||||
// Internal Helpers
|
||||
/// @cond
|
||||
template <class U>
|
||||
inline com_ptr_t(_In_ U* ptr, details::tag_com_query)
|
||||
inline com_ptr_t(_In_ U* ptr, details::tag_com_query) : m_ptr(nullptr)
|
||||
{
|
||||
err_policy::HResult(details::query_policy_t<U>::query(ptr, &m_ptr));
|
||||
}
|
||||
@ -875,14 +881,12 @@ namespace wil
|
||||
}
|
||||
|
||||
template <class U>
|
||||
inline com_ptr_t(_In_opt_ U* ptr, details::tag_com_copy)
|
||||
inline com_ptr_t(_In_opt_ U* ptr, details::tag_com_copy) : m_ptr(nullptr)
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
err_policy::HResult(details::query_policy_t<U>::query(ptr, &m_ptr));
|
||||
return;
|
||||
}
|
||||
m_ptr = nullptr;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
@ -1182,6 +1186,43 @@ namespace wil
|
||||
#endif
|
||||
/// @endcond
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
//! Constructs a `com_ptr` from a raw pointer.
|
||||
//! This avoids having to restate the interface in pre-C++20.
|
||||
//! Starting in C++20, you can write `wil::com_ptr(p)` directly.
|
||||
//! ~~~
|
||||
//! void example(ILongNamedThing* thing)
|
||||
//! {
|
||||
//! callback([thing = wil::make_com_ptr(thing)] { /* do something */ });
|
||||
//! }
|
||||
//! ~~~
|
||||
template <typename T>
|
||||
com_ptr<T> make_com_ptr(T* p) { return p; }
|
||||
#endif
|
||||
|
||||
//! Constructs a `com_ptr_nothrow` from a raw pointer.
|
||||
//! This avoids having to restate the interface in pre-C++20.
|
||||
//! Starting in C++20, you can write `wil::com_ptr_nothrow(p)` directly.
|
||||
//! ~~~
|
||||
//! void example(ILongNamedThing* thing)
|
||||
//! {
|
||||
//! callback([thing = wil::make_com_ptr_nothrow(thing)] { /* do something */ });
|
||||
//! }
|
||||
//! ~~~
|
||||
template <typename T>
|
||||
com_ptr_nothrow<T> make_com_ptr_nothrow(T* p) { return p; }
|
||||
|
||||
//! Constructs a `com_ptr_failfast` from a raw pointer.
|
||||
//! This avoids having to restate the interface in pre-C++20.
|
||||
//! Starting in C++20, you can write `wil::com_ptr_failfast(p)` directly.
|
||||
//! ~~~
|
||||
//! void example(ILongNamedThing* thing)
|
||||
//! {
|
||||
//! callback([thing = wil::make_com_ptr_failfast(thing)] { /* do something */ });
|
||||
//! }
|
||||
//! ~~~
|
||||
template <typename T>
|
||||
com_ptr_failfast<T> make_com_ptr_failfast(T* p) { return p; }
|
||||
|
||||
//! @name Stand-alone query helpers
|
||||
//! * Source pointer can be raw interface pointer, any wil com_ptr, or WRL ComPtr
|
||||
@ -1255,7 +1296,7 @@ namespace wil
|
||||
auto raw = com_raw_ptr(wistd::forward<T>(ptrSource));
|
||||
auto hr = details::query_policy_t<decltype(raw)>::query(raw, ptrResult);
|
||||
__analysis_assume(SUCCEEDED(hr) || (*ptrResult == nullptr));
|
||||
RETURN_HR(hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
@ -1297,7 +1338,7 @@ namespace wil
|
||||
auto raw = com_raw_ptr(wistd::forward<T>(ptrSource));
|
||||
auto hr = details::query_policy_t<decltype(raw)>::query(raw, riid, ptrResult);
|
||||
__analysis_assume(SUCCEEDED(hr) || (*ptrResult == nullptr));
|
||||
RETURN_HR(hr);
|
||||
return hr;
|
||||
}
|
||||
//! @}
|
||||
|
||||
@ -1687,7 +1728,7 @@ namespace wil
|
||||
auto raw = com_raw_ptr(wistd::forward<T>(ptrSource));
|
||||
auto hr = ::RoGetAgileReference(options, __uuidof(raw), raw, ptrResult);
|
||||
__analysis_assume(SUCCEEDED(hr) || (*ptrResult == nullptr));
|
||||
RETURN_HR(hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
@ -1802,7 +1843,7 @@ namespace wil
|
||||
auto raw = com_raw_ptr(wistd::forward<T>(ptrSource));
|
||||
auto hr = details::GetWeakReference(raw, ptrResult);
|
||||
__analysis_assume(SUCCEEDED(hr) || (*ptrResult == nullptr));
|
||||
RETURN_HR(hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
@ -1873,14 +1914,14 @@ namespace wil
|
||||
|
||||
/** constructs a COM object using an CLSID on a specific interface or IUnknown. */
|
||||
template<typename Interface = IUnknown>
|
||||
wil::com_ptr_failfast<Interface> CoCreateInstanceFailFast(REFCLSID rclsid, DWORD dwClsContext = CLSCTX_INPROC_SERVER)
|
||||
wil::com_ptr_failfast<Interface> CoCreateInstanceFailFast(REFCLSID rclsid, DWORD dwClsContext = CLSCTX_INPROC_SERVER) WI_NOEXCEPT
|
||||
{
|
||||
return CoCreateInstance<Interface, err_failfast_policy>(rclsid, dwClsContext);
|
||||
}
|
||||
|
||||
/** constructs a COM object using the class as the identifier (that has an associated CLSID) on a specific interface or IUnknown. */
|
||||
template<typename Class, typename Interface = IUnknown>
|
||||
wil::com_ptr_failfast<Interface> CoCreateInstanceFailFast(DWORD dwClsContext = CLSCTX_INPROC_SERVER)
|
||||
wil::com_ptr_failfast<Interface> CoCreateInstanceFailFast(DWORD dwClsContext = CLSCTX_INPROC_SERVER) WI_NOEXCEPT
|
||||
{
|
||||
return CoCreateInstanceFailFast<Interface>(__uuidof(Class), dwClsContext);
|
||||
}
|
||||
@ -1888,7 +1929,7 @@ namespace wil
|
||||
/** constructs a COM object using an CLSID on a specific interface or IUnknown.
|
||||
Note, failures are reported as a null result, the HRESULT is lost. */
|
||||
template<typename Interface = IUnknown>
|
||||
wil::com_ptr_nothrow<Interface> CoCreateInstanceNoThrow(REFCLSID rclsid, DWORD dwClsContext = CLSCTX_INPROC_SERVER)
|
||||
wil::com_ptr_nothrow<Interface> CoCreateInstanceNoThrow(REFCLSID rclsid, DWORD dwClsContext = CLSCTX_INPROC_SERVER) WI_NOEXCEPT
|
||||
{
|
||||
return CoCreateInstance<Interface, err_returncode_policy>(rclsid, dwClsContext);
|
||||
}
|
||||
@ -1896,7 +1937,7 @@ namespace wil
|
||||
/** constructs a COM object using the class as the identifier (that has an associated CLSID) on a specific interface or IUnknown.
|
||||
Note, failures are reported as a null result, the HRESULT is lost. */
|
||||
template<typename Class, typename Interface = IUnknown>
|
||||
wil::com_ptr_nothrow<Interface> CoCreateInstanceNoThrow(DWORD dwClsContext = CLSCTX_INPROC_SERVER)
|
||||
wil::com_ptr_nothrow<Interface> CoCreateInstanceNoThrow(DWORD dwClsContext = CLSCTX_INPROC_SERVER) WI_NOEXCEPT
|
||||
{
|
||||
return CoCreateInstanceNoThrow<Interface>(__uuidof(Class), dwClsContext);
|
||||
}
|
||||
@ -1949,6 +1990,140 @@ namespace wil
|
||||
{
|
||||
return CoGetClassObjectNoThrow<Interface>(__uuidof(Class), dwClsContext);
|
||||
}
|
||||
|
||||
#if __cpp_lib_apply && __has_include(<type_traits>)
|
||||
namespace details
|
||||
{
|
||||
template <typename error_policy, typename... Results>
|
||||
auto CoCreateInstanceEx(REFCLSID clsid, CLSCTX clsCtx) noexcept
|
||||
{
|
||||
MULTI_QI multiQis[sizeof...(Results)]{};
|
||||
const IID* iids[sizeof...(Results)]{ &__uuidof(Results)... };
|
||||
|
||||
static_assert(sizeof...(Results) > 0);
|
||||
|
||||
for (auto i = 0U; i < sizeof...(Results); ++i)
|
||||
{
|
||||
multiQis[i].pIID = iids[i];
|
||||
}
|
||||
|
||||
const auto hr = CoCreateInstanceEx(clsid, nullptr, clsCtx, nullptr,
|
||||
ARRAYSIZE(multiQis), multiQis);
|
||||
|
||||
std::tuple<wil::com_ptr_t<Results, error_policy>...> resultTuple;
|
||||
|
||||
std::apply([i = 0, &multiQis](auto&... a) mutable
|
||||
{
|
||||
(a.attach(reinterpret_cast<typename std::remove_reference<decltype(a)>::type::pointer>(multiQis[i++].pItf)), ...);
|
||||
}, resultTuple);
|
||||
return std::tuple<HRESULT, decltype(resultTuple)>(hr, std::move(resultTuple));
|
||||
}
|
||||
|
||||
template<typename error_policy, typename... Results>
|
||||
auto com_multi_query(IUnknown* obj)
|
||||
{
|
||||
MULTI_QI multiQis[sizeof...(Results)]{};
|
||||
const IID* iids[sizeof...(Results)]{ &__uuidof(Results)... };
|
||||
|
||||
static_assert(sizeof...(Results) > 0);
|
||||
|
||||
for (auto i = 0U; i < sizeof...(Results); ++i)
|
||||
{
|
||||
multiQis[i].pIID = iids[i];
|
||||
}
|
||||
|
||||
std::tuple<wil::com_ptr_t<Results, error_policy>...> resultTuple{};
|
||||
|
||||
wil::com_ptr_nothrow<IMultiQI> multiQi;
|
||||
auto hr = obj->QueryInterface(IID_PPV_ARGS(&multiQi));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = multiQi->QueryMultipleInterfaces(ARRAYSIZE(multiQis), multiQis);
|
||||
std::apply([i = 0, &multiQis](auto&... a) mutable
|
||||
{
|
||||
(a.attach(reinterpret_cast<typename std::remove_reference<decltype(a)>::type::pointer>(multiQis[i++].pItf)), ...);
|
||||
}, resultTuple);
|
||||
}
|
||||
return std::tuple<HRESULT, decltype(resultTuple)>{hr, std::move(resultTuple)};
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
// CoCreateInstanceEx can be used to improve performance by requesting multiple interfaces
|
||||
// from an object at create time. This is most useful for out of process (OOP) servers, saving
|
||||
// and RPC per extra interface requested.
|
||||
template <typename... Results>
|
||||
auto CoCreateInstanceEx(REFCLSID clsid, CLSCTX clsCtx = CLSCTX_LOCAL_SERVER)
|
||||
{
|
||||
auto [error, result] = details::CoCreateInstanceEx<err_exception_policy, Results...>(clsid, clsCtx);
|
||||
THROW_IF_FAILED(error);
|
||||
THROW_HR_IF(E_NOINTERFACE, error == CO_S_NOTALLINTERFACES);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename... Results>
|
||||
auto TryCoCreateInstanceEx(REFCLSID clsid, CLSCTX clsCtx = CLSCTX_LOCAL_SERVER)
|
||||
{
|
||||
auto [error, result] = details::CoCreateInstanceEx<err_exception_policy, Results...>(clsid, clsCtx);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Returns [error, result] where result is a tuple with each of the requested interfaces.
|
||||
template <typename... Results>
|
||||
auto CoCreateInstanceExNoThrow(REFCLSID clsid, CLSCTX clsCtx = CLSCTX_LOCAL_SERVER) noexcept
|
||||
{
|
||||
auto [error, result] = details::CoCreateInstanceEx<err_returncode_policy, Results...>(clsid, clsCtx);
|
||||
if (SUCCEEDED(error) && (error == CO_S_NOTALLINTERFACES))
|
||||
{
|
||||
return std::tuple<HRESULT, decltype(result)>{E_NOINTERFACE, {}};
|
||||
}
|
||||
return std::tuple<HRESULT, decltype(result)>{error, result};
|
||||
}
|
||||
|
||||
template <typename... Results>
|
||||
auto TryCoCreateInstanceExNoThrow(REFCLSID clsid, CLSCTX clsCtx = CLSCTX_LOCAL_SERVER) noexcept
|
||||
{
|
||||
auto [error, result] = details::CoCreateInstanceEx<err_returncode_policy, Results...>(clsid, clsCtx);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename... Results>
|
||||
auto CoCreateInstanceExFailFast(REFCLSID clsid, CLSCTX clsCtx = CLSCTX_LOCAL_SERVER) noexcept
|
||||
{
|
||||
auto [error, result] = details::CoCreateInstanceEx<err_failfast_policy, Results...>(clsid, clsCtx);
|
||||
FAIL_FAST_IF_FAILED(error);
|
||||
FAIL_FAST_HR_IF(E_NOINTERFACE, error == CO_S_NOTALLINTERFACES);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename... Results>
|
||||
auto TryCoCreateInstanceExFailFast(REFCLSID clsid, CLSCTX clsCtx = CLSCTX_LOCAL_SERVER) noexcept
|
||||
{
|
||||
auto [error, result] = details::CoCreateInstanceEx<err_failfast_policy, Results...>(clsid, clsCtx);
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
template<typename... Results>
|
||||
auto com_multi_query(IUnknown* obj)
|
||||
{
|
||||
auto [error, result] = details::com_multi_query<err_exception_policy, Results...>(obj);
|
||||
THROW_IF_FAILED(error);
|
||||
THROW_HR_IF(E_NOINTERFACE, error == S_FALSE);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename... Results>
|
||||
auto try_com_multi_query(IUnknown* obj)
|
||||
{
|
||||
auto [error, result] = details::com_multi_query<err_exception_policy, Results...>(obj);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __cpp_lib_apply && __has_include(<type_traits>)
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Stream helpers
|
||||
@ -2262,8 +2437,8 @@ namespace wil
|
||||
@param value Set to point to the allocated result of reading a string from `source`
|
||||
*/
|
||||
inline HRESULT stream_read_string_nothrow(
|
||||
_In_ ISequentialStream* source,
|
||||
_When_(options == empty_string_options::returns_empty, _Outptr_result_z_) _When_(options == empty_string_options::returns_null, _Outptr_result_maybenull_z_) wchar_t** value,
|
||||
_In_ ISequentialStream* source,
|
||||
_When_(options == empty_string_options::returns_empty, _Outptr_result_z_) _When_(options == empty_string_options::returns_null, _Outptr_result_maybenull_z_) wchar_t** value,
|
||||
empty_string_options options = empty_string_options::returns_empty)
|
||||
{
|
||||
unsigned short cch;
|
||||
@ -2601,8 +2776,8 @@ namespace wil
|
||||
wil::stream_write_string(target, L"Waffles", 3);
|
||||
~~~~
|
||||
@param target The stream to which to write a string
|
||||
@param source The string to write. Can be null if `writeLength` is zero
|
||||
@param writeLength The number of characters to write from source into `target`
|
||||
@param source The string to write. Can be null if `toWriteCch` is zero
|
||||
@param toWriteCch The number of characters to write from source into `target`
|
||||
*/
|
||||
inline void stream_write_string(_In_ ISequentialStream* target, _In_reads_opt_(toWriteCch) const wchar_t* source, _In_ size_t toWriteCch)
|
||||
{
|
||||
|
Reference in New Issue
Block a user