Reputation: 8050
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
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
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 HRESULT
s.
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 HRESULT
s generically.
Upvotes: 5