According to this, there's no way to convert a HRESULT error code into a Win32 error code. Therefore (at least to my understanding), my use of FormatMessage in order to generate error messages (i.e.
std::wstring Exception::GetWideMessage() const
{
using std::tr1::shared_ptr;
shared_ptr<void> buff;
LPWSTR buffPtr;
DWORD bufferLength = FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetErrorCode(),
0,
reinterpret_cast<LPWSTR>(&buffPtr),
0,
NULL);
buff.reset(buffPtr, LocalFreeHelper());
return std::wstring(buffPtr, bufferLength);
}
) does not work for HRESULTs.
How do I generate these kinds of system-specific error strings for 开发者_运维知识库HRESULTs?
This answer incorporates Raymond Chen's ideas, and correctly discerns the incoming HRESULT, and returns an error string using the correct facility to obtain the error message:
/////////////////////////////
// ComException
CString FormatMessage(HRESULT result)
{
CString strMessage;
WORD facility = HRESULT_FACILITY(result);
CComPtr<IErrorInfo> iei;
if (S_OK == GetErrorInfo(0, &iei) && iei)
{
// get the error description from the IErrorInfo
BSTR bstr = NULL;
if (SUCCEEDED(iei->GetDescription(&bstr)))
{
// append the description to our label
strMessage.Append(bstr);
// done with BSTR, do manual cleanup
SysFreeString(bstr);
}
}
else if (facility == FACILITY_ITF)
{
// interface specific - no standard mapping available
strMessage.Append(_T("FACILITY_ITF - This error is interface specific. No further information is available."));
}
else
{
// attempt to treat as a standard, system error, and ask FormatMessage to explain it
CString error;
CErrorMessage::FormatMessage(error, result); // <- This is just a wrapper for ::FormatMessage, left to reader as an exercise :)
if (!error.IsEmpty())
strMessage.Append(error);
}
return strMessage;
}
精彩评论