HRESULT
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 could be used in any system supporting 32-bit integers. In other words, most modern computers.
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.
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
HRESULT is defined in a system header file as a 32-bit, signed integer[1] and a value is often treated opaquely as an integer, especially in code that consumes a function that returns HRESULT. But a value consists of the following separate items:[2]
- 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:
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 portion of the facility code; corresponds to NT's second severity bit (1 - Severe Failure)
- C - Customer. Specifies whether the value is Microsoft-defined (0) or customer-defined (1)
- N - Reserved portion of the facility code; used to indicate a mapped NT status value [is this reserved or used?]
- X - Reserved portion of the facility code; reserved for internal use; used to indicate a value that is not status but is instead message ids for display strings [is this reserved or used?]
- Facility - indicates the system service that is responsible for the status; examples:
- Code - the facility's status code
Numeric representation
An HRESULT value is sometimes displayed as a hexadecimal value with 8 digits.
Examples:[3]
0x80070005
0x8
- Status: Failure0x7
- Facility: win320x5
- Code: E_FAULT
0x80090032
0x8
- Status: Failure0x9
- Facility: SSPI0x32
- 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
An HRESULT is sometimes represented as a so-called name, an identifier with 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 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
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
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. But 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 0s, 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 test for negative and 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.
What does the H stand for?
The name HRESULT seems like it means "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. But an HRESULT value does not refer to a resource so it's 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
- QuinnRadich. "Windows Data Types (BaseTsd.h) - Win32 apps". docs.microsoft.com. Retrieved 2022-07-10.
- "[MS-ERREF]: HRESULT". docs.microsoft.com. Retrieved 2022-07-10.
- "[MS-ERREF]: Win32 Error Codes". docs.microsoft.com. Retrieved 2022-07-10.
- stevewhims. "Structure of COM Error Codes - Win32 apps". docs.microsoft.com. Retrieved 2022-07-11.
- stevewhims. "Using Macros for Error Handling - Win32 apps". docs.microsoft.com. Retrieved 2022-07-10.
- 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.