How to Get the String Representation of Hresult Value Using Win API

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

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

How to convert HRESULT into an error description?

This is the helper function we use in-house to extract a Win32 error code from an HRESULT:

DWORD Win32FromHResult(HRESULT hr)
{
if ((hr & 0xFFFF0000) == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, 0))
{
return HRESULT_CODE(hr);
}

if (hr == S_OK)
{
return ERROR_SUCCESS;
}

// Not a Win32 HRESULT so return a generic error code.
return ERROR_CAN_NOT_COMPLETE;
}

You can then use FormatMessage to get it into string form.

How can I (is there a way to) convert an HRESULT into a system specific error message?

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;
}

Win32: What is HRESULT 0x80070002?

0x80070002 is the Win32 error code 2 (ERROR_FILE_NOT_FOUND) in HRESULT format, as returned by the HRESULT_FROM_WIN32() macro.

When in doubt, you can use the HRESULT_FACILITY() and HRESULT_CODE() macros to help you figure out what an HRESULT stands for.

In this case, 0x80070002 has a facility of 7 (FACILITY_WIN32), meaning the code (2) is a Win32 error code (ERROR_FILE_NOT_FOUND).

Is there a reason why HRESULT should be assigned to a variable?

Suppose the code is incorrect and the method fails with an error HRESULT. You likely will be debugging this code in the near future. In that situation, what do you prefer? Having to debug into ThrowExceptionForHR to examine the HRESULT that was returned, or putting a watch on the local hr?

I know which I would prefer.

Suppose the hr is only an error code sometimes. What do you prefer, putting a breakpoint inside ThrowExceptionForHR, or putting a conditional breakpoint on the caller that only breaks if the value stored in hr is an error code?

Again, I know which I would prefer.

Design your code to be easy to debug. You'll thank yourself later.

How to use win api to check if the network is a pay-per-traffic link

Windows::Networking::Connectivity::NetworkInformation class is what you seek.

The GetInternetConnetionProfile method on this class returns a ConnectionProfile instance. On that object, you can invoke GetConnectionCost to get the NetworkCostType enum property. There's an event you can register a callback for when the user roams between networks so you know when to query it again.

If this property is "fixed" or "variable", you're on some sort of "metered network" connection where you might not want to have your app be conservative on network usage.

With that in mind, I believe the property that sets this bit simply a property of the network adapter. And maps to the user setting buried in Windows Settings:

Sample Image

I could be mistaken, but I'm not sure if there's any well known standard by which a network or ISP advertises the metered connection property dynamically in which Windows will pick it up. I think the OEM of the device sets this toggle switch when the machine is imaged.

IMetaDataEmit::DefineUserString returns HRESULT: -2147024882 (0x8007000E E_OUTOFMEMORY)

The issue was (apparently) due to an incorrect definition of the IMetaDataEmit interface.

Whatever the target language is, a COM interface definition must match the original binary layout exactly: all methods in same order (don't trust MSDN visual order on this), starting with derived interfaces methods (IUnknown, etc.), and exact binary-compatible signature for each method.

Is there a way to get an application's path to add it to the registry automatically and run alongside Windows startup in C++?

You are clearly compiling with UNICODE undefined in your project, which means RegOpenKeyEx() and RegSetValueEx() are actually calling the ANSI functions RegOpenKeyExA() and RegSetValueExA(), respectively (as evident by you being able to pass char* strings to them without compiler errors).

But, you are retrieving the file path as a Unicode UTF-16 string and passing it as-is to RegSetValueExA(), so you end up with embedded nul characters written to the Registry when RegSetValueExA() misinterprets your UTF-16 string as an ANSI string and re-encodes each of its bytes individually to Unicode characters. Unicode characters in the ASCII range have nul bytes in them.

Since you are using a Unicode function to retrieve the file path, and because the Registry internally stores strings in Unicode form only, you should use the Registry's Unicode functions to match that same encoding.

Also, note that the return value of GetModuleFileName(A|W) does not include the null terminator in the output string's length, but RegSetValueEx(A|W) expects the cbSize parameter to include enough bytes for a null terminator for REG_(EXPAND_|MULTI_)SZ value types.

Try this:

void Open()
{
WCHAR path[MAX_PATH]; //to store the directory

DWORD size = GetModuleFileNameW(NULL, path, MAX_PATH);
if ((size > 0) && (size < MAX_PATH))
{
HKEY hKey;
LONG lnRes = RegOpenKeyExW(HKEY_CURRENT_USER,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
0, KEY_SET_VALUE,
&hKey);
if( ERROR_SUCCESS == lnRes )
{
lnRes = RegSetValueExW(hKey,
L"MyApplication",
0,
REG_SZ,
(LPBYTE)path,
(size + 1) * sizeof(WCHAR) );

RegCloseKey(hKey);
}
}
}


Related Topics



Leave a reply



Submit