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.

538 lines
16 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: comstl/util/value_policies.hpp (originally MOEnSeq.h, ::SynesisCom)
  3. *
  4. * Purpose: Value policies that work with STL sequence types for IEnumXXXX
  5. * enumerator interfaces.
  6. *
  7. * Created: 17th September 1998
  8. * Updated: 5th March 2011
  9. *
  10. * Home: http://stlsoft.org/
  11. *
  12. * Copyright (c) 1998-2011, 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 comstl/util/value_policies.hpp
  41. *
  42. * \brief [C++ only; requires COM] Value policies for various COM types
  43. * (\ref group__library__utility__com "COM Utility" Library).
  44. */
  45. #ifndef COMSTL_INCL_COMSTL_UTIL_HPP_VALUE_POLICIES
  46. #define COMSTL_INCL_COMSTL_UTIL_HPP_VALUE_POLICIES
  47. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  48. # define COMSTL_VER_COMSTL_UTIL_HPP_VALUE_POLICIES_MAJOR 5
  49. # define COMSTL_VER_COMSTL_UTIL_HPP_VALUE_POLICIES_MINOR 1
  50. # define COMSTL_VER_COMSTL_UTIL_HPP_VALUE_POLICIES_REVISION 2
  51. # define COMSTL_VER_COMSTL_UTIL_HPP_VALUE_POLICIES_EDIT 165
  52. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  53. /* /////////////////////////////////////////////////////////////////////////
  54. * Includes
  55. */
  56. #ifndef COMSTL_INCL_COMSTL_H_COMSTL
  57. # include <comstl/comstl.h>
  58. #endif /* !COMSTL_INCL_COMSTL_H_COMSTL */
  59. #ifndef COMSTL_INCL_COMSTL_STRING_H_OLESTRING_FUNCTIONS
  60. # include <comstl/string/olestring_functions.h> // for olestring_dup(), etc.
  61. #endif /* !COMSTL_INCL_COMSTL_STRING_H_OLESTRING_FUNCTIONS */
  62. #ifndef STLSOFT_INCL_STLSOFT_CONVERSION_HPP_SAP_CAST
  63. # include <stlsoft/conversion/sap_cast.hpp>
  64. #endif /* !STLSOFT_INCL_STLSOFT_CONVERSION_HPP_SAP_CAST */
  65. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  66. # ifndef COMSTL_INCL_COMSTL_ERROR_HPP_EXCEPTIONS
  67. # include <comstl/error/exceptions.hpp>
  68. # endif /* !COMSTL_INCL_COMSTL_ERROR_HPP_EXCEPTIONS */
  69. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  70. /* /////////////////////////////////////////////////////////////////////////
  71. * Namespace
  72. */
  73. #ifndef _COMSTL_NO_NAMESPACE
  74. # if defined(_STLSOFT_NO_NAMESPACE) || \
  75. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  76. /* There is no stlsoft namespace, so must define ::comstl */
  77. namespace comstl
  78. {
  79. # else
  80. /* Define stlsoft::comstl_project */
  81. namespace stlsoft
  82. {
  83. namespace comstl_project
  84. {
  85. # endif /* _STLSOFT_NO_NAMESPACE */
  86. #endif /* !_COMSTL_NO_NAMESPACE */
  87. /* /////////////////////////////////////////////////////////////////////////
  88. * Classes
  89. */
  90. /** \brief Value policy for GUID
  91. *
  92. * \ingroup group__library__utility__com
  93. *
  94. * \sa comstl::collection_sequence
  95. * \sa comstl::enumerator_sequence
  96. */
  97. struct GUID_policy
  98. {
  99. public:
  100. typedef GUID value_type;
  101. public:
  102. /// Initialises an instance
  103. ///
  104. /// In the case of the <code>GUID</code> type, this is a no-op
  105. static void init(value_type* ) stlsoft_throw_0()
  106. {}
  107. /// Initialises an instance from another
  108. ///
  109. /// In the case of the <code>GUID</code> type, this is a straight
  110. /// byte-for-byte copy
  111. static void copy(value_type* dest, value_type const* src)
  112. {
  113. *dest = *src;
  114. }
  115. /// Releases an instance
  116. ///
  117. /// In the case of the <code>GUID</code> type, this is a no-op
  118. static void clear(value_type* ) stlsoft_throw_0()
  119. {}
  120. };
  121. /** \brief Value policy for BSTR
  122. *
  123. * \ingroup group__library__utility__com
  124. *
  125. * \sa comstl::collection_sequence
  126. * \sa comstl::enumerator_sequence
  127. */
  128. struct BSTR_policy
  129. {
  130. public:
  131. typedef BSTR value_type;
  132. public:
  133. /// Initialises an instance
  134. ///
  135. /// In the case of the <code>BSTR</code> type, this involves setting
  136. /// the value to NULL
  137. static void init(value_type* p) stlsoft_throw_0()
  138. {
  139. *p = NULL;
  140. }
  141. /// Initialises an instance from another
  142. ///
  143. /// In the case of the <code>BSTR</code> type, this involves calling
  144. /// <code>SysAllocString()</code>
  145. ///
  146. /// \exception comstl::com_exception If exception support is enabled,
  147. /// an instance of <code>comstl::com_exception</code> will be thrown
  148. /// if the copy cannot be made
  149. static void copy(value_type* dest, value_type const* src)
  150. {
  151. *dest = ::SysAllocString(*src);
  152. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  153. if( NULL == *dest &&
  154. NULL != *src &&
  155. L'\0' != (*src)[0])
  156. {
  157. STLSOFT_THROW_X(com_exception("failed to copy BSTR", E_OUTOFMEMORY));
  158. }
  159. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  160. }
  161. /// Releases an instance
  162. ///
  163. /// In the case of the <code>BSTR</code> type, this involves calling
  164. /// <code>SysFreeString()</code>
  165. static void clear(value_type* p) stlsoft_throw_0()
  166. {
  167. ::SysFreeString(*p);
  168. }
  169. };
  170. /** \brief Value policy for LPOLESTR
  171. *
  172. * \ingroup group__library__utility__com
  173. *
  174. * \sa comstl::collection_sequence
  175. * \sa comstl::enumerator_sequence
  176. */
  177. struct LPOLESTR_policy
  178. {
  179. public:
  180. typedef LPOLESTR value_type;
  181. public:
  182. /// Initialises an instance
  183. ///
  184. /// In the case of the OLE string type, this involves setting
  185. /// the value to NULL
  186. static void init(value_type* p) stlsoft_throw_0()
  187. {
  188. *p = NULL;
  189. }
  190. /// Initialises an instance from another
  191. ///
  192. /// In the case of the OLE string type, this involves calling
  193. /// <code>olestring_dup()</code>
  194. ///
  195. /// \exception comstl::com_exception If exception support is enabled,
  196. /// an instance of <code>comstl::com_exception</code> will be thrown
  197. /// if the copy cannot be made
  198. static void copy(value_type* dest, value_type const* src)
  199. {
  200. *dest = olestring_dup(*src);
  201. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  202. if( NULL == *dest &&
  203. NULL != *src)
  204. {
  205. STLSOFT_THROW_X(com_exception("failed to copy OLE string", E_OUTOFMEMORY));
  206. }
  207. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  208. }
  209. /// Releases an instance
  210. ///
  211. /// In the case of the OLE string type, this involves calling
  212. /// <code>olestring_destroy()</code>
  213. static void clear(value_type* p) stlsoft_throw_0()
  214. {
  215. olestring_destroy(*p);
  216. }
  217. };
  218. /** \brief Value policy for VARIANT
  219. *
  220. * \ingroup group__library__utility__com
  221. *
  222. * \sa comstl::collection_sequence
  223. * \sa comstl::enumerator_sequence
  224. */
  225. struct VARIANT_policy
  226. {
  227. public:
  228. typedef VARIANT value_type;
  229. public:
  230. /// Initialises an instance
  231. ///
  232. /// In the case of the <code>VARIANT</code> type, this involves calling
  233. /// <code>VariantInit()</code>
  234. static void init(value_type* p) stlsoft_throw_0()
  235. {
  236. ::VariantInit(p);
  237. }
  238. /// Initialises an instance from another
  239. ///
  240. /// In the case of the <code>VARIANT</code> type, this involves calling
  241. /// <code>VariantCopy()</code>
  242. ///
  243. /// \exception comstl::com_exception If exception support is enabled,
  244. /// an instance of <code>comstl::com_exception</code> will be thrown
  245. /// if the copy cannot be made
  246. static void copy(value_type* dest, value_type const* src)
  247. {
  248. HRESULT hr = ::VariantCopy(dest, const_cast<VARIANT*>(src));
  249. if(FAILED(hr))
  250. {
  251. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  252. STLSOFT_THROW_X(com_exception("failed to copy VARIANT", hr));
  253. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  254. }
  255. }
  256. /// Releases an instance
  257. ///
  258. /// In the case of the <code>VARIANT</code> type, this involves calling
  259. /// <code>VariantClear()</code>
  260. static void clear(value_type* p) stlsoft_throw_0()
  261. {
  262. ::VariantClear(p);
  263. }
  264. };
  265. /** \brief Value policy for interface
  266. *
  267. * \ingroup group__library__utility__com
  268. *
  269. * \param I The interface
  270. *
  271. * \sa comstl::collection_sequence
  272. * \sa comstl::enumerator_sequence
  273. */
  274. template <ss_typename_param_k I>
  275. struct interface_policy
  276. {
  277. public:
  278. typedef I interface_type;
  279. typedef interface_type* value_type;
  280. public:
  281. /// Initialises an instance
  282. ///
  283. /// In the case of an interface pointer type, this involves setting
  284. /// the value to NULL
  285. static void init(value_type* p) stlsoft_throw_0()
  286. {
  287. *p = NULL;
  288. }
  289. /// Initialises an instance from another
  290. ///
  291. /// In the case of an interface pointer type, this involves taking a
  292. /// copy of the pointer and, if the source is non-NULL, invoking
  293. /// <code>AddRef()</code>
  294. static void copy(value_type* dest, value_type const* src)
  295. {
  296. *dest = *src;
  297. if(NULL != *dest)
  298. {
  299. (*dest)->AddRef();
  300. }
  301. }
  302. /// Releases an instance
  303. ///
  304. /// In the case of an interface pointer type, this involves
  305. /// invoking <code>Release()</code> and setting the value to NULL
  306. /// (unless it is already NULL)
  307. static void clear(value_type* p) stlsoft_throw_0()
  308. {
  309. if(NULL != *p)
  310. {
  311. (*p)->Release();
  312. *p = NULL;
  313. }
  314. }
  315. };
  316. /** \brief Value policy for LPUNKNOWN
  317. *
  318. * \ingroup group__library__utility__com
  319. *
  320. * \sa comstl::collection_sequence
  321. * \sa comstl::enumerator_sequence
  322. */
  323. struct LPUNKNOWN_policy
  324. {
  325. public:
  326. typedef LPUNKNOWN value_type;
  327. public:
  328. /// Initialises an instance
  329. ///
  330. /// In the case of the <code>LPUNKNOWN</code> type, this involves setting
  331. /// the value to NULL
  332. static void init(value_type* p) stlsoft_throw_0()
  333. {
  334. *p = NULL;
  335. }
  336. /// Initialises an instance from another
  337. ///
  338. /// In the case of the <code>LPUNKNOWN</code> type, this involves taking
  339. /// a copy of the pointer and, if the source is non-NULL, invoking
  340. /// <code>AddRef()</code>
  341. static void copy(value_type* dest, value_type const* src)
  342. {
  343. *dest = *src;
  344. if(NULL != *dest)
  345. {
  346. (*dest)->AddRef();
  347. }
  348. }
  349. /// Releases an instance
  350. ///
  351. /// In the case of the <code>LPUNKNOWN</code> type, this involves
  352. /// invoking <code>Release()</code> and setting the value to NULL
  353. /// (unless it is already NULL)
  354. static void clear(value_type* p) stlsoft_throw_0()
  355. {
  356. if(NULL != *p)
  357. {
  358. (*p)->Release();
  359. *p = NULL;
  360. }
  361. }
  362. };
  363. /** \brief Value policy for STATSTG
  364. *
  365. * \ingroup group__library__utility__com
  366. *
  367. * \sa comstl::collection_sequence
  368. * \sa comstl::enumerator_sequence
  369. */
  370. struct STATSTG_policy
  371. {
  372. public:
  373. typedef STATSTG value_type;
  374. public:
  375. /// Initialises an instance
  376. ///
  377. /// In the case of the <code>STATSTG</code> type, this involves setting
  378. /// the <code>pwcsName</code> member to NULL
  379. static void init(value_type* p) stlsoft_throw_0()
  380. {
  381. p->pwcsName = NULL;
  382. }
  383. /// Initialises an instance from another
  384. ///
  385. /// In the case of the <code>STATSTG</code> type, this involves a
  386. /// straight byte-for-byte copy of the structure contents, following by
  387. /// invoking <code>olestring_dup()</code> on the <code>pwcsName</code>
  388. /// member, to obtain a deep copy
  389. ///
  390. /// \exception comstl::com_exception If exception support is enabled,
  391. /// an instance of <code>comstl::com_exception</code> will be thrown
  392. /// if the copy cannot be made
  393. static void copy(value_type* dest, value_type const* src)
  394. {
  395. *dest = *src;
  396. if(NULL != src->pwcsName)
  397. {
  398. dest->pwcsName = olestring_dup(src->pwcsName);
  399. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  400. if(NULL == dest->pwcsName)
  401. {
  402. STLSOFT_THROW_X(com_exception("failed to copy OLE string when copying STATSTG", E_OUTOFMEMORY));
  403. }
  404. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  405. };
  406. }
  407. /// Releases an instance
  408. ///
  409. /// In the case of the <code>STATSTG</code> type, this involves invoking
  410. /// <code>olestring_destroy()</code> on the <code>pwcsName</code> member
  411. static void clear(value_type* p) stlsoft_throw_0()
  412. {
  413. olestring_destroy(p->pwcsName);
  414. }
  415. };
  416. /** \brief Value policy for FORMATETC
  417. *
  418. * \ingroup group__library__utility__com
  419. *
  420. * \sa comstl::collection_sequence
  421. * \sa comstl::enumerator_sequence
  422. */
  423. struct FORMATETC_policy
  424. {
  425. public:
  426. typedef FORMATETC value_type;
  427. public:
  428. /// Initialises an instance
  429. ///
  430. /// In the case of the <code>FORMATETC</code> type, this involves setting
  431. /// the <code>ptd</code> member to NULL
  432. static void init(value_type* p) stlsoft_throw_0()
  433. {
  434. p->ptd = NULL;
  435. }
  436. /// Initialises an instance from another
  437. ///
  438. /// In the case of the <code>FORMATETC</code> type, this involves a
  439. /// straight byte-for-byte copy of the structure contents, following by
  440. /// invoking <code>CoTaskMemAlloc()</code> on the <code>ptd</code>
  441. /// member, to obtain a deep copy
  442. ///
  443. /// \exception comstl::com_exception If exception support is enabled,
  444. /// an instance of <code>comstl::com_exception</code> will be thrown
  445. /// if the copy cannot be made
  446. static void copy(value_type* dest, value_type const* src)
  447. {
  448. *dest = *src;
  449. if(NULL != dest->ptd)
  450. {
  451. dest->ptd = static_cast<DVTARGETDEVICE*>(::CoTaskMemAlloc(src->ptd->tdSize));
  452. if(NULL == dest->ptd)
  453. {
  454. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  455. STLSOFT_THROW_X(com_exception("failed to copy DVTARGETDEVICE when copying FORMATETC", E_OUTOFMEMORY));
  456. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  457. }
  458. else
  459. {
  460. BYTE const* src_begin = stlsoft_ns_qual(sap_cast)<BYTE const*>(&src->ptd);
  461. BYTE const* src_end = src_begin + src->ptd->tdSize;
  462. BYTE* dest_begin = stlsoft_ns_qual(sap_cast)<BYTE*>(&dest->ptd);
  463. for(; src_begin != src_end; ++src_begin, ++dest_begin)
  464. {
  465. *dest_begin = *src_begin;
  466. }
  467. }
  468. }
  469. }
  470. /// Releases an instance
  471. ///
  472. /// In the case of the <code>FORMATETC</code> type, this involves invoking
  473. /// <code>CoTaskMemFree()</code> on the <code>ptd</code> member
  474. static void clear(value_type* p) stlsoft_throw_0()
  475. {
  476. ::CoTaskMemFree(p->ptd);
  477. }
  478. };
  479. /* ////////////////////////////////////////////////////////////////////// */
  480. #ifndef _COMSTL_NO_NAMESPACE
  481. # if defined(_STLSOFT_NO_NAMESPACE) || \
  482. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  483. } // namespace comstl
  484. # else
  485. } // namespace stlsoft::comstl_project
  486. } // namespace stlsoft
  487. # endif /* _STLSOFT_NO_NAMESPACE */
  488. #endif /* !_COMSTL_NO_NAMESPACE */
  489. /* ////////////////////////////////////////////////////////////////////// */
  490. #endif /* !COMSTL_INCL_COMSTL_UTIL_HPP_VALUE_POLICIES */
  491. /* ///////////////////////////// end of file //////////////////////////// */