HRESULT is a computer programming data type that represents the completion status of a function.

It is used in the source code of applications targeting Microsoft Windows and earlier IBM/Microsoft OS/2 operating systems, but its design does not limit its use to these environments; it can be used in any system supporting 32-bit integers.

The original purpose of HRESULT was to lay out ranges of status codes for both public and Microsoft internal use in order to prevent collisions between status codes in different subsystems of the OS/2 operating system. [citation needed]

An HRESULT is designed to simultaneously be both a simple numerical value and a structure of fields indicating severity, facility and status code.

Use of HRESULT is most commonly encountered in COM programming, where it forms the basis for a standardized error handling mechanism, but its use is not limited to COM. For example, it can be used as an alternative to the more traditional use of a boolean pass/fail result.

Data structure edit

HRESULT is defined in a system header file as a 32-bit, signed integer[1] and is often treated opaquely as an integer, especially in code that consumes a function that returns HRESULT. A HRESULT value consists of the following separate items:

  • Severity: indicates whether the function succeeded or failed
  • Facility: identifies the part of the system for which the status applies
  • Code: identifies a particular condition in the context of the facility

An HRESULT value is a structure with the following bit-fields:[2]

Bit 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Field S R C N X Facility Code
  • S - Severity - indicates success (0) or failure (1)
  • R - Reserved; corresponds to NTSTATUS's second severity bit (1 - Severe Failure)
  • C - Customer. Specifies whether the value is Microsoft-defined (0) or customer-defined (1)
  • N - Reserved; used to indicate an NTSTATUS value that has been mapped to a HRESULT
  • X - Reserved for internal use; used to indicate a value that is not a status but is instead a message ID for display strings
  • Facility - indicates the system service that is responsible for the status; examples:
    • 1 - RPC
    • 2 - Dispatch (COM dispatch)
    • 3 - Storage (OLE storage)
    • 4 - ITF (COM/OLE Interface management)
    • 7 - Win32 (raw Win32 error codes)
    • 8 - Windows
    • 9 - SSPI
    • 10 - Control
    • 11 - CERT (Client or server certificate)
    • ...
  • Code - the facility's status code

Numeric representation edit

An HRESULT value is sometimes displayed as a hexadecimal value with 8 digits.

Examples:[3]

  • 0x80070005
    • 0x8 - Status: Failure
    • 0x7 - Facility: win32
    • 0x5 - Code: E_FAULT
  • 0x80090032
    • 0x8 - Status: Failure
    • 0x9 - Facility: SSPI
    • 0x32 - Code: The request is not supported

Sometimes an HRESULT value is shown as a signed integer, but this is less common and harder to read.

Name representation edit

An HRESULT is sometimes represented as an identifier with the format Facility_Severity_Reason:[4]

  • Facility is either the facility name or some other distinguishing identifier
  • Severity is a single letter, S for succeeded or E for error (failed)
  • Reason describes the meaning of the code

For example, STG_E_FILENOTFOUND indicates a storage related error, file does not exist.

The facility part is omitted if the facility is 0 (FACILITY_NULL) or for some very common values. For example: S_OK, E_FAIL, E_INVALIDARG.

This representation is easier to read than a numerical format but is less precise since although based on convention there is no definitive algorithm to convert between value and name.

IErrorInfo edit

The HRESULT was originally defined in the IBM/Microsoft OS/2 operating system as a general-purpose error return code, and subsequently adopted in Windows NT.

Microsoft Visual Basic substantially enhanced the HRESULT error reporting mechanisms, by associating an IErrorInfo object with an HRESULT and storing (a pointer to) an IErrorInfo object in thread-local storage. The IErrorInfo mechanism allows programs to associate a broad variety of information with a particular HRESULT error: the class of the object that raised the error, the interface of the object that raised the error, error text; and a link to a help topic in a help file. In addition, receivers of an HRESULT error can obtain localized text for the error message on demand.

Subsequently, HRESULT, and the associated IErrorInfo mechanism were used as the default error reporting mechanism in COM.

Support of the IErrorInfo mechanism in Windows is highly inconsistent. Older Windows APIs tend to not support it at all, returning HRESULTs without any IErrorInfo data. More modern Windows COM subsystems often provide extensive error information in the message description of the IErrorInfo object. The more advanced features of the IErrorInfo error mechanisms—help links, and on-demand localization—are rarely used.

In the .NET Framework, HRESULT/IErrorInfo error codes are translated into CLR exceptions when transitioning from native to managed code; and CLR exceptions are translated to HRESULT/IErrorInfo error codes when transitioning from managed to native COM code.

Using an HRESULT value edit

Since HRESULT is defined as a signed integer and since the severity field is the most significant bit, a negative value indicates failure and other values indicate success. The most commonly used success code is S_OK which has value 0. However, in rare circumstances, a function returns a success code with additional information such as S_FALSE which has value 1.

When an HRESULT value is displayed as hexadecimal (generally for debugging purposes) a developer can identify a value as indicating failure when it starts with digit 8 or greater in the 8th and most significant place. Note that if not padded to 8 digits with leading zeroes, a value might mistakenly be seen as failure. For example, 80005 is success even though it starts with 8. If padded to 8 digits this becomes clear: 00080005. This is somewhat contrived since generally success is 0 which is clearly a success code.

Programmatic ways to check for failure status are to test for negative or to use a system-defined macro.[5]

HRESULT hr = func(...);
if (hr < 0) ; // failed
if (hr >= 0) ; // succeeded
if (FAILED(hr)) ; // failed
if (SUCCEEDED(hr)) ; // succeeded

Testing for 0 such as (hr) or (!hr) will work most of the time but is incorrect for the rarely used success codes other than S_OK such as S_FALSE.

To obtain the code part of an HRESULT, use the HRESULT_CODE() macro.

Use the ERR.EXE tool to translate a value to the corresponding message text.

The ERRLOOK.EXE tool can be used to display error strings associated with a given HRESULT value. It can be run from a Visual Studio command prompt.

The win32SetErrorInfo associates an HRESULT value with a corresponding IErrorInfo object. GetErrorInfo reads this information.

The win32 FormatMessage can be used to get a human readable description of some non-IErrorInfo HRESULT values.

The winerror.h header file defines some commonly used HRESULT values. HRESULT values are sometimes encoded in the header (.h) files of a subsystem. These values are also defined in the corresponding header files of the Microsoft Windows Platforms SDK or DDK.

Origin of name edit

The name HRESULT appears to mean "result handle" since many other Windows types use H to mean handle. For example, HMODULE is a module handle which means an HMODULE value refers to a module resource. However, an HRESULT value does not refer to a resource so it is not a handle. According to Raymond Chen "in the old days it really was a handle to an object that contained rich error information ... The COM team decided that the cost/benefit simply wasn’t worth it, so the HRESULT turned into a simple number. But the name stuck."[6]

References edit

  1. ^ QuinnRadich. "Windows Data Types (BaseTsd.h) - Win32 apps". docs.microsoft.com. Retrieved 2022-07-10.
  2. ^ "[MS-ERREF]: HRESULT". docs.microsoft.com. Retrieved 2022-07-10.
  3. ^ "[MS-ERREF]: Win32 Error Codes". docs.microsoft.com. Retrieved 2022-07-10.
  4. ^ stevewhims. "Structure of COM Error Codes - Win32 apps". docs.microsoft.com. Retrieved 2022-07-11.
  5. ^ stevewhims. "Using Macros for Error Handling - Win32 apps". docs.microsoft.com. Retrieved 2022-07-10.
  6. ^ Chen, Raymond (2018-01-17). "Why does HRESULT begin with H when it's not a handle to anything?". The Old New Thing. Retrieved 2022-07-11.