Deciphering an HRESULT

Aaron Stebner recently blogged about ways to find out the cause of 1935 Windows Installer errors and I wanted to provide a little more background on what an HRESULT defines.


An HRESULT in the 32-bit world and beyond is defined as a long, or a signed 32-bit integer. It is defined in, among other places, winerror.h in the Platform SDK. It defines the severity of an error, whether the error is from user code, a facility that defines where the error came from, and the actual error code. As defined in winerror.h:

//  Values are 32 bit values layed out as follows:
//
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// +—+-+-+———————–+——————————-+
// |Sev|C|R| Facility | Code |
// +—+-+-+———————–+——————————-+
//
// where
//
// Sev – is the severity code
//
// 00 – Success
// 01 – Informational
// 10 – Warning
// 11 – Error
//
// C – is the Customer code flag
//
// R – is a reserved bit
//
// Facility – is the facility code
//
// Code – is the facility’s status code

Return codes like S_OK and S_FALSE have the values 0 and 1, respectively. S_FALSE is not treated as an error because the severity bits are 0. Return codes like E_FAIL have the error bit set to 1 (the high-order bit). The macro HRESULT_SEVERITY can help determine if the return code represents an error or not by performing a bitwise AND on the high-order bit.


A facility helps identify from where the error came. Was it a security error or an error from the Common Language Runtime (CLR)? The macro HRESULT_FACILTY can help you determine that as well. winerror.h defines the following facilities (sorted by value):

#define FACILITY_NULL                    0
#define FACILITY_RPC 1
#define FACILITY_DISPATCH 2
#define FACILITY_STORAGE 3
#define FACILITY_ITF 4
#define FACILITY_WIN32 7
#define FACILITY_WINDOWS 8
#define FACILITY_SSPI 9
#define FACILITY_SECURITY 9
#define FACILITY_CONTROL 10
#define FACILITY_CERT 11
#define FACILITY_INTERNET 12
#define FACILITY_MEDIASERVER 13
#define FACILITY_MSMQ 14
#define FACILITY_SETUPAPI 15
#define FACILITY_SCARD 16
#define FACILITY_COMPLUS 17
#define FACILITY_AAF 18
#define FACILITY_URT 19
#define FACILITY_ACS 20
#define FACILITY_DPLAY 21
#define FACILITY_UMI 22
#define FACILITY_SXS 23
#define FACILITY_WINDOWS_CE 24
#define FACILITY_HTTP 25
#define FACILITY_BACKGROUNDCOPY 32
#define FACILITY_CONFIGURATION 33

All facilities except for FACILITY_ITF are defined by Microsoft. FACILITY_ITF is designated for user-defined error codes returned from interface methods. Microsoft recommends that when using FACILITY_ITF you use errors in the range of 0x0200 to 0xffff.


One might be asking if the 2 high-order bits define the severity and having both set is an error, why – in hexadecimal – does the error code number start with 8 instead of C? In the days of 16-bit computing, an HRESULT was only a 16-bit signed integer while an SCODE was a 32-bit signed integer. Only the highest-order bit designated the severity. The facility was also only 4 bits instead of 11. Error codes such as E_FAIL defined as 0x80004005 are legacy SCODEs and the values have not changed. Newer error codes may set both severity bits like ERROR_AUDITING_DISABLED defined as 0xC0090001.


Hopefully this helps you to decipher error codes and at least get some idea from where the error came.


Edit: Thanks to bgrainger for pointing out the correct recommended range.