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.

499 lines
15 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: comstl/util/initialisers.hpp (originally MOInit.h, ::SynesisCom)
  3. *
  4. * Purpose: Contains classes for initialising COM/OLE.
  5. *
  6. * Created: 8th February 1999
  7. * Updated: 10th August 2009
  8. *
  9. * Thanks: To Adi Shavit, for demanding better documentation of COMSTL.
  10. *
  11. * Home: http://stlsoft.org/
  12. *
  13. * Copyright (c) 1999-2009, Matthew Wilson and Synesis Software
  14. * All rights reserved.
  15. *
  16. * Redistribution and use in source and binary forms, with or without
  17. * modification, are permitted provided that the following conditions are met:
  18. *
  19. * - Redistributions of source code must retain the above copyright notice, this
  20. * list of conditions and the following disclaimer.
  21. * - Redistributions in binary form must reproduce the above copyright notice,
  22. * this list of conditions and the following disclaimer in the documentation
  23. * and/or other materials provided with the distribution.
  24. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  25. * any contributors may be used to endorse or promote products derived from
  26. * this software without specific prior written permission.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  29. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  30. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  34. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  35. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  36. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  37. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  38. * POSSIBILITY OF SUCH DAMAGE.
  39. *
  40. * ////////////////////////////////////////////////////////////////////// */
  41. /** \file comstl/util/initialisers.hpp
  42. *
  43. * \brief [C++ only; requires COM] Definition of the comstl::initialiser
  44. * class template, and its associated policies and specialisations
  45. * (\ref group__library__utility__com "COM Utility" Library).
  46. */
  47. #ifndef COMSTL_INCL_COMSTL_UTIL_HPP_INITIALISERS
  48. #define COMSTL_INCL_COMSTL_UTIL_HPP_INITIALISERS
  49. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  50. # define COMSTL_VER_COMSTL_UTIL_HPP_INITIALISERS_MAJOR 3
  51. # define COMSTL_VER_COMSTL_UTIL_HPP_INITIALISERS_MINOR 3
  52. # define COMSTL_VER_COMSTL_UTIL_HPP_INITIALISERS_REVISION 2
  53. # define COMSTL_VER_COMSTL_UTIL_HPP_INITIALISERS_EDIT 80
  54. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  55. /* /////////////////////////////////////////////////////////////////////////
  56. * Includes
  57. */
  58. #ifndef COMSTL_INCL_COMSTL_H_COMSTL
  59. # include <comstl/comstl.h>
  60. #endif /* !COMSTL_INCL_COMSTL_H_COMSTL */
  61. #ifndef COMSTL_INCL_COMSTL_ERROR_HPP_EXCEPTIONS
  62. # include <comstl/error/exceptions.hpp>
  63. #endif /* !COMSTL_INCL_COMSTL_ERROR_HPP_EXCEPTIONS */
  64. #ifndef STLSOFT_INCL_STLSOFT_ERROR_HPP_THROW_POLICIES
  65. # include <stlsoft/error/throw_policies.hpp>
  66. #endif /* !STLSOFT_INCL_STLSOFT_ERROR_HPP_THROW_POLICIES */
  67. #ifndef STLSOFT_INCL_H_OLE2
  68. # define STLSOFT_INCL_H_OLE2
  69. # include <ole2.h>
  70. #endif /* !STLSOFT_INCL_H_OLE2 */
  71. /* /////////////////////////////////////////////////////////////////////////
  72. * Namespace
  73. */
  74. #ifndef _COMSTL_NO_NAMESPACE
  75. # if defined(_STLSOFT_NO_NAMESPACE) || \
  76. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  77. /* There is no stlsoft namespace, so must define ::comstl */
  78. namespace comstl
  79. {
  80. # else
  81. /* Define stlsoft::comstl_project */
  82. namespace stlsoft
  83. {
  84. namespace comstl_project
  85. {
  86. # endif /* _STLSOFT_NO_NAMESPACE */
  87. #endif /* !_COMSTL_NO_NAMESPACE */
  88. /* /////////////////////////////////////////////////////////////////////////
  89. * Exception classes
  90. */
  91. /** \brief Exception class thrown for COM initialisation failures
  92. *
  93. * \ingroup group__library__error
  94. */
  95. class com_initialisation_exception
  96. : public com_exception
  97. {
  98. /// \name Member Types
  99. /// @{
  100. public:
  101. typedef com_exception parent_class_type;
  102. typedef com_initialisation_exception class_type;
  103. /// @}
  104. /// \name Construction
  105. /// @{
  106. public:
  107. ss_explicit_k com_initialisation_exception(HRESULT hr)
  108. : parent_class_type(hr)
  109. {}
  110. com_initialisation_exception(char const* reason, HRESULT hr)
  111. : parent_class_type(reason, hr)
  112. {}
  113. /// @}
  114. /// \name Implementation
  115. /// @{
  116. private:
  117. virtual char const* real_what_() const throw()
  118. {
  119. return "COM initialisation failure";
  120. }
  121. /// @}
  122. };
  123. ////////////////////////////////////////////////////////////////////////////
  124. // Exception policies
  125. /** \brief Exception policy whose action is to do nothing
  126. *
  127. * \ingroup group__library__error
  128. */
  129. // [[synesis:class:exception-policy: com_initialisation_exception_policy]]
  130. struct com_initialisation_exception_policy
  131. {
  132. /// \name Member Types
  133. /// @{
  134. public:
  135. /// The exception type
  136. typedef com_initialisation_exception thrown_type;
  137. /// @}
  138. /// \name Operators
  139. /// @{
  140. public:
  141. /// The function call operator, which throws the exception
  142. ///
  143. /// \param hr The HRESULT that caused the error
  144. void operator ()(HRESULT hr)
  145. {
  146. STLSOFT_THROW_X(com_initialisation_exception(hr));
  147. }
  148. /// @}
  149. };
  150. /** \brief Exception policy whose action is to do nothing
  151. *
  152. * \ingroup group__library__error
  153. */
  154. typedef stlsoft_ns_qual(null_exception_policy) ignore_initialisation_exception_policy;
  155. /* /////////////////////////////////////////////////////////////////////////
  156. * Classes
  157. */
  158. /** \brief Initialises the COM libraries
  159. *
  160. * \ingroup group__library__utility__com
  161. *
  162. * This class is used to initialise the COM libraries. It can respond to
  163. * CoInitializeEx argument flags when translated in a DCOM build.
  164. *
  165. * It is specialised for COM or OLE library initialisation, and with or
  166. * without throwing an exception on failure, in the following typedefs:
  167. * - \link comstl::com_init com_init\endlink - initialises the COM libraries; throws an instance of \link comstl::com_initialisation_exception com_initialisation_exception\endlink on failure
  168. * - \link comstl::com_init_nothrow com_init_nothrow\endlink - initialises the COM libraries; does not throw on failure
  169. * - \link comstl::ole_init ole_init\endlink - initialises the OLE libraries; throws an instance of \link comstl::com_initialisation_exception com_initialisation_exception\endlink on failure
  170. * - \link comstl::ole_init_nothrow ole_init_nothrow\endlink - initialises the OLE libraries; does not throw on failure
  171. *
  172. * It is commonly used within <code>main()</code> (for a CLI program), or
  173. * <code>WinMain()</code> (for a GUI program). A typical program structure
  174. * is shown as follows:
  175. \code
  176. #include <comstl/util/initialisers.hpp>
  177. #include <stdlib.h>
  178. static int main_(int argc, char **argv)
  179. {
  180. . . . // main application functionality
  181. }
  182. int main(int argc, char **argv)
  183. {
  184. try
  185. {
  186. comstl::com_init init; // Initialise the COM libraries
  187. return main_(argc, argv);
  188. }
  189. catch(comstl::com_initialisation_exception &x) // COM library initialisation failed
  190. {
  191. return EXIT_FAILURE;
  192. }
  193. catch(std::exception &x) // other failures from main_()
  194. {
  195. return EXIT_FAILURE;
  196. }
  197. }
  198. \endcode
  199. *
  200. * In practice, initialisation failure of the COM libraries is unheard of, so
  201. * you can probably dispense with the specific catch clause shown above, and
  202. * rely on comstl::com_initialisation_exception being caught by the
  203. * <code>std::exception</code> clause.
  204. *
  205. * \see comstl::
  206. */
  207. template< ss_typename_param_k IP /* Initialisation policy type */
  208. , ss_typename_param_k XP /* Exception policy type */
  209. >
  210. class initialiser
  211. {
  212. /// \name Member Types
  213. /// @{
  214. private:
  215. typedef initialiser class_type;
  216. public:
  217. /// The initialiation policy type
  218. typedef IP initialisation_policy_type;
  219. /// The exception type
  220. typedef XP exception_policy_type;
  221. /// The thrown type
  222. typedef ss_typename_type_k exception_policy_type::thrown_type thrown_type;
  223. /// @}
  224. /// \name Construction
  225. /// @{
  226. public:
  227. /// Initialises via CoInitialize()
  228. initialiser();
  229. #ifdef __COMSTL_CF_DCOM_SUPPORT
  230. /// Initialises via CoInitializeEx() taking b>COINIT_*</b> flags
  231. ss_explicit_k initialiser(cs_dword_t dwInit /* = COINIT_APARTMENTTHREADED */);
  232. #endif /* __COMSTL_CF_DCOM_SUPPORT */
  233. /// Uninitialises via CoUninitialize()
  234. ~initialiser() stlsoft_throw_0();
  235. /// @}
  236. /// \name Attributes
  237. /// @{
  238. public:
  239. /// Reflects whether the COM libraries were initialised
  240. cs_bool_t is_initialised() const;
  241. /// Reflects whether the COM libraries were not initialised
  242. cs_bool_t operator !() const;
  243. /// The result of the call to CoInitialize()/CoInitializeEx()
  244. HRESULT get_HRESULT() const;
  245. /// @}
  246. /// \name Members
  247. /// @{
  248. private:
  249. HRESULT const m_hr;
  250. /// @}
  251. /// \name Not to be implemented
  252. /// @{
  253. private:
  254. initialiser(class_type const& rhs);
  255. class_type const& operator =(class_type const& rhs);
  256. /// @}
  257. };
  258. ////////////////////////////////////////////////////////////////////////////
  259. // Value policies
  260. /** \brief A policy type, for use with comstl::initialiser, that causes
  261. * initialisation/uninitialisation of the COM libraries with
  262. * <code>CoInitialize()</code>/<code>CoInitializeEx()</code> and
  263. * <code>CoUninitialize()</code>.
  264. *
  265. * \ingroup group__library__utility__com
  266. *
  267. * \see comstl::initialiser
  268. */
  269. struct CoInitialize_policy
  270. {
  271. public:
  272. static HRESULT init()
  273. {
  274. return ::CoInitialize(NULL);
  275. }
  276. #ifdef __COMSTL_CF_DCOM_SUPPORT
  277. static HRESULT init(cs_dword_t coInit)
  278. {
  279. return ::CoInitializeEx(NULL, coInit);
  280. }
  281. #endif /* __COMSTL_CF_DCOM_SUPPORT */
  282. static void uninit()
  283. {
  284. ::CoUninitialize();
  285. }
  286. };
  287. /** \brief A policy type, for use with comstl::initialiser, that causes
  288. * initialisation/uninitialisation of the COM libraries with
  289. * <code>OleInitialize()</code> and <code>OleUninitialize()</code>.
  290. *
  291. * \ingroup group__library__utility__com
  292. *
  293. * \see comstl::initialiser
  294. */
  295. struct OleInitialize_policy
  296. {
  297. public:
  298. static HRESULT init()
  299. {
  300. return ::OleInitialize(NULL);
  301. }
  302. static void uninit()
  303. {
  304. ::OleUninitialize();
  305. }
  306. };
  307. ////////////////////////////////////////////////////////////////////////////
  308. // Typedefs for common instantiations
  309. /** \brief Specialisation of comstl::initialiser that initialises via CoInitialize() but does not throw on failure.
  310. *
  311. * \ingroup group__library__utility__com
  312. *
  313. * \see comstl::initialiser
  314. */
  315. typedef initialiser<CoInitialize_policy, ignore_initialisation_exception_policy> com_init_nothrow;
  316. /** \brief Specialisation of comstl::initialiser that initialises via OleInitialize() but does not throw on failure.
  317. *
  318. * \ingroup group__library__utility__com
  319. *
  320. * \see comstl::initialiser
  321. */
  322. typedef initialiser<OleInitialize_policy, ignore_initialisation_exception_policy> ole_init_nothrow;
  323. /** \brief Specialisation of comstl::initialiser that initialises via CoInitialize() and throws on failure.
  324. *
  325. * \ingroup group__library__utility__com
  326. *
  327. * \see comstl::initialiser
  328. */
  329. typedef initialiser<CoInitialize_policy, com_initialisation_exception_policy> com_init;
  330. /** \brief Specialisation of comstl::initialiser that initialises via OleInitialize() and throws on failure.
  331. *
  332. * \ingroup group__library__utility__com
  333. *
  334. * \see comstl::initialiser
  335. */
  336. typedef initialiser<OleInitialize_policy, com_initialisation_exception_policy> ole_init;
  337. /** \brief [DEPRECATED] Specialisation of comstl::initialiser that initialises via CoInitialize() but does not throw on failure.
  338. *
  339. * \ingroup group__library__utility__com
  340. *
  341. * \deprecated Use com_init_nothrow instead.
  342. *
  343. * \see comstl::initialiser
  344. */
  345. typedef com_init_nothrow com_initialiser;
  346. /** \brief [DEPRECATED] Specialisation of comstl::initialiser that initialises via OleInitialize() but does not throw on failure.
  347. *
  348. * \ingroup group__library__utility__com
  349. *
  350. * \deprecated Use ole_init_nothrow instead.
  351. *
  352. * \see comstl::initialiser
  353. */
  354. typedef ole_init_nothrow ole_initialiser;
  355. ////////////////////////////////////////////////////////////////////////////
  356. // Typedefs for US-English spellers
  357. /** \brief Equivalent to com_initialiser
  358. *
  359. * \ingroup group__library__utility__com
  360. */
  361. typedef com_initialiser com_initializer;
  362. /** \brief Equivalent to ole_initialiser
  363. *
  364. * \ingroup group__library__utility__com
  365. */
  366. typedef ole_initialiser ole_initializer;
  367. ////////////////////////////////////////////////////////////////////////////
  368. // Unit-testing
  369. #ifdef STLSOFT_UNITTEST
  370. # include "./unittest/initialisers_unittest_.h"
  371. #endif /* STLSOFT_UNITTEST */
  372. ////////////////////////////////////////////////////////////////////////////
  373. // Implementation
  374. // initialiser
  375. template< ss_typename_param_k IP
  376. , ss_typename_param_k XP
  377. >
  378. inline initialiser<IP, XP>::initialiser()
  379. : m_hr(initialisation_policy_type::init())
  380. {
  381. if(FAILED(m_hr))
  382. {
  383. exception_policy_type xp;
  384. xp(m_hr);
  385. }
  386. }
  387. #ifdef __COMSTL_CF_DCOM_SUPPORT
  388. template< ss_typename_param_k IP
  389. , ss_typename_param_k XP
  390. >
  391. inline initialiser<IP, XP>::initialiser(cs_dword_t coInit)
  392. : m_hr(initialisation_policy_type::init(coInit))
  393. {
  394. if(FAILED(m_hr))
  395. {
  396. exception_policy_type xp;
  397. xp(m_hr);
  398. }
  399. }
  400. #endif // __COMSTL_CF_DCOM_SUPPORT
  401. template< ss_typename_param_k IP
  402. , ss_typename_param_k XP
  403. >
  404. inline initialiser<IP, XP>::~initialiser() stlsoft_throw_0()
  405. {
  406. if(is_initialised())
  407. {
  408. initialisation_policy_type::uninit();
  409. }
  410. }
  411. template< ss_typename_param_k IP
  412. , ss_typename_param_k XP
  413. >
  414. inline cs_bool_t initialiser<IP, XP>::is_initialised() const
  415. {
  416. return SUCCEEDED(m_hr);
  417. }
  418. template< ss_typename_param_k IP
  419. , ss_typename_param_k XP
  420. >
  421. inline cs_bool_t initialiser<IP, XP>::operator !() const
  422. {
  423. return !is_initialised();
  424. }
  425. template< ss_typename_param_k IP
  426. , ss_typename_param_k XP
  427. >
  428. inline HRESULT initialiser<IP, XP>::get_HRESULT() const
  429. {
  430. return m_hr;
  431. }
  432. /* ////////////////////////////////////////////////////////////////////// */
  433. #ifndef _COMSTL_NO_NAMESPACE
  434. # if defined(_STLSOFT_NO_NAMESPACE) || \
  435. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  436. } // namespace comstl
  437. # else
  438. } // namespace stlsoft::comstl_project
  439. } // namespace stlsoft
  440. # endif /* _STLSOFT_NO_NAMESPACE */
  441. #endif /* !_COMSTL_NO_NAMESPACE */
  442. /* ////////////////////////////////////////////////////////////////////// */
  443. #endif /* !COMSTL_INCL_COMSTL_UTIL_HPP_INITIALISERS */
  444. /* ///////////////////////////// end of file //////////////////////////// */