windows-nt/Source/XPSP1/NT/admin/activec/inc/comerror.h
2020-09-26 16:20:57 +08:00

283 lines
12 KiB
C++

//+-------------------------------------------------------------------------
//
// 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<const IID *piid, const CLSID *pclsid>
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<const IID *piid, const CLSID *pclsid>
class IMMCSupportErrorInfoImpl : public ISupportErrorInfoImpl<piid>
{
// this makes sure that AtlReportError is called in the destructor
public:
typedef comerror::SC<piid, pclsid> SC;
};
#define NYI_COM_METHOD() {SC sc = E_NOTIMPL; return sc.ToHr();}
/************************************************************************
* 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() \
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