in include/wil/winrt.h [1405:1481]
HRESULT WaitForCompletion(_In_ TIOperation operation, COWAIT_FLAGS flags, DWORD timeoutValue, _Out_opt_ bool* timedOut) WI_NOEXCEPT
{
typedef wistd::remove_pointer_t<decltype(GetAsyncDelegateType(operation))> TIDelegate;
class CompletionDelegate : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::Delegate>,
TIDelegate, Microsoft::WRL::FtmBase>
{
public:
HRESULT RuntimeClassInitialize()
{
RETURN_HR(m_completedEventHandle.create());
}
HRESULT STDMETHODCALLTYPE Invoke(_In_ TIOperation, ABI::Windows::Foundation::AsyncStatus status) override
{
m_status = status;
m_completedEventHandle.SetEvent();
return S_OK;
}
HANDLE GetEvent() const
{
return m_completedEventHandle.get();
}
ABI::Windows::Foundation::AsyncStatus GetStatus() const
{
return m_status;
}
private:
volatile ABI::Windows::Foundation::AsyncStatus m_status = ABI::Windows::Foundation::AsyncStatus::Started;
wil::unique_event_nothrow m_completedEventHandle;
};
WI_ASSERT(timedOut || (timeoutValue == INFINITE));
assign_to_opt_param(timedOut, false);
Microsoft::WRL::ComPtr<CompletionDelegate> completedDelegate;
RETURN_IF_FAILED(Microsoft::WRL::MakeAndInitialize<CompletionDelegate>(&completedDelegate));
RETURN_IF_FAILED(operation->put_Completed(completedDelegate.Get()));
HANDLE handles[] = { completedDelegate->GetEvent() };
DWORD dwHandleIndex;
HRESULT hr = CoWaitForMultipleHandles(flags, timeoutValue, ARRAYSIZE(handles), handles, &dwHandleIndex);
// If the caller is listening for timedOut, and we actually timed out, set the bool and return S_OK. Otherwise, fail.
if (timedOut && (hr == RPC_S_CALLPENDING))
{
*timedOut = true;
return S_OK;
}
RETURN_IF_FAILED(hr);
if (completedDelegate->GetStatus() != ABI::Windows::Foundation::AsyncStatus::Completed)
{
// QI to the IAsyncInfo interface. While all operations implement this, it is
// possible that the stub has disconnected, causing the QI to fail.
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncInfo> asyncInfo;
hr = operation->QueryInterface(IID_PPV_ARGS(&asyncInfo));
if (SUCCEEDED(hr))
{
// Save the error code result in a temporary variable to allow us
// to also retrieve the result of the COM call. If the stub has
// disconnected, this call may fail.
HRESULT errorCode = E_UNEXPECTED;
hr = asyncInfo->get_ErrorCode(&errorCode);
if (SUCCEEDED(hr))
{
// Return the operations error code to the caller.
hr = errorCode;
}
}
return hr; // leave it to the caller to log failures.
}
return S_OK;
}