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.

282 lines
12 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1999
  5. //
  6. // File: comerror.h
  7. //
  8. // Contents: Support for Rich COM errors
  9. //
  10. // History: 14-Oct-99 VivekJ Created
  11. //
  12. //--------------------------------------------------------------------------
  13. #ifndef COMERROR_H
  14. #define COMERROR_H
  15. #pragma once
  16. #include "tiedobj.h"
  17. //############################################################################
  18. //############################################################################
  19. //
  20. // COM Rich Error support
  21. //
  22. //############################################################################
  23. //############################################################################
  24. /*+-------------------------------------------------------------------------*
  25. *
  26. * MMCReportError
  27. *
  28. * PURPOSE: Calls AtlReportError and sets the last error condition based
  29. * on an SC.
  30. *
  31. * PARAMETERS:
  32. * SC & sc :
  33. * const IID :
  34. * const CLSID :
  35. *
  36. * RETURNS:
  37. * inline HRESULT
  38. *
  39. *+-------------------------------------------------------------------------*/
  40. inline
  41. HRESULT MMCReportError(SC &sc, const IID &iid, const CLSID & clsid)
  42. {
  43. // only report the error if there was one.
  44. if(sc)
  45. {
  46. USES_CONVERSION;
  47. const int length = 256;
  48. TCHAR sz[length];
  49. sc.GetErrorMessage(length, sz);
  50. // set everything we know about the error - the description, the help file,
  51. // the help ID, and the CLSID and IID of the source.
  52. return AtlReportError(clsid, sz, sc.GetHelpID(), sc.GetHelpFile(), iid, sc.ToHr());
  53. }
  54. else
  55. return S_OK;
  56. }
  57. // see "WHY NAMESPACES ?" comment at the top of mmcerror.h file
  58. namespace comerror {
  59. /*+-------------------------------------------------------------------------*
  60. * class _SC
  61. *
  62. *
  63. * PURPOSE: a local version of the SC class that automatically sets the error
  64. * information when deleted.
  65. *
  66. * NOTE: Because of a compiler bug, this class cannot directly be internal
  67. * to IMMCSupportErrorInfoImpl<>
  68. *
  69. *+-------------------------------------------------------------------------*/
  70. template<const IID *piid, const CLSID *pclsid>
  71. class SC : public mmcerror::SC
  72. {
  73. typedef mmcerror::SC BaseClass;
  74. public:
  75. SC (HRESULT hr = S_OK) : BaseClass(hr)
  76. {
  77. }
  78. ~SC()
  79. {
  80. MMCReportError(*this, *piid, *pclsid);
  81. }
  82. // copy constructor
  83. SC(const BaseClass &rhs) : BaseClass(rhs)
  84. {
  85. }
  86. // assignment
  87. SC& operator= (HRESULT hr) { BaseClass::operator =(hr); return *this; }
  88. SC& operator= (const BaseClass &rhs) { BaseClass::operator =(rhs); return *this; }
  89. SC& operator= (const SC &rhs) { BaseClass::operator =(rhs); return *this; }
  90. };
  91. } // namespace comerror
  92. /*+-------------------------------------------------------------------------*
  93. * class IMMCSupportErrorInfoImpl
  94. *
  95. *
  96. * PURPOSE: Inherits from ISupportErrorInfoImpl. local definition of the
  97. * status code class SC, which makes it easy to return error information
  98. * via the COM rich error handling system, without any extra effort
  99. * on the part of the programmer.
  100. *
  101. *+-------------------------------------------------------------------------*/
  102. template<const IID *piid, const CLSID *pclsid>
  103. class IMMCSupportErrorInfoImpl : public ISupportErrorInfoImpl<piid>
  104. {
  105. // this makes sure that AtlReportError is called in the destructor
  106. public:
  107. typedef comerror::SC<piid, pclsid> SC;
  108. };
  109. #define NYI_COM_METHOD() {SC sc = E_NOTIMPL; return sc.ToHr();}
  110. /************************************************************************
  111. * The following macros make it easy to implement a lightweight
  112. * COM object that "connects" to a non-COM tied object and delegates
  113. * all its methods to the non-COM object. The tied object pointer
  114. * is checked as well.
  115. ************************************************************************/
  116. #define MMC_METHOD_PROLOG() \
  117. SC sc; \
  118. \
  119. CMyTiedObject *pTiedObj = NULL; \
  120. \
  121. sc = ScGetTiedObject(pTiedObj); \
  122. if(sc) \
  123. return (sc.ToHr())
  124. #define MMC_METHOD_CALL(_fn) \
  125. sc = pTiedObj->Sc##_fn
  126. #define MMC_METHOD_EPILOG() \
  127. return sc.ToHr()
  128. #define MMC_METHOD0(_fn) \
  129. STDMETHOD(_fn)() \
  130. { \
  131. MMC_METHOD_PROLOG(); \
  132. MMC_METHOD_CALL(_fn)(); \
  133. MMC_METHOD_EPILOG(); \
  134. }
  135. #define MMC_METHOD0_PARAM(_fn, param) \
  136. STDMETHOD(_fn)() \
  137. { \
  138. MMC_METHOD_PROLOG(); \
  139. MMC_METHOD_CALL(_fn)(param); \
  140. MMC_METHOD_EPILOG(); \
  141. }
  142. #define MMC_METHOD1(_fn, T1) \
  143. STDMETHOD(_fn)(T1 p1) \
  144. { \
  145. MMC_METHOD_PROLOG(); \
  146. MMC_METHOD_CALL(_fn)(p1); \
  147. MMC_METHOD_EPILOG(); \
  148. }
  149. #define MMC_METHOD1_PARAM(_fn, T1, param) \
  150. STDMETHOD(_fn)(T1 p1) \
  151. { \
  152. MMC_METHOD_PROLOG(); \
  153. MMC_METHOD_CALL(_fn)(p1, param); \
  154. MMC_METHOD_EPILOG(); \
  155. }
  156. #define MMC_METHOD2(_fn, T1, T2) \
  157. STDMETHOD(_fn)(T1 p1, T2 p2) \
  158. { \
  159. MMC_METHOD_PROLOG(); \
  160. MMC_METHOD_CALL(_fn)(p1, p2); \
  161. MMC_METHOD_EPILOG(); \
  162. }
  163. #define MMC_METHOD2_PARAM(_fn, T1, T2, param) \
  164. STDMETHOD(_fn)(T1 p1, T2 p2) \
  165. { \
  166. MMC_METHOD_PROLOG(); \
  167. MMC_METHOD_CALL(_fn)(p1, p2, param); \
  168. MMC_METHOD_EPILOG(); \
  169. }
  170. #define MMC_METHOD3(_fn, T1, T2, T3) \
  171. STDMETHOD(_fn)(T1 p1, T2 p2, T3 p3) \
  172. { \
  173. MMC_METHOD_PROLOG(); \
  174. MMC_METHOD_CALL(_fn)(p1, p2, p3); \
  175. MMC_METHOD_EPILOG(); \
  176. }
  177. #define MMC_METHOD3_PARAM(_fn, T1, T2, T3, param) \
  178. STDMETHOD(_fn)(T1 p1, T2 p2, T3 p3) \
  179. { \
  180. MMC_METHOD_PROLOG(); \
  181. MMC_METHOD_CALL(_fn)(p1, p2, p3, param); \
  182. MMC_METHOD_EPILOG(); \
  183. }
  184. #define MMC_METHOD4(_fn, T1, T2, T3, T4) \
  185. STDMETHOD(_fn)(T1 p1, T2 p2, T3 p3, T4 p4) \
  186. { \
  187. MMC_METHOD_PROLOG(); \
  188. MMC_METHOD_CALL(_fn)(p1, p2, p3, p4); \
  189. MMC_METHOD_EPILOG(); \
  190. }
  191. #define MMC_METHOD4_PARAM(_fn, T1, T2, T3, T4, param) \
  192. STDMETHOD(_fn)(T1 p1, T2 p2, T3 p3, T4 p4) \
  193. { \
  194. MMC_METHOD_PROLOG(); \
  195. MMC_METHOD_CALL(_fn)(p1, p2, p3, p4, param); \
  196. MMC_METHOD_EPILOG(); \
  197. }
  198. #define MMC_METHOD5(_fn, T1, T2, T3, T4, T5) \
  199. STDMETHOD(_fn)(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5) \
  200. { \
  201. MMC_METHOD_PROLOG(); \
  202. MMC_METHOD_CALL(_fn)(p1, p2, p3, p4, p5); \
  203. MMC_METHOD_EPILOG(); \
  204. }
  205. #define MMC_METHOD5_PARAM(_fn, T1, T2, T3, T4, T5, param) \
  206. STDMETHOD(_fn)(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5) \
  207. { \
  208. MMC_METHOD_PROLOG(); \
  209. MMC_METHOD_CALL(_fn)(p1, p2, p3, p4, p5, param); \
  210. MMC_METHOD_EPILOG(); \
  211. }
  212. /************************************************************************
  213. * A version of the above macros that adds a prefix to the Sc methods.
  214. * This is useful for disambiguating method names if the same object serves
  215. * as the tied object for more than one COM object with identical methods.
  216. ************************************************************************/
  217. #define MMC_METHOD0_EX(_prefix, _fn) \
  218. STDMETHOD(_fn)() \
  219. { \
  220. MMC_METHOD_PROLOG(); \
  221. MMC_METHOD_CALL(_prefix##_fn)(); \
  222. MMC_METHOD_EPILOG(); \
  223. }
  224. #define MMC_METHOD1_EX(_prefix, _fn, T1) \
  225. STDMETHOD(_fn)(T1 p1) \
  226. { \
  227. MMC_METHOD_PROLOG(); \
  228. MMC_METHOD_CALL(_prefix##_fn)(p1); \
  229. MMC_METHOD_EPILOG(); \
  230. }
  231. #define MMC_METHOD2_EX(_prefix, _fn, T1, T2) \
  232. STDMETHOD(_fn)(T1 p1, T2 p2) \
  233. { \
  234. MMC_METHOD_PROLOG(); \
  235. MMC_METHOD_CALL(_prefix##_fn)(p1, p2); \
  236. MMC_METHOD_EPILOG(); \
  237. }
  238. #define MMC_METHOD3_EX(_prefix, _fn, T1, T2, T3) \
  239. STDMETHOD(_fn)(T1 p1, T2 p2, T3 p3) \
  240. { \
  241. MMC_METHOD_PROLOG(); \
  242. MMC_METHOD_CALL(_prefix##_fn)(p1, p2, p3, param); \
  243. MMC_METHOD_EPILOG(); \
  244. }
  245. #endif // COMERROR_H