Implementation of ISupportErrorInfo - what does it mean?
Asked Answered
P

2

15

What does the ISupportErrorInfo interface mean? I'm at a bit of a loss to understand it. From MSDN:

This interface ensures that error information can be propagated up the call chain correctly. Automation objects that use the error handling interfaces must implement ISupportErrorInfo.

This method indicates whether or not an interface supports the IErrorInfo interface.

HRESULT InterfaceSupportsErrorInfo(
  REFIID riid
);

What does it mean to return S_OK in InterfaceSupportsErrorInfo? Should you return S_OK for all interfaces? Just some?

Pauperize answered 6/10, 2008 at 1:4 Comment(0)
U
23

My understanding of it (based on some related MSDN pages) is that by implementing ISupportErrorInfo, you are indicating that one or more interfaces on your class returns error information by calling SetErrorInfo, as opposed to just returning a failure HRESULT.

To that end, your implementation of ISuportErrorInfo::InterfaceSupportsErrorInfo should return S_OK only for those interfaces on your class that actually use SetErrorInfo to return error information to the caller, and only those interfaces.

For example, say you have a class that implements an interface you wrote called IFoo that has a DoSomething method. If someone else creates an instance of your class and calls IFoo::DoSomething, they are supposed to do the following if DoSomething returns a failure HRESULT (paraphrasing from various MSDN pages, but I started from here: http://msdn.microsoft.com/en-us/library/ms221510.aspx):

  • Call QueryInterface on the IFoo pointer to get the ISupportErrorInfo interface for the object that is implementing IFoo

  • If the called object doesn't implement ISupportErrorInfo, then the caller will have to handle the error based on the HRESULT value, or pass it up the call stack.

  • If the called object does implement ISupportErrorInfo, then the caller should call ISupportErrorInfo::InterfaceSupportsErrorInfo, passing in a REFIID for the interface that returned the error. In this case, the DoSomething method of the IFoo interface returned an error, so you would pass REFIID_IFoo (assuming it's defined) to InterfaceSupportsErrorInfo.

  • If InterfaceSupportsErrorInfo returns S_OK, then the caller knows at this point that it can retrieve more detailed information about the error by calling GetErrorInfo. If InterfaceSupportsErrorInfo returns S_FALSE, the caller can assume the called interface doesn't supply detailed error information, and will have to rely on the returned HRESULT to figure out what happened.

The reason for this somewhat confusing/convoluted error-handling API seems to be for flexibility (as far I as I can tell anyway. This is COM after all ;). With this design, a class can support multiple interfaces, but not every interface is required to use SetErrorInfo to return error information from its methods. You can have certain, select interfaces on your class return detailed error information via SetErrorInfo, while other interfaces can continue to use normal HRESULTs to indicate errors.

In summary, the ISupportErrorInfo interface is a way to inform the calling code that at least one of the interfaces your class implements can return detailed error information, and the InterfaceSupportsErrorInfo method tells the caller whether a given interface is one of those interfaces. If so, then the caller can retrieve the detailed error information by calling GetErrorInfo.

Udella answered 6/10, 2008 at 4:40 Comment(2)
"If the called object does implement ISupportErrorInfo, then the caller is supposed to QueryInterface for a ISupportErrorInfo" This is probably an error, because the caller just DID that call before to determine if this interface is supported in the first place? Shouldn't the caller then call ISupportErrorInfo::InterfaceSupportsErrorInfo directly without having to call QI a 2nd time?Doriedorin
@FelixDombek I agree. I edited the post to remove the redundant QueryInterface call.Udella
N
0

It is possible to set custom text error messages, via ICreateErrorInfo::SetDescription.

The deprecated Microsoft article Returning Error Information provides a good overview (and a flowchart!) of how to set the error. The following quote includes updated links:

To return error information

  1. Implement the ISupportErrorInfo interface.
  2. To create an instance of the generic error object, call the CreateErrorInfo function.
  3. To set its contents, use the ICreateErrorInfo methods.
  4. To associate the error object with the current logical thread, call the SetErrorInfo function.

Once the error is set, the method should avoid showing any kind of modal dialog or making other calls -- i.e. the method should return soon after calling SetErrorInfo. Likewise, the caller should retrieve the error with GetErrorInfo soon after the call returns.

Nurserymaid answered 11/7, 2024 at 19:15 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.