update wil to 0b2d6c2d822bb301e7558a14ee66d567c14f5dc7

This commit is contained in:
Shawn Hoffman
2023-02-22 13:12:56 -08:00
parent 95ce41ac56
commit 69c335ca8c
66 changed files with 14776 additions and 2507 deletions

View File

@ -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
{