Is there a way to get the string representation of HRESULT value using win API?
Asked Answered
A

4

81

Is there a function in win API which can be used to extract the string representation of HRESULT value?

The problem is that not all return values are documented in MSDN, for example ExecuteInDefaultAppDomain() function is not documented to return "0x80070002 - The system cannot find the file specified.", however, it does! Therefore, I was wondering whether there is a function to be used in common case.

Aloke answered 10/8, 2011 at 8:44 Comment(1)
Title is different, but essentially the answer will be the same as for this one.Lonnylonslesaunier
M
115

You can use _com_error:

_com_error err(hr);
LPCTSTR errMsg = err.ErrorMessage();

If you don't want to use _com_error for whatever reason, you can still take a look at its source, and see how it's done.

Don't forget to include the header comdef.h

Molest answered 10/8, 2011 at 8:50 Comment(8)
A more complete sample for convenience: inline CString GetMessageForHresult(HRESULT hr) { _com_error error(hr); CString cs; cs.Format(_T("Error 0x%08x: %s"), hr, error.ErrorMessage()); return cs; }Propitiate
header file required: #include<comdef.h>Exemplification
@Propitiate what is CString?Broadspectrum
@PhaniRithvij, CString is MFC's string type (actual C++ class, that is; not a pointer to a C string like LPCTSTR and such).Molest
how we should free the errMsg?Nerva
@CEOatApartico the string returned by ErrorMessage will be released when the _com_error object is destructed. So you should neither free errMsg yourself nor store the returned string in some variable that outlives the _com_error object.Molest
yes, I have read that in the documentation that the lifetime of the _com_error is over when it exits from a block. thank you, for your response :)Nerva
"To use CString, include the atlstr.h header." - Microsoft docsBriarroot
P
37

Since c++11, this functionality is built into the standard library:

#include <system_error>

std::string message = std::system_category().message(hr)
Pokpoke answered 4/6, 2019 at 22:57 Comment(2)
This works for system errors, not generic HRESULT error codes. @che You are confusing HRESILT with NT_STATUS. Though they have similar encodings, the former is used throughout the Windows API (COM) as well as the Windows Runtime. You won't be using either one in a kernel mode module.Materse
_com_error from <comdef.h> nicely encapsulates all for you without using the "dreaded" <system_error> ... sadly that pushes you into a windows unresolved legacy land. We might actually reimplement that, minus the IErrorInfo functionality. Without using the std lib.Coelom
B
19

The Windows API for this is FormatMessage. Here is a link that explains how to do it: Retrieving Error Messages.

For Win32 messages (messages with an HRESULT that begins with 0x8007, which is FACILITY_WIN32), you need to remove the hi order word. For example in the 0x80070002, you need to call FormatMessage with 0x0002.

However, it does not always work for any type of message. And for some specific messages (specific to a technology, a vendor, etc.), you need to load the corresponding resource DLL, which is not always an easy task, because you need to find this DLL.

Botswana answered 10/8, 2011 at 9:3 Comment(2)
The 7 in 0x8007 is FACILITY_WIN32 and it is not FACILITY_ITF. See for example "Structure of COM Error Codes" at msdn.microsoft.com/en-us/library/ms690088Jugum
HRESULT_CODE(hr) can turn that into win32 error codeArteriovenous
G
4

Here's a sample using FormatMessage()

LPTSTR SRUTIL_WinErrorMsg(int nErrorCode, LPTSTR pStr, WORD wLength )
{
    try
    {
        LPTSTR  szBuffer = pStr;
        int nBufferSize = wLength;

        //
        // prime buffer with error code
        //
        wsprintf( szBuffer, _T("Error code %u"), nErrorCode);

        //
        // if we have a message, replace default with msg.
        //
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
                NULL, nErrorCode,
                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                (LPTSTR) szBuffer,   
                nBufferSize,    
                NULL );
    }
    catch(...)
    {
    }
    return pStr;
} // End of SRUTIL_WinErrorMsg()
Garygarza answered 26/5, 2016 at 15:27 Comment(1)
Win32 is C. That above is a mixture of C and C++ exceptions. I am unaware that FormatMessage or any other Win32 function trows c++ exceptions? FormatMessage is returning a value and it is well documented. And. That function can not be used on raw HERROR values. HRESULT_CODE(hr) will (likely) give you the error code you need to call that function with it.Coelom

© 2022 - 2024 — McMap. All rights reserved.