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.

365 lines
12 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: winstl/registry/util/shared_handles.hpp
  3. *
  4. * Purpose: Contains the shared_handle and monitored_shared_handle classes.
  5. *
  6. * Created: 19th January 2002
  7. * Updated: 10th August 2009
  8. *
  9. * Thanks: To Austin Ziegler for fixes to defects evident on x64.
  10. *
  11. * Home: http://stlsoft.org/
  12. *
  13. * Copyright (c) 2002-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 winstl/registry/util/shared_handles.hpp
  42. *
  43. *\brief [C++ only] [IMPLEMENTATION] Contains the
  44. * \link winstl::registry_util::shared_handle shared_handle\endlink
  45. * and
  46. * \link winstl::registry_util::monitored_shared_handle monitored_shared_handle\endlink
  47. * classes that are used to provide shared context between iterators implement
  48. * the \ref group__pattern__externally_invalidatable_iterator "Externally Invalidatable Iterator"
  49. * pattern
  50. * (\ref group__library__windows_registry "Windows Registry" Library).
  51. */
  52. #ifndef WINSTL_INCL_WINSTL_REGISTRY_UTIL_HPP_SHARED_HANDLES
  53. #define WINSTL_INCL_WINSTL_REGISTRY_UTIL_HPP_SHARED_HANDLES
  54. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  55. # define WINSTL_VER_WINSTL_REGISTRY_UTIL_HPP_SHARED_HANDLES_MAJOR 2
  56. # define WINSTL_VER_WINSTL_REGISTRY_UTIL_HPP_SHARED_HANDLES_MINOR 0
  57. # define WINSTL_VER_WINSTL_REGISTRY_UTIL_HPP_SHARED_HANDLES_REVISION 5
  58. # define WINSTL_VER_WINSTL_REGISTRY_UTIL_HPP_SHARED_HANDLES_EDIT 29
  59. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  60. /* /////////////////////////////////////////////////////////////////////////
  61. * Includes
  62. */
  63. #ifndef WINSTL_INCL_WINSTL_H_WINSTL
  64. # include <winstl/winstl.h>
  65. #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
  66. #ifndef WINSTL_INCL_WINSTL_REGISTRY_HPP_REGFWD
  67. # include <winstl/registry/regfwd.hpp>
  68. #endif /* !WINSTL_INCL_WINSTL_REGISTRY_HPP_REGFWD */
  69. #ifndef WINSTL_INCL_WINSTL_REGISTRY_UTIL_HPP_DEFS
  70. # include <winstl/registry/util/defs.hpp>
  71. #endif /* !WINSTL_INCL_WINSTL_REGISTRY_UTIL_HPP_DEFS */
  72. #ifndef WINSTL_INCL_WINSTL_REGISTRY_HPP_REG_TRAITS
  73. # include <winstl/registry/reg_traits.hpp>
  74. #endif /* !WINSTL_INCL_WINSTL_REGISTRY_HPP_REG_TRAITS */
  75. #ifndef WINSTL_INCL_WINSTL_REGISTRY_HPP_REG_KEY
  76. # include <winstl/registry/reg_key.hpp>
  77. #endif /* !WINSTL_INCL_WINSTL_REGISTRY_HPP_REG_KEY */
  78. #ifndef WINSTL_INCL_SYNCH_WINSTL_HPP_EVENT
  79. # include <winstl/synch/event.hpp>
  80. #endif /* !WINSTL_INCL_SYNCH_WINSTL_HPP_EVENT */
  81. #if !defined(STLSOFT_COMPILER_IS_COMO) && \
  82. !defined(STLSOFT_COMPILER_IS_WATCOM)
  83. # ifndef WINSTL_INCL_WINSTL_DL_HPP_DL_CALL
  84. # include <winstl/dl/dl_call.hpp>
  85. # endif /* !WINSTL_INCL_WINSTL_DL_HPP_DL_CALL */
  86. #endif /* compiler */
  87. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  88. # ifndef STLSOFT_INCL_STLSOFT_ERROR_HPP_EXTERNAL_ITERATOR_INVALIDATION
  89. # include <stlsoft/error/external_iterator_invalidation.hpp>
  90. # endif /* !STLSOFT_INCL_STLSOFT_ERROR_HPP_EXTERNAL_ITERATOR_INVALIDATION */
  91. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  92. /* /////////////////////////////////////////////////////////////////////////
  93. * Namespace
  94. */
  95. #ifndef _WINSTL_NO_NAMESPACE
  96. # if defined(_STLSOFT_NO_NAMESPACE) || \
  97. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  98. /* There is no stlsoft namespace, so must define ::winstl */
  99. namespace winstl
  100. {
  101. # else
  102. /* Define stlsoft::winstl_project */
  103. namespace stlsoft
  104. {
  105. namespace winstl_project
  106. {
  107. # endif /* _STLSOFT_NO_NAMESPACE */
  108. #endif /* !_WINSTL_NO_NAMESPACE */
  109. /* /////////////////////////////////////////////////////////////////////////
  110. * Classes
  111. */
  112. #ifndef _STLSOFT_NO_NAMESPACES
  113. /** \brief Internal/implementation namespace containing shared handles.
  114. *
  115. * \ingroup group__library__windows_registry
  116. */
  117. namespace registry_util
  118. {
  119. #endif /* !_STLSOFT_NO_NAMESPACES */
  120. /// \brief [IMPLEMENTATION] Non-monitoring shared registry key context
  121. ///
  122. /// \ingroup group__library__windows_registry
  123. #ifdef _STLSOFT_NO_NAMESPACES
  124. struct registry_util::shared_handle
  125. #else /* ? _STLSOFT_NO_NAMESPACES */
  126. struct shared_handle
  127. #endif /* _STLSOFT_NO_NAMESPACES */
  128. {
  129. /// \name Member Types
  130. /// @{
  131. public:
  132. typedef shared_handle class_type;
  133. typedef HKEY handle_type;
  134. /// @}
  135. /// \name Members
  136. /// @{
  137. public:
  138. handle_type m_hkey;
  139. private:
  140. ss_sint32_t m_refCount;
  141. /// @}
  142. /// \name Construction
  143. /// @{
  144. public:
  145. ss_explicit_k shared_handle(handle_type hkey)
  146. : m_hkey(hkey)
  147. , m_refCount(1)
  148. {}
  149. protected:
  150. shared_handle(handle_type hkey, ss_sint32_t refCount)
  151. : m_hkey(hkey)
  152. , m_refCount(refCount)
  153. {}
  154. protected:
  155. virtual ~shared_handle() stlsoft_throw_0()
  156. {
  157. WINSTL_MESSAGE_ASSERT("Shared search handle being destroyed with outstanding references!", 0 == m_refCount);
  158. if(NULL != m_hkey)
  159. {
  160. ::RegCloseKey(m_hkey);
  161. }
  162. }
  163. /// @}
  164. /// \name Operations
  165. /// @{
  166. public:
  167. ss_sint32_t AddRef()
  168. {
  169. return ++m_refCount;
  170. }
  171. ss_sint32_t Release()
  172. {
  173. ss_sint32_t rc = --m_refCount;
  174. if(0 == rc)
  175. {
  176. delete this;
  177. }
  178. return rc;
  179. }
  180. virtual void test_reset_and_throw()
  181. {}
  182. /// @}
  183. /// \name Not to be implemented
  184. /// @{
  185. private:
  186. shared_handle(class_type const&);
  187. class_type& operator =(class_type const&);
  188. /// @}
  189. };
  190. #if defined(STLSOFT_CF_EXCEPTION_SUPPORT) && \
  191. !defined(STLSOFT_COMPILER_IS_COMO) && \
  192. !defined(STLSOFT_COMPILER_IS_WATCOM)
  193. /// \brief [IMPLEMENTATION] Monitoring shared registry key context
  194. ///
  195. /// \ingroup group__library__windows_registry
  196. ///
  197. /// \note This class is not defined in compilation modes that do not
  198. /// support exception throwing/handling.
  199. struct monitored_shared_handle
  200. : public shared_handle
  201. {
  202. public:
  203. typedef shared_handle parent_class_type;
  204. typedef monitored_shared_handle class_type;
  205. public:
  206. monitored_shared_handle(handle_type hkey, int eventType)
  207. : parent_class_type(hkey, 0)
  208. , m_eventType(eventType)
  209. , m_monitor(true, false)
  210. {
  211. set();
  212. AddRef();
  213. }
  214. /// \name Operations
  215. /// @{
  216. private:
  217. virtual void test_reset_and_throw()
  218. {
  219. // 1. Test, . . .
  220. if(WAIT_OBJECT_0 == ::WaitForSingleObject(m_monitor.handle(), 0))
  221. {
  222. // Must set to watch again here, because several iterators from the same
  223. // same reg_key_sequence could be open simultaneously
  224. // 2. Reset, . . .
  225. set();
  226. // 3. . . . and Throw
  227. STLSOFT_THROW_X(stlsoft_ns_qual(external_iterator_invalidation)("registry contents changed"));
  228. }
  229. }
  230. private:
  231. void set()
  232. {
  233. try
  234. {
  235. dl_call<LONG>( "ADVAPI32.DLL"
  236. #if defined(WINSTL_OS_IS_WIN64)
  237. , "C:RegNotifyChangeKeyValue"
  238. #elif defined(WINSTL_OS_IS_WIN32)
  239. , "S:RegNotifyChangeKeyValue"
  240. #else /* ? WIN?? */
  241. # error Windows operating system not recognised
  242. #endif /* WIN?? */
  243. , m_hkey
  244. , false
  245. , (int)m_eventType
  246. , m_monitor.handle()
  247. , true);
  248. }
  249. catch(missing_entry_point_exception &)
  250. {
  251. if( 0 != (::GetVersion() & 0x80000000) &&
  252. LOBYTE(LOWORD(GetVersion())) == 4 &&
  253. HIBYTE(LOWORD(GetVersion())) < 10)
  254. {
  255. // If it's Windows 95, which doesn't support this function, we need to
  256. // quench it, and simply not do any external iterator invalidation
  257. // checking
  258. ;
  259. }
  260. else
  261. {
  262. throw;
  263. }
  264. }
  265. }
  266. /// @}
  267. /// \name Members
  268. /// @{
  269. private:
  270. const int m_eventType;
  271. event m_monitor; // The event that will monitor changes to the API.
  272. /// @}
  273. /// \name Not to be implemented
  274. /// @{
  275. private:
  276. monitored_shared_handle(class_type const&);
  277. class_type& operator =(class_type const&);
  278. /// @}
  279. };
  280. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  281. /// \brief [IMPLEMENTATION] Simple factory function for creating an appropriate shared handle
  282. ///
  283. /// \ingroup group__library__windows_registry
  284. ///
  285. /// Used by basic_reg_key_sequence and basic_reg_value_sequence.
  286. ///
  287. /// \param hkey The registry key handle to be owned
  288. /// \param bMonitorExternalInvalidation If non-zero, the given \c eventType event is monitored.
  289. /// \param eventType The type of the event to monitor. One of REG_NOTIFY_CHANGE_NAME or REG_NOTIFY_CHANGE_LAST_SET
  290. ///
  291. /// \note The <code>bMonitorExternalInvalidation</code> and
  292. /// <code>eventType</code> parameters are ignored in compilation
  293. /// modes that do not support exception throwing/handling.
  294. static shared_handle *create_shared_handle(HKEY hkey, ws_bool_t bMonitorExternalInvalidation, int eventType)
  295. {
  296. #if defined(STLSOFT_CF_EXCEPTION_SUPPORT) && \
  297. !defined(STLSOFT_COMPILER_IS_COMO) && \
  298. !defined(STLSOFT_COMPILER_IS_WATCOM)
  299. if(bMonitorExternalInvalidation)
  300. {
  301. return new monitored_shared_handle(hkey, eventType);
  302. }
  303. else
  304. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  305. STLSOFT_SUPPRESS_UNUSED(bMonitorExternalInvalidation);
  306. STLSOFT_SUPPRESS_UNUSED(eventType);
  307. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  308. {
  309. return new shared_handle(hkey);
  310. }
  311. }
  312. #ifndef _STLSOFT_NO_NAMESPACES
  313. } // namespace registry_util
  314. #endif /* !_STLSOFT_NO_NAMESPACES */
  315. /* ////////////////////////////////////////////////////////////////////// */
  316. #ifndef _WINSTL_NO_NAMESPACE
  317. # if defined(_STLSOFT_NO_NAMESPACE) || \
  318. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  319. } // namespace winstl
  320. # else
  321. } // namespace winstl_project
  322. } // namespace stlsoft
  323. # endif /* _STLSOFT_NO_NAMESPACE */
  324. #endif /* !_WINSTL_NO_NAMESPACE */
  325. /* ////////////////////////////////////////////////////////////////////// */
  326. #endif /* WINSTL_INCL_WINSTL_REGISTRY_UTIL_HPP_SHARED_HANDLES */
  327. /* ///////////////////////////// end of file //////////////////////////// */