| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| #pragma once | ||
| //********************************************************* | ||
| // | ||
| // Copyright (c) Microsoft. All rights reserved. | ||
| // This code is licensed under the MIT License. | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF | ||
| // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED | ||
| // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | ||
| // PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
| // | ||
| //********************************************************* | ||
|
|
||
| #ifndef __WIL_TRACELOGGING_CONFIG_H | ||
| #define __WIL_TRACELOGGING_CONFIG_H | ||
|
|
||
| // Configuration macro for use in TRACELOGGING_DEFINE_PROVIDER. The definition | ||
| // in this file configures the provider as a normal (non-telemetry) provider. | ||
| #define TraceLoggingOptionMicrosoftTelemetry() \ | ||
| // Empty definition for TraceLoggingOptionMicrosoftTelemetry | ||
|
|
||
| // Configuration macro for use in TRACELOGGING_DEFINE_PROVIDER. The definition | ||
| // in this file configures the provider as a normal (non-telemetry) provider. | ||
| #define TraceLoggingOptionWindowsCoreTelemetry() \ | ||
| // Empty definition for TraceLoggingOptionWindowsCoreTelemetry | ||
|
|
||
| // Event privacy tags. Use the PDT macro values for the tag parameter, e.g.: | ||
| // TraceLoggingWrite(..., | ||
| // TelemetryPrivacyDataTag(PDT_BrowsingHistory | PDT_ProductAndServiceUsage), | ||
| // ...); | ||
| #define TelemetryPrivacyDataTag(tag) TraceLoggingUInt64((tag), "PartA_PrivTags") | ||
| #define PDT_BrowsingHistory 0x0000000000000002u | ||
| #define PDT_DeviceConnectivityAndConfiguration 0x0000000000000800u | ||
| #define PDT_InkingTypingAndSpeechUtterance 0x0000000000020000u | ||
| #define PDT_ProductAndServicePerformance 0x0000000001000000u | ||
| #define PDT_ProductAndServiceUsage 0x0000000002000000u | ||
| #define PDT_SoftwareSetupAndInventory 0x0000000080000000u | ||
|
|
||
| // Event categories specified via keywords, e.g.: | ||
| // TraceLoggingWrite(..., | ||
| // TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), | ||
| // ...); | ||
| #define MICROSOFT_KEYWORD_CRITICAL_DATA 0x0000800000000000 // Bit 47 | ||
| #define MICROSOFT_KEYWORD_MEASURES 0x0000400000000000 // Bit 46 | ||
| #define MICROSOFT_KEYWORD_TELEMETRY 0x0000200000000000 // Bit 45 | ||
| #define MICROSOFT_KEYWORD_RESERVED_44 0x0000100000000000 // Bit 44 (reserved for future assignment) | ||
|
|
||
| // Event categories specified via event tags, e.g.: | ||
| // TraceLoggingWrite(..., | ||
| // TraceLoggingEventTag(MICROSOFT_EVENTTAG_REALTIME_LATENCY), | ||
| // ...); | ||
| #define MICROSOFT_EVENTTAG_DROP_USER_IDS 0x00008000 | ||
| #define MICROSOFT_EVENTTAG_AGGREGATE 0x00010000 | ||
| #define MICROSOFT_EVENTTAG_DROP_PII_EXCEPT_IP 0x00020000 | ||
| #define MICROSOFT_EVENTTAG_COSTDEFERRED_LATENCY 0x00040000 | ||
| #define MICROSOFT_EVENTTAG_CORE_DATA 0x00080000 | ||
| #define MICROSOFT_EVENTTAG_INJECT_XTOKEN 0x00100000 | ||
| #define MICROSOFT_EVENTTAG_REALTIME_LATENCY 0x00200000 | ||
| #define MICROSOFT_EVENTTAG_NORMAL_LATENCY 0x00400000 | ||
| #define MICROSOFT_EVENTTAG_CRITICAL_PERSISTENCE 0x00800000 | ||
| #define MICROSOFT_EVENTTAG_NORMAL_PERSISTENCE 0x01000000 | ||
| #define MICROSOFT_EVENTTAG_DROP_PII 0x02000000 | ||
| #define MICROSOFT_EVENTTAG_HASH_PII 0x04000000 | ||
| #define MICROSOFT_EVENTTAG_MARK_PII 0x08000000 | ||
|
|
||
| // Field categories specified via field tags, e.g.: | ||
| // TraceLoggingWrite(..., | ||
| // TraceLoggingString(szUser, "UserName", "User's name", MICROSOFT_FIELDTAG_HASH_PII), | ||
| // ...); | ||
| #define MICROSOFT_FIELDTAG_DROP_PII 0x04000000 | ||
| #define MICROSOFT_FIELDTAG_HASH_PII 0x08000000 | ||
| #endif // __WIL_TRACELOGGING_CONFIG_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| //********************************************************* | ||
| // | ||
| // Copyright (c) Microsoft. All rights reserved. | ||
| // This code is licensed under the MIT License. | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF | ||
| // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED | ||
| // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | ||
| // PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
| // | ||
| //********************************************************* | ||
| #ifndef __WIL_WIN32_RESULTMACROS_INCLUDED | ||
| #define __WIL_WIN32_RESULTMACROS_INCLUDED | ||
|
|
||
| #include "result_macros.h" | ||
|
|
||
| // Helpers for return macros | ||
| #define __WIN32_RETURN_WIN32(error, str) __WI_SUPPRESS_4127_S do { const auto __error = (error); if (FAILED_WIN32(__error)) { __R_FN(Return_Win32)(__R_INFO(str) __error); } return __error; } __WI_SUPPRESS_4127_E while ((void)0, 0) | ||
| #define __WIN32_RETURN_GLE_FAIL(str) return __R_FN(Win32_Return_GetLastError)(__R_INFO_ONLY(str)) | ||
|
|
||
| FORCEINLINE long __WIN32_FROM_HRESULT(HRESULT hr) | ||
| { | ||
| if (SUCCEEDED(hr)) | ||
| { | ||
| return ERROR_SUCCESS; | ||
| } | ||
| return HRESULT_FACILITY(hr) == FACILITY_WIN32 ? HRESULT_CODE(hr) : hr; | ||
| } | ||
|
|
||
| //***************************************************************************** | ||
| // Macros for returning failures as WIN32 error codes | ||
| //***************************************************************************** | ||
|
|
||
| // Always returns a known result (WIN32 error code) - always logs failures | ||
| #define WIN32_RETURN_WIN32(error) __WIN32_RETURN_WIN32(wil::verify_win32(error), #error) | ||
| #define WIN32_RETURN_LAST_ERROR() __WIN32_RETURN_GLE_FAIL(nullptr) | ||
|
|
||
| // Conditionally returns failures (WIN32 error code) - always logs failures | ||
| #define WIN32_RETURN_IF_WIN32_ERROR(error) __WI_SUPPRESS_4127_S do { const auto __errorRet = wil::verify_win32(error); if (FAILED_WIN32(__errorRet)) { __WIN32_RETURN_WIN32(__errorRet, #error); }} __WI_SUPPRESS_4127_E while ((void)0, 0) | ||
| #define WIN32_RETURN_WIN32_IF(error, condition) __WI_SUPPRESS_4127_S do { if (wil::verify_bool(condition)) { __WIN32_RETURN_WIN32(wil::verify_win32(error), #condition); }} __WI_SUPPRESS_4127_E while ((void)0, 0) | ||
| #define WIN32_RETURN_WIN32_IF_NULL(error, ptr) __WI_SUPPRESS_4127_S do { if ((ptr) == nullptr) { __WIN32_RETURN_WIN32(wil::verify_win32(error), #ptr); }} __WI_SUPPRESS_4127_E while ((void)0, 0) | ||
| #define WIN32_RETURN_LAST_ERROR_IF(condition) __WI_SUPPRESS_4127_S do { if (wil::verify_bool(condition)) { __WIN32_RETURN_GLE_FAIL(#condition); }} __WI_SUPPRESS_4127_E while ((void)0, 0) | ||
| #define WIN32_RETURN_LAST_ERROR_IF_NULL(ptr) __WI_SUPPRESS_4127_S do { if ((ptr) == nullptr) { __WIN32_RETURN_GLE_FAIL(#ptr); }} __WI_SUPPRESS_4127_E while ((void)0, 0) | ||
|
|
||
| // Conditionally returns failures (WIN32 error code) - use for failures that are expected in common use - failures are not logged - macros are only for control flow pattern | ||
| #define WIN32_RETURN_IF_WIN32_ERROR_EXPECTED(error) __WI_SUPPRESS_4127_S do { const auto __errorRet = wil::verify_win32(error); if (FAILED_WIN32(__errorRet)) { return __errorRet; }} __WI_SUPPRESS_4127_E while ((void)0, 0) | ||
| #define WIN32_RETURN_WIN32_IF_EXPECTED(error, condition) __WI_SUPPRESS_4127_S do { if (wil::verify_bool(condition)) { return wil::verify_win32(error); }} __WI_SUPPRESS_4127_E while ((void)0, 0) | ||
| #define WIN32_RETURN_WIN32_IF_NULL_EXPECTED(error, ptr) __WI_SUPPRESS_4127_S do { if ((ptr) == nullptr) { return wil::verify_win32(error); }} __WI_SUPPRESS_4127_E while ((void)0, 0) | ||
| #define WIN32_RETURN_LAST_ERROR_IF_EXPECTED(condition) __WI_SUPPRESS_4127_S do { if (wil::verify_bool(condition)) { return wil::verify_win32(wil::details::GetLastErrorFail()); }} __WI_SUPPRESS_4127_E while ((void)0, 0) | ||
| #define WIN32_RETURN_LAST_ERROR_IF_NULL_EXPECTED(ptr) __WI_SUPPRESS_4127_S do { if ((ptr) == nullptr) { return wil::verify_win32(wil::details::GetLastErrorFail()); }} __WI_SUPPRESS_4127_E while ((void)0, 0) | ||
|
|
||
|
|
||
| //***************************************************************************** | ||
| // Macros to catch and convert exceptions on failure | ||
| //***************************************************************************** | ||
|
|
||
| // Use these macros *within* a catch (...) block to handle exceptions | ||
| #define WIN32_RETURN_CAUGHT_EXCEPTION() return __R_FN(Win32_Return_CaughtException)(__R_INFO_ONLY(nullptr)) | ||
|
|
||
| // Use these macros in place of a catch block to handle exceptions | ||
| #define WIN32_CATCH_RETURN() catch (...) { WIN32_RETURN_CAUGHT_EXCEPTION(); } | ||
|
|
||
| namespace wil | ||
| { | ||
| //***************************************************************************** | ||
| // Public Helpers that catch -- mostly only enabled when exceptions are enabled | ||
| //***************************************************************************** | ||
|
|
||
| // Win32ErrorFromCaughtException is a function that is meant to be called from within a catch(...) block. Internally | ||
| // it re-throws and catches the exception to convert it to a WIN32 error code. If an exception is of an unrecognized type | ||
| // the function will fail fast. | ||
| // | ||
| // try | ||
| // { | ||
| // // Code | ||
| // } | ||
| // catch (...) | ||
| // { | ||
| // status = wil::Win32ErrorFromCaughtException(); | ||
| // } | ||
| _Always_(_Post_satisfies_(return > 0)) | ||
| __declspec(noinline) inline long Win32ErrorFromCaughtException() WI_NOEXCEPT | ||
| { | ||
| return __WIN32_FROM_HRESULT(ResultFromCaughtException()); | ||
| } | ||
|
|
||
| namespace details::__R_NS_NAME | ||
| { | ||
| #ifdef WIL_ENABLE_EXCEPTIONS | ||
| __R_DIRECT_METHOD(long, Win32_Return_CaughtException)(__R_DIRECT_FN_PARAMS_ONLY) WI_NOEXCEPT | ||
| { | ||
| __R_FN_LOCALS; | ||
| return __WIN32_FROM_HRESULT(wil::details::ReportFailure_CaughtException<FailureType::Return>(__R_DIRECT_FN_CALL_ONLY)); | ||
| } | ||
| #endif | ||
|
|
||
| __R_DIRECT_METHOD(long, Win32_Return_GetLastError)(__R_DIRECT_FN_PARAMS_ONLY) WI_NOEXCEPT | ||
| { | ||
| __R_FN_LOCALS; | ||
| return __WIN32_FROM_HRESULT(wil::details::ReportFailure_GetLastErrorHr<FailureType::Return>(__R_DIRECT_FN_CALL_ONLY)); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #endif // __WIL_WIN32_RESULTMACROS_INCLUDED |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <!-- | ||
| Copyright (c) Microsoft. All rights reserved. | ||
| This code is licensed under the MIT License. | ||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF | ||
| ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED | ||
| TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | ||
| PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
| --> | ||
| <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> | ||
| <Type Name="wistd::_Func_impl<*>"> | ||
| <DisplayString>{_Callee._Object}</DisplayString> | ||
| <Expand> | ||
| </Expand> | ||
| </Type> | ||
|
|
||
| <Type Name="wistd::function<*>"> | ||
| <DisplayString Condition="_Impl == 0">empty</DisplayString> | ||
| <DisplayString Condition="_Impl != 0">{*_Impl}</DisplayString> | ||
| <Expand> | ||
| <ExpandedItem Condition="_Impl != 0">*_Impl</ExpandedItem> | ||
| </Expand> | ||
| </Type> | ||
|
|
||
| <Type Name="wistd::unique_ptr<*>"> | ||
| <DisplayString Condition="_Myptr == 0">empty</DisplayString> | ||
| <DisplayString Condition="_Myptr != 0">{*_Myptr}</DisplayString> | ||
| <StringView>_Myptr</StringView> | ||
| <Expand> | ||
| <Item Name="[pointer]" Condition="_Myptr != 0">_Myptr</Item> | ||
| </Expand> | ||
| </Type> | ||
|
|
||
| <Type Name="wistd::unique_ptr<wchar_t[*],*>"> | ||
| <DisplayString Condition="_Myptr == 0">empty</DisplayString> | ||
| <DisplayString Condition="_Myptr != 0">{_Myptr,su}</DisplayString> | ||
| <StringView>_Myptr</StringView> | ||
| <Expand> | ||
| <Item Name="[pointer]" Condition="_Myptr != 0">_Myptr</Item> | ||
| <Item Name="[length]" Condition="_Myptr != 0">wcslen(_Myptr)</Item> | ||
| </Expand> | ||
| </Type> | ||
|
|
||
| <Type Name="wistd::unique_ptr<char[*],*>"> | ||
| <DisplayString Condition="_Myptr == 0">empty</DisplayString> | ||
| <DisplayString Condition="_Myptr != 0">{_Myptr,s}</DisplayString> | ||
| <StringView>_Myptr</StringView> | ||
| <Expand> | ||
| <Item Name="[pointer]" Condition="_Myptr != 0">_Myptr</Item> | ||
| <Item Name="[length]" Condition="_Myptr != 0">strlen(_Myptr)</Item> | ||
| </Expand> | ||
| </Type> | ||
|
|
||
| <Type Name="wil::details::shared_storage<*>"> | ||
| <DisplayString Condition="m_ptr == 0">empty</DisplayString> | ||
| <DisplayString Condition="m_ptr != 0">{*m_ptr}</DisplayString> | ||
| <StringView>m_ptr</StringView> | ||
| <Expand> | ||
| <Item Name="[pointer]" Condition="m_ptr != 0">m_ptr</Item> | ||
| </Expand> | ||
| </Type> | ||
|
|
||
| <Type Name="wil::details::unique_storage<wil::details::handle_null_resource_policy<*>>"> | ||
| <DisplayString Condition="m_ptr == 0">empty</DisplayString> | ||
| <DisplayString Condition="m_ptr != 0">{m_ptr}</DisplayString> | ||
| <Expand> | ||
| </Expand> | ||
| </Type> | ||
| <Type Name="wil::details::unique_storage<wil::details::handle_invalid_resource_policy<*>>"> | ||
| <DisplayString Condition="m_ptr == 0">empty</DisplayString> | ||
| <DisplayString Condition="m_ptr != 0">{m_ptr}</DisplayString> | ||
| <Expand> | ||
| </Expand> | ||
| </Type> | ||
| <Type Name="wil::details::unique_storage<wil::details::resource_policy<*>>"> | ||
| <DisplayString Condition="m_ptr == 0">empty</DisplayString> | ||
| <DisplayString Condition="m_ptr != 0">{m_ptr}</DisplayString> | ||
| <StringView>m_ptr</StringView> | ||
| <Expand> | ||
| </Expand> | ||
| </Type> | ||
| <Type Name="wil::details::unique_storage<wil::details::resource_policy<wchar_t *,*>>"> | ||
| <DisplayString Condition="m_ptr == 0">empty</DisplayString> | ||
| <DisplayString Condition="m_ptr != 0">{m_ptr,su}</DisplayString> | ||
| <StringView>m_ptr</StringView> | ||
| <Expand> | ||
| <Item Name="[length]" Condition="m_ptr != 0">wcslen(m_ptr)</Item> | ||
| </Expand> | ||
| </Type> | ||
| <Type Name="wil::details::unique_storage<wil::details::resource_policy<char *,*>>"> | ||
| <DisplayString Condition="m_ptr == 0">empty</DisplayString> | ||
| <DisplayString Condition="m_ptr != 0">{m_ptr,s}</DisplayString> | ||
| <StringView>m_ptr</StringView> | ||
| <Expand> | ||
| <Item Name="[length]" Condition="m_ptr != 0">strlen(m_ptr)</Item> | ||
| </Expand> | ||
| </Type> | ||
|
|
||
| <Type Name="wil::com_ptr_t<*>"> | ||
| <DisplayString>{m_ptr}</DisplayString> | ||
| <Expand> | ||
| <ExpandedItem>m_ptr</ExpandedItem> | ||
| </Expand> | ||
| </Type> | ||
|
|
||
| <Type Name="wil::basic_zstring_view<*>"> | ||
| <Intrinsic Name="size" Expression="_Mysize" /> | ||
| <Intrinsic Name="data" Expression="_Mydata" /> | ||
| <DisplayString>{_Mydata,[_Mysize]}</DisplayString> | ||
| <Expand> | ||
| <Item Name="[size]" ExcludeView="simple">size()</Item> | ||
| </Expand> | ||
| </Type> | ||
| </AutoVisualizer> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,14 @@ | ||
| @echo off | ||
| setlocal | ||
| setlocal EnableDelayedExpansion | ||
|
|
||
| :: NOTE: Architecture is picked up from the command window, so we can't control that here :( | ||
| set COMPILERS=clang msvc | ||
| set BUILD_TYPES=debug relwithdebinfo | ||
|
|
||
| for %%c in (%COMPILERS%) do ( | ||
| for %%b in (%BUILD_TYPES%) do ( | ||
| call %~dp0\init.cmd -c %%c -g ninja -b %%b %* | ||
| if !ERRORLEVEL! NEQ 0 ( goto :eof ) | ||
| ) | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,19 +1,98 @@ | ||
|
|
||
| include(${PROJECT_SOURCE_DIR}/cmake/common_build_flags.cmake) | ||
|
|
||
| # All projects need to reference the WIL headers | ||
| include_directories(${PROJECT_SOURCE_DIR}/include) | ||
|
|
||
| # TODO: Might be worth trying to conditionally do this on SDK version, assuming there's a semi-easy way to detect that | ||
| include_directories(BEFORE SYSTEM ./workarounds/wrl) | ||
|
|
||
| # Because we don't always use msbuild, we need to run nuget manually | ||
| find_program(NUGET nuget) | ||
| if (NOT NUGET) | ||
| message(FATAL_ERROR "Unable to find the nuget CLI tool. Please install it from https://www.nuget.org/downloads and ensure it has been added to the PATH") | ||
| endif() | ||
|
|
||
| execute_process(COMMAND | ||
| ${NUGET} install Microsoft.Windows.CppWinRT -Version ${CPPWINRT_VERSION} -OutputDirectory packages | ||
| WORKING_DIRECTORY ${CMAKE_BINARY_DIR} | ||
| RESULT_VARIABLE ret) | ||
| if (NOT ret EQUAL 0) | ||
| message(FATAL_ERROR "Failed to install nuget package Microsoft.Windows.CppWinRT.${CPPWINRT_VERSION}") | ||
| endif() | ||
|
|
||
| set(CPPWINRT ${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.CppWinRT.${CPPWINRT_VERSION}/bin/cppwinrt.exe) | ||
| execute_process(COMMAND | ||
| ${CPPWINRT} -input sdk -output include | ||
| WORKING_DIRECTORY ${CMAKE_BINARY_DIR} | ||
| RESULT_VARIABLE ret) | ||
| if (NOT ret EQUAL 0) | ||
| message(FATAL_ERROR "Failed to run cppwinrt.exe") | ||
| endif() | ||
|
|
||
| include_directories(BEFORE SYSTEM ${CMAKE_BINARY_DIR}/include) | ||
|
|
||
| # The build pipelines have limitations that local development environments do not, so turn a few knobs | ||
| if (${FAST_BUILD}) | ||
| replace_cxx_flag("/GR" "/GR-") # Disables RTTI | ||
| add_definitions(-DCATCH_CONFIG_FAST_COMPILE -DWIL_FAST_BUILD) | ||
| endif() | ||
|
|
||
| # For some unknown reason, 'RelWithDebInfo' compiles with '/Ob1' as opposed to '/Ob2' which prevents inlining of | ||
| # functions not marked 'inline'. The reason we prefer 'RelWithDebInfo' over 'Release' is to get debug info, so manually | ||
| # revert to the desired (and default) inlining behavior as that exercises more interesting code paths | ||
| if (${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo") | ||
| # TODO: This is currently blocked by an apparent Clang bug: https://github.com/llvm/llvm-project/issues/59690 | ||
| # replace_cxx_flag("/Ob1" "/Ob2") | ||
| endif() | ||
|
|
||
| set(COMMON_SOURCES | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/CommonTests.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/ComTests.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/FileSystemTests.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/NTResultTests.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/ResourceTests.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/ResultTests.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/Rpc.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/SafeCastTests.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/TraceLoggingTests.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/WistdTests.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/wiTest.cpp | ||
| ${CMAKE_CURRENT_SOURCE_DIR}/../natvis/wil.natvis | ||
| ) | ||
|
|
||
| add_subdirectory(app) | ||
| add_subdirectory(cpplatest) | ||
| add_subdirectory(noexcept) | ||
| add_subdirectory(normal) | ||
| add_subdirectory(win7) | ||
|
|
||
| set(DEBUG_BUILD FALSE) | ||
| set(HAS_DEBUG_INFO FALSE) | ||
|
|
||
| if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") | ||
| set(DEBUG_BUILD TRUE) | ||
| set(HAS_DEBUG_INFO TRUE) | ||
| elseif(${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo") | ||
| set(HAS_DEBUG_INFO TRUE) | ||
| endif() | ||
|
|
||
| set(ASAN_AVAILABLE FALSE) | ||
| set(UBSAN_AVAILABLE FALSE) | ||
| if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") | ||
| # Address Sanitizer is available for all architectures and build types, but warns/errors if debug info is not enabled | ||
| set(ASAN_AVAILABLE ${HAS_DEBUG_INFO}) | ||
| elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") | ||
| # Address Sanitizer is not available with debug libraries | ||
| set(ASAN_AVAILABLE NOT ${DEBUG_BUILD}) | ||
| set(UBSAN_AVAILABLE NOT ${DEBUG_BUILD}) | ||
| endif() | ||
|
|
||
| if (${ASAN_AVAILABLE}) | ||
| add_subdirectory(sanitize-address) | ||
| endif() | ||
|
|
||
| if (${UBSAN_AVAILABLE}) | ||
| add_subdirectory(sanitize-undefined-behavior) | ||
| endif() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,165 @@ | ||
|
|
||
| #include <wil/result.h> | ||
| #include <wil/nt_result_macros.h> | ||
|
|
||
| #include "common.h" | ||
|
|
||
| #define STATUS_OBJECT_PATH_NOT_FOUND ((NTSTATUS)0xC000003AL) | ||
| #define STATUS_INTERNAL_ERROR ((NTSTATUS)0xC00000E5L) | ||
| #define STATUS_INVALID_CONNECTION ((NTSTATUS)0xC0000140L) | ||
| #define E_LOAD_NAMESERVICE_FAILED ((HRESULT)0x80000140L) | ||
|
|
||
| TEST_CASE("NtResultTests::NtReturn", "[result]") | ||
| { | ||
| auto status = []() | ||
| { | ||
| NT_RETURN_NTSTATUS(STATUS_INVALID_CONNECTION); | ||
| }(); | ||
| REQUIRE(status == STATUS_INVALID_CONNECTION); | ||
|
|
||
| status = []() | ||
| { | ||
| NT_RETURN_NTSTATUS_MSG(STATUS_INVALID_CONNECTION, "Test NT_RETURN_NTSTATUS_MSG"); | ||
| }(); | ||
| REQUIRE(status == STATUS_INVALID_CONNECTION); | ||
|
|
||
| status = []() | ||
| { | ||
| NT_RETURN_NTSTATUS_MSG(STATUS_INVALID_CONNECTION, "Test NT_RETURN_NTSTATUS_MSG %s", L"with parameter"); | ||
| }(); | ||
| REQUIRE(status == STATUS_INVALID_CONNECTION); | ||
|
|
||
| status = []() | ||
| { | ||
| NT_RETURN_IF_NTSTATUS_FAILED(STATUS_INVALID_CONNECTION); | ||
| return STATUS_SUCCESS; | ||
| }(); | ||
| REQUIRE(status == STATUS_INVALID_CONNECTION); | ||
|
|
||
| status = []() | ||
| { | ||
| NT_RETURN_IF_NTSTATUS_FAILED_MSG(STATUS_INVALID_CONNECTION, "Test NT_RETURN_NTSTATUS_MSG %s", L"with parameter"); | ||
| return STATUS_SUCCESS; | ||
| }(); | ||
| REQUIRE(status == STATUS_INVALID_CONNECTION); | ||
|
|
||
| status = []() | ||
| { | ||
| NT_RETURN_IF_NTSTATUS_FAILED(STATUS_SUCCESS); | ||
| return STATUS_INVALID_CONNECTION; | ||
| }(); | ||
| REQUIRE(status == STATUS_INVALID_CONNECTION); | ||
| } | ||
|
|
||
| #ifdef WIL_ENABLE_EXCEPTIONS | ||
| TEST_CASE("NtResultTests::NtThrowCatch", "[result]") | ||
| { | ||
| // Throw NTSTATUS with immediate conversion to HRESULT. HRESULT would appear in the logs. | ||
| auto hr = []() | ||
| { | ||
| try | ||
| { | ||
| THROW_NTSTATUS(STATUS_INVALID_CONNECTION); | ||
| } | ||
| CATCH_RETURN(); | ||
| }(); | ||
| // THROW_NTSTATUS converts NTSTATUS to HRESULT through WIN32 error code. | ||
| REQUIRE(hr == wil::details::NtStatusToHr(STATUS_INVALID_CONNECTION)); | ||
|
|
||
| // Verify that conversion NTSTATUS -> HRESULT -> NTSTATUS is not 1:1. | ||
| auto status = []() | ||
| { | ||
| try | ||
| { | ||
| THROW_HR(wil::details::NtStatusToHr(STATUS_INVALID_CONNECTION)); | ||
| } | ||
| NT_CATCH_RETURN(); | ||
| }(); | ||
| if (wil::details::g_pfnRtlNtStatusToDosErrorNoTeb) | ||
| { | ||
| REQUIRE(status != STATUS_INVALID_CONNECTION); | ||
| } | ||
| else | ||
| { | ||
| REQUIRE(status == STATUS_INVALID_CONNECTION); | ||
| } | ||
|
|
||
| // Throw HRESULT with conversion to NTSTATUS on a best effort. NTSTATUS would appear in the logs. | ||
| status = []() | ||
| { | ||
| try | ||
| { | ||
| THROW_HR(__HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)); | ||
| } | ||
| NT_CATCH_RETURN(); | ||
| }(); | ||
| REQUIRE(status == STATUS_OBJECT_PATH_NOT_FOUND); | ||
|
|
||
| // Throw HRESULT with conversion to NTSTATUS on a best effort that maps to generic error. NTSTATUS would appear in the logs. | ||
| status = []() | ||
| { | ||
| try | ||
| { | ||
| THROW_HR(E_LOAD_NAMESERVICE_FAILED); | ||
| } | ||
| NT_CATCH_RETURN(); | ||
| }(); | ||
| REQUIRE(status == STATUS_INTERNAL_ERROR); | ||
|
|
||
| // Throw NTSTATUS without conversion. NTSTATUS would appear in the logs. | ||
| status = []() | ||
| { | ||
| try | ||
| { | ||
| THROW_NTSTATUS(STATUS_INVALID_CONNECTION); | ||
| } | ||
| NT_CATCH_RETURN(); | ||
| }(); | ||
| REQUIRE(status == STATUS_INVALID_CONNECTION); | ||
|
|
||
| status = []() | ||
| { | ||
| try | ||
| { | ||
| THROW_NTSTATUS_MSG(STATUS_INVALID_CONNECTION, "Throw STATUS_INVALID_CONNECTION as NTSTATUS"); | ||
| } | ||
| NT_CATCH_RETURN(); | ||
| }(); | ||
| REQUIRE(status == STATUS_INVALID_CONNECTION); | ||
|
|
||
| status = []() | ||
| { | ||
| try | ||
| { | ||
| THROW_NTSTATUS_MSG(STATUS_INVALID_CONNECTION, "Throw STATUS_INVALID_CONNECTION as NTSTATUS with custom catch"); | ||
| } | ||
| catch (...) | ||
| { | ||
| LOG_CAUGHT_EXCEPTION(); | ||
|
|
||
| return wil::StatusFromCaughtException(); | ||
| } | ||
| }(); | ||
| REQUIRE(status == STATUS_INVALID_CONNECTION); | ||
|
|
||
| hr = []() | ||
| { | ||
| try | ||
| { | ||
| THROW_NTSTATUS_MSG(STATUS_INVALID_CONNECTION, "Throw STATUS_INVALID_CONNECTION as NTSTATUS"); | ||
| } | ||
| CATCH_RETURN(); | ||
| }(); | ||
| REQUIRE(hr == wil::details::NtStatusToHr(STATUS_INVALID_CONNECTION)); | ||
|
|
||
| status = []() | ||
| { | ||
| try | ||
| { | ||
| THROW_NTSTATUS_MSG(STATUS_INVALID_CONNECTION, "Throw STATUS_INVALID_CONNECTION as NTSTATUS"); | ||
| } | ||
| NT_CATCH_RETURN_MSG("Catching STATUS_INVALID_CONNECTION thrown by NT_THROW_NTSTATUS_MSG"); | ||
| }(); | ||
| REQUIRE(status == STATUS_INVALID_CONNECTION); | ||
| } | ||
| #endif |