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_STRINGIZE_imp(x) #x
#define _wiltlg_LSTRINGIZE(x) _wiltlg_LSTRINGIZE_imp1(x) #define _wiltlg_LSTRINGIZE(x) _wiltlg_LSTRINGIZE_imp1(x)
#define _wiltlg_LSTRINGIZE_imp1(x) _wiltlg_LSTRINGIZE_imp2(#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): Macro __TRACELOGGING_DEFINE_PROVIDER_STORAGE_LINK(name1, name2):
@ -261,7 +261,8 @@ namespace details
public: public:
StoredCallContextInfo() WI_NOEXCEPT 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() StoredCallContextInfo(StoredCallContextInfo&& other) WI_NOEXCEPT : StoredCallContextInfo()
@ -1510,7 +1511,7 @@ public: \
#define __IMPLEMENT_CALLCONTEXT_CLASS(ActivityClassName) \ #define __IMPLEMENT_CALLCONTEXT_CLASS(ActivityClassName) \
protected: \ 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) \ ActivityBase(contextName) \
{ \ { \
GetCallContext()->SetMessage(formatString, argList); \ GetCallContext()->SetMessage(formatString, argList); \
@ -6444,7 +6445,13 @@ namespace details
if (*lastNamespaceNode) 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 else
{ {

View File

@ -16,12 +16,13 @@
#include <WeakReference.h> #include <WeakReference.h>
#include <combaseapi.h> #include <combaseapi.h>
#include "result.h" #include "result.h"
#include "win32_helpers.h"
#include "resource.h" // last to ensure _COMBASEAPI_H_ protected definitions are available #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> #include <tuple>
#endif #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> #include <type_traits>
#endif #endif
@ -2112,7 +2113,7 @@ wil::com_ptr_nothrow<Interface> CoGetClassObjectNoThrow(DWORD dwClsContext = CLS
return CoGetClassObjectNoThrow<Interface>(__uuidof(Class), dwClsContext); 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 /// @cond
namespace details namespace details
{ {
@ -2246,7 +2247,7 @@ auto try_com_multi_query(IUnknown* obj)
} }
#endif #endif
#endif // __cpp_lib_apply && __has_include(<type_traits>) #endif // __cpp_lib_apply && WI_HAS_INCLUDE(<type_traits>, 1)
#pragma endregion #pragma endregion
@ -3135,8 +3136,7 @@ void for_each_site(_In_opt_ IUnknown* siteInput, TLambda&& callback)
#endif // __IObjectWithSite_INTERFACE_DEFINED__ #endif // __IObjectWithSite_INTERFACE_DEFINED__
// if C++17 or greater #if __cpp_deduction_guides >= 201703L
#if WIL_HAS_CXX_17
#ifdef WIL_ENABLE_EXCEPTIONS #ifdef WIL_ENABLE_EXCEPTIONS
/// @cond /// @cond
namespace details namespace details
@ -3303,14 +3303,14 @@ WI_NODISCARD auto make_range(IEnumXxx* enumPtr)
using enumerator_type = com_iterator<TActualStoredType, IEnumXxx>; using enumerator_type = com_iterator<TActualStoredType, IEnumXxx>;
IEnumXxx* m_enumerator{}; wil::com_ptr<IEnumXxx> m_enumerator{};
iterator_range(IEnumXxx* enumPtr) : m_enumerator(enumPtr) iterator_range(IEnumXxx* enumPtr) : m_enumerator(enumPtr)
{ {
} }
WI_NODISCARD auto begin() WI_NODISCARD auto begin()
{ {
return enumerator_type(m_enumerator); return enumerator_type(m_enumerator.get());
} }
WI_NODISCARD constexpr auto end() const noexcept WI_NODISCARD constexpr auto end() const noexcept
@ -3322,9 +3322,131 @@ WI_NODISCARD auto make_range(IEnumXxx* enumPtr)
return iterator_range(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 #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 } // namespace wil
#endif #endif

View File

@ -69,15 +69,14 @@
/// @cond /// @cond
#if defined(_MSVC_LANG) #if defined(_MSVC_LANG)
#define __WI_SUPPRESS_4127_S \ #define __WI_SUPPRESS_BREAKING_WARNINGS_S __pragma(warning(push)) __pragma(warning(disable : 4127 26498 4245 26814))
__pragma(warning(push)) __pragma(warning(disable : 4127)) __pragma(warning(disable : 26498)) __pragma(warning(disable : 4245)) #define __WI_SUPPRESS_BREAKING_WARNINGS_E __pragma(warning(pop))
#define __WI_SUPPRESS_4127_E __pragma(warning(pop)) #define __WI_SUPPRESS_NULLPTR_ANALYSIS __pragma(warning(suppress : 28285 6504))
#define __WI_SUPPRESS_NULLPTR_ANALYSIS __pragma(warning(suppress : 28285)) __pragma(warning(suppress : 6504))
#define __WI_SUPPRESS_NONINIT_ANALYSIS __pragma(warning(suppress : 26495)) #define __WI_SUPPRESS_NONINIT_ANALYSIS __pragma(warning(suppress : 26495))
#define __WI_SUPPRESS_NOEXCEPT_ANALYSIS __pragma(warning(suppress : 26439)) #define __WI_SUPPRESS_NOEXCEPT_ANALYSIS __pragma(warning(suppress : 26439))
#else #else
#define __WI_SUPPRESS_4127_S #define __WI_SUPPRESS_BREAKING_WARNINGS_S
#define __WI_SUPPRESS_4127_E #define __WI_SUPPRESS_BREAKING_WARNINGS_E
#define __WI_SUPPRESS_NULLPTR_ANALYSIS #define __WI_SUPPRESS_NULLPTR_ANALYSIS
#define __WI_SUPPRESS_NONINIT_ANALYSIS #define __WI_SUPPRESS_NONINIT_ANALYSIS
#define __WI_SUPPRESS_NOEXCEPT_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 #error Must enable exceptions when WIL_EXCEPTION_MODE == 1
#endif #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 /// @cond
#ifndef WIL_ITERATOR_DEBUG_LEVEL #ifndef WIL_ITERATOR_DEBUG_LEVEL
// NOTE: See the definition of 'RESULT_DEBUG' for commentary on the use of 'WIL_KERNEL_MODE' below // 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 #endif
/// @cond /// @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 // Until we'll have C++17 enabled in our code base, we're falling back to SAL
#define WI_NODISCARD __WI_LIBCPP_NODISCARD_ATTRIBUTE #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_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 #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 /// @endcond
//! @defgroup bitwise Bitwise Inspection and Manipulation //! @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 @param val The logical bool expression
@return A C++ bool representing the evaluation of `val`. */ @return A C++ bool representing the evaluation of `val`. */
template <typename T, __R_ENABLE_IF_IS_CLASS(T)> 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); return static_cast<bool>(val);
} }
template <typename T, __R_ENABLE_IF_IS_NOT_CLASS(T)> 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"); static_assert(!wistd::is_same<T, T>::value, "Wrong Type: bool/BOOL/BOOLEAN/boolean expected");
return false; return false;
} }
template <> 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; return val;
} }
template <> 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); return (val != 0);
} }
template <> 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); 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 @param val The Win32 BOOL returning expression
@return A Win32 BOOL representing the evaluation of `val`. */ @return A Win32 BOOL representing the evaluation of `val`. */
template <typename T> 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; // 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"); 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) == 2 ? static_cast<unsigned short>(val) \
: sizeof(val) == 4 ? static_cast<unsigned long>(val) \ : sizeof(val) == 4 ? static_cast<unsigned long>(val) \
: static_cast<unsigned long long>(val)) __pragma(warning(pop))) : 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)) #define __WI_IS_SINGLE_FLAG_SET(val) __WI_IS_UNSIGNED_SINGLE_FLAG_SET(__WI_MAKE_UNSIGNED(val))
template <typename TVal, typename TFlags> template <typename TVal, typename TFlags>

View File

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

View File

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

View File

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

View File

@ -13,9 +13,17 @@
#ifndef __WIL_REGISTRY_HELPERS_INCLUDED #ifndef __WIL_REGISTRY_HELPERS_INCLUDED
#define __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 <functional>
#include <iterator> #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 #endif
#include <stdint.h> #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 * @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 * 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; return strings;
} }
#endif // #if defined(_VECTOR_) && defined(_STRING_) && defined(WIL_ENABLE_EXCEPTIONS) #endif
#if defined(__WIL_OBJBASE_H_) #if defined(__WIL_OBJBASE_H_)
template <size_t C> template <size_t C>
@ -442,7 +450,7 @@ namespace reg
return static_cast<DWORD>((::wcslen(value) + 1) * sizeof(wchar_t)); 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 inline void* get_buffer(const ::std::vector<uint8_t>& buffer) WI_NOEXCEPT
{ {
return const_cast<uint8_t*>(buffer.data()); return const_cast<uint8_t*>(buffer.data());
@ -517,9 +525,9 @@ namespace reg
} }
return S_OK; 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 inline void* get_buffer(const ::std::wstring& string) WI_NOEXCEPT
{ {
return const_cast<wchar_t*>(string.data()); return const_cast<wchar_t*>(string.data());
@ -575,7 +583,7 @@ namespace reg
} }
return buffer.size(); return buffer.size();
} }
#endif // #if defined(_STRING_) && defined(WIL_ENABLE_EXCEPTIONS) #endif
#if defined(__WIL_OLEAUTO_H_) #if defined(__WIL_OLEAUTO_H_)
inline void* get_buffer(const BSTR& value) WI_NOEXCEPT inline void* get_buffer(const BSTR& value) WI_NOEXCEPT
@ -972,7 +980,7 @@ namespace reg
return REG_SZ; return REG_SZ;
} }
#if defined(_STRING_) && defined(WIL_ENABLE_EXCEPTIONS) #if (WIL_USE_STL && defined(WIL_ENABLE_EXCEPTIONS)) || defined(WIL_DOXYGEN)
template <> template <>
constexpr DWORD get_value_type<::std::wstring>() WI_NOEXCEPT constexpr DWORD get_value_type<::std::wstring>() WI_NOEXCEPT
{ {
@ -984,7 +992,7 @@ namespace reg
{ {
return REG_SZ; return REG_SZ;
} }
#endif // #if defined(_STRING_) && defined(WIL_ENABLE_EXCEPTIONS) #endif
#if defined(__WIL_OLEAUTO_H_) #if defined(__WIL_OLEAUTO_H_)
template <> template <>
@ -1129,7 +1137,7 @@ namespace reg
return err_policy::HResult(hr); 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 // intended for err_exception_policy as err_returncode_policy will not get an error code
template <typename R> template <typename R>
::std::optional<R> try_get_value( ::std::optional<R> try_get_value(
@ -1151,7 +1159,7 @@ namespace reg
err_policy::HResult(hr); err_policy::HResult(hr);
return ::std::nullopt; return ::std::nullopt;
} }
#endif // #if defined (_OPTIONAL_) && defined(__cpp_lib_optional) #endif
template <typename R> template <typename R>
typename err_policy::result set_value( typename err_policy::result set_value(
@ -1313,7 +1321,7 @@ namespace reg
} }
#endif // #if defined(__WIL_WINREG_STL) #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 // 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 // these overloads must be declared before the template functions below, as some of those template functions
// reference these overload functions // reference these overload functions
@ -1340,7 +1348,7 @@ namespace reg
{ {
return !name.empty(); return !name.empty();
} }
#endif // #if defined(WIL_ENABLE_EXCEPTIONS) && defined(_STRING_) #endif
// string manipulation functions needed for iterator functions // string manipulation functions needed for iterator functions
template <typename T> template <typename T>
@ -1730,7 +1738,7 @@ namespace reg
// Notice this is a forward_iterator // Notice this is a forward_iterator
// - does not support random-access (e.g. vector::iterator) // - does not support random-access (e.g. vector::iterator)
// - does not support bidirectional access (e.g. list::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; using iterator_category = ::std::forward_iterator_tag;
#endif #endif
using value_type = T; using value_type = T;

View File

@ -16,6 +16,10 @@
#include "wistd_functional.h" #include "wistd_functional.h"
#include "wistd_memory.h" #include "wistd_memory.h"
#if WIL_USE_STL
#include <iterator>
#endif
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 26135 26110) // Missing locking annotation, Caller failing to hold lock #pragma warning(disable : 26135 26110) // Missing locking annotation, Caller failing to hold lock
#pragma warning(disable : 4714) // __forceinline not honored #pragma warning(disable : 4714) // __forceinline not honored
@ -1004,7 +1008,8 @@ private:
void call_init(wistd::true_type) 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) void call_init(wistd::false_type)
@ -3717,6 +3722,14 @@ namespace details
{ {
::HeapFree(::GetProcessHeap(), 0, p); ::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 } // namespace details
/// @endcond /// @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 /** Manages a typed pointer allocated with VirtualAlloc
A specialization of wistd::unique_ptr<> that frees via VirtualFree(p, 0, MEM_RELEASE). 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 #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)) || \ #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) defined(WIL_DOXYGEN)
/// @cond /// @cond
@ -4508,32 +4589,6 @@ namespace details
} // namespace details } // namespace details
/// @endcond /// @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_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<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; typedef unique_any<PSECURITY_DESCRIPTOR, decltype(&::LocalFree), ::LocalFree> unique_hlocal_security_descriptor;
@ -7296,7 +7351,7 @@ namespace details
struct iterator 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. // muse be input_iterator_tag as use of one instance invalidates the other.
typedef ::std::input_iterator_tag iterator_category; typedef ::std::input_iterator_tag iterator_category;
#endif #endif

View File

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

View File

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

View File

@ -44,6 +44,12 @@ namespace details
template <typename NewT, typename OldT> template <typename NewT, typename OldT>
constexpr bool both_integral_v = wistd::is_integral<NewT>::value && wistd::is_integral<OldT>::value; 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): // 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 // 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 // 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); *newTResult = static_cast<NewT>(var);
return S_OK; 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 } // namespace wil
#endif // __WIL_SAFECAST_INCLUDED #endif // __WIL_SAFECAST_INCLUDED

View File

@ -19,7 +19,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <utility> #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> #include <string_view>
#endif #endif
@ -132,7 +132,7 @@ inline PCWSTR str_raw_ptr(const std::wstring& str)
return str.c_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. 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. * 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 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); 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); return zwstring_view(str, len);
} }
} // namespace literals } // namespace literals
#endif // _HAS_CXX17 #endif // __cpp_lib_string_view >= 201606L
} // namespace wil } // namespace wil

View File

@ -20,11 +20,21 @@
#include <winreg.h> #include <winreg.h>
#include <objbase.h> #include <objbase.h>
// detect std::bit_cast #include "common.h"
#ifdef __has_include
#if (__cplusplus >= 202002L || _MSVC_LANG >= 202002L) && __has_include(<bit>) #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> #include <bit>
#endif #endif
#if WI_HAS_INCLUDE(<compare>, 1) // Assume present if C++20
#include <compare>
#endif
#endif
#endif #endif
/// @cond /// @cond
@ -40,25 +50,16 @@
#include "wistd_functional.h" #include "wistd_functional.h"
#include "wistd_type_traits.h" #include "wistd_type_traits.h"
/// @cond EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#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
/// @cond /// @cond
namespace wistd namespace wistd
{ {
#if defined(__WI_DEFINE_STRING_ORDINAL_FUNCTIONS) #if WIL_USE_STL && (__cpp_lib_three_way_comparison >= 201907L)
#if _HAS_CXX20
using weak_ordering = std::weak_ordering; using weak_ordering = std::weak_ordering;
#else // _HAS_CXX20 #else
struct weak_ordering 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::equivalent{static_cast<signed char>(0)};
inline constexpr weak_ordering weak_ordering::greater{static_cast<signed char>(1)}; inline constexpr weak_ordering weak_ordering::greater{static_cast<signed char>(1)};
#endif // !_HAS_CXX20 #endif
#endif // defined(__WI_DEFINE_STRING_ORDINAL_FUNCTIONS)
} // namespace wistd } // namespace wistd
/// @endcond /// @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, // 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). // 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 /// @cond
namespace details namespace details
{ {
@ -192,8 +190,7 @@ namespace details
return wistd::weak_ordering::equivalent; return wistd::weak_ordering::equivalent;
} }
} }
#endif
#endif // defined(__WI_DEFINE_STRING_ORDINAL_FUNCTIONS)
#pragma endregion #pragma endregion
@ -686,6 +683,7 @@ inline DWORD GetCurrentProcessExecutionOption(PCWSTR valueName, DWORD defaultVal
return defaultValue; 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. // Waits for a debugger to attach to the current process based on registry configuration.
// //
// Example: // Example:
@ -717,6 +715,7 @@ inline void WaitForDebuggerPresent(bool checkRegistryConfig = true)
Sleep(500); Sleep(500);
} }
} }
#endif
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
#endif #endif
@ -724,7 +723,6 @@ inline void WaitForDebuggerPresent(bool checkRegistryConfig = true)
/** Retrieve the HINSTANCE for the current DLL or EXE using this symbol that /** 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 the linker provides for every module. This avoids the need for a global HINSTANCE variable
and provides access to this value for static libraries. */ and provides access to this value for static libraries. */
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
inline HINSTANCE GetModuleInstanceHandle() WI_NOEXCEPT inline HINSTANCE GetModuleInstanceHandle() WI_NOEXCEPT
{ {
return reinterpret_cast<HINSTANCE>(&__ImageBase); return reinterpret_cast<HINSTANCE>(&__ImageBase);
@ -894,6 +892,237 @@ bool init_once(_Inout_ INIT_ONCE& initOnce, T func)
} }
} }
#endif // WIL_ENABLE_EXCEPTIONS #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 } // namespace wil
// Macro for calling GetProcAddress(), with type safety for C++ clients // Macro for calling GetProcAddress(), with type safety for C++ clients

View File

@ -19,7 +19,7 @@
// Helpers for return macros // Helpers for return macros
/// @cond /// @cond
#define __WIN32_RETURN_WIN32(error, str) \ #define __WIN32_RETURN_WIN32(error, str) \
__WI_SUPPRESS_4127_S do \ __WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \ { \
const auto __error = (error); \ const auto __error = (error); \
if (FAILED_WIN32(__error)) \ if (FAILED_WIN32(__error)) \
@ -28,7 +28,7 @@
} \ } \
return __error; \ 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)) #define __WIN32_RETURN_GLE_FAIL(str) return __R_FN(Win32_Return_GetLastError)(__R_INFO_ONLY(str))
FORCEINLINE long __WIN32_FROM_HRESULT(HRESULT hr) 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 // Conditionally returns failures (WIN32 error code) - always logs failures
#define WIN32_RETURN_IF_WIN32_ERROR(error) \ #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); \ const auto __errorRet = wil::verify_win32(error); \
if (FAILED_WIN32(__errorRet)) \ if (FAILED_WIN32(__errorRet)) \
@ -59,47 +59,47 @@ FORCEINLINE long __WIN32_FROM_HRESULT(HRESULT hr)
__WIN32_RETURN_WIN32(__errorRet, #error); \ __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) \ #define WIN32_RETURN_WIN32_IF(error, condition) \
__WI_SUPPRESS_4127_S do \ __WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \ { \
if (wil::verify_bool(condition)) \ if (wil::verify_bool(condition)) \
{ \ { \
__WIN32_RETURN_WIN32(wil::verify_win32(error), #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) \ #define WIN32_RETURN_WIN32_IF_NULL(error, ptr) \
__WI_SUPPRESS_4127_S do \ __WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \ { \
if ((ptr) == nullptr) \ if ((ptr) == nullptr) \
{ \ { \
__WIN32_RETURN_WIN32(wil::verify_win32(error), #ptr); \ __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) \ #define WIN32_RETURN_LAST_ERROR_IF(condition) \
__WI_SUPPRESS_4127_S do \ __WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \ { \
if (wil::verify_bool(condition)) \ if (wil::verify_bool(condition)) \
{ \ { \
__WIN32_RETURN_GLE_FAIL(#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) \ #define WIN32_RETURN_LAST_ERROR_IF_NULL(ptr) \
__WI_SUPPRESS_4127_S do \ __WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \ { \
if ((ptr) == nullptr) \ if ((ptr) == nullptr) \
{ \ { \
__WIN32_RETURN_GLE_FAIL(#ptr); \ __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 // 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) \ #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); \ const auto __errorRet = wil::verify_win32(error); \
if (FAILED_WIN32(__errorRet)) \ if (FAILED_WIN32(__errorRet)) \
@ -107,43 +107,43 @@ FORCEINLINE long __WIN32_FROM_HRESULT(HRESULT hr)
return __errorRet; \ 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) \ #define WIN32_RETURN_WIN32_IF_EXPECTED(error, condition) \
__WI_SUPPRESS_4127_S do \ __WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \ { \
if (wil::verify_bool(condition)) \ if (wil::verify_bool(condition)) \
{ \ { \
return wil::verify_win32(error); \ 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) \ #define WIN32_RETURN_WIN32_IF_NULL_EXPECTED(error, ptr) \
__WI_SUPPRESS_4127_S do \ __WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \ { \
if ((ptr) == nullptr) \ if ((ptr) == nullptr) \
{ \ { \
return wil::verify_win32(error); \ 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) \ #define WIN32_RETURN_LAST_ERROR_IF_EXPECTED(condition) \
__WI_SUPPRESS_4127_S do \ __WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \ { \
if (wil::verify_bool(condition)) \ if (wil::verify_bool(condition)) \
{ \ { \
return wil::verify_win32(wil::details::GetLastErrorFail()); \ 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) \ #define WIN32_RETURN_LAST_ERROR_IF_NULL_EXPECTED(ptr) \
__WI_SUPPRESS_4127_S do \ __WI_SUPPRESS_BREAKING_WARNINGS_S do \
{ \ { \
if ((ptr) == nullptr) \ if ((ptr) == nullptr) \
{ \ { \
return wil::verify_win32(wil::details::GetLastErrorFail()); \ 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 // Macros to catch and convert exceptions on failure

View File

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

View File

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

View File

@ -76,8 +76,12 @@
#define __WI_LIBCPP_STD_VER 14 #define __WI_LIBCPP_STD_VER 14
#elif __WI_CPLUSPLUS <= 201703L #elif __WI_CPLUSPLUS <= 201703L
#define __WI_LIBCPP_STD_VER 17 #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 #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
#endif // __WI_LIBCPP_STD_VER #endif // __WI_LIBCPP_STD_VER

View File

@ -182,7 +182,7 @@ namespace __function
} }
template <class _Ret, class _Class> 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; return __ptr;
} }

View File

@ -86,9 +86,7 @@ using conditional_t = typename conditional<_Bp, _If, _Then>::type;
#endif #endif
template <bool, class _Tp> template <bool, class _Tp>
struct __WI_LIBCPP_TEMPLATE_VIS __lazy_enable_if struct __WI_LIBCPP_TEMPLATE_VIS __lazy_enable_if{};
{
};
template <class _Tp> template <class _Tp>
struct __WI_LIBCPP_TEMPLATE_VIS __lazy_enable_if<true, _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> template <bool, class _Tp = void>
struct __WI_LIBCPP_TEMPLATE_VIS enable_if struct __WI_LIBCPP_TEMPLATE_VIS enable_if{};
{
};
template <class _Tp> template <class _Tp>
struct __WI_LIBCPP_TEMPLATE_VIS enable_if<true, _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 // is_signed
template <class _Tp, bool = is_integral<_Tp>::value> 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> template <class _Tp>
struct __libcpp_is_signed_impl<_Tp, false> : public true_type 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 // is_unsigned
template <class _Tp, bool = is_integral<_Tp>::value> 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> template <class _Tp>
struct __libcpp_is_unsigned_impl<_Tp, false> : public false_type 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 // bullet 1 - sizeof...(Tp) == 0
template <class... _Tp> template <class... _Tp>
struct __WI_LIBCPP_TEMPLATE_VIS common_type struct __WI_LIBCPP_TEMPLATE_VIS common_type{};
{
};
// bullet 2 - sizeof...(Tp) == 1 // bullet 2 - sizeof...(Tp) == 1
@ -4693,7 +4683,7 @@ namespace __detail
{ {
static const bool value = static const bool value =
#ifndef __WI_LIBCPP_HAS_NO_NOEXCEPT #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 #else
false; false;
#endif #endif