Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

291 lines
12 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corp., 1991 **/
  4. /**********************************************************************/
  5. /*
  6. base.hxx
  7. Universal base class for error cascading and debugging information
  8. This file assumes that 0 denotes NERR_Success, the "no error" state.
  9. FILE HISTORY
  10. beng 09-Jul-1990 created
  11. beng 17-Jul-1990 added standard comment header to BASE
  12. beng 31-Jul-1991 added FORWARDING_BASE
  13. rustanl 11-Sep-1991 Added DECLARE_OUTLINE_NEWBASE,
  14. DECLARE_MI_NEWBASE, DEFINE_MI2_NEWBASE,
  15. DEFINE_MI3_NEWBASE, and DEFINE_MI4_NEWBASE
  16. KeithMo 23-Oct-1991 Added forward references.
  17. chuckc 26-Feb-1992 made ReportError non-inline if DEBUG
  18. beng 30-Mar-1992 Added ResetError members
  19. */
  20. #ifndef _BASE_HXX_
  21. #define _BASE_HXX_
  22. //
  23. // Forward references.
  24. //
  25. DLL_CLASS ALLOC_BASE;
  26. DLL_CLASS BASE;
  27. DLL_CLASS FORWARDING_BASE;
  28. DLL_CLASS ALLOC_BASE
  29. {
  30. public:
  31. void * operator new ( size_t cbSize ) ;
  32. void * operator new ( size_t cbSize, void * p ) ;
  33. void operator delete ( void * p ) ;
  34. };
  35. /*************************************************************************
  36. NAME: BASE (base)
  37. SYNOPSIS: Universal base object, root of every class.
  38. It contains universal error status and debugging
  39. support.
  40. INTERFACE: ReportError() - report an error on the object from
  41. within the object.
  42. QueryError() - return the current error state,
  43. or 0 if no error outstanding.
  44. operator!() - return TRUE if an error is outstanding.
  45. Typically means that construction failed.
  46. ResetError() - restores object to pristine non-error
  47. state.
  48. CAVEATS: This sort of error reporting is safe enough in a single-
  49. threaded system, but loses robustness when multiple threads
  50. access shared objects. Use it for constructor-time error
  51. handling primarily.
  52. NOTES: A class which inherits BASE through a private class should
  53. use the NEWBASE macro (q.v.) in its definition; otherwise
  54. its clients will lose the use of ! and QueryError.
  55. HISTORY:
  56. rustanl 07-Jun-1990 Created as part of LMOD
  57. beng 09-Jul-1990 Gutted, removing LMOD methods
  58. beng 17-Jul-1990 Added USHORT error methods
  59. beng 19-Oct-1990 Finally, removed BOOL error methods
  60. johnl 14-Nov-1990 Changed QueryError to be a const method
  61. beng 25-Jan-1991 Added the ! Boolean operator and NEWBASE
  62. beng 31-Jul-1991 Made FORWARDING_BASE a friend
  63. beng 05-Oct-1991 Win32 conversion
  64. beng 30-Mar-1992 Added ResetError member
  65. DavidHov 19-Nov-1992 Made ReportError inline always
  66. *************************************************************************/
  67. DLL_CLASS BASE : virtual public ALLOC_BASE
  68. {
  69. friend class FORWARDING_BASE;
  70. private:
  71. APIERR _err;
  72. protected:
  73. BASE() : _err(0) {}
  74. VOID _ReportError ( APIERR errSet ); // Debug assistant
  75. // Report construction failure: out/inline depending on DEBUG
  76. VOID ReportError( APIERR errSet )
  77. #if defined(DEBUG)
  78. { _ReportError( errSet ) ; }
  79. #else
  80. { _err = errSet; }
  81. #endif
  82. VOID ResetError() { _err = 0; }
  83. public:
  84. APIERR QueryError() const { return _err; }
  85. BOOL operator!() const { return (_err != 0); }
  86. };
  87. /*************************************************************************
  88. NAME: FORWARDING_BASE
  89. SYNOPSIS: A BASE which forwards its errors to some other object
  90. INTERFACE: ReportError() - report an error on the object from
  91. within the object.
  92. QueryError() - return the current error state,
  93. or 0 if no error outstanding.
  94. operator!() - return TRUE if an error is outstanding.
  95. Typically means that construction failed.
  96. ResetError() - restores object to pristine non-error
  97. state.
  98. NOTES:
  99. The canonical example of a FORWARDING object is a control
  100. within a window: if any control fails construction, the entire
  101. window fails.
  102. HISTORY:
  103. beng 31-Jul-1991 Created
  104. beng 05-Oct-1991 Win32 conversion
  105. beng 30-Mar-1992 Added ResetError
  106. **************************************************************************/
  107. DLL_CLASS FORWARDING_BASE : virtual public ALLOC_BASE
  108. {
  109. private:
  110. BASE * _pbase;
  111. protected:
  112. FORWARDING_BASE(BASE* pbase) : _pbase(pbase) {}
  113. VOID ReportError(APIERR errSet) { _pbase->ReportError(errSet); }
  114. VOID ResetError() { _pbase->ResetError(); }
  115. public:
  116. APIERR QueryError() const { return _pbase->QueryError(); }
  117. BOOL operator!() const { return (_pbase->QueryError() != 0); }
  118. };
  119. //
  120. // The NEWBASE macro adds forwarding methods to a class.
  121. // Use it when a class loses ! and QueryError through private inheritance,
  122. // or else when a class includes FORWARDING_BASE and wants that to override
  123. // its previous BASE inheritance.
  124. //
  125. #define NEWBASE(class) \
  126. protected: \
  127. VOID ReportError( APIERR errSet ) { class::ReportError(errSet); } \
  128. VOID ResetError() { class::ResetError(); } \
  129. public: \
  130. APIERR QueryError() const { return class::QueryError(); } \
  131. BOOL operator!() const { return (class::QueryError() != 0); }
  132. //
  133. // The following macro declares ReportError and QueryError as outline
  134. // methods. Only use today is in the DECLARE_MI_NEWBASE macro.
  135. //
  136. #define DECLARE_OUTLINE_NEWBASE( class ) \
  137. protected: \
  138. VOID ResetError(); \
  139. VOID ReportError( APIERR err ); \
  140. public: \
  141. APIERR QueryError() const; \
  142. BOOL operator!() const { return (class::QueryError() != 0 ); }
  143. //
  144. // This macro redeclares the BASE methods for a class that
  145. // multiply inherits from (any number of) BASE objects. Use
  146. // appropriate macro defined below to define these methods.
  147. //
  148. // This macro and the definition macros below provide a
  149. // very cheap work-around for not making BASE a virtual class.
  150. //
  151. #define DECLARE_MI_NEWBASE( class ) DECLARE_OUTLINE_NEWBASE( class )
  152. //
  153. // The following macros redefines the BASE methods for a class
  154. // that multiply inherits from 2, 3, or 4 classes which inherit from
  155. // BASE. If needed, MI maniacs may add more such macros in the future.
  156. //
  157. #define DEFINE_MI2_NEWBASE( class, parent_class0, \
  158. parent_class1 ) \
  159. VOID class::ReportError( APIERR err ) \
  160. { \
  161. parent_class0::ReportError( err ); \
  162. parent_class1::ReportError( err ); \
  163. } \
  164. VOID class::ResetError() \
  165. { \
  166. parent_class0::ResetError(); \
  167. parent_class1::ResetError(); \
  168. } \
  169. APIERR class::QueryError() const \
  170. { \
  171. APIERR err; \
  172. if ( ( err = parent_class0::QueryError()) != 0 || \
  173. ( err = parent_class1::QueryError()) != 0 ) \
  174. { \
  175. /* nothing */ \
  176. } \
  177. return err; \
  178. }
  179. #define DEFINE_MI3_NEWBASE( class, parent_class0, \
  180. parent_class1, \
  181. parent_class2 ) \
  182. VOID class::ReportError( APIERR err ) \
  183. { \
  184. parent_class0::ReportError( err ); \
  185. parent_class1::ReportError( err ); \
  186. parent_class2::ReportError( err ); \
  187. } \
  188. VOID class::ResetError() \
  189. { \
  190. parent_class0::ResetError(); \
  191. parent_class1::ResetError(); \
  192. parent_class2::ResetError(); \
  193. } \
  194. APIERR class::QueryError() const \
  195. { \
  196. APIERR err; \
  197. if ( ( err = parent_class0::QueryError()) != 0 || \
  198. ( err = parent_class1::QueryError()) != 0 || \
  199. ( err = parent_class2::QueryError()) != 0 ) \
  200. { \
  201. /* nothing */ \
  202. } \
  203. return err; \
  204. }
  205. #define DEFINE_MI4_NEWBASE( class, parent_class0, \
  206. parent_class1, \
  207. parent_class2, \
  208. parent_class3 ) \
  209. VOID class::ReportError( APIERR err ) \
  210. { \
  211. parent_class0::ReportError( err ); \
  212. parent_class1::ReportError( err ); \
  213. parent_class2::ReportError( err ); \
  214. parent_class3::ReportError( err ); \
  215. } \
  216. VOID class::ResetError() \
  217. { \
  218. parent_class0::ResetError(); \
  219. parent_class1::ResetError(); \
  220. parent_class2::ResetError(); \
  221. parent_class3::ResetError(); \
  222. } \
  223. APIERR class::QueryError() const \
  224. { \
  225. APIERR err; \
  226. if ( ( err = parent_class0::QueryError()) != 0 || \
  227. ( err = parent_class1::QueryError()) != 0 || \
  228. ( err = parent_class2::QueryError()) != 0 || \
  229. ( err = parent_class3::QueryError()) != 0 ) \
  230. { \
  231. /* nothing */ \
  232. } \
  233. return err; \
  234. }
  235. #endif // _BASE_HXX_