Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Errors in Windows - DWORD (GetLastError) vs HRESULT vs LSTATUS

Tags:

I'm doing some programming in Win32 + WTL, and I'm confused with the available types of errors.

In general, I want to check for an error, and feed it to AtlGetErrorDescription (which calls FormatMessage).

My questions are:

  1. What's the difference between:

    • DWORD, returned by GetLastError.
    • HRESULT, returned by e.g. the CAtlFile wrapper, which uses HRESULT_FROM_WIN32 to convert from DWORD.
    • LSTATUS, returned by e.g. RegCreateKeyEx.
  2. Which types of errors can I feed to FormatMessage? Its signature indicates it accepts HRESULT, but there are lots of examples where the return value of GetLastError is directly passed to FormatMessage.

like image 664
Paul Avatar asked Oct 23 '13 16:10

Paul


1 Answers

They just reflect different APIs used in Windows:

  • GetLastError() returns a winapi error code. A simple number starting at 1. They are usually mapped from an underlying native api error code. Like ERROR_FILE_NOT_FOUND is mapped from the STATUS_OBJECT_NAME_NOT_FOUND file system driver error code. Winapi error codes are declared in the WinError.h SDK header file. You can count on getting a descriptive string from FormatMessage() with the FORMAT_MESSAGE_FROM_SYSTEM option.

  • An HRESULT is a COM error code. It is built up from three basic parts, the high bits indicate the severity, the middle bits encode the facility which indicates the source of the error, the low 16 bits encode an error number. The HRESULT_FROM_WIN32() macro is a helper macro to map a winapi error code to a COM error code. It just sets the severity to "fail", the facility code to 7 (winapi) and copies the error code into the low bits. There are a lot of possible COM error codes and only a few of them are convertible to a string by FormatMessage(). You should use the ISupportErrorInfo interface to ask if the COM server can provide a description of the error through IErrorInfo.

  • LSTATUS is obscure, RegCreateEx actually returns LONG, just the winapi error code. It does pop up in some shell wrapper functions, like SHGetValue(). It is often very unclear to me why the shell team does what it does.

  • Not mentioned in your question but worth noting are the error codes generated by the native api. They are documented in the ntstatus.h SDK header. The winapi is supposed to wrap the native api but these error codes do peek around the edges sometimes, particularly in exceptions. Most any programmer has seen the 0xc0000005 (STATUS_ACCESS_VIOLATION) exception code. 0xc00000fd matches this site's name. FormatMessage() can convert the common ones to a string as long as it wasn't a custom error code generated by a driver. There are several apis that use these kind of error codes, even though they run in user mode. Common examples are WIC and Media Foundation, otherwise without a strong hint why they preferred it this way. Getting a string for such an error code requires using FormatMessage with the FORMAT_MESSAGE_FROM_HMODULE option.

like image 198
Hans Passant Avatar answered Sep 21 '22 12:09

Hans Passant