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.

373 lines
13 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: atlstl/automation/property_method_helpers.hpp
  3. *
  4. * Purpose: Contains functions for assisting in the implementation of
  5. * property methods of ATL COM server classes.
  6. *
  7. * Created: 25th June 2002
  8. * Updated: 10th August 2009
  9. *
  10. * Home: http://stlsoft.org/
  11. *
  12. * Copyright (c) 2002-2009, Matthew Wilson and Synesis Software
  13. * All rights reserved.
  14. *
  15. * Redistribution and use in source and binary forms, with or without
  16. * modification, are permitted provided that the following conditions are met:
  17. *
  18. * - Redistributions of source code must retain the above copyright notice, this
  19. * list of conditions and the following disclaimer.
  20. * - Redistributions in binary form must reproduce the above copyright notice,
  21. * this list of conditions and the following disclaimer in the documentation
  22. * and/or other materials provided with the distribution.
  23. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  24. * any contributors may be used to endorse or promote products derived from
  25. * this software without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  28. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  31. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  32. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  33. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  34. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  35. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  36. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  37. * POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. * ////////////////////////////////////////////////////////////////////// */
  40. /** \file atlstl/automation/property_method_helpers.hpp
  41. * \brief [C++ only; requires ATL library] Definition of the
  42. * atlstl::get_MemberValue(), atlstl::put_MemberValue() and
  43. * atlstl::get_ConstantValue() function suites, which simplify the
  44. * definition of property methods in ATL COM servers
  45. * (\ref group__library__com_automation "COM Automation" Library).
  46. */
  47. #ifndef ATLSTL_INCL_ATLSTL_AUTOMATION_HPP_PROPERTY_METHOD_HELPERS
  48. #define ATLSTL_INCL_ATLSTL_AUTOMATION_HPP_PROPERTY_METHOD_HELPERS
  49. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  50. # define ATLSTL_VER_ATLSTL_AUTOMATION_HPP_PROPERTY_METHOD_HELPERS_MAJOR 4
  51. # define ATLSTL_VER_ATLSTL_AUTOMATION_HPP_PROPERTY_METHOD_HELPERS_MINOR 0
  52. # define ATLSTL_VER_ATLSTL_AUTOMATION_HPP_PROPERTY_METHOD_HELPERS_REVISION 3
  53. # define ATLSTL_VER_ATLSTL_AUTOMATION_HPP_PROPERTY_METHOD_HELPERS_EDIT 69
  54. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  55. /* /////////////////////////////////////////////////////////////////////////
  56. * Compatibility
  57. */
  58. /*
  59. [Incompatibilies-start]
  60. STLSOFT_COMPILER_IS_BORLAND:
  61. STLSOFT_COMPILER_IS_DMC:
  62. [Incompatibilies-end]
  63. */
  64. /* /////////////////////////////////////////////////////////////////////////
  65. * Includes
  66. */
  67. #ifndef ATLSTL_INCL_ATLSTL_HPP_ATLSTL
  68. # include <atlstl/atlstl.hpp>
  69. #endif /* !ATLSTL_INCL_ATLSTL_HPP_ATLSTL */
  70. #if defined(STLSOFT_COMPILER_IS_BORLAND)
  71. # error No recognised Borland compiler generates correct code when used with these functions
  72. #endif /* compiler */
  73. /* /////////////////////////////////////////////////////////////////////////
  74. * Namespace
  75. */
  76. #ifndef _ATLSTL_NO_NAMESPACE
  77. # if defined(_STLSOFT_NO_NAMESPACE) || \
  78. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  79. /* There is no stlsoft namespace, so must define ::atlstl */
  80. namespace atlstl
  81. {
  82. # else
  83. /* Define stlsoft::atlstl_project */
  84. namespace stlsoft
  85. {
  86. namespace atlstl_project
  87. {
  88. # endif /* _STLSOFT_NO_NAMESPACE */
  89. #endif /* !_ATLSTL_NO_NAMESPACE */
  90. /* /////////////////////////////////////////////////////////////////////////
  91. * get_MemberValue
  92. *
  93. * This can be used to get a member variable value. The function has the
  94. * general usage:
  95. *
  96. * HRESULT Class::get_Member(MemberType *ret)
  97. * {
  98. * return get_MemberValue(this, ret, &Class::m_memberVariable);
  99. * }
  100. */
  101. /** \brief Inline retrieval of member variable value
  102. *
  103. * \ingroup group__library__com_automation
  104. *
  105. * This function takes a pointer to a class, a pointer to a return value
  106. * and a pointer to member of the given class, and retrieves the value
  107. * of the member into the return value.
  108. *
  109. * \note This generic version should only be used for built-in types, or those which have value semantics.
  110. *
  111. * \param cls Pointer to the class instance
  112. * \param ret Pointer to the return value
  113. * \param mem Pointer to the member variable
  114. * \return An HRESULT code indicating whether the access succeeded or failed
  115. * \retval E_POINTER ret was a null pointer
  116. * \retval S_OK The value was retrieved successfully
  117. */
  118. template <class C, ss_typename_param_k T>
  119. inline HRESULT get_MemberValue(C *const cls, T *ret, T C::*mem)
  120. {
  121. return (ret == 0) ? E_POINTER : (*ret = cls->*mem, S_OK);
  122. }
  123. /** \brief Ghost overload to prevent use of get_MemberValue with pointer types
  124. *
  125. * \ingroup group__library__com_automation
  126. *
  127. * This version is overloaded to deal with pointer types, and is not
  128. * implemented so as to prevent the generic version being used with such types.
  129. *
  130. * Although this is inconvenient, there is no other way to prevent the use of
  131. * free functions. In such circumstances, the shorthand of get_memberValue()
  132. * must be eschewed for full and congnisant implementation.
  133. *
  134. * \note This is deemed worth the inconvenience since using the generic version would like lead to code that violated COM's memory rules
  135. *
  136. */
  137. template <class C, ss_typename_param_k T>
  138. inline HRESULT get_MemberValue(C *const cls, T **ret, T *C::*mem);
  139. /** \brief Inline retrieval of a CComBSTR member variable value
  140. *
  141. * \ingroup group__library__com_automation
  142. *
  143. * This function takes a pointer to a class, a pointer to a return value
  144. * and a pointer to a CComBSTR member of the given class, and retrieves the
  145. * value of the member into the BSTR return value.
  146. *
  147. * \param cls Pointer to the class instance
  148. * \param ret Pointer to the BSTR return value
  149. * \param mem Pointer to the CComBSTR member variable
  150. * \return An HRESULT code indicating whether the access succeeded or failed
  151. * \retval E_POINTER ret was a null pointer
  152. * \retval E_OUTOFMEMORY Not enough memory to create a copy for the returned value
  153. * \retval S_OK The value was retrieved successfully
  154. */
  155. template <class C>
  156. inline HRESULT get_MemberValue(C *const cls, BSTR *ret, CComBSTR C::*mem)
  157. {
  158. return (ret == 0) ? E_POINTER : (*ret = (cls->*mem).Copy(), (*ret != 0 ? S_OK : E_OUTOFMEMORY));
  159. }
  160. /** \brief Inline retrieval of a VARIANT member variable value
  161. *
  162. * \ingroup group__library__com_automation
  163. *
  164. * This function takes a pointer to a class, a pointer to a return value
  165. * and a pointer to a VARIANT member of the given class, and retrieves the
  166. * value of the member into the VARIANT return value.
  167. *
  168. * \param cls Pointer to the class instance
  169. * \param ret Pointer to the VARIANT return value
  170. * \param mem Pointer to the VARIANT member variable
  171. * \return An HRESULT code indicating whether the access succeeded or failed
  172. * \retval E_POINTER ret was a null pointer
  173. * \retval DISP_E_ARRAYISLOCKED The variant contains an array that is locked.
  174. * \retval DISP_E_BADVARTYPE The source and destination have an invalid variant type (usually uninitialized).
  175. * \retval E_OUTOFMEMORY Memory could not be allocated for the copy.
  176. * \retval E_INVALIDARG One of the arguments is invalid.
  177. * \retval S_OK The value was retrieved successfully
  178. */
  179. template <class C>
  180. inline HRESULT get_MemberValue(C *const cls, VARIANT *ret, CComVariant C::*mem)
  181. {
  182. return (ret == 0) ? E_POINTER : ::VariantCopy(ret, &(cls->*mem));
  183. }
  184. /** \brief Inline retrieval of method value
  185. *
  186. * \ingroup group__library__com_automation
  187. *
  188. * This function takes a pointer to a class, a pointer to a return value
  189. * and a pointer to method of the given class, and retrieves the return value
  190. * of the method into the return value.
  191. *
  192. * \note This generic version should only be used for built-in types, or those which have value semantics.
  193. *
  194. * \param cls Pointer to the class instance
  195. * \param ret Pointer to the return value
  196. * \param pfn Pointer to the method
  197. * \return An HRESULT code indicating whether the access succeeded or failed
  198. * \retval E_POINTER ret was a null pointer
  199. * \retval S_OK The value was retrieved successfully
  200. */
  201. template<class C, ss_typename_param_k T, ss_typename_param_k T2>
  202. inline HRESULT get_MemberValue(C *const cls, T *ret, T2 (C::*pfn)() const)
  203. {
  204. return (ret == 0) ? E_POINTER : (*ret = (cls->*pfn)(), S_OK);
  205. }
  206. /* /////////////////////////////////////////////////////////////////////////
  207. * put_MemberValue
  208. *
  209. * This can be used to put a member variable value. The function has the
  210. * general usage:
  211. *
  212. * HRESULT Class::put_Member(MemberType newValue)
  213. * {
  214. * return put_MemberValue(this, newValue, &Class::m_memberVariable);
  215. * }
  216. */
  217. /** \brief Inline assignment of a member variable value
  218. *
  219. * \ingroup group__library__com_automation
  220. *
  221. * This function takes a pointer to a class, a new value and a pointer to
  222. * member of the given class, and assigns the new value to the member.
  223. *
  224. * \note This generic version should only be used for built-in types, or those which have value semantics.
  225. *
  226. * \param cls Pointer to the class instance
  227. * \param newVal The new value
  228. * \param mem Pointer to the member variable
  229. * \retval S_OK The value was assigned successfully
  230. */
  231. template <ss_typename_param_k C, ss_typename_param_k T>
  232. inline HRESULT put_MemberValue(C *const cls, T const& newVal, T C::*mem)
  233. {
  234. return (cls->*mem = newVal, S_OK);
  235. }
  236. /** \brief Inline assignment of a CComBSTR member variable value
  237. *
  238. * \ingroup group__library__com_automation
  239. *
  240. * This function takes a pointer to a class, a new BSTR value and a pointer to
  241. * CComBSTR member of the given class, and assigns the new value to the
  242. * member.
  243. *
  244. * \param cls Pointer to the class instance
  245. * \param newVal The new BSTR value
  246. * \param mem Pointer to the CComBSTR member variable
  247. * \retval S_OK The value was assigned successfully
  248. */
  249. template <ss_typename_param_k C>
  250. inline HRESULT put_MemberValue(C *const cls, BSTR newVal, CComBSTR C::*mem)
  251. {
  252. return (cls->*mem = newVal, S_OK);
  253. }
  254. /** \brief Inline assignment of a CComBSTR member variable value
  255. *
  256. * \ingroup group__library__com_automation
  257. *
  258. * This function takes a pointer to a class, a new CComBSTR value and a pointer
  259. * to CComBSTR member of the given class, and assigns the new value to the
  260. * member.
  261. *
  262. * \param cls Pointer to the class instance
  263. * \param newVal The new CComBSTR value
  264. * \param mem Pointer to the CComBSTR member variable
  265. * \retval S_OK The value was assigned successfully
  266. */
  267. template <ss_typename_param_k C>
  268. inline HRESULT put_MemberValue(C *const cls, CComBSTR const& newVal, CComBSTR C::*mem)
  269. {
  270. return put_MemberValue(cls, (BSTR)newVal, mem);
  271. }
  272. /** \brief Inline assignment of a CComVariant member variable value
  273. *
  274. * \ingroup group__library__com_automation
  275. *
  276. * This function takes a pointer to a class, a new CComVariant value and a
  277. * pointer to CComVariant member of the given class, and assigns the new value
  278. * to the member.
  279. *
  280. * \param cls Pointer to the class instance
  281. * \param newVal The new CComVariant value
  282. * \param mem Pointer to the CComVariant member variable
  283. * \retval S_OK The value was assigned successfully
  284. */
  285. template <ss_typename_param_k C>
  286. inline HRESULT put_MemberValue(C *const cls, CComVariant const& newVal, CComVariant C::*mem)
  287. {
  288. return (cls->*mem = newVal, (VT_ERROR == (cls->*mem).vt) ? (cls->*mem).scode : S_OK);
  289. }
  290. /** \brief Shorthand for implementing methods that return a constant value
  291. *
  292. * \ingroup group__library__com_automation
  293. *
  294. * This method is used to implement methods that return a value of a
  295. * known constant, e.g.
  296. *
  297. \code
  298. STDMETHODIMP DatabaseFlags::get_OrderFields(BOOL *pVal)
  299. {
  300. return atlstl::get_ConstantValue(pVal, openrj::ORJ_FLAG_ORDERFIELDS);
  301. }
  302. \endcode
  303. *
  304. * \param ret Pointer to the return value
  305. *
  306. */
  307. template <ss_typename_type_k T1, ss_typename_type_k T2>
  308. inline HRESULT get_ConstantValue(T1 *ret, T2 const& value)
  309. {
  310. return (NULL == ret) ? E_POINTER : (*ret = value, S_OK);
  311. }
  312. ////////////////////////////////////////////////////////////////////////////
  313. // Unit-testing
  314. #ifdef STLSOFT_UNITTEST
  315. # include "./unittest/property_method_helpers_unittest_.h"
  316. #endif /* STLSOFT_UNITTEST */
  317. /* ////////////////////////////////////////////////////////////////////// */
  318. #ifndef _ATLSTL_NO_NAMESPACE
  319. # if defined(_STLSOFT_NO_NAMESPACE) || \
  320. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  321. } // namespace atlstl
  322. # else
  323. } // namespace atlstl_project
  324. } // namespace stlsoft
  325. # endif /* _STLSOFT_NO_NAMESPACE */
  326. #endif /* !_ATLSTL_NO_NAMESPACE */
  327. /* ////////////////////////////////////////////////////////////////////// */
  328. #endif /* !ATLSTL_INCL_ATLSTL_AUTOMATION_HPP_PROPERTY_METHOD_HELPERS */
  329. /* ///////////////////////////// end of file //////////////////////////// */