Ответ 1
Мое понимание этого (на основе некоторых связанных страниц MSDN) заключается в том, что, реализуя ISupportErrorInfo
, вы указываете, что один или несколько интерфейсов в вашем классе возвращают информацию об ошибках, вызывая SetErrorInfo
, а не просто возвращая отказ HRESULT
.
Для этого ваша реализация ISuportErrorInfo::InterfaceSupportsErrorInfo
должна возвращать S_OK
только для тех интерфейсов в вашем классе, которые фактически используют SetErrorInfo
, чтобы возвращать информацию об ошибке вызывающему, и только эти интерфейсы.
Например, скажем, у вас есть класс, который реализует интерфейс, который вы написали, называется IFoo
, который имеет метод DoSomething
. Если кто-то другой создает экземпляр вашего класса и вызывает IFoo::DoSomething
, они должны делать следующее, если DoSomething
возвращает сбой HRESULT
(перефразируя с разных страниц MSDN, но я начал здесь: http://msdn.microsoft.com/en-us/library/ms221510.aspx):
-
Вызвать
QueryInterface
указателемIFoo
для получения интерфейсаISupportErrorInfo
для объекта, который реализуетIFoo
-
Если вызываемый объект не реализует
ISupportErrorInfo
, то вызывающий для обработки ошибки на основеHRESULT
или передать его стек вызовов. -
Если вызываемый объект реализует
ISupportErrorInfo
, то вызывающий должен вызватьISupportErrorInfo::InterfaceSupportsErrorInfo
, передав вREFIID
для интерфейса, который возвратил ошибку. В этом случае методDoSomething
интерфейсаIFoo
возвратил ошибку, поэтому вы передали быREFIID_IFoo
(при условии, что он определен) наInterfaceSupportsErrorInfo
. -
Если
InterfaceSupportsErrorInfo
возвращаетS_OK
, затем вызывающий на данный момент знает, что он может получить более подробную информацию об ошибке, вызвавGetErrorInfo
. ЕслиInterfaceSupportsErrorInfo
возвращаетS_FALSE
, вызывающий может предположить, что вызываемый интерфейс не предоставляет подробную информацию об ошибке, и ему придется полагаться на возвращенный HRESULT, чтобы выяснить, что произошло.
Причина этого несколько запутывающего/запутанного API обработки ошибок представляется для гибкости (насколько я могу сказать в любом случае. Это COM все-таки;). С помощью этой конструкции класс может поддерживать несколько интерфейсов, но не каждый интерфейс должен использовать SetErrorInfo
для возврата информации об ошибках из своих методов. Вы можете иметь определенные, выбирать интерфейсы в своем классе, возвращать подробную информацию об ошибке через SetErrorInfo
, в то время как другие интерфейсы могут продолжать использовать обычный HRESULT
для указания ошибок.
Таким образом, интерфейс ISupportErrorInfo
является способом информирования вызывающего кода, что хотя бы один из интерфейсов, реализуемых вашим классом, может возвращать подробную информацию об ошибках, а метод InterfaceSupportsErrorInfo
сообщает вызывающему абоненту, является ли данный интерфейс одним этих интерфейсов. Если это так, то вызывающий абонент может получить подробную информацию об ошибке, вызвав GetErrorInfo
.