//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1999 // // File: comerror.h // // Contents: Support for Rich COM errors // // History: 14-Oct-99 VivekJ Created // //-------------------------------------------------------------------------- #ifndef COMERROR_H #define COMERROR_H #pragma once #include "tiedobj.h" //############################################################################ //############################################################################ // // COM Rich Error support // //############################################################################ //############################################################################ /*+-------------------------------------------------------------------------* * * MMCReportError * * PURPOSE: Calls AtlReportError and sets the last error condition based * on an SC. * * PARAMETERS: * SC & sc : * const IID : * const CLSID : * * RETURNS: * inline HRESULT * *+-------------------------------------------------------------------------*/ inline HRESULT MMCReportError(SC &sc, const IID &iid, const CLSID & clsid) { // only report the error if there was one. if(sc) { USES_CONVERSION; const int length = 256; TCHAR sz[length]; sc.GetErrorMessage(length, sz); // set everything we know about the error - the description, the help file, // the help ID, and the CLSID and IID of the source. return AtlReportError(clsid, sz, sc.GetHelpID(), sc.GetHelpFile(), iid, sc.ToHr()); } else return S_OK; } // see "WHY NAMESPACES ?" comment at the top of mmcerror.h file namespace comerror { /*+-------------------------------------------------------------------------* * class _SC * * * PURPOSE: a local version of the SC class that automatically sets the error * information when deleted. * * NOTE: Because of a compiler bug, this class cannot directly be internal * to IMMCSupportErrorInfoImpl<> * *+-------------------------------------------------------------------------*/ template class SC : public mmcerror::SC { typedef mmcerror::SC BaseClass; public: SC (HRESULT hr = S_OK) : BaseClass(hr) { } ~SC() { MMCReportError(*this, *piid, *pclsid); } // copy constructor SC(const BaseClass &rhs) : BaseClass(rhs) { } // assignment SC& operator= (HRESULT hr) { BaseClass::operator =(hr); return *this; } SC& operator= (const BaseClass &rhs) { BaseClass::operator =(rhs); return *this; } SC& operator= (const SC &rhs) { BaseClass::operator =(rhs); return *this; } }; } // namespace comerror /*+-------------------------------------------------------------------------* * class IMMCSupportErrorInfoImpl * * * PURPOSE: Inherits from ISupportErrorInfoImpl. local definition of the * status code class SC, which makes it easy to return error information * via the COM rich error handling system, without any extra effort * on the part of the programmer. * *+-------------------------------------------------------------------------*/ template class IMMCSupportErrorInfoImpl : public ISupportErrorInfoImpl { // this makes sure that AtlReportError is called in the destructor public: typedef comerror::SC SC; }; #define NYI_COM_METHOD() {SC sc = E_NOTIMPL; return sc.ToHr();} #ifdef AFX_MANAGE_STATE #define MMC_COM_MANAGE_STATE() AFX_MANAGE_STATE (AfxGetAppModuleState()) #else #define MMC_COM_MANAGE_STATE() /**/ #endif /************************************************************************ * The following macros make it easy to implement a lightweight * COM object that "connects" to a non-COM tied object and delegates * all its methods to the non-COM object. The tied object pointer * is checked as well. ************************************************************************/ #define MMC_METHOD_PROLOG() \ MMC_COM_MANAGE_STATE(); \ \ SC sc; \ \ CMyTiedObject *pTiedObj = NULL; \ \ sc = ScGetTiedObject(pTiedObj); \ if(sc) \ return (sc.ToHr()) #define MMC_METHOD_CALL(_fn) \ sc = pTiedObj->Sc##_fn #define MMC_METHOD_EPILOG() \ return sc.ToHr() #define MMC_METHOD0(_fn) \ STDMETHOD(_fn)() \ { \ MMC_METHOD_PROLOG(); \ MMC_METHOD_CALL(_fn)(); \ MMC_METHOD_EPILOG(); \ } #define MMC_METHOD0_PARAM(_fn, param) \ STDMETHOD(_fn)() \ { \ MMC_METHOD_PROLOG(); \ MMC_METHOD_CALL(_fn)(param); \ MMC_METHOD_EPILOG(); \ } #define MMC_METHOD1(_fn, T1) \ STDMETHOD(_fn)(T1 p1) \ { \ MMC_METHOD_PROLOG(); \ MMC_METHOD_CALL(_fn)(p1); \ MMC_METHOD_EPILOG(); \ } #define MMC_METHOD1_PARAM(_fn, T1, param) \ STDMETHOD(_fn)(T1 p1) \ { \ MMC_METHOD_PROLOG(); \ MMC_METHOD_CALL(_fn)(p1, param); \ MMC_METHOD_EPILOG(); \ } #define MMC_METHOD2(_fn, T1, T2) \ STDMETHOD(_fn)(T1 p1, T2 p2) \ { \ MMC_METHOD_PROLOG(); \ MMC_METHOD_CALL(_fn)(p1, p2); \ MMC_METHOD_EPILOG(); \ } #define MMC_METHOD2_PARAM(_fn, T1, T2, param) \ STDMETHOD(_fn)(T1 p1, T2 p2) \ { \ MMC_METHOD_PROLOG(); \ MMC_METHOD_CALL(_fn)(p1, p2, param); \ MMC_METHOD_EPILOG(); \ } #define MMC_METHOD3(_fn, T1, T2, T3) \ STDMETHOD(_fn)(T1 p1, T2 p2, T3 p3) \ { \ MMC_METHOD_PROLOG(); \ MMC_METHOD_CALL(_fn)(p1, p2, p3); \ MMC_METHOD_EPILOG(); \ } #define MMC_METHOD3_PARAM(_fn, T1, T2, T3, param) \ STDMETHOD(_fn)(T1 p1, T2 p2, T3 p3) \ { \ MMC_METHOD_PROLOG(); \ MMC_METHOD_CALL(_fn)(p1, p2, p3, param); \ MMC_METHOD_EPILOG(); \ } #define MMC_METHOD4(_fn, T1, T2, T3, T4) \ STDMETHOD(_fn)(T1 p1, T2 p2, T3 p3, T4 p4) \ { \ MMC_METHOD_PROLOG(); \ MMC_METHOD_CALL(_fn)(p1, p2, p3, p4); \ MMC_METHOD_EPILOG(); \ } #define MMC_METHOD4_PARAM(_fn, T1, T2, T3, T4, param) \ STDMETHOD(_fn)(T1 p1, T2 p2, T3 p3, T4 p4) \ { \ MMC_METHOD_PROLOG(); \ MMC_METHOD_CALL(_fn)(p1, p2, p3, p4, param); \ MMC_METHOD_EPILOG(); \ } #define MMC_METHOD5(_fn, T1, T2, T3, T4, T5) \ STDMETHOD(_fn)(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5) \ { \ MMC_METHOD_PROLOG(); \ MMC_METHOD_CALL(_fn)(p1, p2, p3, p4, p5); \ MMC_METHOD_EPILOG(); \ } #define MMC_METHOD5_PARAM(_fn, T1, T2, T3, T4, T5, param) \ STDMETHOD(_fn)(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5) \ { \ MMC_METHOD_PROLOG(); \ MMC_METHOD_CALL(_fn)(p1, p2, p3, p4, p5, param); \ MMC_METHOD_EPILOG(); \ } /************************************************************************ * A version of the above macros that adds a prefix to the Sc methods. * This is useful for disambiguating method names if the same object serves * as the tied object for more than one COM object with identical methods. ************************************************************************/ #define MMC_METHOD0_EX(_prefix, _fn) \ STDMETHOD(_fn)() \ { \ MMC_METHOD_PROLOG(); \ MMC_METHOD_CALL(_prefix##_fn)(); \ MMC_METHOD_EPILOG(); \ } #define MMC_METHOD1_EX(_prefix, _fn, T1) \ STDMETHOD(_fn)(T1 p1) \ { \ MMC_METHOD_PROLOG(); \ MMC_METHOD_CALL(_prefix##_fn)(p1); \ MMC_METHOD_EPILOG(); \ } #define MMC_METHOD2_EX(_prefix, _fn, T1, T2) \ STDMETHOD(_fn)(T1 p1, T2 p2) \ { \ MMC_METHOD_PROLOG(); \ MMC_METHOD_CALL(_prefix##_fn)(p1, p2); \ MMC_METHOD_EPILOG(); \ } #define MMC_METHOD3_EX(_prefix, _fn, T1, T2, T3) \ STDMETHOD(_fn)(T1 p1, T2 p2, T3 p3) \ { \ MMC_METHOD_PROLOG(); \ MMC_METHOD_CALL(_prefix##_fn)(p1, p2, p3, param); \ MMC_METHOD_EPILOG(); \ } #endif // COMERROR_H