mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-25 23:29:44 -06:00
update wil to 0b2d6c2d822bb301e7558a14ee66d567c14f5dc7
This commit is contained in:
199
Externals/WIL/include/wil/winrt.h
vendored
199
Externals/WIL/include/wil/winrt.h
vendored
@ -19,24 +19,40 @@
|
||||
#include "result.h"
|
||||
#include "com.h"
|
||||
#include "resource.h"
|
||||
#include <windows.foundation.h>
|
||||
#include <windows.foundation.collections.h>
|
||||
|
||||
#ifdef __cplusplus_winrt
|
||||
#include <collection.h> // bring in the CRT iterator for support for C++ CX code
|
||||
#endif
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
/// @cond
|
||||
#if defined(WIL_ENABLE_EXCEPTIONS) && !defined(__WI_HAS_STD_LESS)
|
||||
#ifdef __has_include
|
||||
#if __has_include(<functional>)
|
||||
#define __WI_HAS_STD_LESS 1
|
||||
#include <functional>
|
||||
#endif // Otherwise, not using STL; don't specialize std::less
|
||||
#else
|
||||
// Fall back to the old way of forward declaring std::less
|
||||
#define __WI_HAS_STD_LESS 1
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4643) // Forward declaring '...' in namespace std is not permitted by the C++ Standard.
|
||||
namespace std
|
||||
{
|
||||
template<class _Elem, class _Traits, class _Alloc>
|
||||
class basic_string;
|
||||
|
||||
template<class _Ty>
|
||||
struct less;
|
||||
}
|
||||
/// @endcond
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#endif
|
||||
#if defined(WIL_ENABLE_EXCEPTIONS) && defined(__has_include)
|
||||
#if __has_include(<vector>)
|
||||
#define __WI_HAS_STD_VECTOR 1
|
||||
#include <vector>
|
||||
#endif
|
||||
#endif
|
||||
/// @endcond
|
||||
|
||||
// This enables this code to be used in code that uses the ABI prefix or not.
|
||||
// Code using the public SDK and C++ CX code has the ABI prefix, windows internal
|
||||
@ -50,10 +66,9 @@ namespace std
|
||||
|
||||
namespace wil
|
||||
{
|
||||
#ifdef _INC_TIME
|
||||
// time_t is the number of 1 - second intervals since January 1, 1970.
|
||||
long long const SecondsToStartOf1970 = 0x2b6109100;
|
||||
long long const HundredNanoSecondsInSecond = 10000000LL;
|
||||
constexpr long long SecondsToStartOf1970 = 0x2b6109100;
|
||||
constexpr long long HundredNanoSecondsInSecond = 10000000LL;
|
||||
|
||||
inline __time64_t DateTime_to_time_t(ABI::Windows::Foundation::DateTime dateTime)
|
||||
{
|
||||
@ -67,7 +82,6 @@ namespace wil
|
||||
dateTime.UniversalTime = (timeT + SecondsToStartOf1970) * HundredNanoSecondsInSecond;
|
||||
return dateTime;
|
||||
}
|
||||
#endif // _INC_TIME
|
||||
|
||||
#pragma region HSTRING Helpers
|
||||
/// @cond
|
||||
@ -145,16 +159,17 @@ namespace wil
|
||||
return str;
|
||||
}
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
template<class TraitsT, class AllocT>
|
||||
static const wchar_t* get_buffer(
|
||||
const std::basic_string<wchar_t, TraitsT, AllocT>& str,
|
||||
UINT32* length) WI_NOEXCEPT
|
||||
// Overload for std::wstring, or at least things that behave like std::wstring, without adding a dependency
|
||||
// on STL headers
|
||||
template <typename StringT>
|
||||
static wistd::enable_if_t<wistd::conjunction_v<
|
||||
wistd::is_same<const wchar_t*, decltype(wistd::declval<StringT>().c_str())>,
|
||||
wistd::is_same<typename StringT::size_type, decltype(wistd::declval<StringT>().length())>>,
|
||||
const wchar_t*> get_buffer(const StringT& str, UINT32* length) WI_NOEXCEPT
|
||||
{
|
||||
*length = static_cast<UINT32>(str.length());
|
||||
return str.c_str();
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename LhsT, typename RhsT>
|
||||
static auto compare(LhsT&& lhs, RhsT&& rhs) ->
|
||||
@ -224,8 +239,8 @@ namespace wil
|
||||
//! Detects if one or more embedded null is present in an HSTRING.
|
||||
inline bool HasEmbeddedNull(_In_opt_ HSTRING value)
|
||||
{
|
||||
BOOL hasEmbeddedNull;
|
||||
WindowsStringHasEmbeddedNull(value, &hasEmbeddedNull);
|
||||
BOOL hasEmbeddedNull = FALSE;
|
||||
(void)WindowsStringHasEmbeddedNull(value, &hasEmbeddedNull);
|
||||
return hasEmbeddedNull != FALSE;
|
||||
}
|
||||
|
||||
@ -429,14 +444,14 @@ namespace wil
|
||||
#pragma warning(disable:4702) // https://github.com/Microsoft/wil/issues/2
|
||||
struct type // T holder
|
||||
{
|
||||
type() {};
|
||||
type(T&& value) : m_value(wistd::forward<T>(value)) {};
|
||||
type() = default;
|
||||
type(T&& value) : m_value(wistd::forward<T>(value)) {}
|
||||
operator T() const { return m_value; }
|
||||
type& operator=(T&& value) { m_value = wistd::forward<T>(value); return *this; }
|
||||
T Get() const { return m_value; }
|
||||
|
||||
// Returning T&& to support move only types
|
||||
// In case of absense of T::operator=(T&&) a call to T::operator=(const T&) will happen
|
||||
// In case of absence of T::operator=(T&&) a call to T::operator=(const T&) will happen
|
||||
T&& Get() { return wistd::move(m_value); }
|
||||
|
||||
HRESULT CopyTo(T* result) const { *result = m_value; return S_OK; }
|
||||
@ -730,7 +745,7 @@ namespace wil
|
||||
vector_range_nothrow(const vector_range_nothrow&) = delete;
|
||||
vector_range_nothrow& operator=(const vector_range_nothrow&) = delete;
|
||||
|
||||
vector_range_nothrow(vector_range_nothrow&& other) :
|
||||
vector_range_nothrow(vector_range_nothrow&& other) WI_NOEXCEPT :
|
||||
m_v(other.m_v), m_size(other.m_size), m_result(other.m_result), m_resultStorage(other.m_resultStorage),
|
||||
m_currentElement(wistd::move(other.m_currentElement))
|
||||
{
|
||||
@ -985,6 +1000,39 @@ namespace wil
|
||||
};
|
||||
#pragma endregion
|
||||
|
||||
#if defined(__WI_HAS_STD_VECTOR)
|
||||
/** Converts WinRT vectors to std::vector by requesting the collection's data in a single
|
||||
operation. This can be more efficient in terms of IPC cost than iteratively processing it.
|
||||
~~~
|
||||
ComPtr<IVector<IPropertyValue*>> values = GetValues();
|
||||
std::vector<ComPtr<IPropertyValue>> allData = wil::to_vector(values);
|
||||
for (ComPtr<IPropertyValue> const& item : allData)
|
||||
{
|
||||
// use item
|
||||
}
|
||||
Can be used for ABI::Windows::Foundation::Collections::IVector<T> and
|
||||
ABI::Windows::Foundation::Collections::IVectorView<T>
|
||||
*/
|
||||
template<typename VectorType> auto to_vector(VectorType* src)
|
||||
{
|
||||
using TResult = typename details::MapVectorResultType<VectorType>::type;
|
||||
using TSmart = typename details::MapToSmartType<TResult>::type;
|
||||
static_assert(sizeof(TResult) == sizeof(TSmart), "result and smart sizes are different");
|
||||
std::vector<TSmart> output;
|
||||
UINT32 expected = 0;
|
||||
THROW_IF_FAILED(src->get_Size(&expected));
|
||||
if (expected > 0)
|
||||
{
|
||||
output.resize(expected + 1);
|
||||
UINT32 fetched = 0;
|
||||
THROW_IF_FAILED(src->GetMany(0, static_cast<UINT32>(output.size()), reinterpret_cast<TResult*>(output.data()), &fetched));
|
||||
THROW_HR_IF(E_CHANGED_STATE, fetched > expected);
|
||||
output.resize(fetched);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma region error code base IIterable<>
|
||||
template <typename T>
|
||||
class iterable_range_nothrow
|
||||
@ -998,7 +1046,7 @@ namespace wil
|
||||
iterable_range_nothrow& operator=(const iterable_range_nothrow&) = delete;
|
||||
iterable_range_nothrow& operator=(iterable_range_nothrow &&) = delete;
|
||||
|
||||
iterable_range_nothrow(iterable_range_nothrow&& other) :
|
||||
iterable_range_nothrow(iterable_range_nothrow&& other) WI_NOEXCEPT :
|
||||
m_iterator(wistd::move(other.m_iterator)), m_element(wistd::move(other.m_element)),
|
||||
m_resultStorage(other.m_resultStorage)
|
||||
{
|
||||
@ -1274,9 +1322,9 @@ namespace details
|
||||
// LastType<int, bool>::type boolValue;
|
||||
template <typename... Ts> struct LastType
|
||||
{
|
||||
template<typename T, typename... Ts> struct LastTypeOfTs
|
||||
template<typename T, typename... OtherTs> struct LastTypeOfTs
|
||||
{
|
||||
typedef typename LastTypeOfTs<Ts...>::type type;
|
||||
typedef typename LastTypeOfTs<OtherTs...>::type type;
|
||||
};
|
||||
|
||||
template<typename T> struct LastTypeOfTs<T>
|
||||
@ -1284,8 +1332,8 @@ namespace details
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename... Ts>
|
||||
static typename LastTypeOfTs<Ts...>::type LastTypeOfTsFunc() {}
|
||||
template<typename... OtherTs>
|
||||
static typename LastTypeOfTs<OtherTs...>::type LastTypeOfTsFunc() {}
|
||||
typedef decltype(LastTypeOfTsFunc<Ts...>()) type;
|
||||
};
|
||||
|
||||
@ -1315,14 +1363,28 @@ namespace details
|
||||
typedef wistd::remove_pointer_t<decltype(GetAsyncDelegateType(operation))> TIDelegate;
|
||||
|
||||
auto callback = Callback<Implements<RuntimeClassFlags<ClassicCom>, TIDelegate, TBaseAgility>>(
|
||||
[func = wistd::forward<TFunction>(func)](TIOperation operation, AsyncStatus status) mutable -> HRESULT
|
||||
[func = wistd::forward<TFunction>(func)](TIOperation operation, ABI::Windows::Foundation::AsyncStatus status) mutable -> HRESULT
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (status != AsyncStatus::Completed) // avoid a potentially costly marshaled QI / call if we completed successfully
|
||||
if (status != ABI::Windows::Foundation::AsyncStatus::Completed) // avoid a potentially costly marshaled QI / call if we completed successfully
|
||||
{
|
||||
ComPtr<IAsyncInfo> asyncInfo;
|
||||
operation->QueryInterface(IID_PPV_ARGS(&asyncInfo)); // All must implement IAsyncInfo
|
||||
asyncInfo->get_ErrorCode(&hr);
|
||||
// QI to the IAsyncInfo interface. While all operations implement this, it is
|
||||
// possible that the stub has disconnected, causing the QI to fail.
|
||||
ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
|
||||
hr = operation->QueryInterface(IID_PPV_ARGS(&asyncInfo));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Save the error code result in a temporary variable to allow us
|
||||
// to also retrieve the result of the COM call. If the stub has
|
||||
// disconnected, this call may fail.
|
||||
HRESULT errorCode = E_UNEXPECTED;
|
||||
hr = asyncInfo->get_ErrorCode(&errorCode);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Return the operations error code to the caller.
|
||||
hr = errorCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CallAndHandleErrors(func, hr);
|
||||
@ -1340,21 +1402,35 @@ namespace details
|
||||
typedef wistd::remove_pointer_t<decltype(GetAsyncDelegateType(operation))> TIDelegate;
|
||||
|
||||
auto callback = Callback<Implements<RuntimeClassFlags<ClassicCom>, TIDelegate, TBaseAgility>>(
|
||||
[func = wistd::forward<TFunction>(func)](TIOperation operation, AsyncStatus status) mutable -> HRESULT
|
||||
[func = wistd::forward<TFunction>(func)](TIOperation operation, ABI::Windows::Foundation::AsyncStatus status) mutable -> HRESULT
|
||||
{
|
||||
typename details::MapToSmartType<typename GetAbiType<typename wistd::remove_pointer<TIOperation>::type::TResult_complex>::type>::type result;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
if (status == AsyncStatus::Completed)
|
||||
// avoid a potentially costly marshaled QI / call if we completed successfully
|
||||
if (status == ABI::Windows::Foundation::AsyncStatus::Completed)
|
||||
{
|
||||
hr = operation->GetResults(result.GetAddressOf());
|
||||
}
|
||||
else
|
||||
{
|
||||
// avoid a potentially costly marshaled QI / call if we completed successfully
|
||||
ComPtr<IAsyncInfo> asyncInfo;
|
||||
operation->QueryInterface(IID_PPV_ARGS(&asyncInfo)); // all must implement this
|
||||
asyncInfo->get_ErrorCode(&hr);
|
||||
// QI to the IAsyncInfo interface. While all operations implement this, it is
|
||||
// possible that the stub has disconnected, causing the QI to fail.
|
||||
ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
|
||||
hr = operation->QueryInterface(IID_PPV_ARGS(&asyncInfo));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Save the error code result in a temporary variable to allow us
|
||||
// to also retrieve the result of the COM call. If the stub has
|
||||
// disconnected, this call may fail.
|
||||
HRESULT errorCode = E_UNEXPECTED;
|
||||
hr = asyncInfo->get_ErrorCode(&errorCode);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Return the operations error code to the caller.
|
||||
hr = errorCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CallAndHandleErrors(func, hr, result.Get());
|
||||
@ -1378,7 +1454,7 @@ namespace details
|
||||
RETURN_HR(m_completedEventHandle.create());
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE Invoke(_In_ TIOperation, AsyncStatus status) override
|
||||
HRESULT STDMETHODCALLTYPE Invoke(_In_ TIOperation, ABI::Windows::Foundation::AsyncStatus status) override
|
||||
{
|
||||
m_status = status;
|
||||
m_completedEventHandle.SetEvent();
|
||||
@ -1390,13 +1466,13 @@ namespace details
|
||||
return m_completedEventHandle.get();
|
||||
}
|
||||
|
||||
AsyncStatus GetStatus() const
|
||||
ABI::Windows::Foundation::AsyncStatus GetStatus() const
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
private:
|
||||
volatile AsyncStatus m_status = AsyncStatus::Started;
|
||||
volatile ABI::Windows::Foundation::AsyncStatus m_status = ABI::Windows::Foundation::AsyncStatus::Started;
|
||||
wil::unique_event_nothrow m_completedEventHandle;
|
||||
};
|
||||
|
||||
@ -1419,12 +1495,25 @@ namespace details
|
||||
}
|
||||
RETURN_IF_FAILED(hr);
|
||||
|
||||
if (completedDelegate->GetStatus() != AsyncStatus::Completed)
|
||||
if (completedDelegate->GetStatus() != ABI::Windows::Foundation::AsyncStatus::Completed)
|
||||
{
|
||||
Microsoft::WRL::ComPtr<IAsyncInfo> asyncInfo;
|
||||
operation->QueryInterface(IID_PPV_ARGS(&asyncInfo)); // all must implement this
|
||||
hr = E_UNEXPECTED;
|
||||
asyncInfo->get_ErrorCode(&hr); // error return ignored, ok?
|
||||
// QI to the IAsyncInfo interface. While all operations implement this, it is
|
||||
// possible that the stub has disconnected, causing the QI to fail.
|
||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
|
||||
hr = operation->QueryInterface(IID_PPV_ARGS(&asyncInfo));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Save the error code result in a temporary variable to allow us
|
||||
// to also retrieve the result of the COM call. If the stub has
|
||||
// disconnected, this call may fail.
|
||||
HRESULT errorCode = E_UNEXPECTED;
|
||||
hr = asyncInfo->get_ErrorCode(&errorCode);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Return the operations error code to the caller.
|
||||
hr = errorCode;
|
||||
}
|
||||
}
|
||||
return hr; // leave it to the caller to log failures.
|
||||
}
|
||||
return S_OK;
|
||||
@ -1669,7 +1758,7 @@ namespace details
|
||||
|
||||
IFACEMETHODIMP put_Completed(ABI::Windows::Foundation::IAsyncOperationCompletedHandler<TResult>* competed) override
|
||||
{
|
||||
competed->Invoke(this, AsyncStatus::Completed);
|
||||
competed->Invoke(this, ABI::Windows::Foundation::AsyncStatus::Completed);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -1708,7 +1797,7 @@ namespace details
|
||||
public:
|
||||
IFACEMETHODIMP put_Completed(ABI::Windows::Foundation::IAsyncActionCompletedHandler* competed) override
|
||||
{
|
||||
competed->Invoke(this, AsyncStatus::Completed);
|
||||
competed->Invoke(this, ABI::Windows::Foundation::AsyncStatus::Completed);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -1866,7 +1955,19 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
auto resolvedSender = m_weakSender.Resolve<T>();
|
||||
auto resolvedSender = [&]()
|
||||
{
|
||||
try
|
||||
{
|
||||
return m_weakSender.Resolve<T>();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Ignore RPC or other failures that are unavoidable in some cases
|
||||
// matching wil::unique_winrt_event_token and winrt::event_revoker
|
||||
return static_cast<T^>(nullptr);
|
||||
}
|
||||
}();
|
||||
if (resolvedSender)
|
||||
{
|
||||
(resolvedSender->*m_removalFunction)(m_token);
|
||||
@ -2205,7 +2306,7 @@ struct ABI::Windows::Foundation::IAsyncOperationWithProgressCompletedHandler<ABI
|
||||
#pragma pop_macro("ABI")
|
||||
#endif
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
#if __WI_HAS_STD_LESS
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
Reference in New Issue
Block a user