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.

317 lines
10 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: comstl/util/creation_functions.hpp
  3. *
  4. * Purpose: COM instance creation helper functions
  5. *
  6. * Created: 21st September 2005
  7. * Updated: 6th June 2010
  8. *
  9. * Thanks: To Adi Shavit for demanding more usability in these
  10. * functions, which led to the adoption of stlsoft::ref_ptr<X>
  11. * as the unit of currency throughout COMSTL.
  12. *
  13. * Home: http://stlsoft.org/
  14. *
  15. * Copyright (c) 2005-2010, Matthew Wilson and Synesis Software
  16. * All rights reserved.
  17. *
  18. * Redistribution and use in source and binary forms, with or without
  19. * modification, are permitted provided that the following conditions are met:
  20. *
  21. * - Redistributions of source code must retain the above copyright notice, this
  22. * list of conditions and the following disclaimer.
  23. * - Redistributions in binary form must reproduce the above copyright notice,
  24. * this list of conditions and the following disclaimer in the documentation
  25. * and/or other materials provided with the distribution.
  26. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  27. * any contributors may be used to endorse or promote products derived from
  28. * this software without specific prior written permission.
  29. *
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  31. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  32. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  34. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  35. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  36. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  37. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  38. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  39. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  40. * POSSIBILITY OF SUCH DAMAGE.
  41. *
  42. * ////////////////////////////////////////////////////////////////////// */
  43. /** \file comstl/util/creation_functions.hpp
  44. *
  45. * \brief [C++ only; requires COM] COM instance creation helper functions
  46. * (\ref group__library__utility__com "COM Utility" Library).
  47. */
  48. #ifndef COMSTL_INCL_COMSTL_UTIL_HPP_CREATION_FUNCTIONS
  49. #define COMSTL_INCL_COMSTL_UTIL_HPP_CREATION_FUNCTIONS
  50. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  51. # define COMSTL_VER_COMSTL_UTIL_HPP_CREATION_FUNCTIONS_MAJOR 2
  52. # define COMSTL_VER_COMSTL_UTIL_HPP_CREATION_FUNCTIONS_MINOR 3
  53. # define COMSTL_VER_COMSTL_UTIL_HPP_CREATION_FUNCTIONS_REVISION 2
  54. # define COMSTL_VER_COMSTL_UTIL_HPP_CREATION_FUNCTIONS_EDIT 22
  55. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  56. /* /////////////////////////////////////////////////////////////////////////
  57. * Includes
  58. */
  59. #ifndef COMSTL_INCL_COMSTL_H_COMSTL
  60. # include <comstl/comstl.h>
  61. #endif /* !COMSTL_INCL_COMSTL_H_COMSTL */
  62. #ifndef COMSTL_INCL_COMSTL_UTIL_HPP_INTERFACE_TRAITS
  63. # include <comstl/util/interface_traits.hpp>
  64. #endif /* !COMSTL_INCL_COMSTL_UTIL_HPP_INTERFACE_TRAITS */
  65. #ifndef STLSOFT_INCL_STLSOFT_SMARTPTR_HPP_REF_PTR
  66. # include <stlsoft/smartptr/ref_ptr.hpp>
  67. #endif /* !STLSOFT_INCL_STLSOFT_SMARTPTR_HPP_REF_PTR */
  68. /* /////////////////////////////////////////////////////////////////////////
  69. * Namespace
  70. */
  71. #ifndef _COMSTL_NO_NAMESPACE
  72. # if defined(_STLSOFT_NO_NAMESPACE) || \
  73. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  74. /* There is no stlsoft namespace, so must define ::comstl */
  75. namespace comstl
  76. {
  77. # else
  78. /* Define stlsoft::comstl_project */
  79. namespace stlsoft
  80. {
  81. namespace comstl_project
  82. {
  83. # endif /* _STLSOFT_NO_NAMESPACE */
  84. #endif /* !_COMSTL_NO_NAMESPACE */
  85. /* /////////////////////////////////////////////////////////////////////////
  86. * Functions
  87. */
  88. /** \brief Type-safe creation of a COM object, acquiring the requisite
  89. * interface pointer.
  90. *
  91. * \ingroup group__library__utility__com
  92. *
  93. * \param clsid The CLSID of the component to be created.
  94. * \param ppi Pointer to the interface pointer.
  95. * \param dwClsContext Class creation context
  96. *
  97. * The following example demonstrates how to use the function to create an
  98. * instance of the Pantheios.COM Logger Manager component by specifying its
  99. * CLSID, and requesting the <code>IDispatch</code> interface:
  100. \code
  101. const CLSID CLSID_pantheios_COM_LoggerManager = { 0x4E7D5C47, 0x8F96, 0x45DE, { 0x90, 0x5D, 0xAA, 0x3E, 0x9E, 0x59, 0x2D, 0xE3 } };
  102. IDispatch* logmgr;
  103. if(SUCCEEDED(comstl::co_create_instance(CLSID_pantheios_COM_LoggerManager, &logmgr)))
  104. {
  105. logmgr->Release();
  106. }
  107. \endcode
  108. */
  109. template <ss_typename_param_k I>
  110. inline HRESULT co_create_instance(
  111. REFCLSID clsid
  112. , I** ppi
  113. , DWORD dwClsContext = CLSCTX_ALL
  114. )
  115. {
  116. return ::CoCreateInstance(clsid, NULL, dwClsContext, IID_traits<I>::iid(), reinterpret_cast<void**>(ppi));
  117. }
  118. /** \brief Type-safe creation of a COM object from a Programmatic Id,
  119. * acquiring the requisite interface pointer.
  120. *
  121. * \ingroup group__library__utility__com
  122. *
  123. * \param id Can be the Programatic Identifier (ProgId) - e.g.
  124. * pantheios.com.LoggerManager - or the string form of the
  125. * class id - e.g. {4E7D5C47-8F96-45DE-905D-AA3E9E592DE3}
  126. * \param ppi Pointer to the interface pointer.
  127. * \param dwClsContext Class creation context
  128. *
  129. * The following example demonstrates how to use the function to create an
  130. * instance of the Pantheios.COM Logger Manager component by specifying the
  131. * string form of its CLSID, and requesting the <code>IDispatch</code>
  132. * interface:
  133. \code
  134. IDispatch* logmgr;
  135. if(SUCCEEDED(comstl::co_create_instance(L"{4E7D5C47-8F96-45DE-905D-AA3E9E592DE3}", &logmgr)))
  136. {
  137. logmgr->Release();
  138. }
  139. \endcode
  140. *
  141. * The following example demonstrates how to use the function to create an
  142. * instance of the Pantheios.COM Logger Manager component by specifying the
  143. * Programmatic Identifier (ProgID), and requesting the <code>IDispatch</code>
  144. * interface:
  145. \code
  146. IDispatch* logmgr;
  147. if(SUCCEEDED(comstl::co_create_instance(L"pantheios.COM.LoggerManager", &logmgr)))
  148. {
  149. logmgr->Release();
  150. }
  151. \endcode
  152. */
  153. template <ss_typename_param_k I>
  154. inline HRESULT co_create_instance(
  155. LPCOLESTR id
  156. , I** ppi
  157. , DWORD dwClsContext = CLSCTX_ALL
  158. )
  159. {
  160. CLSID clsid;
  161. HRESULT hr = ::CLSIDFromProgID(id, &clsid);
  162. if(FAILED(hr))
  163. {
  164. hr = ::CLSIDFromString(const_cast<LPOLESTR>(id), &clsid);
  165. }
  166. if(SUCCEEDED(hr))
  167. {
  168. hr = co_create_instance(clsid, ppi, dwClsContext);
  169. }
  170. return hr;
  171. }
  172. /** \brief Type-safe creation of a COM object, acquiring the requisite
  173. * interface pointer into an interface wrapper instance.
  174. *
  175. * \ingroup group__library__utility__com
  176. *
  177. * \param clsid The CLSID of the component to be created.
  178. * \param wi A mutable (non-const) reference to an interface wrapper
  179. * instance. The wrapper's <code>interface_type</code> determines the
  180. * interface queried by the COM runtime's creation facilities on the
  181. * created instance.
  182. * \param dwClsContext Class creation context
  183. *
  184. * The following example demonstrates how to use the function to create an
  185. * instance of the Pantheios.COM Logger Manager component by specifying its
  186. * CLSID, and requesting the <code>IDispatch</code> interface:
  187. \code
  188. const CLSID CLSID_pantheios_COM_LoggerManager = { 0x4E7D5C47, 0x8F96, 0x45DE, { 0x90, 0x5D, 0xAA, 0x3E, 0x9E, 0x59, 0x2D, 0xE3 } };
  189. stlsoft::ref_ptr<IDispatch> logmgr;
  190. if(SUCCEEDED(comstl::co_create_instance(CLSID_pantheios_COM_LoggerManager, logmgr)))
  191. {
  192. . . .
  193. } // Release() automatically invoked here
  194. \endcode
  195. */
  196. template< ss_typename_param_k T
  197. , ss_typename_param_k I
  198. , ss_typename_param_k U
  199. >
  200. inline HRESULT co_create_instance(
  201. REFCLSID clsid
  202. , stlsoft_ns_qual(ref_ptr)<T, I, U>& wi
  203. , DWORD dwClsContext = CLSCTX_ALL
  204. )
  205. {
  206. I* pi;
  207. HRESULT hr = co_create_instance(clsid, &pi, dwClsContext);
  208. if(FAILED(hr))
  209. {
  210. pi = NULL;
  211. }
  212. wi.set(pi, false); // Eat the reference
  213. return hr;
  214. }
  215. /** \brief Type-safe creation of a COM object from a Programmatic Id,
  216. * acquiring the requisite interface wrapper instance.
  217. *
  218. * \ingroup group__library__utility__com
  219. *
  220. * \param id Can be the Programatic Identifier (ProgId) - e.g.
  221. * pantheios.com.LoggerManager - or the string form of the
  222. * class id - e.g. {4E7D5C47-8F96-45DE-905D-AA3E9E592DE3}
  223. * \param wi A mutable (non-const) reference to an interface wrapper
  224. * instance. The wrapper's <code>interface_type</code> determines the
  225. * interface queried by the COM runtime's creation facilities on the
  226. * created instance.
  227. * \param dwClsContext Class creation context
  228. *
  229. * The following example demonstrates how to use the function to create an
  230. * instance of the Pantheios.COM Logger Manager component by specifying the
  231. * string form of its CLSID, and requesting the <code>IDispatch</code>
  232. * interface:
  233. \code
  234. stlsoft::ref_ptr<IDispatch> logmgr;
  235. if(SUCCEEDED(comstl::co_create_instance(L"{4E7D5C47-8F96-45DE-905D-AA3E9E592DE3}", logmgr)))
  236. {
  237. . . .
  238. } // Release() automatically invoked here
  239. \endcode
  240. *
  241. * The following example demonstrates how to use the function to create an
  242. * instance of the Pantheios.COM Logger Manager component by specifying the
  243. * Programmatic Identifier (ProgID), and requesting the <code>IDispatch</code>
  244. * interface:
  245. \code
  246. stlsoft::ref_ptr<IDispatch> logmgr;
  247. if(SUCCEEDED(comstl::co_create_instance(L"pantheios.COM.LoggerManager", logmgr)))
  248. {
  249. . . .
  250. } // Release() automatically invoked here
  251. \endcode
  252. */
  253. template< ss_typename_param_k T
  254. , ss_typename_param_k I
  255. , ss_typename_param_k U
  256. >
  257. inline HRESULT co_create_instance(
  258. LPCOLESTR id
  259. , stlsoft_ns_qual(ref_ptr)<T, I, U>& wi
  260. , DWORD dwClsContext = CLSCTX_ALL
  261. )
  262. {
  263. I* pi;
  264. HRESULT hr = co_create_instance(id, &pi, dwClsContext);
  265. if(FAILED(hr))
  266. {
  267. pi = NULL;
  268. }
  269. wi = stlsoft_ns_qual(ref_ptr)<T, I, U>(pi, false); // Eat the reference
  270. return hr;
  271. }
  272. /* ////////////////////////////////////////////////////////////////////// */
  273. #ifndef _COMSTL_NO_NAMESPACE
  274. # if defined(_STLSOFT_NO_NAMESPACE) || \
  275. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  276. } // namespace comstl
  277. # else
  278. } // namespace comstl_project
  279. } // namespace stlsoft
  280. # endif /* _STLSOFT_NO_NAMESPACE */
  281. #endif /* !_COMSTL_NO_NAMESPACE */
  282. /* ////////////////////////////////////////////////////////////////////// */
  283. #endif /* !COMSTL_INCL_COMSTL_UTIL_HPP_CREATION_FUNCTIONS */
  284. /* ///////////////////////////// end of file //////////////////////////// */