windows-nt/Source/XPSP1/NT/admin/netui/common/h/base.hxx
2020-09-26 16:20:57 +08:00

292 lines
12 KiB
C++

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corp., 1991 **/
/**********************************************************************/
/*
base.hxx
Universal base class for error cascading and debugging information
This file assumes that 0 denotes NERR_Success, the "no error" state.
FILE HISTORY
beng 09-Jul-1990 created
beng 17-Jul-1990 added standard comment header to BASE
beng 31-Jul-1991 added FORWARDING_BASE
rustanl 11-Sep-1991 Added DECLARE_OUTLINE_NEWBASE,
DECLARE_MI_NEWBASE, DEFINE_MI2_NEWBASE,
DEFINE_MI3_NEWBASE, and DEFINE_MI4_NEWBASE
KeithMo 23-Oct-1991 Added forward references.
chuckc 26-Feb-1992 made ReportError non-inline if DEBUG
beng 30-Mar-1992 Added ResetError members
*/
#ifndef _BASE_HXX_
#define _BASE_HXX_
//
// Forward references.
//
DLL_CLASS ALLOC_BASE;
DLL_CLASS BASE;
DLL_CLASS FORWARDING_BASE;
DLL_CLASS ALLOC_BASE
{
public:
void * operator new ( size_t cbSize ) ;
void * operator new ( size_t cbSize, void * p ) ;
void operator delete ( void * p ) ;
};
/*************************************************************************
NAME: BASE (base)
SYNOPSIS: Universal base object, root of every class.
It contains universal error status and debugging
support.
INTERFACE: ReportError() - report an error on the object from
within the object.
QueryError() - return the current error state,
or 0 if no error outstanding.
operator!() - return TRUE if an error is outstanding.
Typically means that construction failed.
ResetError() - restores object to pristine non-error
state.
CAVEATS: This sort of error reporting is safe enough in a single-
threaded system, but loses robustness when multiple threads
access shared objects. Use it for constructor-time error
handling primarily.
NOTES: A class which inherits BASE through a private class should
use the NEWBASE macro (q.v.) in its definition; otherwise
its clients will lose the use of ! and QueryError.
HISTORY:
rustanl 07-Jun-1990 Created as part of LMOD
beng 09-Jul-1990 Gutted, removing LMOD methods
beng 17-Jul-1990 Added USHORT error methods
beng 19-Oct-1990 Finally, removed BOOL error methods
johnl 14-Nov-1990 Changed QueryError to be a const method
beng 25-Jan-1991 Added the ! Boolean operator and NEWBASE
beng 31-Jul-1991 Made FORWARDING_BASE a friend
beng 05-Oct-1991 Win32 conversion
beng 30-Mar-1992 Added ResetError member
DavidHov 19-Nov-1992 Made ReportError inline always
*************************************************************************/
DLL_CLASS BASE : virtual public ALLOC_BASE
{
friend class FORWARDING_BASE;
private:
APIERR _err;
protected:
BASE() : _err(0) {}
VOID _ReportError ( APIERR errSet ); // Debug assistant
// Report construction failure: out/inline depending on DEBUG
VOID ReportError( APIERR errSet )
#if defined(DEBUG)
{ _ReportError( errSet ) ; }
#else
{ _err = errSet; }
#endif
VOID ResetError() { _err = 0; }
public:
APIERR QueryError() const { return _err; }
BOOL operator!() const { return (_err != 0); }
};
/*************************************************************************
NAME: FORWARDING_BASE
SYNOPSIS: A BASE which forwards its errors to some other object
INTERFACE: ReportError() - report an error on the object from
within the object.
QueryError() - return the current error state,
or 0 if no error outstanding.
operator!() - return TRUE if an error is outstanding.
Typically means that construction failed.
ResetError() - restores object to pristine non-error
state.
NOTES:
The canonical example of a FORWARDING object is a control
within a window: if any control fails construction, the entire
window fails.
HISTORY:
beng 31-Jul-1991 Created
beng 05-Oct-1991 Win32 conversion
beng 30-Mar-1992 Added ResetError
**************************************************************************/
DLL_CLASS FORWARDING_BASE : virtual public ALLOC_BASE
{
private:
BASE * _pbase;
protected:
FORWARDING_BASE(BASE* pbase) : _pbase(pbase) {}
VOID ReportError(APIERR errSet) { _pbase->ReportError(errSet); }
VOID ResetError() { _pbase->ResetError(); }
public:
APIERR QueryError() const { return _pbase->QueryError(); }
BOOL operator!() const { return (_pbase->QueryError() != 0); }
};
//
// The NEWBASE macro adds forwarding methods to a class.
// Use it when a class loses ! and QueryError through private inheritance,
// or else when a class includes FORWARDING_BASE and wants that to override
// its previous BASE inheritance.
//
#define NEWBASE(class) \
protected: \
VOID ReportError( APIERR errSet ) { class::ReportError(errSet); } \
VOID ResetError() { class::ResetError(); } \
public: \
APIERR QueryError() const { return class::QueryError(); } \
BOOL operator!() const { return (class::QueryError() != 0); }
//
// The following macro declares ReportError and QueryError as outline
// methods. Only use today is in the DECLARE_MI_NEWBASE macro.
//
#define DECLARE_OUTLINE_NEWBASE( class ) \
protected: \
VOID ResetError(); \
VOID ReportError( APIERR err ); \
public: \
APIERR QueryError() const; \
BOOL operator!() const { return (class::QueryError() != 0 ); }
//
// This macro redeclares the BASE methods for a class that
// multiply inherits from (any number of) BASE objects. Use
// appropriate macro defined below to define these methods.
//
// This macro and the definition macros below provide a
// very cheap work-around for not making BASE a virtual class.
//
#define DECLARE_MI_NEWBASE( class ) DECLARE_OUTLINE_NEWBASE( class )
//
// The following macros redefines the BASE methods for a class
// that multiply inherits from 2, 3, or 4 classes which inherit from
// BASE. If needed, MI maniacs may add more such macros in the future.
//
#define DEFINE_MI2_NEWBASE( class, parent_class0, \
parent_class1 ) \
VOID class::ReportError( APIERR err ) \
{ \
parent_class0::ReportError( err ); \
parent_class1::ReportError( err ); \
} \
VOID class::ResetError() \
{ \
parent_class0::ResetError(); \
parent_class1::ResetError(); \
} \
APIERR class::QueryError() const \
{ \
APIERR err; \
if ( ( err = parent_class0::QueryError()) != 0 || \
( err = parent_class1::QueryError()) != 0 ) \
{ \
/* nothing */ \
} \
return err; \
}
#define DEFINE_MI3_NEWBASE( class, parent_class0, \
parent_class1, \
parent_class2 ) \
VOID class::ReportError( APIERR err ) \
{ \
parent_class0::ReportError( err ); \
parent_class1::ReportError( err ); \
parent_class2::ReportError( err ); \
} \
VOID class::ResetError() \
{ \
parent_class0::ResetError(); \
parent_class1::ResetError(); \
parent_class2::ResetError(); \
} \
APIERR class::QueryError() const \
{ \
APIERR err; \
if ( ( err = parent_class0::QueryError()) != 0 || \
( err = parent_class1::QueryError()) != 0 || \
( err = parent_class2::QueryError()) != 0 ) \
{ \
/* nothing */ \
} \
return err; \
}
#define DEFINE_MI4_NEWBASE( class, parent_class0, \
parent_class1, \
parent_class2, \
parent_class3 ) \
VOID class::ReportError( APIERR err ) \
{ \
parent_class0::ReportError( err ); \
parent_class1::ReportError( err ); \
parent_class2::ReportError( err ); \
parent_class3::ReportError( err ); \
} \
VOID class::ResetError() \
{ \
parent_class0::ResetError(); \
parent_class1::ResetError(); \
parent_class2::ResetError(); \
parent_class3::ResetError(); \
} \
APIERR class::QueryError() const \
{ \
APIERR err; \
if ( ( err = parent_class0::QueryError()) != 0 || \
( err = parent_class1::QueryError()) != 0 || \
( err = parent_class2::QueryError()) != 0 || \
( err = parent_class3::QueryError()) != 0 ) \
{ \
/* nothing */ \
} \
return err; \
}
#endif // _BASE_HXX_