GME
13
|
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