Return Types: HRESULT and SCODE

Except in special circumstances, nearly every COM and OLE API function and nearly every interface member function returns a value of the type HRESULT. HRESULT is also called a "handle to a result" and has a structure identical to the Win32 error codes structure, as shown in Figure 2-2.

Figure 2-2.

Structure of an HRESULT and an SCODE.

Another name for an HRESULT on 32-bit platforms is SCODE, which has exactly the same structure. Historically, these were different types on 16-bit platforms, but they have since been made identical. Because many of the samples in this book also compile to 16 bits, you'll see some 16-bit COM API functions used in the code. These compile to nothing under 32 bits.

A major benefit of this error structure is that it not only defines the error but also includes the facility or layer within the system or component that caused the error, such as whether it was an error in the RPC transport between processes or an error that occurred inside the implementation of a member function. This can help tremendously when you are trying to determine when and where the error occurred. The other big gain with HRESULT/SCODE is that the severity bit allows you to have multiple success codes in addition to multiple failure codes.5 Traditionally, functions have returned only Boolean information or returned only one success code and any number of error codes. With OLE, you can write a function that returns a TRUE or FALSE value if the function works and an error code if it doesn't work.

Because there are both multiple success and multiple error codes, OLE follows a naming convention for different codes. Any name with E_ in it, which may be at the beginning as in E_FAIL or RPC_E_NOTCONNECTED means that the function failed. Any name with S_, as in S_TRUE, S_FALSE, or STG_S_CONVERTED, means that the function succeeded. The most common codes are listed in Table 2-2. Because there can be multiple codes in each category, there are also two macros, SUCCEEDED and FAILED, that determine whether a code falls into the appropriate category, returning a Boolean TRUE or FALSE value. (SUCCEEDED returns TRUE when FAILED returns FALSE, and vice versa.) These macros actually do nothing more than test the high bit in the code, but they are used frequently in conditional statements.

Value

Meaning

S_OK

Function succeeded. Also used for functions that semantically return a Boolean TRUE result to indicate that the function succeeded.

S_FALSE

Used for functions that semantically return a Boolean FALSE result to indicate that the function succeeded.

E_NOINTERFACE

QueryInterface did not recognize the requested interface.

E_NOTIMPL

Member function contains no implementation.

E_FAIL

Unspecified failure.

E_OUTOFMEMORY

Function failed to allocate necessary memory.


Table 2-2.

Common SCODE values.

There is one special value that has the symbol NOERROR, which is defined as 0 and is equivalent to S_OK. (Win32 also defines NO_ERROR and ERROR_SUCCESS as 0.) You'll see this used quite often as a return value for a function, but you must be careful when you use it in a conditional statement. A common mistake is to compare the return value of a function to NOERROR to see whether it worked, but if the function returns a nonzero success code, such as S_FALSE (which is 1), the comparison will be wrong. There are only a few cases in which you really want to know whether the function returns exactly NOERROR. Otherwise, you should always use SUCCEEDED and FAILED.

You may have occasion to display a useful message to an end user when you encounter an error represented by an HRESULT. For this purpose, OLE offers the function FormatMessage that returns a user-readable message for any given HRESULT, localized to the user's language as appropriate. See the OLE Programmer's Reference for more information on this function.

5 Note that a function's possible success codes are part of that function's behavior and must be fixed when the function is first published. Error codes however can be added at any later time.