GME  13
mfcdual.h
Go to the documentation of this file.
00001 // mfcdual.h: Helpful macros for adding dual interface support to
00002 //            MFC applications
00003 
00004 // This is a part of the Microsoft Foundation Classes C++ library.
00005 // Copyright (c) Microsoft Corporation.  All rights reserved.
00006 //
00007 // This source code is only intended as a supplement to the
00008 // Microsoft Foundation Classes Reference and related
00009 // electronic documentation provided with the library.
00010 // See these sources for detailed information regarding the
00011 // Microsoft Foundation Classes product.
00012 
00014 // BEGIN_DUAL_INTERFACE_PART is just like BEGIN_INTERFACE_PART,
00015 // except that it also adds the IDispatch methods to your class
00016 // declaration.
00017 #define BEGIN_DUAL_INTERFACE_PART(localClass, baseClass) \
00018         BEGIN_INTERFACE_PART(localClass, baseClass) \
00019            STDMETHOD(GetTypeInfoCount)(UINT FAR* pctinfo); \
00020            STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo); \
00021            STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR FAR* FAR* rgszNames, UINT cNames, LCID lcid, DISPID FAR* rgdispid); \
00022            STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pdispparams, VARIANT FAR* pvarResult, EXCEPINFO FAR* pexcepinfo, UINT FAR* puArgErr); \
00023 
00024 
00025 // END_DUAL_INTERFACE_PART is just like END_INTERFACE_PART. It
00026 // is only added for symmetry...
00027 #define END_DUAL_INTERFACE_PART(localClass) \
00028         END_INTERFACE_PART(localClass) \
00029 
00030 
00031 
00033 // DELEGATE_DUAL_INTERFACE expands to define the standard IDispatch
00034 // methods for a dual interface, delegating back to the default
00035 // MFC implementation
00036 #define DELEGATE_DUAL_INTERFACE(objectClass, dualClass) \
00037         STDMETHODIMP_(ULONG) objectClass::X##dualClass::AddRef() \
00038         { \
00039                 METHOD_PROLOGUE(objectClass, dualClass) \
00040                 return pThis->ExternalAddRef(); \
00041         } \
00042         STDMETHODIMP_(ULONG) objectClass::X##dualClass::Release() \
00043         { \
00044                 METHOD_PROLOGUE(objectClass, dualClass) \
00045                 return pThis->ExternalRelease(); \
00046         } \
00047         STDMETHODIMP objectClass::X##dualClass::QueryInterface( \
00048                 REFIID iid, LPVOID* ppvObj) \
00049         { \
00050                 METHOD_PROLOGUE(objectClass, dualClass) \
00051                 return pThis->ExternalQueryInterface(&iid, ppvObj); \
00052         } \
00053         STDMETHODIMP objectClass::X##dualClass::GetTypeInfoCount( \
00054                 UINT FAR* pctinfo) \
00055         { \
00056                 METHOD_PROLOGUE(objectClass, dualClass) \
00057                 LPDISPATCH lpDispatch = pThis->GetIDispatch(FALSE); \
00058                 ASSERT(lpDispatch != NULL); \
00059                 return lpDispatch->GetTypeInfoCount(pctinfo); \
00060         } \
00061         STDMETHODIMP objectClass::X##dualClass::GetTypeInfo( \
00062                 UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo) \
00063         { \
00064                 METHOD_PROLOGUE(objectClass, dualClass) \
00065                 LPDISPATCH lpDispatch = pThis->GetIDispatch(FALSE); \
00066                 ASSERT(lpDispatch != NULL); \
00067                 return lpDispatch->GetTypeInfo(itinfo, lcid, pptinfo); \
00068         } \
00069         STDMETHODIMP objectClass::X##dualClass::GetIDsOfNames( \
00070                 REFIID riid, OLECHAR FAR* FAR* rgszNames, UINT cNames, \
00071                 LCID lcid, DISPID FAR* rgdispid) \
00072         { \
00073                 METHOD_PROLOGUE(objectClass, dualClass) \
00074                 LPDISPATCH lpDispatch = pThis->GetIDispatch(FALSE); \
00075                 ASSERT(lpDispatch != NULL); \
00076                 return lpDispatch->GetIDsOfNames(riid, rgszNames, cNames, \
00077                                                                                  lcid, rgdispid); \
00078         } \
00079         STDMETHODIMP objectClass::X##dualClass::Invoke( \
00080                 DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, \
00081                 DISPPARAMS FAR* pdispparams, VARIANT FAR* pvarResult, \
00082                 EXCEPINFO FAR* pexcepinfo, UINT FAR* puArgErr) \
00083         { \
00084                 METHOD_PROLOGUE(objectClass, dualClass) \
00085                 LPDISPATCH lpDispatch = pThis->GetIDispatch(FALSE); \
00086                 ASSERT(lpDispatch != NULL); \
00087                 return lpDispatch->Invoke(dispidMember, riid, lcid, \
00088                                                                   wFlags, pdispparams, pvarResult, \
00089                                                                   pexcepinfo, puArgErr); \
00090         } \
00091 
00092 
00093 
00095 // TRY_DUAL and CATCH_ALL_DUAL are used to provide exception handling
00096 // for your dual interface methods. CATCH_ALL_DUAL takes care of
00097 // returning the appropriate error code.
00098 
00099 #define TRY_DUAL(iidSource) \
00100         HRESULT _hr = S_OK; \
00101         REFIID  _riidSource = iidSource; \
00102         TRY \
00103 
00104 #define CATCH_ALL_DUAL \
00105         CATCH(COleException, e) \
00106         { \
00107                 _hr = e->m_sc; \
00108         } \
00109         AND_CATCH_ALL(e) \
00110         { \
00111                 AFX_MANAGE_STATE(pThis->m_pModuleState); \
00112                 _hr = DualHandleException(_riidSource, e); \
00113         } \
00114         END_CATCH_ALL \
00115         return _hr; \
00116 
00117 
00118 // DualHandleException is a helper function used to set the system's
00119 // error object, so that container applications that call through
00120 // VTBLs can retrieve rich error information
00121 HRESULT DualHandleException(REFIID riidSource, const CException* pAnyException);
00122 
00124 // DECLARE_DUAL_ERRORINFO expands to declare the ISupportErrorInfo
00125 // support class. It works together with DUAL_ERRORINFO_PART and
00126 // IMPLEMENT_DUAL_ERRORINFO defined below.
00127 #define DECLARE_DUAL_ERRORINFO() \
00128         BEGIN_INTERFACE_PART(SupportErrorInfo, ISupportErrorInfo) \
00129                 STDMETHOD(InterfaceSupportsErrorInfo)(THIS_ REFIID riid); \
00130         END_INTERFACE_PART(SupportErrorInfo) \
00131 
00132 
00133 // DUAL_ERRORINFO_PART adds the appropriate entry to the interface map
00134 // for ISupportErrorInfo, if you used DECLARE_DUAL_ERRORINFO.
00135 #define DUAL_ERRORINFO_PART(objectClass) \
00136         INTERFACE_PART(objectClass, IID_ISupportErrorInfo, SupportErrorInfo) \
00137 
00138 
00139 // IMPLEMENT_DUAL_ERRORINFO expands to an implementation of
00140 // ISupportErrorInfo which matches the declaration in
00141 // DECLARE_DUAL_ERRORINFO.
00142 #define IMPLEMENT_DUAL_ERRORINFO(objectClass, riidSource) \
00143         STDMETHODIMP_(ULONG) objectClass::XSupportErrorInfo::AddRef() \
00144         { \
00145                 METHOD_PROLOGUE(objectClass, SupportErrorInfo) \
00146                 return pThis->ExternalAddRef(); \
00147         } \
00148         STDMETHODIMP_(ULONG) objectClass::XSupportErrorInfo::Release() \
00149         { \
00150                 METHOD_PROLOGUE(objectClass, SupportErrorInfo) \
00151                 return pThis->ExternalRelease(); \
00152         } \
00153         STDMETHODIMP objectClass::XSupportErrorInfo::QueryInterface( \
00154                 REFIID iid, LPVOID* ppvObj) \
00155         { \
00156                 METHOD_PROLOGUE(objectClass, SupportErrorInfo) \
00157                 return pThis->ExternalQueryInterface(&iid, ppvObj); \
00158         } \
00159         STDMETHODIMP objectClass::XSupportErrorInfo::InterfaceSupportsErrorInfo( \
00160                 REFIID iid) \
00161         { \
00162                 METHOD_PROLOGUE(objectClass, SupportErrorInfo) \
00163                 return (iid == riidSource) ? S_OK : S_FALSE; \
00164         }
00165 
00166 
00167