How to Fill EXCEPINFO in IDispatch Implementation

Last reviewed: November 12, 1995
Article ID: Q139073
The information in this article applies to:
  • OLE 2.03 for Windows 3.1x
  • Microsoft OLE libraries included with:

        - Microsoft Windows NT version 3.51
        - Microsoft Windows 95 version 4.0
    

SUMMARY

DispInvoke will fill the EXCEPINFO parameter of IDispatch::Invoke if the property or method implementation returns a failure HRESULT and uses SetErrorInfo() to provide rich error information.

MORE INFORMATION

An automation client that uses late-binding or id-binding to an automation server will use IDispatch::Invoke to invoke the server's property or method. Such a client will typically pass an EXCEPINFO structure as a parameter to IDispatch::Invoke to obtain rich error information on failure. The server will fill the EXCEPINFO structure on failure. A typical IDispatch::Invoke implementation in the server calls DispInvoke. Then DispInvoke calls the appropriate property or method implementation. Consequently, the property or method implementation doesn't have access to the EXCEPINFO parameter of IDispatch::Invoke to provide rich error information on failure.

The solution is to return a failure HRESULT from the property or method implementation and use SetErrorInfo in the property or method implementation. DispInvoke will check if the property or method returned a failure HRESULT. If so, it will fill the EXCEPINFO parameter using the information that the property or method provided with SetErrorInfo.

DispInvoke will not fill out the EXCEPINFO parameter if the return type of the property or method is not HRESULT. Therefore, this method is best suited for a dual interface, which requires HRESULT to be the return type for its methods and properties. Note that an id-binding or late- binding client will see the type of the parameter with the retval attibute as the return type.

For example, in the following code, the server implements IDispatch::Invoke in CServer::Invoke by using DispInvoke. If the client passes the DISPID of the Test method, DispInvoke will call CServer::Test - whose address is provided in the vtbl that is the first parameter of DispInvoke. Note that CServer::Test does not have direct access to the EXCEPINFO parameter. DispInvoke will fill the EXCEPINFO parameter using the information that CServer::Test provides using SetErrorInfo - if Test returns a failure HRESULT.

STDMETHODIMP CServer::Invoke(

      DISPID dispidMember,
      REFIID riid,
      LCID lcid,
      WORD wFlags,
      DISPPARAMS FAR* pdispparams,
      VARIANT FAR* pvarResult,
      EXCEPINFO FAR* pexcepinfo,
      UINT FAR* puArgErr)
{
    return  DispInvoke(
        this, m_ptinfo,
        dispidMember, wFlags, pdispparams,
        pvarResult, pexcepinfo, puArgErr);
}

STDMETHODIMP CServer::Test() {
    HRESULT hr, hr2;
    ICreateErrorInfo FAR* pcerrinfo;
    IErrorInfo FAR* perrinfo;

    hr = DoProcessing();
    if (FAILED(hr)
    {
        hr2 = CreateErrorInfo(&pcerrinfo);
        if (SUCCEEDED(hr2))
        {
            pcerrinfo->SetGUID(...);
            pcerrinfo->SetSource(...);
            pcerrinfo->SetDescription(...);
            pcerrinfo->SetHelpFile(...);
            pcerrinfo->SetHelpContext(...);
            hr2 = pcerrinfo->QueryInterface(IID_IErrorInfo,
                                   (LPVOID FAR*) &perrinfo);
            if (SUCCEEDED(hr2))
            {
               SetErrorInfo(0, perrinfo);
               perrinfo->Release();
            }
            pcerrinfo->Release();
        }
        return hr;
    }
    else return NOERROR;
}

If the property or method implementation has a return type other that HRESULT, it could write the rich error information to a variable that is accessible by the IDispatch::Invoke implementation. The IDispatch::Invoke implementation would copy this information to the EXCEPINFO parameter. Thread local storage of EXCEPINFO information should be used in a mutithreaded implementation. On the other hand, SetErrorInfo will work in a multithreaded environment and thread local storage is not required. Microsoft recommends the use of dual interfaces in which SetErrorInfo can be used to fill the EXCEPINFO structure.

NOTE: Documention of SetErrorInfo and related interfaces can be found in Chapter 10 of the OLE Programmer's Reference, Volume 2, second edition. For information on how to obtain the second edition of this book, please see the following article in the Microsoft Knowledge Base:

   ARTICLE-ID: Q124385
   TITLE     : SAMPLE: OLE Automation '94 Documentation and Samples


Additional reference words: 4.00
KBCategory: kbprg kbcode kbhowto
KBSubcategory: LeTwoAto


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: November 12, 1995
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.