The De Facto COM Return Type: HRESULT

 < Free Open Study > 



All of your COM interface methods should return the standard HRESULT return type. In the vast land of COM, only a tiny handful of interface methods (such as AddRef() and Release()) return otherwise, and that is only for quick and dirty debugging by the client. While nothing is syntactically preventing you from returning something other than an HRESULT from an interface method, you should get in the habit of always returning an HRESULT.

Note 

Any interface that may be remotely accessed must return an HRESULT.

The HRESULT return type allows your client to investigate if the method invocation succeeded, and if not, why. The HRESULT is a 32-bit value, logically partitioned into discrete sectors. The most significant bit of the HRESULT (bit 31) is used to determine if a call succeeded or failed. Bits 30-29 are reserved, while 28-16 define the "facility" of the error. The remaining bits define specific information concerning the error. Here is the physical layout of an HRESULT:

click to expand
Figure 3-9: Fields of the 32-bit HRESULT.

We have already seen some predefined COM HRESULT types, such as S_OK and E_NOINTERFACE. Here is a brief list of some of the more common existing HRESULTs (we will see more as necessary):

Standard HRESULT

Meaning in Life

S_OK

The method invocation returned successfully.

E_NOTIMPL

A member function of an interface is not implemented.

E_NOINTERFACE

Coclass does not support the requested interface.

E_OUTOFMEMORY

The coclass failed to allocate some memory.

E_FAIL

Something, in general, failed.

Clients are typically only really interested in the success or failure of the method invocation. For this purpose, COM provides two macros: SUCCEEDED and FAILED. These macros simply test the most significant bit of the HRESULT on your behalf and return true or false. Just send in an HRESULT to either macro, and it will return a Boolean. For example, assume a client has an interface pointer to IUnknown, and wishes to see if a call to QueryInterface() succeeded. Typical client-side COM code would be as follows:

// The SUCCEEDED macro tests the most significant bit of the HRESULT. // In the code below, assume we have already obtained an IUnknown pointer, // and now wish to grab IDraw off the object. IDraw* pDraw = NULL; HRESULT hr; hr = pUnk -> QueryInterface(IID_IDraw, (void**)&pDraw); // Did the QI call work? (i.e., does the object have an IDraw interface?) if(SUCCEEDED(hr))      pDraw->Draw(); // Clients must release all interface pointers when finished. pUnk->Release();        // Done with IUnknown pointer. pDraw->Release();       // Done drawing.

Analyzing an HRESULT

Beyond simply testing for the success or failure of a given interface method invocation, we can extract more specific information about the error in a number of ways. First of all, <winerror.h> defines all standard HRESULT errors, with a text description explaining exactly what went wrong. Here is the information for HRESULT number 0x80040111 (or the more readable CLASS_E_CLASSNOTAVAILABLE):

// MessageId: CLASS_E_CLASSNOTAVAILABLE // MessageText: // ClassFactory cannot supply requested class #define CLASS_E_CLASSNOTAVAILABLE _HRESULT_TYPEDEF_(0x80040111L)

If you don't like the idea of looking up HRESULTs by examining <winerror.h>, you can make use of a CASE tool supplied by DevStudio. From the Tools menu, select Error Lookup. You may paste in any HRESULT (which can be copied directly from the build tab of the Visual C++ output window), and look up the error information as shown in Figure 3-10:


Figure 3-10: The Error Lookup utility.

Finally, if you wish to examine the error description programmatically, you may use the Win32 FormatMessage() function. The parameters to this function are a bit hefty, but provide maximum flexibility (see online help for complete details). Here is an example of this function taking an HRESULT and storing the text message in a local buffer:

// The FormatMessage() function will programmatically grab the textual message for a // given HRESULT. HRESULT hr; hr = CoCreateInstance(...);          // COM library function. char buff[100]; BOOL bRet = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,                         0, hr, 0, buff, sizeof(buff), 0); cout << buff << endl; // Code on...



 < Free Open Study > 



Developer's Workshop to COM and ATL 3.0
Developers Workshop to COM and ATL 3.0
ISBN: 1556227043
EAN: 2147483647
Year: 2000
Pages: 171

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net