3rdparty: Update WIL to v1.0.250325.1

This commit is contained in:
JordanTheToaster 2025-07-06 22:25:30 +01:00 committed by lightningterror
parent 7dd4ab947b
commit 7e00b2c9a9
20 changed files with 857 additions and 411 deletions

View File

@ -65,7 +65,7 @@
#define _wiltlg_STRINGIZE_imp(x) #x
#define _wiltlg_LSTRINGIZE(x) _wiltlg_LSTRINGIZE_imp1(x)
#define _wiltlg_LSTRINGIZE_imp1(x) _wiltlg_LSTRINGIZE_imp2(#x)
#define _wiltlg_LSTRINGIZE_imp2(s) L##s
#define _wiltlg_LSTRINGIZE_imp2(s) L"" #s
/*
Macro __TRACELOGGING_DEFINE_PROVIDER_STORAGE_LINK(name1, name2):
@ -261,7 +261,8 @@ namespace details
public:
StoredCallContextInfo() WI_NOEXCEPT
{
::ZeroMemory(this, sizeof(*this));
// Suppress '-Wnontrivial-memcall' with 'static_cast'
::ZeroMemory(static_cast<void*>(this), sizeof(*this));
}
StoredCallContextInfo(StoredCallContextInfo&& other) WI_NOEXCEPT : StoredCallContextInfo()
@ -1510,7 +1511,7 @@ public: \
#define __IMPLEMENT_CALLCONTEXT_CLASS(ActivityClassName) \
protected: \
ActivityClassName(_In_opt_ void**, PCSTR contextName, _In_opt_ _Printf_format_string_ PCSTR formatString, _In_opt_ va_list argList) : \
ActivityClassName(_In_opt_ void**, PCSTR contextName, _In_ _Printf_format_string_ PCSTR formatString, _In_opt_ va_list argList) : \
ActivityBase(contextName) \
{ \
GetCallContext()->SetMessage(formatString, argList); \
@ -6444,7 +6445,13 @@ namespace details
if (*lastNamespaceNode)
{
root.swap((*lastNamespaceNode)->next);
// Delete everything from the current root to the lastNamespaceNode
// (inclusive), considering the possibility that they are the same. Continue
// processing from the node following lastNamespaceNode, if any. root will
// be made to point to that.
auto newRoot = wistd::move((*lastNamespaceNode)->next);
const auto toDelete = wistd::move(root);
root = wistd::move(newRoot);
}
else
{

View File

@ -16,12 +16,13 @@
#include <WeakReference.h>
#include <combaseapi.h>
#include "result.h"
#include "win32_helpers.h"
#include "resource.h" // last to ensure _COMBASEAPI_H_ protected definitions are available
#if __has_include(<tuple>)
#if WIL_USE_STL && WI_HAS_INCLUDE(<tuple>, 1) // Tuple is C++11... assume available
#include <tuple>
#endif
#if __has_include(<type_traits>)
#if WIL_USE_STL && WI_HAS_INCLUDE(<type_traits>, 1) // Type traits is old... assume available
#include <type_traits>
#endif
@ -2112,7 +2113,7 @@ wil::com_ptr_nothrow<Interface> CoGetClassObjectNoThrow(DWORD dwClsContext = CLS
return CoGetClassObjectNoThrow<Interface>(__uuidof(Class), dwClsContext);
}
#if __cpp_lib_apply && __has_include(<type_traits>)
#if __cpp_lib_apply && WIL_USE_STL && WI_HAS_INCLUDE(<type_traits>, 1)
/// @cond
namespace details
{
@ -2246,7 +2247,7 @@ auto try_com_multi_query(IUnknown* obj)
}
#endif
#endif // __cpp_lib_apply && __has_include(<type_traits>)
#endif // __cpp_lib_apply && WI_HAS_INCLUDE(<type_traits>, 1)
#pragma endregion
@ -3135,8 +3136,7 @@ void for_each_site(_In_opt_ IUnknown* siteInput, TLambda&& callback)
#endif // __IObjectWithSite_INTERFACE_DEFINED__
// if C++17 or greater
#if WIL_HAS_CXX_17
#if __cpp_deduction_guides >= 201703L
#ifdef WIL_ENABLE_EXCEPTIONS
/// @cond
namespace details
@ -3303,14 +3303,14 @@ WI_NODISCARD auto make_range(IEnumXxx* enumPtr)
using enumerator_type = com_iterator<TActualStoredType, IEnumXxx>;
IEnumXxx* m_enumerator{};
wil::com_ptr<IEnumXxx> m_enumerator{};
iterator_range(IEnumXxx* enumPtr) : m_enumerator(enumPtr)
{
}
WI_NODISCARD auto begin()
{
return enumerator_type(m_enumerator);
return enumerator_type(m_enumerator.get());
}
WI_NODISCARD constexpr auto end() const noexcept
@ -3322,9 +3322,131 @@ WI_NODISCARD auto make_range(IEnumXxx* enumPtr)
return iterator_range(enumPtr);
}
#endif // WIL_HAS_CXX_17
template <typename TEnum, typename = wistd::enable_if_t<wil::details::has_next_v<TEnum*>>>
auto make_range(const wil::com_ptr<TEnum>& e)
{
using Enumerated = typename wil::details::com_enumerator_traits<TEnum>::smart_result;
return wil::make_range<Enumerated>(e.get());
}
#ifdef __IShellItemArray_INTERFACE_DEFINED__
inline auto make_range(IShellItemArray* sia)
{
wil::com_ptr<IEnumShellItems> enumShellItems;
THROW_IF_FAILED(sia->EnumItems(&enumShellItems));
return make_range(enumShellItems);
}
inline auto make_range(const wil::com_ptr<IShellItemArray>& sia)
{
return make_range(sia.get());
}
#endif // __IShellItemArray_INTERFACE_DEFINED__
#endif // __cpp_deduction_guides >= 201703L
#endif // WIL_ENABLE_EXCEPTIONS
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
namespace details
{
inline void CoDisableCallCancellationNull()
{
(void)::CoDisableCallCancellation(nullptr);
}
} // namespace details
/** RAII support for making cross-apartment (or cross process) COM calls with a timeout applied to them.
* When this is active any timed out calls will fail with an RPC error code such as RPC_E_CALL_CANCELED.
* This is a shared timeout that applies to all calls made on the current thread for the lifetime of
* the wil::com_timeout object.
* A periodic timer is used to cancel calls that have been blocked too long. If multiple blocking calls
* are made, and multiple are timing out, then there may be a total delay of (timeoutInMilliseconds * N)
* where N is the number of calls.
~~~
{
auto timeout = wil::com_timeout(5000);
remote_object->BlockingCOMCall();
remote_object->AnotherBlockingCOMCall();
}
~~~
*/
template <typename err_policy>
class com_timeout_t
{
public:
com_timeout_t(DWORD timeoutInMilliseconds) : m_threadId(GetCurrentThreadId())
{
const HRESULT cancelEnablementResult = CoEnableCallCancellation(nullptr);
err_policy::HResult(cancelEnablementResult);
if (SUCCEEDED(cancelEnablementResult))
{
m_ensureDisable.activate();
m_timer.reset(CreateThreadpoolTimer(&com_timeout_t::timer_callback, this, nullptr));
err_policy::LastErrorIfFalse(static_cast<bool>(m_timer));
if (m_timer)
{
FILETIME ft = filetime::get_system_time();
ft = filetime::add(ft, filetime::convert_msec_to_100ns(timeoutInMilliseconds));
SetThreadpoolTimer(m_timer.get(), &ft, timeoutInMilliseconds, 0);
}
}
}
bool timed_out() const
{
return m_timedOut;
}
operator bool() const noexcept
{
// All construction calls must succeed to provide us with a non-null m_timer value.
return static_cast<bool>(m_timer);
}
private:
// Disable use of new as this class should only be declared on the stack, never the heap.
void* operator new(size_t) = delete;
void* operator new[](size_t) = delete;
// not copyable or movable because the timer_callback receives "this"
com_timeout_t(com_timeout_t const&) = delete;
void operator=(com_timeout_t const&) = delete;
static void __stdcall timer_callback(PTP_CALLBACK_INSTANCE /*instance*/, PVOID context, PTP_TIMER /*timer*/)
{
// The timer is waited upon during destruction so it is safe to rely on the this pointer in context.
com_timeout_t* self = static_cast<com_timeout_t*>(context);
if (SUCCEEDED(CoCancelCall(self->m_threadId, 0)))
{
self->m_timedOut = true;
}
}
wil::unique_call<decltype(&details::CoDisableCallCancellationNull), details::CoDisableCallCancellationNull, false> m_ensureDisable{};
DWORD m_threadId{};
bool m_timedOut{};
// The threadpool timer goes last so that it destructs first, waiting until the timer callback has completed.
wil::unique_threadpool_timer_nocancel m_timer;
};
// Error-policy driven forms of com_timeout
#ifdef WIL_ENABLE_EXCEPTIONS
//! COM timeout, errors throw exceptions (see @ref com_timeout_t for details)
using com_timeout = com_timeout_t<err_exception_policy>;
#endif
//! COM timeout, errors return error codes (see @ref com_timeout_t for details)
using com_timeout_nothrow = com_timeout_t<err_returncode_policy>;
//! COM timeout, errors fail-fast (see @ref com_timeout_t for details)
using com_timeout_failfast = com_timeout_t<err_failfast_policy>;
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
} // namespace wil
#endif

View File

@ -69,15 +69,14 @@
/// @cond
#if defined(_MSVC_LANG)
#define __WI_SUPPRESS_4127_S \
__pragma(warning(push)) __pragma(warning(disable : 4127)) __pragma(warning(disable : 26498)) __pragma(warning(disable : 4245))
#define __WI_SUPPRESS_4127_E __pragma(warning(pop))
#define __WI_SUPPRESS_NULLPTR_ANALYSIS __pragma(warning(suppress : 28285)) __pragma(warning(suppress : 6504))
#define __WI_SUPPRESS_BREAKING_WARNINGS_S __pragma(warning(push)) __pragma(warning(disable : 4127 26498 4245 26814))
#define __WI_SUPPRESS_BREAKING_WARNINGS_E __pragma(warning(pop))
#define __WI_SUPPRESS_NULLPTR_ANALYSIS __pragma(warning(suppress : 28285 6504))
#define __WI_SUPPRESS_NONINIT_ANALYSIS __pragma(warning(suppress : 26495))
#define __WI_SUPPRESS_NOEXCEPT_ANALYSIS __pragma(warning(suppress : 26439))
#else
#define __WI_SUPPRESS_4127_S
#define __WI_SUPPRESS_4127_E
#define __WI_SUPPRESS_BREAKING_WARNINGS_S
#define __WI_SUPPRESS_BREAKING_WARNINGS_E
#define __WI_SUPPRESS_NULLPTR_ANALYSIS
#define __WI_SUPPRESS_NONINIT_ANALYSIS
#define __WI_SUPPRESS_NOEXCEPT_ANALYSIS
@ -306,6 +305,29 @@ static_assert(WIL_EXCEPTION_MODE <= 2, "Invalid exception mode");
#error Must enable exceptions when WIL_EXCEPTION_MODE == 1
#endif
#ifdef WIL_DOXYGEN
/** This define is used to control whether or not WIL assumes safe access to the STL.
This define can be set manually (1 to enable, 0 to disable), otherwise heuristics will be applied in an attempt to
deduce whether or not the STL is available and can be safely used.
*/
#define WIL_USE_STL 1
#elif !defined(WIL_USE_STL)
#if !defined(WIL_ENABLE_EXCEPTIONS) || !defined(__has_include)
// Assume it's not safe to use the STL when:
// * Exceptions are not enabled, OR
// * We can't check for header presence
#define WIL_USE_STL 0
#else
// Check for several STL headers that have been around since the dawn of time
#if __has_include(<algorithm>) && __has_include(<exception>) && __has_include(<iterator>) && __has_include(<new>) && \
__has_include(<string>) && __has_include(<utility>) && __has_include(<vector>)
#define WIL_USE_STL 1
#else
#define WIL_USE_STL 0
#endif
#endif
#endif
/// @cond
#ifndef WIL_ITERATOR_DEBUG_LEVEL
// NOTE: See the definition of 'RESULT_DEBUG' for commentary on the use of 'WIL_KERNEL_MODE' below
@ -373,19 +395,19 @@ check fails as opposed to the invalid parameter handler that the STL invokes. Th
#endif
/// @cond
#if (__cplusplus >= 201703) || (_MSVC_LANG >= 201703)
#define WIL_HAS_CXX_17 1
#else
#define WIL_HAS_CXX_17 0
#endif
// Until we'll have C++17 enabled in our code base, we're falling back to SAL
#define WI_NODISCARD __WI_LIBCPP_NODISCARD_ATTRIBUTE
/// @endcond
/// @cond
#define __R_ENABLE_IF_IS_CLASS(ptrType) wistd::enable_if_t<wistd::is_class<ptrType>::value, void*> = nullptr
#define __R_ENABLE_IF_IS_NOT_CLASS(ptrType) wistd::enable_if_t<!wistd::is_class<ptrType>::value, void*> = nullptr
// Uses the __has_include macro, if available. Otherwise uses a user-provided fallback. E.g. the fallback could always
// default to true or false, or it could do something like a C++ standard version check
#ifdef __has_include
#define WI_HAS_INCLUDE(header, fallback) __has_include(header)
#else
#define WI_HAS_INCLUDE(header, fallback) (fallback)
#endif
/// @endcond
//! @defgroup bitwise Bitwise Inspection and Manipulation
@ -690,32 +712,32 @@ boolean, BOOLEAN, and classes with an explicit bool cast.
@param val The logical bool expression
@return A C++ bool representing the evaluation of `val`. */
template <typename T, __R_ENABLE_IF_IS_CLASS(T)>
_Post_satisfies_(return == static_cast<bool>(val)) __forceinline constexpr bool verify_bool(const T& val) WI_NOEXCEPT
_Post_satisfies_(return == static_cast<bool>(val)) inline constexpr bool verify_bool(const T& val) WI_NOEXCEPT
{
return static_cast<bool>(val);
}
template <typename T, __R_ENABLE_IF_IS_NOT_CLASS(T)>
__forceinline constexpr bool verify_bool(T /*val*/) WI_NOEXCEPT
inline constexpr bool verify_bool(T /*val*/) WI_NOEXCEPT
{
static_assert(!wistd::is_same<T, T>::value, "Wrong Type: bool/BOOL/BOOLEAN/boolean expected");
return false;
}
template <>
_Post_satisfies_(return == val) __forceinline constexpr bool verify_bool<bool>(bool val) WI_NOEXCEPT
_Post_satisfies_(return == val) inline constexpr bool verify_bool<bool>(bool val) WI_NOEXCEPT
{
return val;
}
template <>
_Post_satisfies_(return == (val != 0)) __forceinline constexpr bool verify_bool<int>(int val) WI_NOEXCEPT
_Post_satisfies_(return == (val != 0)) inline constexpr bool verify_bool<int>(int val) WI_NOEXCEPT
{
return (val != 0);
}
template <>
_Post_satisfies_(return == (val != 0)) __forceinline constexpr bool verify_bool<unsigned char>(unsigned char val) WI_NOEXCEPT
_Post_satisfies_(return == (val != 0)) inline constexpr bool verify_bool<unsigned char>(unsigned char val) WI_NOEXCEPT
{
return (val != 0);
}
@ -726,7 +748,7 @@ accept any `int` value as long as that is the underlying typedef behind `BOOL`.
@param val The Win32 BOOL returning expression
@return A Win32 BOOL representing the evaluation of `val`. */
template <typename T>
_Post_satisfies_(return == val) __forceinline constexpr int verify_BOOL(T val) WI_NOEXCEPT
_Post_satisfies_(return == val) inline constexpr int verify_BOOL(T val) WI_NOEXCEPT
{
// Note: Written in terms of 'int' as BOOL is actually: typedef int BOOL;
static_assert((wistd::is_same<T, int>::value), "Wrong Type: BOOL expected");
@ -820,7 +842,7 @@ namespace details
: sizeof(val) == 2 ? static_cast<unsigned short>(val) \
: sizeof(val) == 4 ? static_cast<unsigned long>(val) \
: static_cast<unsigned long long>(val)) __pragma(warning(pop)))
#define __WI_IS_UNSIGNED_SINGLE_FLAG_SET(val) ((val) && !((val) & ((val)-1)))
#define __WI_IS_UNSIGNED_SINGLE_FLAG_SET(val) ((val) && !((val) & ((val) - 1)))
#define __WI_IS_SINGLE_FLAG_SET(val) __WI_IS_UNSIGNED_SINGLE_FLAG_SET(__WI_MAKE_UNSIGNED(val))
template <typename TVal, typename TFlags>

View File

@ -26,6 +26,10 @@
#include "win32_helpers.h"
#include "resource.h"
#if WIL_USE_STL
#include <iterator>
#endif
namespace wil
{
//! Determines if a path is an extended length path that can be used to access paths longer than MAX_PATH.
@ -403,7 +407,7 @@ struct next_entry_offset_iterator
using value_type = T;
using pointer = const T*;
using reference = const T&;
#ifdef _XUTILITY_
#if WIL_USE_STL
using iterator_category = ::std::forward_iterator_tag;
#endif

View File

@ -19,7 +19,7 @@
// Helpers for return macros
/// @cond
#define __NT_RETURN_NTSTATUS(status, str) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
NTSTATUS __status = (status); \
if (FAILED_NTSTATUS(__status)) \
@ -28,9 +28,9 @@
} \
return __status; \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define __NT_RETURN_NTSTATUS_MSG(status, str, fmt, ...) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
NTSTATUS __status = (status); \
if (FAILED_NTSTATUS(__status)) \
@ -39,7 +39,7 @@
} \
return __status; \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
/// @endcond
//*****************************************************************************
@ -55,7 +55,7 @@
// Conditionally returns failures (NTSTATUS) - always logs failures
#define NT_RETURN_IF_NTSTATUS_FAILED(status) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const auto __statusRet = wil::verify_ntstatus(status); \
if (FAILED_NTSTATUS(__statusRet)) \
@ -63,11 +63,11 @@
__NT_RETURN_NTSTATUS(__statusRet, #status); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
// Conditionally returns failures (NTSTATUS) - always logs a var-arg message on failure
#define NT_RETURN_IF_NTSTATUS_FAILED_MSG(status, fmt, ...) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const auto __statusRet = wil::verify_ntstatus(status); \
if (FAILED_NTSTATUS(__statusRet)) \
@ -75,7 +75,7 @@
__NT_RETURN_NTSTATUS_MSG(__statusRet, #status, fmt, ##__VA_ARGS__); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
//*****************************************************************************
// Macros to catch and convert exceptions on failure
@ -138,11 +138,11 @@ _Always_(_Post_satisfies_(return < 0)) __declspec(noinline) inline NTSTATUS Stat
namespace details
{
template <FailureType>
__declspec(noinline) inline NTSTATUS
ReportStatus_CaughtException(__R_FN_PARAMS_FULL, SupportedExceptions supported = SupportedExceptions::Default);
__declspec(noinline) inline NTSTATUS ReportStatus_CaughtException(
__R_FN_PARAMS_FULL, SupportedExceptions supported = SupportedExceptions::Default);
template <FailureType>
__declspec(noinline) inline NTSTATUS
ReportStatus_CaughtExceptionMsg(__R_FN_PARAMS_FULL, _Printf_format_string_ PCSTR formatString, va_list argList);
__declspec(noinline) inline NTSTATUS ReportStatus_CaughtExceptionMsg(
__R_FN_PARAMS_FULL, _Printf_format_string_ PCSTR formatString, va_list argList);
namespace __R_NS_NAME
{
@ -191,8 +191,7 @@ namespace details
}
template <FailureType T>
__declspec(noinline) inline NTSTATUS
ReportStatus_CaughtExceptionMsg(__R_FN_PARAMS_FULL, _Printf_format_string_ PCSTR formatString, va_list argList)
__declspec(noinline) inline NTSTATUS ReportStatus_CaughtExceptionMsg(__R_FN_PARAMS_FULL, _Printf_format_string_ PCSTR formatString, va_list argList)
{
// Pre-populate the buffer with our message, the exception message will be added to it...
wchar_t message[2048];

View File

@ -223,7 +223,7 @@ namespace reg
//
#if defined(WIL_ENABLE_EXCEPTIONS)
#if defined(_STRING_) || defined(WIL_DOXYGEN)
#if WIL_USE_STL || defined(WIL_DOXYGEN)
using key_iterator = ::wil::reg::iterator_t<::wil::reg::key_iterator_data<::std::wstring>>;
using value_iterator = ::wil::reg::iterator_t<::wil::reg::value_iterator_data<::std::wstring>>;
#endif
@ -583,7 +583,7 @@ namespace reg
::wil::reg::set_value_expanded_string(key, nullptr, value_name, data);
}
#if (defined(_VECTOR_) && defined(_STRING_)) || defined(WIL_DOXYGEN)
#if WIL_USE_STL || defined(WIL_DOXYGEN)
/**
* @brief The generic set_value template function to write a REG_MULTI_SZ value from a std::vector<std::wstring>
* @param key An open or well-known registry key
@ -645,9 +645,9 @@ namespace reg
{
::wil::reg::set_value(key, nullptr, value_name, data);
}
#endif // #if defined(_VECTOR_) && defined(_STRING_)
#endif
#if defined(_VECTOR_) || defined(WIL_DOXYGEN)
#if WIL_USE_STL || defined(WIL_DOXYGEN)
/**
* @brief Writes a registry value of the specified type from a `std::vector<uint8_t>`/`std::vector<BYTE>`
* @param key An open or well-known registry key
@ -680,8 +680,8 @@ namespace reg
{
::wil::reg::set_value_binary(key, nullptr, value_name, type, data);
}
#endif // #if defined(_VECTOR_)
#endif // #if defined(WIL_ENABLE_EXCEPTIONS)
#endif
#endif
//
// template <typename T>
@ -1087,7 +1087,7 @@ namespace reg
return ::wil::reg::get_value<uint64_t>(key, nullptr, value_name);
}
#if defined(_STRING_) || defined(WIL_DOXYGEN)
#if WIL_USE_STL || defined(WIL_DOXYGEN)
/**
* @brief Reads a REG_SZ value, returning a std::wstring
* @param key An open or well-known registry key
@ -1210,7 +1210,7 @@ namespace reg
{
return ::wil::reg::get_value_expanded_string(key, nullptr, value_name);
}
#endif // #if defined(_STRING_)
#endif
#if defined(__WIL_OLEAUTO_H_) || defined(WIL_DOXYGEN)
/**
@ -1482,7 +1482,7 @@ namespace reg
#endif // #if defined(__WIL_OBJBASE_H_STL)
#endif // defined(__WIL_OBJBASE_H_)
#if defined(_VECTOR_) || defined(WIL_DOXYGEN)
#if WIL_USE_STL || defined(WIL_DOXYGEN)
/**
* @brief Reads a registry value of the specified type, returning a std::vector<BYTE>
* @param key An open or well-known registry key
@ -1515,9 +1515,9 @@ namespace reg
{
return ::wil::reg::get_value_binary(key, nullptr, value_name, type);
}
#endif // #if defined(_VECTOR_)
#endif
#if (defined(_VECTOR_) && defined(_STRING_)) || defined(WIL_DOXYGEN)
#if WIL_USE_STL || defined(WIL_DOXYGEN)
/**
* @brief Reads a REG_MULTI_SZ value, returning a std::vector<std::wstring>
* @param key An open or well-known registry key
@ -1600,9 +1600,9 @@ namespace reg
{
return ::wil::reg::get_value<::std::vector<::std::wstring>>(key, nullptr, value_name);
}
#endif // #if defined(_VECTOR_) && defined(_STRING_)
#endif
#if (defined(_OPTIONAL_) && defined(__cpp_lib_optional)) || defined(WIL_DOXYGEN)
#if (WIL_USE_STL && (__cpp_lib_optional >= 201606L)) || defined(WIL_DOXYGEN)
//
// template <typename T>
// void try_get_value(...)
@ -1819,7 +1819,7 @@ namespace reg
return ::wil::reg::try_get_value<uint64_t>(key, nullptr, value_name);
}
#if defined(_VECTOR_) || defined(WIL_DOXYGEN)
#if WIL_USE_STL || defined(WIL_DOXYGEN)
/**
* @brief Attempts to read a value under a specified key requiring the specified type, returning the raw bytes in a
* std::optional
@ -1854,9 +1854,9 @@ namespace reg
{
return ::wil::reg::try_get_value_binary(key, nullptr, value_name, type);
}
#endif // #if defined(_VECTOR_)
#endif
#if defined(_STRING_) || defined(WIL_DOXYGEN)
#if WIL_USE_STL || defined(WIL_DOXYGEN)
/**
* @brief Attempts to read a REG_SZ value under a specified key, returning the value in a std::optional
* @param key An open or well-known registry key
@ -1986,7 +1986,7 @@ namespace reg
{
return ::wil::reg::try_get_value_expanded_string(key, nullptr, value_name);
}
#endif // #if defined(_STRING_)
#endif
#if defined(__WIL_OLEAUTO_H_STL) || defined(WIL_DOXYGEN)
/**
@ -2132,7 +2132,7 @@ namespace reg
}
#endif // defined(__WIL_OBJBASE_H_STL)
#if (defined(_VECTOR_) && defined(_STRING_)) || defined(WIL_DOXYGEN)
#if WIL_USE_STL || defined(WIL_DOXYGEN)
/**
* @brief Attempts to read a REG_MULTI_SZ value under a specified key, returning the value in a std::optional
* @param key An open or well-known registry key
@ -2209,9 +2209,9 @@ namespace reg
{
return ::wil::reg::try_get_value<::std::vector<::std::wstring>>(key, nullptr, value_name);
}
#endif // #if defined (_VECTOR_) && defined (_STRING_)
#endif // #if defined (_OPTIONAL_) && defined(__cpp_lib_optional)
#endif // #if defined(WIL_ENABLE_EXCEPTIONS)
#endif
#endif
#endif
//
// template <typename T>

View File

@ -13,9 +13,17 @@
#ifndef __WIL_REGISTRY_HELPERS_INCLUDED
#define __WIL_REGISTRY_HELPERS_INCLUDED
#if defined(_STRING_) || defined(_VECTOR_) || (defined(__cpp_lib_optional) && defined(_OPTIONAL_)) || defined(WIL_DOXYGEN)
#include "common.h"
#if WIL_USE_STL
#include <functional>
#include <iterator>
#include <string>
#include <vector>
#if (__WI_LIBCPP_STD_VER >= 17) && WI_HAS_INCLUDE(<optional>, 1) // Assume present if C++17 or later
#include <optional>
#endif
#endif
#include <stdint.h>
@ -142,7 +150,7 @@ namespace reg
}
}
#if defined(_VECTOR_) && defined(_STRING_) && defined(WIL_ENABLE_EXCEPTIONS)
#if (WIL_USE_STL && defined(WIL_ENABLE_EXCEPTIONS)) || defined(WIL_DOXYGEN)
/**
* @brief A translation function taking iterators referencing std::wstring objects and returns a corresponding
* std::vector<wchar_t> to be written to a MULTI_SZ registry value. The translation follows the rules for how
@ -203,7 +211,7 @@ namespace reg
});
return strings;
}
#endif // #if defined(_VECTOR_) && defined(_STRING_) && defined(WIL_ENABLE_EXCEPTIONS)
#endif
#if defined(__WIL_OBJBASE_H_)
template <size_t C>
@ -442,7 +450,7 @@ namespace reg
return static_cast<DWORD>((::wcslen(value) + 1) * sizeof(wchar_t));
}
#if defined(_VECTOR_) && defined(WIL_ENABLE_EXCEPTIONS)
#if (WIL_USE_STL && defined(WIL_ENABLE_EXCEPTIONS)) || defined(WIL_DOXYGEN)
inline void* get_buffer(const ::std::vector<uint8_t>& buffer) WI_NOEXCEPT
{
return const_cast<uint8_t*>(buffer.data());
@ -517,9 +525,9 @@ namespace reg
}
return S_OK;
}
#endif // #if defined(_VECTOR_) && defined(WIL_ENABLE_EXCEPTIONS)
#endif
#if defined(_STRING_) && defined(WIL_ENABLE_EXCEPTIONS)
#if (WIL_USE_STL && defined(WIL_ENABLE_EXCEPTIONS)) || defined(WIL_DOXYGEN)
inline void* get_buffer(const ::std::wstring& string) WI_NOEXCEPT
{
return const_cast<wchar_t*>(string.data());
@ -575,7 +583,7 @@ namespace reg
}
return buffer.size();
}
#endif // #if defined(_STRING_) && defined(WIL_ENABLE_EXCEPTIONS)
#endif
#if defined(__WIL_OLEAUTO_H_)
inline void* get_buffer(const BSTR& value) WI_NOEXCEPT
@ -972,7 +980,7 @@ namespace reg
return REG_SZ;
}
#if defined(_STRING_) && defined(WIL_ENABLE_EXCEPTIONS)
#if (WIL_USE_STL && defined(WIL_ENABLE_EXCEPTIONS)) || defined(WIL_DOXYGEN)
template <>
constexpr DWORD get_value_type<::std::wstring>() WI_NOEXCEPT
{
@ -984,7 +992,7 @@ namespace reg
{
return REG_SZ;
}
#endif // #if defined(_STRING_) && defined(WIL_ENABLE_EXCEPTIONS)
#endif
#if defined(__WIL_OLEAUTO_H_)
template <>
@ -1129,7 +1137,7 @@ namespace reg
return err_policy::HResult(hr);
}
#if defined(_OPTIONAL_) && defined(__cpp_lib_optional)
#if (WIL_USE_STL && (__cpp_lib_optional >= 201606L)) || defined(WIL_DOXYGEN)
// intended for err_exception_policy as err_returncode_policy will not get an error code
template <typename R>
::std::optional<R> try_get_value(
@ -1151,7 +1159,7 @@ namespace reg
err_policy::HResult(hr);
return ::std::nullopt;
}
#endif // #if defined (_OPTIONAL_) && defined(__cpp_lib_optional)
#endif
template <typename R>
typename err_policy::result set_value(
@ -1313,7 +1321,7 @@ namespace reg
}
#endif // #if defined(__WIL_WINREG_STL)
#if defined(WIL_ENABLE_EXCEPTIONS) && defined(_STRING_)
#if (WIL_USE_STL && defined(WIL_ENABLE_EXCEPTIONS)) || defined(WIL_DOXYGEN)
// overloads for some of the below string functions - specific for std::wstring
// these overloads must be declared before the template functions below, as some of those template functions
// reference these overload functions
@ -1340,7 +1348,7 @@ namespace reg
{
return !name.empty();
}
#endif // #if defined(WIL_ENABLE_EXCEPTIONS) && defined(_STRING_)
#endif
// string manipulation functions needed for iterator functions
template <typename T>
@ -1730,7 +1738,7 @@ namespace reg
// Notice this is a forward_iterator
// - does not support random-access (e.g. vector::iterator)
// - does not support bidirectional access (e.g. list::iterator)
#if defined(_ITERATOR_) || defined(WIL_DOXYGEN)
#if WIL_USE_STL || defined(WIL_DOXYGEN)
using iterator_category = ::std::forward_iterator_tag;
#endif
using value_type = T;

View File

@ -16,6 +16,10 @@
#include "wistd_functional.h"
#include "wistd_memory.h"
#if WIL_USE_STL
#include <iterator>
#endif
#pragma warning(push)
#pragma warning(disable : 26135 26110) // Missing locking annotation, Caller failing to hold lock
#pragma warning(disable : 4714) // __forceinline not honored
@ -1004,7 +1008,8 @@ private:
void call_init(wistd::true_type)
{
RtlZeroMemory(this, sizeof(*this));
// Suppress '-Wnontrivial-memcall' with 'static_cast'
RtlZeroMemory(static_cast<void*>(this), sizeof(*this));
}
void call_init(wistd::false_type)
@ -3717,6 +3722,14 @@ namespace details
{
::HeapFree(::GetProcessHeap(), 0, p);
}
struct heap_allocator
{
static _Ret_opt_bytecap_(size) void* allocate(size_t size) WI_NOEXCEPT
{
return ::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, size);
}
};
} // namespace details
/// @endcond
@ -3747,25 +3760,6 @@ struct mapview_deleter
}
};
template <typename T = void>
using unique_process_heap_ptr = wistd::unique_ptr<details::ensure_trivially_destructible_t<T>, process_heap_deleter>;
typedef unique_any<PWSTR, decltype(&details::FreeProcessHeap), details::FreeProcessHeap> unique_process_heap_string;
/// @cond
namespace details
{
template <>
struct string_allocator<unique_process_heap_string>
{
static _Ret_opt_bytecap_(size) void* allocate(size_t size) WI_NOEXCEPT
{
return ::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, size);
}
};
} // namespace details
/// @endcond
/** Manages a typed pointer allocated with VirtualAlloc
A specialization of wistd::unique_ptr<> that frees via VirtualFree(p, 0, MEM_RELEASE).
*/
@ -4061,6 +4055,93 @@ typedef weak_any<shared_hfind_change> weak_hfind_change;
#endif // __WIL_WINBASE_STL
#if (defined(_HEAPAPI_H_) && !defined(__WIL__WIL_HEAP_API) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) && !defined(WIL_KERNEL_MODE)) || \
defined(WIL_DOXYGEN)
/// @cond
#define __WIL__WIL_HEAP_API
/// @endcond
template <typename T = void>
using unique_process_heap_ptr = wistd::unique_ptr<details::ensure_trivially_destructible_t<T>, process_heap_deleter>;
typedef unique_any<void*, decltype(&details::FreeProcessHeap), details::FreeProcessHeap> unique_process_heap;
typedef unique_any<PWSTR, decltype(&details::FreeProcessHeap), details::FreeProcessHeap> unique_process_heap_string;
#ifndef WIL_NO_ANSI_STRINGS
typedef unique_any<PSTR, decltype(&wil::details::FreeProcessHeap), wil::details::FreeProcessHeap> unique_process_heap_ansistring;
#endif // WIL_NO_ANSI_STRINGS
/// @cond
namespace details
{
template <>
struct string_allocator<wil::unique_process_heap_string> : heap_allocator
{
};
#ifndef WIL_NO_ANSI_STRINGS
template <>
struct string_allocator<unique_process_heap_ansistring> : heap_allocator
{
};
#endif
} // namespace details
/// @endcond
inline auto make_process_heap_string_nothrow(
_When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
_When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_) PCWSTR source,
size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
{
return make_unique_string_nothrow<unique_process_heap_string>(source, length);
}
inline auto make_process_heap_string_failfast(
_When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
_When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_) PCWSTR source,
size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
{
return make_unique_string_failfast<unique_process_heap_string>(source, length);
}
#ifndef WIL_NO_ANSI_STRINGS
inline auto make_process_heap_ansistring_nothrow(
_When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
_When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_) PCSTR source,
size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
{
return make_unique_ansistring_nothrow<unique_process_heap_ansistring>(source, length);
}
inline auto make_process_heap_ansistring_failfast(
_When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
_When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_) PCSTR source,
size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
{
return make_unique_ansistring_failfast<unique_process_heap_ansistring>(source, length);
}
#endif // WIL_NO_ANSI_STRINGS
#ifdef WIL_ENABLE_EXCEPTIONS
inline auto make_process_heap_string(
_When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
_When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_) PCWSTR source,
size_t length = static_cast<size_t>(-1))
{
return make_unique_string<unique_process_heap_string>(source, length);
}
#ifndef WIL_NO_ANSI_STRINGS
inline auto make_process_heap_ansistring(
_When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
_When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_) PCSTR source,
size_t length = static_cast<size_t>(-1))
{
return make_unique_ansistring<unique_process_heap_ansistring>(source, length);
}
#endif // WIL_NO_ANSI_STRINGS
#endif // WIL_ENABLE_EXCEPTIONS
#endif // _HEAPAPI_H_
#if (defined(__WIL_WINBASE_) && defined(__NOTHROW_T_DEFINED) && !defined(__WIL_WINBASE_NOTHROW_T_DEFINED_STL) && defined(WIL_RESOURCE_STL) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) || \
defined(WIL_DOXYGEN)
/// @cond
@ -4508,32 +4589,6 @@ namespace details
} // namespace details
/// @endcond
inline auto make_process_heap_string_nothrow(
_When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
_When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_) PCWSTR source,
size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
{
return make_unique_string_nothrow<unique_process_heap_string>(source, length);
}
inline auto make_process_heap_string_failfast(
_When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
_When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_) PCWSTR source,
size_t length = static_cast<size_t>(-1)) WI_NOEXCEPT
{
return make_unique_string_failfast<unique_process_heap_string>(source, length);
}
#ifdef WIL_ENABLE_EXCEPTIONS
inline auto make_process_heap_string(
_When_((source != nullptr) && length != static_cast<size_t>(-1), _In_reads_(length))
_When_((source != nullptr) && length == static_cast<size_t>(-1), _In_z_) PCWSTR source,
size_t length = static_cast<size_t>(-1))
{
return make_unique_string<unique_process_heap_string>(source, length);
}
#endif // WIL_ENABLE_EXCEPTIONS
typedef unique_any_handle_null<decltype(&::HeapDestroy), ::HeapDestroy> unique_hheap;
typedef unique_any<DWORD, decltype(&::TlsFree), ::TlsFree, details::pointer_access_all, DWORD, DWORD, TLS_OUT_OF_INDEXES, DWORD> unique_tls;
typedef unique_any<PSECURITY_DESCRIPTOR, decltype(&::LocalFree), ::LocalFree> unique_hlocal_security_descriptor;
@ -7296,7 +7351,7 @@ namespace details
struct iterator
{
#if defined(_XUTILITY_) || defined(WIL_DOXYGEN)
#if WIL_USE_STL || defined(WIL_DOXYGEN)
// muse be input_iterator_tag as use of one instance invalidates the other.
typedef ::std::input_iterator_tag iterator_category;
#endif

View File

@ -435,7 +435,7 @@ namespace details_abi
private:
struct Node
{
DWORD threadId = 0xffffffff; // MAXDWORD
DWORD threadId = 0xffffffffu;
Node* pNext = nullptr;
T value{};
};
@ -1166,8 +1166,8 @@ inline void WilInitialize_Result(WilInitializeCommand state)
namespace details
{
#ifndef RESULT_SUPPRESS_STATIC_INITIALIZERS
__declspec(selectany)::wil::details_abi::ProcessLocalStorage<::wil::details_abi::ProcessLocalData> g_processLocalData("WilError_03");
__declspec(selectany)::wil::details_abi::ThreadLocalStorage<ThreadFailureCallbackHolder*> g_threadFailureCallbacks;
__declspec(selectany) ::wil::details_abi::ProcessLocalStorage<::wil::details_abi::ProcessLocalData> g_processLocalData("WilError_03");
__declspec(selectany) ::wil::details_abi::ThreadLocalStorage<ThreadFailureCallbackHolder*> g_threadFailureCallbacks;
WI_HEADER_INITIALIZATION_FUNCTION(InitializeResultHeader, [] {
g_pfnGetContextAndNotifyFailure = GetContextAndNotifyFailure;

View File

@ -123,7 +123,7 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
// It would appear as though the C++17 "noexcept is part of the type system" update in MSVC has "infected" the behavior
// when compiling with C++14 (the default...), however the updated behavior for decltype understanding noexcept is _not_
// present... So, work around it
#if __WI_LIBCPP_STD_VER >= 17
#if __cpp_noexcept_function_type >= 201510L
#define WI_PFN_NOEXCEPT WI_NOEXCEPT
#else
#define WI_PFN_NOEXCEPT
@ -671,7 +671,7 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
// Helpers for return macros
#define __RETURN_HR_MSG(hr, str, fmt, ...) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const HRESULT __hr = (hr); \
if (FAILED(__hr)) \
@ -680,17 +680,17 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
} \
return __hr; \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define __RETURN_HR_MSG_FAIL(hr, str, fmt, ...) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const HRESULT __hr = (hr); \
__R_FN(Return_HrMsg)(__R_INFO(str) __hr, __WI_CHECK_MSG_FMT(fmt, ##__VA_ARGS__)); \
return __hr; \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define __RETURN_WIN32_MSG(err, str, fmt, ...) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const DWORD __err = (err); \
if (FAILED_WIN32(__err)) \
@ -699,18 +699,18 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
} \
return S_OK; \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define __RETURN_WIN32_MSG_FAIL(err, str, fmt, ...) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const DWORD __err = (err); \
return __R_FN(Return_Win32Msg)(__R_INFO(str) __err, __WI_CHECK_MSG_FMT(fmt, ##__VA_ARGS__)); \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define __RETURN_GLE_MSG_FAIL(str, fmt, ...) \
return __R_FN(Return_GetLastErrorMsg)(__R_INFO(str) __WI_CHECK_MSG_FMT(fmt, ##__VA_ARGS__))
#define __RETURN_NTSTATUS_MSG(status, str, fmt, ...) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const NTSTATUS __status = (status); \
if (FAILED_NTSTATUS(__status)) \
@ -719,16 +719,16 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
} \
return S_OK; \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define __RETURN_NTSTATUS_MSG_FAIL(status, str, fmt, ...) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const NTSTATUS __status = (status); \
return __R_FN(Return_NtStatusMsg)(__R_INFO(str) __status, __WI_CHECK_MSG_FMT(fmt, ##__VA_ARGS__)); \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define __RETURN_HR(hr, str) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const HRESULT __hr = (hr); \
if (FAILED(__hr)) \
@ -737,9 +737,9 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
} \
return __hr; \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define __RETURN_HR_NOFILE(hr, str) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const HRESULT __hr = (hr); \
if (FAILED(__hr)) \
@ -748,33 +748,33 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
} \
return __hr; \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define __RETURN_HR_FAIL(hr, str) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const HRESULT __hr = (hr); \
__R_FN(Return_Hr)(__R_INFO(str) __hr); \
return __hr; \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define __RETURN_HR_FAIL_SUPPRESS_TELEMETRY(hr, str) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const HRESULT __hr = (hr); \
__R_FN(Return_HrSuppressTelemetry)(__R_INFO(str) __hr); \
return __hr; \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define __RETURN_HR_FAIL_NOFILE(hr, str) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const HRESULT __hr = (hr); \
__R_FN(Return_Hr)(__R_INFO_NOFILE(str) __hr); \
return __hr; \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define __RETURN_WIN32(err, str) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const DWORD __err = (err); \
if (FAILED_WIN32(__err)) \
@ -783,18 +783,18 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
} \
return S_OK; \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define __RETURN_WIN32_FAIL(err, str) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const DWORD __err = (err); \
return __R_FN(Return_Win32)(__R_INFO(str) __err); \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define __RETURN_GLE_FAIL(str) return __R_FN(Return_GetLastError)(__R_INFO_ONLY(str))
#define __RETURN_GLE_FAIL_NOFILE(str) return __R_FN(Return_GetLastError)(__R_INFO_NOFILE_ONLY(str))
#define __RETURN_NTSTATUS(status, str) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const NTSTATUS __status = (status); \
if (FAILED_NTSTATUS(__status)) \
@ -803,14 +803,14 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
} \
return S_OK; \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define __RETURN_NTSTATUS_FAIL(status, str) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const NTSTATUS __status = (status); \
return __R_FN(Return_NtStatus)(__R_INFO(str) __status); \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
/// @endcond
//*****************************************************************************
@ -825,7 +825,7 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
// Conditionally returns failures (HRESULT) - always logs failures
#define RETURN_IF_FAILED(hr) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const auto __hrRet = wil::verify_hresult(hr); \
if (FAILED(__hrRet)) \
@ -833,9 +833,9 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
__RETURN_HR_FAIL(__hrRet, #hr); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_IF_WIN32_BOOL_FALSE(win32BOOL) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const auto __boolRet = wil::verify_BOOL(win32BOOL); \
if (!__boolRet) \
@ -843,9 +843,9 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
__RETURN_GLE_FAIL(#win32BOOL); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_IF_WIN32_ERROR(win32err) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const DWORD __errRet = (win32err); \
if (FAILED_WIN32(__errRet)) \
@ -853,54 +853,54 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
__RETURN_WIN32_FAIL(__errRet, #win32err); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_IF_NULL_ALLOC(ptr) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if ((ptr) == nullptr) \
{ \
__RETURN_HR_FAIL(E_OUTOFMEMORY, #ptr); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_HR_IF(hr, condition) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if (wil::verify_bool(condition)) \
{ \
__RETURN_HR(wil::verify_hresult(hr), #condition); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_HR_IF_NULL(hr, ptr) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if ((ptr) == nullptr) \
{ \
__RETURN_HR(wil::verify_hresult(hr), #ptr); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_LAST_ERROR_IF(condition) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if (wil::verify_bool(condition)) \
{ \
__RETURN_GLE_FAIL(#condition); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_LAST_ERROR_IF_NULL(ptr) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if ((ptr) == nullptr) \
{ \
__RETURN_GLE_FAIL(#ptr); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_IF_NTSTATUS_FAILED(status) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const NTSTATUS __statusRet = (status); \
if (FAILED_NTSTATUS(__statusRet)) \
@ -908,7 +908,7 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
__RETURN_NTSTATUS_FAIL(__statusRet, #status); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
// Always returns a known failure (HRESULT) - always logs a var-arg message on failure
#define RETURN_HR_MSG(hr, fmt, ...) __RETURN_HR_MSG(wil::verify_hresult(hr), #hr, fmt, ##__VA_ARGS__)
@ -918,7 +918,7 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
// Conditionally returns failures (HRESULT) - always logs a var-arg message on failure
#define RETURN_IF_FAILED_MSG(hr, fmt, ...) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const auto __hrRet = wil::verify_hresult(hr); \
if (FAILED(__hrRet)) \
@ -926,18 +926,18 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
__RETURN_HR_MSG_FAIL(__hrRet, #hr, fmt, ##__VA_ARGS__); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_IF_WIN32_BOOL_FALSE_MSG(win32BOOL, fmt, ...) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if (!wil::verify_BOOL(win32BOOL)) \
{ \
__RETURN_GLE_MSG_FAIL(#win32BOOL, fmt, ##__VA_ARGS__); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_IF_WIN32_ERROR_MSG(win32err, fmt, ...) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const DWORD __errRet = (win32err); \
if (FAILED_WIN32(__errRet)) \
@ -945,54 +945,54 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
__RETURN_WIN32_MSG_FAIL(__errRet, #win32err, fmt, ##__VA_ARGS__); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_IF_NULL_ALLOC_MSG(ptr, fmt, ...) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if ((ptr) == nullptr) \
{ \
__RETURN_HR_MSG_FAIL(E_OUTOFMEMORY, #ptr, fmt, ##__VA_ARGS__); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_HR_IF_MSG(hr, condition, fmt, ...) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if (wil::verify_bool(condition)) \
{ \
__RETURN_HR_MSG(wil::verify_hresult(hr), #condition, fmt, ##__VA_ARGS__); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_HR_IF_NULL_MSG(hr, ptr, fmt, ...) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if ((ptr) == nullptr) \
{ \
__RETURN_HR_MSG(wil::verify_hresult(hr), #ptr, fmt, ##__VA_ARGS__); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_LAST_ERROR_IF_MSG(condition, fmt, ...) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if (wil::verify_bool(condition)) \
{ \
__RETURN_GLE_MSG_FAIL(#condition, fmt, ##__VA_ARGS__); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_LAST_ERROR_IF_NULL_MSG(ptr, fmt, ...) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if ((ptr) == nullptr) \
{ \
__RETURN_GLE_MSG_FAIL(#ptr, fmt, ##__VA_ARGS__); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_IF_NTSTATUS_FAILED_MSG(status, fmt, ...) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const NTSTATUS __statusRet = (status); \
if (FAILED_NTSTATUS(__statusRet)) \
@ -1000,11 +1000,11 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
__RETURN_NTSTATUS_MSG_FAIL(__statusRet, #status, fmt, ##__VA_ARGS__); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
// Conditionally returns failures (HRESULT) - use for failures that are expected in common use - failures are not logged - macros are only for control flow pattern
#define RETURN_IF_FAILED_EXPECTED(hr) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const auto __hrRet = wil::verify_hresult(hr); \
if (FAILED(__hrRet)) \
@ -1012,18 +1012,18 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
return __hrRet; \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_IF_WIN32_BOOL_FALSE_EXPECTED(win32BOOL) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if (!wil::verify_BOOL(win32BOOL)) \
{ \
return wil::details::GetLastErrorFailHr(); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_IF_WIN32_ERROR_EXPECTED(win32err) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const DWORD __errRet = (win32err); \
if (FAILED_WIN32(__errRet)) \
@ -1031,54 +1031,54 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
return __HRESULT_FROM_WIN32(__errRet); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_IF_NULL_ALLOC_EXPECTED(ptr) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if ((ptr) == nullptr) \
{ \
return E_OUTOFMEMORY; \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_HR_IF_EXPECTED(hr, condition) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if (wil::verify_bool(condition)) \
{ \
return wil::verify_hresult(hr); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_HR_IF_NULL_EXPECTED(hr, ptr) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if ((ptr) == nullptr) \
{ \
return wil::verify_hresult(hr); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_LAST_ERROR_IF_EXPECTED(condition) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if (wil::verify_bool(condition)) \
{ \
return wil::details::GetLastErrorFailHr(); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_LAST_ERROR_IF_NULL_EXPECTED(ptr) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if ((ptr) == nullptr) \
{ \
return wil::details::GetLastErrorFailHr(); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define RETURN_IF_NTSTATUS_FAILED_EXPECTED(status) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const NTSTATUS __statusRet = (status); \
if (FAILED_NTSTATUS(__statusRet)) \
@ -1086,7 +1086,7 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
return wil::details::NtStatusToHr(__statusRet); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
/// @cond
#define __WI_OR_IS_EXPECTED_HRESULT(e) || (__hrRet == wil::verify_hresult(e))
@ -1689,6 +1689,19 @@ enum class ErrorReturn
None
};
/// @cond
namespace details
{
// 'FARPROC' is declared in such a way that it cannot safely be assumed cast-able to other function pointer types.
// This function helps alleviate warnings that can arise from this
template <typename FuncPtr>
inline FuncPtr GetProcAddress(_In_ HMODULE module, _In_ LPCSTR procName) WI_NOEXCEPT
{
return reinterpret_cast<FuncPtr>(reinterpret_cast<void (*)()>(::GetProcAddress(module, procName)));
}
} // namespace details
/// @endcond
// [optionally] Plug in error logging
// Note: This callback is deprecated. Please use SetResultTelemetryFallback for telemetry or
// SetResultLoggingCallback for observation.
@ -1978,8 +1991,7 @@ namespace details
__declspec(selectany) void(__stdcall* g_pfnRaiseFailFastException)(PEXCEPTION_RECORD, PCONTEXT, DWORD) = nullptr;
// Exception-based compiled additions
__declspec(selectany)
HRESULT(__stdcall* g_pfnRunFunctorWithExceptionFilter)(IFunctor& functor, IFunctorHost& host, void* returnAddress) = nullptr;
__declspec(selectany) HRESULT(__stdcall* g_pfnRunFunctorWithExceptionFilter)(IFunctor& functor, IFunctorHost& host, void* returnAddress) = nullptr;
__declspec(selectany) void(__stdcall* g_pfnRethrow)() = nullptr;
__declspec(selectany) void(__stdcall* g_pfnThrowResultException)(const FailureInfo& failure) = nullptr;
extern "C" __declspec(selectany) ResultStatus(__stdcall* g_pfnResultFromCaughtExceptionInternal)(
@ -2025,8 +2037,8 @@ namespace details
{
if (auto ntdllModule = ::GetModuleHandleW(L"ntdll.dll"))
{
pfnRtlDisownModuleHeapAllocation = reinterpret_cast<decltype(pfnRtlDisownModuleHeapAllocation)>(
::GetProcAddress(ntdllModule, "RtlDisownModuleHeapAllocation"));
pfnRtlDisownModuleHeapAllocation =
details::GetProcAddress<decltype(pfnRtlDisownModuleHeapAllocation)>(ntdllModule, "RtlDisownModuleHeapAllocation");
}
fetchedRtlDisownModuleHeapAllocation = true;
@ -2200,8 +2212,8 @@ namespace details
template <FailureType>
__declspec(noinline) inline void ReportFailure_Hr(__R_FN_PARAMS_FULL, HRESULT hr, FailureFlags flags = FailureFlags::None);
template <FailureType>
__declspec(noinline) inline HRESULT
ReportFailure_CaughtException(__R_FN_PARAMS_FULL, SupportedExceptions supported = SupportedExceptions::Default);
__declspec(noinline) inline HRESULT ReportFailure_CaughtException(
__R_FN_PARAMS_FULL, SupportedExceptions supported = SupportedExceptions::Default);
//*****************************************************************************
// Fail fast helpers (for use only internally to WIL)
@ -2509,6 +2521,8 @@ namespace details
#if __clang_major__ >= 13
__WI_CLANG_DISABLE_WARNING(-Wunused-but-set-variable) // s_hrErrorLast used for debugging. We intentionally only assign to it
#endif
__WI_MSVC_DISABLE_WARNING(4746) // s_hrErrorLast' is subject to /volatile:<iso|ms> setting; consider using __iso_volatile_load/store intrinsic functions
__declspec(noinline) inline int RecordException(HRESULT hr) WI_NOEXCEPT
{
static HRESULT volatile s_hrErrorLast = S_OK;
@ -2590,6 +2604,8 @@ namespace details
return true;
}
__WI_PUSH_WARNINGS
__WI_MSVC_DISABLE_WARNING(4746) // s_fModuleValid' is subject to /volatile:<iso|ms> setting; consider using __iso_volatile_load/store intrinsic functions
inline PCSTR __stdcall GetCurrentModuleName() WI_NOEXCEPT
{
static char s_szModule[64] = {};
@ -2601,6 +2617,7 @@ namespace details
}
return s_szModule;
}
__WI_POP_WARNINGS
inline void __stdcall DebugBreak() WI_NOEXCEPT
{
@ -2612,7 +2629,7 @@ namespace details
auto k32handle = GetModuleHandleW(L"kernelbase.dll");
_Analysis_assume_(k32handle != nullptr);
auto pfnRaiseFailFastException =
reinterpret_cast<decltype(WilDynamicLoadRaiseFailFastException)*>(GetProcAddress(k32handle, "RaiseFailFastException"));
details::GetProcAddress<decltype(WilDynamicLoadRaiseFailFastException)*>(k32handle, "RaiseFailFastException");
if (pfnRaiseFailFastException)
{
pfnRaiseFailFastException(er, cr, flags);
@ -3120,7 +3137,7 @@ namespace details
g_pfnRaiseFailFastException = ::RaiseFailFastException;
return 1;
});
}
} // namespace details
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
//*****************************************************************************
@ -3419,7 +3436,7 @@ public:
}
//! Returns the failed HRESULT that this exception represents.
_Always_(_Post_satisfies_(return < 0)) WI_NODISCARD HRESULT GetErrorCode() const WI_NOEXCEPT
WI_NODISCARD _Always_(_Post_satisfies_(return < 0)) HRESULT GetErrorCode() const WI_NOEXCEPT
{
HRESULT const hr = m_failure.GetFailureInfo().hr;
__analysis_assume(hr < 0);
@ -3427,7 +3444,7 @@ public:
}
//! Returns the failed NTSTATUS that this exception represents.
_Always_(_Post_satisfies_(return < 0)) WI_NODISCARD NTSTATUS GetStatusCode() const WI_NOEXCEPT
WI_NODISCARD _Always_(_Post_satisfies_(return < 0)) NTSTATUS GetStatusCode() const WI_NOEXCEPT
{
NTSTATUS const status = m_failure.GetFailureInfo().status;
__analysis_assume(status < 0);
@ -4106,8 +4123,7 @@ namespace details
}
}
__declspec(noinline) inline HRESULT
ResultFromException(const DiagnosticsInfo& diagnostics, SupportedExceptions supported, IFunctor& functor) WI_NOEXCEPT
__declspec(noinline) inline HRESULT ResultFromException(const DiagnosticsInfo& diagnostics, SupportedExceptions supported, IFunctor& functor) WI_NOEXCEPT
{
#ifdef RESULT_DEBUG
// We can't do debug SEH handling if the caller also wants a shot at mapping the exceptions
@ -4127,8 +4143,8 @@ namespace details
}
}
__declspec(noinline) inline HRESULT
ResultFromExceptionDebug(const DiagnosticsInfo& diagnostics, SupportedExceptions supported, IFunctor& functor) WI_NOEXCEPT
__declspec(noinline) inline HRESULT ResultFromExceptionDebug(
const DiagnosticsInfo& diagnostics, SupportedExceptions supported, IFunctor& functor) WI_NOEXCEPT
{
return wil::details::ResultFromExceptionSeh(diagnostics, _ReturnAddress(), supported, functor);
}
@ -4566,8 +4582,8 @@ namespace details
}
template <FailureType T>
inline __declspec(noinline) RESULT_NORETURN
void ReportFailure_NoReturn(__R_FN_PARAMS_FULL, const ResultStatus& resultPair, PCWSTR message, ReportFailureOptions options)
inline __declspec(noinline) RESULT_NORETURN void ReportFailure_NoReturn(
__R_FN_PARAMS_FULL, const ResultStatus& resultPair, PCWSTR message, ReportFailureOptions options)
{
bool needPlatformException =
((T == FailureType::Exception) && WI_IsFlagClear(options, ReportFailureOptions::MayRethrow) &&
@ -4590,7 +4606,7 @@ namespace details
ARRAYSIZE(callContextString),
FailureFlags::None,
&failure);
__WI_SUPPRESS_4127_S
__WI_SUPPRESS_BREAKING_WARNINGS_S
if ((T == FailureType::FailFast) || WI_IsFlagSet(failure.flags, FailureFlags::RequestFailFast))
{
WilFailFast(const_cast<FailureInfo&>(failure));
@ -4612,7 +4628,7 @@ namespace details
// Wil was instructed to throw, but doesn't have any capability to do so (global function pointers are not setup)
WilFailFast(const_cast<FailureInfo&>(failure));
}
__WI_SUPPRESS_4127_E
__WI_SUPPRESS_BREAKING_WARNINGS_E
}
template <>
@ -4801,15 +4817,13 @@ namespace details
}
template <>
__declspec(noinline) inline RESULT_NORETURN
void ReportFailure_Hr<FailureType::FailFast>(__R_FN_PARAMS_FULL, HRESULT hr, FailureFlags)
__declspec(noinline) inline RESULT_NORETURN void ReportFailure_Hr<FailureType::FailFast>(__R_FN_PARAMS_FULL, HRESULT hr, FailureFlags)
{
ReportFailure_Base<FailureType::FailFast>(__R_FN_CALL_FULL, ResultStatus::FromResult(hr));
}
template <>
__declspec(noinline) inline RESULT_NORETURN
void ReportFailure_Hr<FailureType::Exception>(__R_FN_PARAMS_FULL, HRESULT hr, FailureFlags)
__declspec(noinline) inline RESULT_NORETURN void ReportFailure_Hr<FailureType::Exception>(__R_FN_PARAMS_FULL, HRESULT hr, FailureFlags)
{
ReportFailure_Base<FailureType::Exception>(__R_FN_CALL_FULL, ResultStatus::FromResult(hr));
}
@ -4983,15 +4997,15 @@ namespace details
}
template <>
__declspec(noinline) inline RESULT_NORETURN
void ReportFailure_HrMsg<FailureType::FailFast>(__R_FN_PARAMS_FULL, HRESULT hr, _Printf_format_string_ PCSTR formatString, va_list argList)
__declspec(noinline) inline RESULT_NORETURN void ReportFailure_HrMsg<FailureType::FailFast>(
__R_FN_PARAMS_FULL, HRESULT hr, _Printf_format_string_ PCSTR formatString, va_list argList)
{
ReportFailure_Msg<FailureType::FailFast>(__R_FN_CALL_FULL, ResultStatus::FromResult(hr), formatString, argList);
}
template <>
__declspec(noinline) inline RESULT_NORETURN
void ReportFailure_HrMsg<FailureType::Exception>(__R_FN_PARAMS_FULL, HRESULT hr, _Printf_format_string_ PCSTR formatString, va_list argList)
__declspec(noinline) inline RESULT_NORETURN void ReportFailure_HrMsg<FailureType::Exception>(
__R_FN_PARAMS_FULL, HRESULT hr, _Printf_format_string_ PCSTR formatString, va_list argList)
{
ReportFailure_Msg<FailureType::Exception>(__R_FN_CALL_FULL, ResultStatus::FromResult(hr), formatString, argList);
}
@ -4999,8 +5013,7 @@ namespace details
template <FailureType T>
_Success_(true)
_Translates_Win32_to_HRESULT_(err)
__declspec(noinline) inline HRESULT
ReportFailure_Win32Msg(__R_FN_PARAMS_FULL, DWORD err, _Printf_format_string_ PCSTR formatString, va_list argList)
__declspec(noinline) inline HRESULT ReportFailure_Win32Msg(__R_FN_PARAMS_FULL, DWORD err, _Printf_format_string_ PCSTR formatString, va_list argList)
{
auto hr = __HRESULT_FROM_WIN32(err);
ReportFailure_Msg<T>(__R_FN_CALL_FULL, ResultStatus::FromResult(hr), formatString, argList);
@ -5030,8 +5043,7 @@ namespace details
}
template <FailureType T>
__declspec(noinline) inline DWORD
ReportFailure_GetLastErrorMsg(__R_FN_PARAMS_FULL, _Printf_format_string_ PCSTR formatString, va_list argList)
__declspec(noinline) inline DWORD ReportFailure_GetLastErrorMsg(__R_FN_PARAMS_FULL, _Printf_format_string_ PCSTR formatString, va_list argList)
{
auto err = GetLastErrorFail(__R_FN_CALL_FULL);
auto hr = __HRESULT_FROM_WIN32(err);
@ -5041,8 +5053,8 @@ namespace details
}
template <>
__declspec(noinline) inline RESULT_NORETURN DWORD ReportFailure_GetLastErrorMsg<FailureType::FailFast>(
__R_FN_PARAMS_FULL, _Printf_format_string_ PCSTR formatString, va_list argList)
__declspec(noinline) inline RESULT_NORETURN DWORD
ReportFailure_GetLastErrorMsg<FailureType::FailFast>(__R_FN_PARAMS_FULL, _Printf_format_string_ PCSTR formatString, va_list argList)
{
auto err = GetLastErrorFail(__R_FN_CALL_FULL);
auto hr = __HRESULT_FROM_WIN32(err);
@ -5063,8 +5075,7 @@ namespace details
template <FailureType T>
_Success_(true)
_Translates_last_error_to_HRESULT_
__declspec(noinline) inline HRESULT
ReportFailure_GetLastErrorHrMsg(__R_FN_PARAMS_FULL, _Printf_format_string_ PCSTR formatString, va_list argList)
__declspec(noinline) inline HRESULT ReportFailure_GetLastErrorHrMsg(__R_FN_PARAMS_FULL, _Printf_format_string_ PCSTR formatString, va_list argList)
{
auto hr = GetLastErrorFailHr(__R_FN_CALL_FULL);
ReportFailure_Msg<T>(__R_FN_CALL_FULL, ResultStatus::FromResult(hr), formatString, argList);
@ -5096,8 +5107,8 @@ namespace details
template <FailureType T>
_Success_(true)
_Translates_NTSTATUS_to_HRESULT_(status)
__declspec(noinline) inline HRESULT
ReportFailure_NtStatusMsg(__R_FN_PARAMS_FULL, NTSTATUS status, _Printf_format_string_ PCSTR formatString, va_list argList)
__declspec(noinline) inline HRESULT ReportFailure_NtStatusMsg(
__R_FN_PARAMS_FULL, NTSTATUS status, _Printf_format_string_ PCSTR formatString, va_list argList)
{
const auto resultPair = ResultStatus::FromStatus(status);
ReportFailure_Msg<T>(__R_FN_CALL_FULL, resultPair, formatString, argList);
@ -5127,8 +5138,7 @@ namespace details
}
template <FailureType T>
__declspec(noinline) inline HRESULT
ReportFailure_CaughtExceptionMsg(__R_FN_PARAMS_FULL, _Printf_format_string_ PCSTR formatString, va_list argList)
__declspec(noinline) inline HRESULT ReportFailure_CaughtExceptionMsg(__R_FN_PARAMS_FULL, _Printf_format_string_ PCSTR formatString, va_list argList)
{
// Pre-populate the buffer with our message, the exception message will be added to it...
wchar_t message[2048];
@ -5237,8 +5247,8 @@ namespace details
}
template <typename T>
__declspec(noinline) RESULT_NORETURN
inline void ReportFailure_CustomExceptionMsg(__R_FN_PARAMS _In_ T exception, _In_ _Printf_format_string_ PCSTR formatString, ...)
__declspec(noinline) RESULT_NORETURN inline void ReportFailure_CustomExceptionMsg(
__R_FN_PARAMS _In_ T exception, _In_ _Printf_format_string_ PCSTR formatString, ...)
{
va_list argList;
va_start(argList, formatString);
@ -5512,8 +5522,7 @@ namespace details
}
template <__R_CONDITIONAL_PARTIAL_TEMPLATE typename PointerT, __R_ENABLE_IF_IS_CLASS(PointerT)>
__R_CONDITIONAL_TEMPLATE_METHOD(void, Log_IfNullAlloc)
(__R_CONDITIONAL_FN_PARAMS const PointerT& pointer) WI_NOEXCEPT
__R_CONDITIONAL_TEMPLATE_METHOD(void, Log_IfNullAlloc)(__R_CONDITIONAL_FN_PARAMS const PointerT& pointer) WI_NOEXCEPT
{
if (pointer == nullptr)
{
@ -5554,8 +5563,7 @@ namespace details
}
template <__R_CONDITIONAL_PARTIAL_TEMPLATE typename PointerT, __R_ENABLE_IF_IS_CLASS(PointerT)>
__R_CONDITIONAL_TEMPLATE_METHOD(void, Log_HrIfNull)
(__R_CONDITIONAL_FN_PARAMS HRESULT hr, _In_opt_ const PointerT& pointer) WI_NOEXCEPT
__R_CONDITIONAL_TEMPLATE_METHOD(void, Log_HrIfNull)(__R_CONDITIONAL_FN_PARAMS HRESULT hr, _In_opt_ const PointerT& pointer) WI_NOEXCEPT
{
if (pointer == nullptr)
{
@ -5596,8 +5604,7 @@ namespace details
}
template <__R_CONDITIONAL_PARTIAL_TEMPLATE typename PointerT, __R_ENABLE_IF_IS_CLASS(PointerT)>
__R_CONDITIONAL_TEMPLATE_METHOD(void, Log_GetLastErrorIfNull)
(__R_CONDITIONAL_FN_PARAMS _In_opt_ const PointerT& pointer) WI_NOEXCEPT
__R_CONDITIONAL_TEMPLATE_METHOD(void, Log_GetLastErrorIfNull)(__R_CONDITIONAL_FN_PARAMS _In_opt_ const PointerT& pointer) WI_NOEXCEPT
{
if (pointer == nullptr)
{
@ -5776,8 +5783,8 @@ namespace details
}
template <__R_CONDITIONAL_PARTIAL_TEMPLATE typename PointerT, __R_ENABLE_IF_IS_CLASS(PointerT)>
__R_CONDITIONAL_NOINLINE_TEMPLATE_METHOD(void, Log_IfNullAllocMsg)
(__R_CONDITIONAL_FN_PARAMS const PointerT& pointer, _Printf_format_string_ PCSTR formatString, ...) WI_NOEXCEPT
__R_CONDITIONAL_NOINLINE_TEMPLATE_METHOD(void, Log_IfNullAllocMsg)(
__R_CONDITIONAL_FN_PARAMS const PointerT& pointer, _Printf_format_string_ PCSTR formatString, ...) WI_NOEXCEPT
{
if (pointer == nullptr)
{
@ -5826,8 +5833,8 @@ namespace details
}
template <__R_CONDITIONAL_PARTIAL_TEMPLATE typename PointerT, __R_ENABLE_IF_IS_CLASS(PointerT)>
__R_CONDITIONAL_NOINLINE_TEMPLATE_METHOD(void, Log_HrIfNullMsg)
(__R_CONDITIONAL_FN_PARAMS HRESULT hr, _In_opt_ const PointerT& pointer, _Printf_format_string_ PCSTR formatString, ...) WI_NOEXCEPT
__R_CONDITIONAL_NOINLINE_TEMPLATE_METHOD(void, Log_HrIfNullMsg)(
__R_CONDITIONAL_FN_PARAMS HRESULT hr, _In_opt_ const PointerT& pointer, _Printf_format_string_ PCSTR formatString, ...) WI_NOEXCEPT
{
if (pointer == nullptr)
{
@ -5875,8 +5882,8 @@ namespace details
}
template <__R_CONDITIONAL_PARTIAL_TEMPLATE typename PointerT, __R_ENABLE_IF_IS_CLASS(PointerT)>
__R_CONDITIONAL_NOINLINE_TEMPLATE_METHOD(void, Log_GetLastErrorIfNullMsg)
(__R_CONDITIONAL_FN_PARAMS _In_opt_ const PointerT& pointer, _Printf_format_string_ PCSTR formatString, ...) WI_NOEXCEPT
__R_CONDITIONAL_NOINLINE_TEMPLATE_METHOD(void, Log_GetLastErrorIfNullMsg)(
__R_CONDITIONAL_FN_PARAMS _In_opt_ const PointerT& pointer, _Printf_format_string_ PCSTR formatString, ...) WI_NOEXCEPT
{
if (pointer == nullptr)
{
@ -6035,8 +6042,7 @@ namespace details
// Should be decorated WI_NOEXCEPT, but conflicts with forceinline.
template <__RFF_CONDITIONAL_PARTIAL_TEMPLATE typename PointerT, __R_ENABLE_IF_IS_CLASS(PointerT)>
__RFF_CONDITIONAL_TEMPLATE_METHOD(void, FailFast_IfNullAlloc)
(__RFF_CONDITIONAL_FN_PARAMS const PointerT& pointer)
__RFF_CONDITIONAL_TEMPLATE_METHOD(void, FailFast_IfNullAlloc)(__RFF_CONDITIONAL_FN_PARAMS const PointerT& pointer)
{
if (pointer == nullptr)
{
@ -6079,8 +6085,7 @@ namespace details
// Should be decorated WI_NOEXCEPT, but conflicts with forceinline.
template <__RFF_CONDITIONAL_PARTIAL_TEMPLATE typename PointerT, __R_ENABLE_IF_IS_CLASS(PointerT)>
__RFF_CONDITIONAL_TEMPLATE_METHOD(void, FailFast_HrIfNull)
(__RFF_CONDITIONAL_FN_PARAMS HRESULT hr, _In_opt_ const PointerT& pointer)
__RFF_CONDITIONAL_TEMPLATE_METHOD(void, FailFast_HrIfNull)(__RFF_CONDITIONAL_FN_PARAMS HRESULT hr, _In_opt_ const PointerT& pointer)
{
if (pointer == nullptr)
{
@ -6123,8 +6128,7 @@ namespace details
// Should be decorated WI_NOEXCEPT, but conflicts with forceinline.
template <__RFF_CONDITIONAL_PARTIAL_TEMPLATE typename PointerT, __R_ENABLE_IF_IS_CLASS(PointerT)>
__RFF_CONDITIONAL_TEMPLATE_METHOD(void, FailFast_GetLastErrorIfNull)
(__RFF_CONDITIONAL_FN_PARAMS _In_opt_ const PointerT& pointer)
__RFF_CONDITIONAL_TEMPLATE_METHOD(void, FailFast_GetLastErrorIfNull)(__RFF_CONDITIONAL_FN_PARAMS _In_opt_ const PointerT& pointer)
{
if (pointer == nullptr)
{
@ -6310,8 +6314,8 @@ namespace details
}
template <__RFF_CONDITIONAL_PARTIAL_TEMPLATE typename PointerT, __R_ENABLE_IF_IS_CLASS(PointerT)>
__RFF_CONDITIONAL_NOINLINE_TEMPLATE_METHOD(void, FailFast_IfNullAllocMsg)
(__RFF_CONDITIONAL_FN_PARAMS const PointerT& pointer, _Printf_format_string_ PCSTR formatString, ...) WI_NOEXCEPT
__RFF_CONDITIONAL_NOINLINE_TEMPLATE_METHOD(void, FailFast_IfNullAllocMsg)(
__RFF_CONDITIONAL_FN_PARAMS const PointerT& pointer, _Printf_format_string_ PCSTR formatString, ...) WI_NOEXCEPT
{
if (pointer == nullptr)
{
@ -6366,8 +6370,8 @@ namespace details
}
template <__RFF_CONDITIONAL_PARTIAL_TEMPLATE typename PointerT, __R_ENABLE_IF_IS_CLASS(PointerT)>
__RFF_CONDITIONAL_NOINLINE_TEMPLATE_METHOD(void, FailFast_HrIfNullMsg)
(__RFF_CONDITIONAL_FN_PARAMS HRESULT hr, _In_opt_ const PointerT& pointer, _Printf_format_string_ PCSTR formatString, ...) WI_NOEXCEPT
__RFF_CONDITIONAL_NOINLINE_TEMPLATE_METHOD(void, FailFast_HrIfNullMsg)(
__RFF_CONDITIONAL_FN_PARAMS HRESULT hr, _In_opt_ const PointerT& pointer, _Printf_format_string_ PCSTR formatString, ...) WI_NOEXCEPT
{
if (pointer == nullptr)
{
@ -6422,8 +6426,8 @@ namespace details
}
template <__RFF_CONDITIONAL_PARTIAL_TEMPLATE typename PointerT, __R_ENABLE_IF_IS_CLASS(PointerT)>
__RFF_CONDITIONAL_NOINLINE_TEMPLATE_METHOD(void, FailFast_GetLastErrorIfNullMsg)
(__RFF_CONDITIONAL_FN_PARAMS _In_opt_ const PointerT& pointer, _Printf_format_string_ PCSTR formatString, ...) WI_NOEXCEPT
__RFF_CONDITIONAL_NOINLINE_TEMPLATE_METHOD(void, FailFast_GetLastErrorIfNullMsg)(
__RFF_CONDITIONAL_FN_PARAMS _In_opt_ const PointerT& pointer, _Printf_format_string_ PCSTR formatString, ...) WI_NOEXCEPT
{
if (pointer == nullptr)
{
@ -6564,8 +6568,8 @@ namespace details
}
template <__RFF_CONDITIONAL_PARTIAL_TEMPLATE typename PointerT, __R_ENABLE_IF_IS_CLASS(PointerT)>
__RFF_CONDITIONAL_NOINLINE_TEMPLATE_METHOD(void, FailFast_IfNullMsg)
(__RFF_CONDITIONAL_FN_PARAMS _In_opt_ const PointerT& pointer, _Printf_format_string_ PCSTR formatString, ...) WI_NOEXCEPT
__RFF_CONDITIONAL_NOINLINE_TEMPLATE_METHOD(void, FailFast_IfNullMsg)(
__RFF_CONDITIONAL_FN_PARAMS _In_opt_ const PointerT& pointer, _Printf_format_string_ PCSTR formatString, ...) WI_NOEXCEPT
{
if (pointer == nullptr)
{
@ -6635,8 +6639,7 @@ namespace details
// Should be decorated WI_NOEXCEPT, but conflicts with forceinline.
template <__RFF_CONDITIONAL_PARTIAL_TEMPLATE typename PointerT, __R_ENABLE_IF_IS_CLASS(PointerT)>
__RFF_CONDITIONAL_TEMPLATE_METHOD(void, FailFastImmediate_IfNull)
(_In_opt_ const PointerT& pointer)
__RFF_CONDITIONAL_TEMPLATE_METHOD(void, FailFastImmediate_IfNull)(_In_opt_ const PointerT& pointer)
{
if (pointer == nullptr)
{
@ -6785,8 +6788,7 @@ namespace details
}
template <__R_CONDITIONAL_PARTIAL_TEMPLATE typename PointerT, __R_ENABLE_IF_IS_CLASS(PointerT)>
__R_CONDITIONAL_TEMPLATE_METHOD(void, Throw_IfNullAlloc)
(__R_CONDITIONAL_FN_PARAMS const PointerT& pointer)
__R_CONDITIONAL_TEMPLATE_METHOD(void, Throw_IfNullAlloc)(__R_CONDITIONAL_FN_PARAMS const PointerT& pointer)
{
if (pointer == nullptr)
{
@ -6827,8 +6829,7 @@ namespace details
}
template <__R_CONDITIONAL_PARTIAL_TEMPLATE typename PointerT, __R_ENABLE_IF_IS_CLASS(PointerT)>
__R_CONDITIONAL_TEMPLATE_METHOD(void, Throw_HrIfNull)
(__R_CONDITIONAL_FN_PARAMS HRESULT hr, _In_opt_ const PointerT& pointer)
__R_CONDITIONAL_TEMPLATE_METHOD(void, Throw_HrIfNull)(__R_CONDITIONAL_FN_PARAMS HRESULT hr, _In_opt_ const PointerT& pointer)
{
if (pointer == nullptr)
{
@ -6879,8 +6880,7 @@ namespace details
}
template <__R_CONDITIONAL_PARTIAL_TEMPLATE typename PointerT, __R_ENABLE_IF_IS_CLASS(PointerT)>
__R_CONDITIONAL_TEMPLATE_METHOD(void, Throw_GetLastErrorIfNull)
(__R_CONDITIONAL_FN_PARAMS _In_opt_ const PointerT& pointer)
__R_CONDITIONAL_TEMPLATE_METHOD(void, Throw_GetLastErrorIfNull)(__R_CONDITIONAL_FN_PARAMS _In_opt_ const PointerT& pointer)
{
if (pointer == nullptr)
{

View File

@ -68,7 +68,7 @@ namespace details
wil::unique_hmodule errorModule;
if (GetModuleHandleExW(0, L"api-ms-win-core-winrt-error-l1-1-1.dll", &errorModule))
{
auto pfn = reinterpret_cast<decltype(&::RoOriginateErrorW)>(GetProcAddress(errorModule.get(), "RoOriginateErrorW"));
auto pfn = details::GetProcAddress<decltype(&::RoOriginateErrorW)>(errorModule.get(), "RoOriginateErrorW");
if (pfn != nullptr)
{
pfn(failure.hr, 0, failure.pszMessage);

View File

@ -44,6 +44,12 @@ namespace details
template <typename NewT, typename OldT>
constexpr bool both_integral_v = wistd::is_integral<NewT>::value && wistd::is_integral<OldT>::value;
// Helper template to determine that the cast from OldT to NewT is going to sign extend the
// value. This is only true when the size of NewT is larger than OldT and OldT is signed.
template <typename NewT, typename OldT>
constexpr bool is_sign_extending_cast_v =
(sizeof(NewT) >= sizeof(OldT)) && both_integral_v<NewT, OldT> && wistd::is_signed_v<OldT>;
// Note on native wchar_t (__wchar_t):
// Intsafe.h does not currently handle native wchar_t. When compiling with /Zc:wchar_t-, this is fine as wchar_t is
// typedef'd to unsigned short. However, when compiling with /Zc:wchar_t or wchar_t as a native type, the lack of
@ -374,6 +380,22 @@ HRESULT safe_cast_nothrow(const OldT var, NewT* newTResult)
*newTResult = static_cast<NewT>(var);
return S_OK;
}
// This conversion takes a signed integer value and grows it with the upper bits set to zero. This is
// useful when the resulting value is cast to a pointer type as it prevents the upper bits from being fill
// which would adjust the pointed-to address.
//
// For example:
// wil::safe_zero_extending_cast<ULONG_PTR>(-1)
// will return 0x00000000`FFFFFFFF on a 64-bit system.
template <typename NewT, typename OldT, wistd::enable_if_t<details::is_sign_extending_cast_v<NewT, OldT>, int> = 0>
NewT safe_zero_extending_cast(const OldT var)
{
// The first cast is to an unsigned type of the same size as the original. The second cast is to the
// larger type. Being an unsigned cast, the upper bits are zeroed out.
using unsigned_old_t = wistd::make_unsigned_t<OldT>;
return static_cast<NewT>(static_cast<unsigned_old_t>(var));
}
} // namespace wil
#endif // __WIL_SAFECAST_INCLUDED

View File

@ -19,7 +19,7 @@
#include <string>
#include <vector>
#include <utility>
#if _HAS_CXX17
#if (__WI_LIBCPP_STD_VER >= 17) && WI_HAS_INCLUDE(<string_view>, 1) // Assume present if C++17
#include <string_view>
#endif
@ -132,7 +132,7 @@ inline PCWSTR str_raw_ptr(const std::wstring& str)
return str.c_str();
}
#if _HAS_CXX17
#if __cpp_lib_string_view >= 201606L
/**
zstring_view. A zstring_view is identical to a std::string_view except it is always nul-terminated (unless empty).
* zstring_view can be used for storing string literals without "forgetting" the length or that it is nul-terminated.
@ -213,18 +213,18 @@ using zwstring_view = basic_zstring_view<wchar_t>;
inline namespace literals
{
constexpr zstring_view operator"" _zv(const char* str, std::size_t len) noexcept
constexpr zstring_view operator""_zv(const char* str, std::size_t len) noexcept
{
return zstring_view(str, len);
}
constexpr zwstring_view operator"" _zv(const wchar_t* str, std::size_t len) noexcept
constexpr zwstring_view operator""_zv(const wchar_t* str, std::size_t len) noexcept
{
return zwstring_view(str, len);
}
} // namespace literals
#endif // _HAS_CXX17
#endif // __cpp_lib_string_view >= 201606L
} // namespace wil

View File

@ -20,11 +20,21 @@
#include <winreg.h>
#include <objbase.h>
// detect std::bit_cast
#ifdef __has_include
#if (__cplusplus >= 202002L || _MSVC_LANG >= 202002L) && __has_include(<bit>)
#include "common.h"
#if WIL_USE_STL
#include <string>
#if (__WI_LIBCPP_STD_VER >= 17) && WI_HAS_INCLUDE(<string_view>, 1) // Assume present if C++17
#include <string_view>
#endif
#if (__WI_LIBCPP_STD_VER >= 20)
#if WI_HAS_INCLUDE(<bit>, 1) // Assume present if C++20
#include <bit>
#endif
#if WI_HAS_INCLUDE(<compare>, 1) // Assume present if C++20
#include <compare>
#endif
#endif
#endif
/// @cond
@ -40,25 +50,16 @@
#include "wistd_functional.h"
#include "wistd_type_traits.h"
/// @cond
#if _HAS_CXX20 && defined(_STRING_VIEW_) && defined(_COMPARE_)
// If we're using c++20, then <compare> must be included to use the string ordinal functions
#define __WI_DEFINE_STRING_ORDINAL_FUNCTIONS
#elif !_HAS_CXX20 && defined(_STRING_VIEW_)
#define __WI_DEFINE_STRING_ORDINAL_FUNCTIONS
#endif
/// @endcond
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
/// @cond
namespace wistd
{
#if defined(__WI_DEFINE_STRING_ORDINAL_FUNCTIONS)
#if _HAS_CXX20
#if WIL_USE_STL && (__cpp_lib_three_way_comparison >= 201907L)
using weak_ordering = std::weak_ordering;
#else // _HAS_CXX20
#else
struct weak_ordering
{
@ -133,9 +134,7 @@ inline constexpr weak_ordering weak_ordering::less{static_cast<signed char>(-1)}
inline constexpr weak_ordering weak_ordering::equivalent{static_cast<signed char>(0)};
inline constexpr weak_ordering weak_ordering::greater{static_cast<signed char>(1)};
#endif // !_HAS_CXX20
#endif // defined(__WI_DEFINE_STRING_ORDINAL_FUNCTIONS)
#endif
} // namespace wistd
/// @endcond
@ -165,8 +164,7 @@ constexpr size_t guid_string_length = 38;
// Indentifiers require a locale-less (ordinal), and often case-insensitive, comparison (filenames, registry keys, XML node names,
// etc). DO NOT use locale-sensitive (lexical) comparisons for resource identifiers (e.g.wcs*() functions in the CRT).
#if defined(__WI_DEFINE_STRING_ORDINAL_FUNCTIONS) || defined(WIL_DOXYGEN)
#if WIL_USE_STL && (__cpp_lib_string_view >= 201606L)
/// @cond
namespace details
{
@ -192,8 +190,7 @@ namespace details
return wistd::weak_ordering::equivalent;
}
}
#endif // defined(__WI_DEFINE_STRING_ORDINAL_FUNCTIONS)
#endif
#pragma endregion
@ -686,6 +683,7 @@ inline DWORD GetCurrentProcessExecutionOption(PCWSTR valueName, DWORD defaultVal
return defaultValue;
}
#ifndef DebugBreak // Some code defines 'DebugBreak' to garbage to force build breaks in release builds
// Waits for a debugger to attach to the current process based on registry configuration.
//
// Example:
@ -717,6 +715,7 @@ inline void WaitForDebuggerPresent(bool checkRegistryConfig = true)
Sleep(500);
}
}
#endif
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
#endif
@ -724,7 +723,6 @@ inline void WaitForDebuggerPresent(bool checkRegistryConfig = true)
/** Retrieve the HINSTANCE for the current DLL or EXE using this symbol that
the linker provides for every module. This avoids the need for a global HINSTANCE variable
and provides access to this value for static libraries. */
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
inline HINSTANCE GetModuleInstanceHandle() WI_NOEXCEPT
{
return reinterpret_cast<HINSTANCE>(&__ImageBase);
@ -894,6 +892,237 @@ bool init_once(_Inout_ INIT_ONCE& initOnce, T func)
}
}
#endif // WIL_ENABLE_EXCEPTIONS
#if WIL_USE_STL && defined(WIL_ENABLE_EXCEPTIONS) && (__cpp_lib_string_view >= 201606L)
/// @cond
namespace details
{
template <typename RangeT>
struct deduce_char_type_from_string_range
{
template <typename T = RangeT>
static auto deduce(T& range)
{
using std::begin;
return (*begin(range))[0];
}
using type = decltype(deduce(wistd::declval<RangeT&>()));
};
template <typename RangeT>
using deduce_char_type_from_string_range_t = typename deduce_char_type_from_string_range<RangeT>::type;
// Internal helper span-like type for passing arrays as an iterable collection
template <typename T>
struct iterable_span
{
T* pointer;
size_t size;
constexpr T* begin() const noexcept
{
return pointer;
}
constexpr T* end() const noexcept
{
return pointer + size;
}
};
} // namespace details
/// @endcond
//! Flags that control the behavior of `ArgvToCommandLine`
enum class ArgvToCommandLineFlags : uint8_t
{
None = 0,
//! By default, arguments are only surrounded by quotes when necessary (i.e. the argument contains a space). When
//! this flag is specified, all arguments are surrounded with quotes, regardless of whether or not they contain
//! space(s). This is an optimization as it means that we are not required to search for spaces in each argument and
//! we don't need to potentially go back and insert a quotation character in the middle of the string after we've
//! already written part of the argument to the result. That said, wrapping all arguments with quotes can have some
//! adverse effects with some applications, most notably cmd.exe, which do their own command line processing.
ForceQuotes = 0x01 << 0,
//! `CommandLineToArgvW` has an "optimization" that assumes that the first argument is the path to an executable.
//! Because valid NTFS paths cannot contain quotation characters, `CommandLineToArgvW` disables its quote escaping
//! logic for the first argument. By default, `ArgvToCommandLine` aims to ensure that an argv array can "round trip"
//! to a string and back, meaning it tries to replicate this logic in reverse. This flag disables this logic and
//! escapes backslashes and quotes the same for all arguments, including the first one. This is useful if the output
//! string is only an intermediate command line string (e.g. if the executable path is prepended later).
FirstArgumentIsNotPath = 0x01 << 1,
};
DEFINE_ENUM_FLAG_OPERATORS(ArgvToCommandLineFlags);
//! Performs the reverse operation of CommandLineToArgvW.
//! Converts an argv array to a command line string that is guaranteed to "round trip" with CommandLineToArgvW. That is,
//! a call to wil::ArgvToCommandLine followed by a call to ArgvToCommandLineW will produce the same array that was
//! passed to wil::ArgvToCommandLine. Note that the reverse is not true. I.e. calling ArgvToCommandLineW followed by
//! wil::ArgvToCommandLine will not produce the original string due to the optionality of of quotes in the command line
//! string. This functionality is useful in a number of scenarios, most notably:
//! 1. When implementing a "driver" application. That is, an application that consumes some command line arguments,
//! translates others into new arguments, and preserves the rest, "forwarding" the resulting command line to a
//! separate application.
//! 2. When reading command line arguments from some data storage, e.g. from a JSON array, which then need to get
//! compiled into a command line string that's used for creating a new process.
//! Unlike CommandLineToArgvW, this function accepts both "narrow" and "wide" strings to support calling both
//! CreateProcessW and CreateProcessA with the result. See the values in @ref wil::ArgvToCommandLineFlags for more
//! information on how to control the behavior of this function as well as scenarios when you may want to use each one.
template <typename RangeT, typename CharT = details::deduce_char_type_from_string_range_t<RangeT>>
inline std::basic_string<CharT> ArgvToCommandLine(RangeT&& range, ArgvToCommandLineFlags flags = ArgvToCommandLineFlags::None)
{
using string_type = std::basic_string<CharT>;
using string_view_type = std::basic_string_view<CharT>;
// Somewhat of a hack to avoid the fact that we can't conditionalize a string literal on a template
static constexpr const CharT empty_string[] = {'\0'};
static constexpr const CharT single_quote_string[] = {'"', '\0'};
static constexpr const CharT space_string[] = {' ', '\0'};
static constexpr const CharT quoted_space_string[] = {'"', ' ', '"', '\0'};
static constexpr const CharT search_string_no_space[] = {'\\', '"', '\0'};
static constexpr const CharT search_string_with_space[] = {'\\', '"', ' ', '\t', '\0'};
const bool forceQuotes = WI_IsFlagSet(flags, ArgvToCommandLineFlags::ForceQuotes);
const CharT* const initialSearchString = forceQuotes ? search_string_no_space : search_string_with_space;
const CharT* prefix = forceQuotes ? single_quote_string : empty_string;
const CharT* const nextPrefix = forceQuotes ? quoted_space_string : space_string;
string_type result;
int index = 0;
for (auto&& strRaw : range)
{
auto currentIndex = index++;
result += prefix;
const CharT* searchString = initialSearchString;
// Info just in case we need to come back and insert quotes
auto startPos = result.size();
bool terminateWithQuotes = false; // With forceQuotes == true, this is baked into the prefix
// We need to escape any quotes and CONDITIONALLY any backslashes
string_view_type str(strRaw);
size_t pos = 0;
while (pos < str.size())
{
auto nextPos = str.find_first_of(searchString, pos);
if ((nextPos != str.npos) && ((str[nextPos] == ' ') || (str[nextPos] == '\t')))
{
// Insert the quote now since we'll need to otherwise stomp over data we're about to write
// NOTE: By updating the search string here, we don't need to worry about manually inserting the
// character later since we'll just include it in our next iteration
WI_ASSERT(!forceQuotes); // Otherwise, shouldn't be part of our search string
searchString = search_string_no_space; // We're already adding a quote; don't do it again
result.insert(startPos, 1, '"');
terminateWithQuotes = true;
}
result.append(str, pos, nextPos - pos);
pos = nextPos;
if (pos == str.npos)
break;
if (str[pos] == '"')
{
// Kinda easy case; just escape the quotes, *unless* this is the first argument and we assume a path
if ((currentIndex > 0) || WI_IsFlagSet(flags, ArgvToCommandLineFlags::FirstArgumentIsNotPath))
{
result.append({'\\', '"'}); // Escape case
}
else
{
// Realistically, this likely signals a bug since paths cannot contain quotes. That said, the
// behavior of CommandLineToArgvW is to just preserve "interior" quotes, so we do that.
// NOTE: 'CommandLineToArgvW' treats "interior" quotes as terminating quotes when the executable
// path begins with a quote, even if the next character is not a space. This assert won't catch all
// of such issues as we may detect a space, and therefore the need to surroud the argument with
// quotes, later in the string; this is best effort. Such arguments wouldn't be valid and are not
// representable anyway
WI_ASSERT((pos > 0) && !WI_IsFlagSet(flags, ArgvToCommandLineFlags::ForceQuotes) && !terminateWithQuotes);
result.push_back('"'); // Not escaping case
}
++pos; // Skip past quote on next search
}
else if (str[pos] == '\\')
{
// More complex case... Only need to escape if followed by 0+ backslashes and then either a quote or
// the end of the string and we're adding quotes
nextPos = str.find_first_not_of(L'\\', pos);
// NOTE: This is an optimization taking advantage of the fact that doing a double append of 1+
// backslashes will be functionally equivalent to escaping each one. This copies all of the backslashes
// once. We _might_ do it again later
result.append(str, pos, nextPos - pos);
// If this is the first argument and is being interpreted as a path, we never escape slashes
if ((currentIndex == 0) && !WI_IsFlagSet(flags, ArgvToCommandLineFlags::FirstArgumentIsNotPath))
{
pos = nextPos;
continue;
}
if ((nextPos != str.npos) && (str[nextPos] != L'"'))
{
// Simplest case... don't need to escape when followed by a non-quote character
pos = nextPos;
continue;
}
// If this is the end of the string and we're not appending a quotation to the end, we're in the
// same boat as the above where we don't need to escape
if ((nextPos == str.npos) && !forceQuotes && !terminateWithQuotes)
{
pos = nextPos;
continue;
}
// Otherwise, we need to escape all backslashes. See above; this can be done with another append
result.append(str, pos, nextPos - pos);
pos = nextPos;
if (pos != str.npos)
{
// Must be followed by a quote; make sure we escape it, too. NOTE: We should have already early
// exited if this argument is being interpreted as an executable path
WI_ASSERT(str[pos] == '"');
result.append({'\\', '"'});
++pos;
}
}
else
{
// Otherwise space, which we handled above
WI_ASSERT((str[pos] == ' ') || (str[pos] == '\t'));
}
}
if (terminateWithQuotes)
{
result.push_back('"');
}
prefix = nextPrefix;
}
// NOTE: We optimize the force quotes case by including them in the prefix string. We're not appending a prefix
// anymore, so we need to make sure we close off the string
if (forceQuotes)
{
result.push_back(L'\"');
}
return result;
}
template <typename CharT>
inline std::basic_string<wistd::remove_cv_t<CharT>> ArgvToCommandLine(
int argc, CharT* const* argv, ArgvToCommandLineFlags flags = ArgvToCommandLineFlags::None)
{
return ArgvToCommandLine(details::iterable_span<CharT* const>{argv, static_cast<size_t>(argc)}, flags);
}
#endif
} // namespace wil
// Macro for calling GetProcAddress(), with type safety for C++ clients

View File

@ -19,7 +19,7 @@
// Helpers for return macros
/// @cond
#define __WIN32_RETURN_WIN32(error, str) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const auto __error = (error); \
if (FAILED_WIN32(__error)) \
@ -28,7 +28,7 @@
} \
return __error; \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define __WIN32_RETURN_GLE_FAIL(str) return __R_FN(Win32_Return_GetLastError)(__R_INFO_ONLY(str))
FORCEINLINE long __WIN32_FROM_HRESULT(HRESULT hr)
@ -51,7 +51,7 @@ FORCEINLINE long __WIN32_FROM_HRESULT(HRESULT hr)
// Conditionally returns failures (WIN32 error code) - always logs failures
#define WIN32_RETURN_IF_WIN32_ERROR(error) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const auto __errorRet = wil::verify_win32(error); \
if (FAILED_WIN32(__errorRet)) \
@ -59,47 +59,47 @@ FORCEINLINE long __WIN32_FROM_HRESULT(HRESULT hr)
__WIN32_RETURN_WIN32(__errorRet, #error); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define WIN32_RETURN_WIN32_IF(error, condition) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if (wil::verify_bool(condition)) \
{ \
__WIN32_RETURN_WIN32(wil::verify_win32(error), #condition); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define WIN32_RETURN_WIN32_IF_NULL(error, ptr) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if ((ptr) == nullptr) \
{ \
__WIN32_RETURN_WIN32(wil::verify_win32(error), #ptr); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define WIN32_RETURN_LAST_ERROR_IF(condition) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if (wil::verify_bool(condition)) \
{ \
__WIN32_RETURN_GLE_FAIL(#condition); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define WIN32_RETURN_LAST_ERROR_IF_NULL(ptr) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if ((ptr) == nullptr) \
{ \
__WIN32_RETURN_GLE_FAIL(#ptr); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
// Conditionally returns failures (WIN32 error code) - use for failures that are expected in common use - failures are not logged - macros are only for control flow pattern
#define WIN32_RETURN_IF_WIN32_ERROR_EXPECTED(error) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
const auto __errorRet = wil::verify_win32(error); \
if (FAILED_WIN32(__errorRet)) \
@ -107,43 +107,43 @@ FORCEINLINE long __WIN32_FROM_HRESULT(HRESULT hr)
return __errorRet; \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define WIN32_RETURN_WIN32_IF_EXPECTED(error, condition) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if (wil::verify_bool(condition)) \
{ \
return wil::verify_win32(error); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define WIN32_RETURN_WIN32_IF_NULL_EXPECTED(error, ptr) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if ((ptr) == nullptr) \
{ \
return wil::verify_win32(error); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define WIN32_RETURN_LAST_ERROR_IF_EXPECTED(condition) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if (wil::verify_bool(condition)) \
{ \
return wil::verify_win32(wil::details::GetLastErrorFail()); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
#define WIN32_RETURN_LAST_ERROR_IF_NULL_EXPECTED(ptr) \
__WI_SUPPRESS_4127_S do \
__WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \
if ((ptr) == nullptr) \
{ \
return wil::verify_win32(wil::details::GetLastErrorFail()); \
} \
} \
__WI_SUPPRESS_4127_E while ((void)0, 0)
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
//*****************************************************************************
// Macros to catch and convert exceptions on failure

View File

@ -14,6 +14,8 @@
#include <WinUser.h>
#include <exception>
#include "common.h"
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
namespace wil
{
@ -28,7 +30,7 @@ namespace details
BOOL __stdcall EnumWindowsCallbackNoThrow(HWND hwnd, LPARAM lParam)
{
auto pCallback = reinterpret_cast<TCallback*>(lParam);
#ifdef __cpp_if_constexpr
#if __cpp_if_constexpr >= 201606L
using result_t = decltype((*pCallback)(hwnd));
if constexpr (wistd::is_void_v<result_t>)
{
@ -74,7 +76,7 @@ namespace details
try
{
auto pCallback = pCallbackData->pCallback;
#ifdef __cpp_if_constexpr
#if __cpp_if_constexpr >= 201606L
using result_t = decltype((*pCallback)(hwnd));
if constexpr (std::is_void_v<result_t>)
{

View File

@ -29,31 +29,11 @@
#endif
/// @cond
#if defined(WIL_ENABLE_EXCEPTIONS) && !defined(__WI_HAS_STD_LESS)
#ifdef __has_include
#if __has_include(<functional>)
#define __WI_HAS_STD_LESS 1
#if WIL_USE_STL
#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 _Ty>
struct less;
}
#pragma warning(pop)
#endif
#endif
#if defined(WIL_ENABLE_EXCEPTIONS) && defined(__has_include)
#if __has_include(<vector>)
#define __WI_HAS_STD_VECTOR 1
#include <iterator>
#include <vector>
#endif
#endif
/// @endcond
// This enables this code to be used in code that uses the ABI prefix or not.
@ -188,41 +168,43 @@ namespace details
}
template <typename LhsT, typename RhsT>
static auto equals(LhsT&& lhs, RhsT&& rhs) WI_NOEXCEPT->decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
static auto equals(LhsT&& lhs, RhsT&& rhs) WI_NOEXCEPT
-> decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
{
return compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)) == CSTR_EQUAL;
}
template <typename LhsT, typename RhsT>
static auto not_equals(LhsT&& lhs, RhsT&& rhs)
WI_NOEXCEPT->decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
static auto not_equals(LhsT&& lhs, RhsT&& rhs) WI_NOEXCEPT
-> decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
{
return compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)) != CSTR_EQUAL;
}
template <typename LhsT, typename RhsT>
static auto less(LhsT&& lhs, RhsT&& rhs) WI_NOEXCEPT->decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
static auto less(LhsT&& lhs, RhsT&& rhs) WI_NOEXCEPT
-> decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
{
return compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)) == CSTR_LESS_THAN;
}
template <typename LhsT, typename RhsT>
static auto less_equals(LhsT&& lhs, RhsT&& rhs)
WI_NOEXCEPT->decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
static auto less_equals(LhsT&& lhs, RhsT&& rhs) WI_NOEXCEPT
-> decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
{
return compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)) != CSTR_GREATER_THAN;
}
template <typename LhsT, typename RhsT>
static auto greater(LhsT&& lhs, RhsT&& rhs)
WI_NOEXCEPT->decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
static auto greater(LhsT&& lhs, RhsT&& rhs) WI_NOEXCEPT
-> decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
{
return compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)) == CSTR_GREATER_THAN;
}
template <typename LhsT, typename RhsT>
static auto greater_equals(LhsT&& lhs, RhsT&& rhs)
WI_NOEXCEPT->decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
static auto greater_equals(LhsT&& lhs, RhsT&& rhs) WI_NOEXCEPT
-> decltype(compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)), bool())
{
return compare(wistd::forward<LhsT>(lhs), wistd::forward<RhsT>(rhs)) != CSTR_LESS_THAN;
}
@ -608,7 +590,7 @@ public:
class vector_iterator
{
public:
#if defined(_XUTILITY_) || defined(WIL_DOXYGEN)
#if WIL_USE_STL || defined(WIL_DOXYGEN)
// could be random_access_iterator_tag but missing some features
typedef ::std::bidirectional_iterator_tag iterator_category;
#endif
@ -799,7 +781,7 @@ public:
class vector_iterator_nothrow
{
public:
#if defined(_XUTILITY_) || defined(WIL_DOXYGEN)
#if WIL_USE_STL || defined(WIL_DOXYGEN)
// must be input_iterator_tag as use (via ++, --, etc.) of one invalidates the other.
typedef ::std::input_iterator_tag iterator_category;
#endif
@ -969,7 +951,7 @@ public:
class iterable_iterator
{
public:
#if defined(_XUTILITY_) || defined(WIL_DOXYGEN)
#if WIL_USE_STL || defined(WIL_DOXYGEN)
typedef ::std::forward_iterator_tag iterator_category;
#endif
typedef TSmart value_type;
@ -1079,7 +1061,7 @@ private:
};
#pragma endregion
#if defined(__WI_HAS_STD_VECTOR) || defined(WIL_DOXYGEN)
#if (WIL_USE_STL && defined(WIL_ENABLE_EXCEPTIONS)) || defined(WIL_DOXYGEN)
/** 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.
@code
@ -1174,7 +1156,7 @@ public:
class iterable_iterator_nothrow
{
public:
#if defined(_XUTILITY_) || defined(WIL_DOXYGEN)
#if WIL_USE_STL || defined(WIL_DOXYGEN)
// muse be input_iterator_tag as use of one instance invalidates the other.
typedef ::std::input_iterator_tag iterator_category;
#endif
@ -2496,7 +2478,7 @@ struct ABI::Windows::Foundation::IAsyncOperationWithProgressCompletedHandler<ABI
#pragma pop_macro("ABI")
#endif
#if __WI_HAS_STD_LESS
#if WIL_USE_STL
namespace std
{

View File

@ -76,8 +76,12 @@
#define __WI_LIBCPP_STD_VER 14
#elif __WI_CPLUSPLUS <= 201703L
#define __WI_LIBCPP_STD_VER 17
#elif __WI_CPLUSPLUS <= 202002L
#define __WI_LIBCPP_STD_VER 20
#elif __WI_CPLUSPLUS <= 202302L
#define __WI_LIBCPP_STD_VER 23
#else
#define __WI_LIBCPP_STD_VER 18 // current year, or date of c++2a ratification
#define __WI_LIBCPP_STD_VER 24 // Newer standard or prerelease standard
#endif
#endif // __WI_LIBCPP_STD_VER

View File

@ -182,7 +182,7 @@ namespace __function
}
template <class _Ret, class _Class>
__WI_LIBCPP_INLINE_VISIBILITY bool __not_null(_Ret _Class::*__ptr)
__WI_LIBCPP_INLINE_VISIBILITY bool __not_null(_Ret _Class::* __ptr)
{
return __ptr;
}

View File

@ -86,9 +86,7 @@ using conditional_t = typename conditional<_Bp, _If, _Then>::type;
#endif
template <bool, class _Tp>
struct __WI_LIBCPP_TEMPLATE_VIS __lazy_enable_if
{
};
struct __WI_LIBCPP_TEMPLATE_VIS __lazy_enable_if{};
template <class _Tp>
struct __WI_LIBCPP_TEMPLATE_VIS __lazy_enable_if<true, _Tp>
{
@ -96,9 +94,7 @@ struct __WI_LIBCPP_TEMPLATE_VIS __lazy_enable_if<true, _Tp>
};
template <bool, class _Tp = void>
struct __WI_LIBCPP_TEMPLATE_VIS enable_if
{
};
struct __WI_LIBCPP_TEMPLATE_VIS enable_if{};
template <class _Tp>
struct __WI_LIBCPP_TEMPLATE_VIS enable_if<true, _Tp>
{
@ -1194,9 +1190,7 @@ using type_identity_t = typename type_identity<_Tp>::type;
// is_signed
template <class _Tp, bool = is_integral<_Tp>::value>
struct __libcpp_is_signed_impl : public __WI_LIBCPP_BOOL_CONSTANT(_Tp(-1) < _Tp(0))
{
};
struct __libcpp_is_signed_impl : public __WI_LIBCPP_BOOL_CONSTANT(_Tp(-1) < _Tp(0)){};
template <class _Tp>
struct __libcpp_is_signed_impl<_Tp, false> : public true_type
@ -1226,9 +1220,7 @@ __WI_LIBCPP_INLINE_VAR __WI_LIBCPP_CONSTEXPR bool is_signed_v = is_signed<_Tp>::
// is_unsigned
template <class _Tp, bool = is_integral<_Tp>::value>
struct __libcpp_is_unsigned_impl : public __WI_LIBCPP_BOOL_CONSTANT(_Tp(0) < _Tp(-1))
{
};
struct __libcpp_is_unsigned_impl : public __WI_LIBCPP_BOOL_CONSTANT(_Tp(0) < _Tp(-1)){};
template <class _Tp>
struct __libcpp_is_unsigned_impl<_Tp, false> : public false_type
@ -2282,9 +2274,7 @@ struct __WI_LIBCPP_TEMPLATE_VIS common_type<_Tp, _Up, void>
// bullet 1 - sizeof...(Tp) == 0
template <class... _Tp>
struct __WI_LIBCPP_TEMPLATE_VIS common_type
{
};
struct __WI_LIBCPP_TEMPLATE_VIS common_type{};
// bullet 2 - sizeof...(Tp) == 1
@ -4693,7 +4683,7 @@ namespace __detail
{
static const bool value =
#ifndef __WI_LIBCPP_HAS_NO_NOEXCEPT
noexcept(swap_wil(declval<_Tp>(), declval<_Up>()))&& noexcept(swap_wil(declval<_Up>(), declval<_Tp>()));
noexcept(swap_wil(declval<_Tp>(), declval<_Up>())) && noexcept(swap_wil(declval<_Up>(), declval<_Tp>()));
#else
false;
#endif