rodrigocfd
rodrigocfd

Reputation: 8050

How to throw an std::system_error exception from a FAILED(HRESULT)?

This is how to throw ordinary Win32 errors correctly, automatically retrieving the error description, and it works marvellously well:

if (!SomeWinFunc()) {
  throw std::system_error(GetLastError(),
    std::system_category(),
    "SomeWinFunc crashed badly");
}

However, I'm uncertain on how to deal with COM errors, which are checked idiomatically like this:

HRESULT hr = comObj->SomeFunc();
if (FAILED(hr)) {
  throw std::system_error(hr, // <-- is it correct here?
    std::system_category(),
    "SomeFunc crashed right now");
}

Is it correct to pass an HRESULT to system_error, or there is another way to throw exceptions from a COM function?

Upvotes: 2

Views: 3281

Answers (2)

MHebes
MHebes

Reputation: 3247

This article has a great walkthrough of how to define an std::error_code for COM API errors: https://kb.firedaemon.com/support/solutions/articles/4000121648-fitting-com-into-c-system-error-handling

The gist of it is to just use _com_error to get the message, and the rest is mostly std boilerplate for creating error_codes.

Upvotes: 0

Michael Gunter
Michael Gunter

Reputation: 12811

Typically, I handle this using the Microsoft standard _com_error exception type, which can be easily raised by one of the following.

_com_util::CheckError(hr); // throws when FAILED(hr)
_com_issue_error(hr); // throws always

A Win32 error can be converted to an HRESULT like so:

hr = HRESULT_FROM_WIN32(GetLastError());

However, this means that you have to deal with a new exception type, which may be problematic. To do this the pure STL way, I think you need to derive a new error_category and use that instead of system_category. I would look at the <system_error> header and copy the implementation of system_category, updating as necessary for HRESULTs.

Ideally, the different facility codes in the HRESULT would be served by different error_category implementations -- doing so would very effectively communicate the exception and its source. But that is tricky, and you can probably get away with a single com_category that deals with HRESULTs generically.

Upvotes: 5

Related Questions