diff --git a/include/wil/winrt.h b/include/wil/winrt.h index 4d66e2f0..c5292fb5 100644 --- a/include/wil/winrt.h +++ b/include/wil/winrt.h @@ -1648,6 +1648,13 @@ namespace details HRESULT WaitForCompletion(_In_ TIOperation operation, _Out_ TIResults result, COWAIT_FLAGS flags, DWORD timeoutValue, _Out_opt_ bool* timedOut) WI_NOEXCEPT { RETURN_IF_FAILED_EXPECTED(details::WaitForCompletion(operation, flags, timeoutValue, timedOut)); + + // If the caller is listening for timedOut, and we actually timed out, return S_OK. + if (timedOut && *timedOut) + { + return S_OK; + } + return operation->GetResults(result); } #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) diff --git a/tests/FakeWinRTTypes.h b/tests/FakeWinRTTypes.h index ed4c87d6..cc11f726 100644 --- a/tests/FakeWinRTTypes.h +++ b/tests/FakeWinRTTypes.h @@ -172,7 +172,18 @@ struct FakeAsyncOperation IFACEMETHODIMP GetResults(Abi* results) override { - return m_storage.CopyTo(results); + auto lock = m_lock.lock_shared(); + switch (m_status) + { + case AsyncStatus::Started: + return E_ILLEGAL_METHOD_CALL; + case AsyncStatus::Completed: + return m_storage.CopyTo(results); + case AsyncStatus::Error: + return m_result; + default: + return E_NOTIMPL; + } } // Test functions diff --git a/tests/WinRTTests.cpp b/tests/WinRTTests.cpp index 5c108c31..47c43f7b 100644 --- a/tests/WinRTTests.cpp +++ b/tests/WinRTTests.cpp @@ -580,6 +580,20 @@ TEST_CASE("WinRTTests::WaitForCompletionTimeout", "[winrt][wait_for_completion]" REQUIRE(timedOut); } +TEST_CASE("WinRTTests::WaitForCompletionTimeoutWithResult", "[winrt][wait_for_completion]") +{ + auto op = Make>(); + REQUIRE(op); + + // The wait_for_completion* functions don't properly deduce the "decayed" async type, so force it here + auto asyncOp = static_cast*>(op.Get()); + + boolean result = false; + bool timedOut = false; + REQUIRE_SUCCEEDED(wil::wait_for_completion_or_timeout_nothrow(asyncOp, &result, 1, &timedOut)); + REQUIRE(timedOut); +} + // This is not a test method, nor should it be called. This is a compilation-only test. #pragma warning(push) #pragma warning(disable : 4702) // Unreachable code