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.

393 lines
12 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: winstl/toolhelp/sequence_base.hpp
  3. *
  4. * Purpose: TOOLHELP sequence_base class template.
  5. *
  6. * Created: 21st May 2005
  7. * Updated: 10th August 2009
  8. *
  9. * Thanks: To Pablo for contributing this great library.
  10. *
  11. * Home: http://stlsoft.org/
  12. *
  13. * Copyright (c) 2005-2009, Pablo Aguilar
  14. * Copyright (c) 2006-2007, Matthew Wilson
  15. * All rights reserved.
  16. *
  17. * Redistribution and use in source and binary forms, with or without
  18. * modification, are permitted provided that the following conditions are met:
  19. *
  20. * - Redistributions of source code must retain the above copyright notice, this
  21. * list of conditions and the following disclaimer.
  22. * - Redistributions in binary form must reproduce the above copyright notice,
  23. * this list of conditions and the following disclaimer in the documentation
  24. * and/or other materials provided with the distribution.
  25. * - Neither the name(s) of Matthew Wilson and Synesis Software, nor Pablo
  26. * Aguilar, nor the names of any contributors may be used to endorse or
  27. * promote products derived from this software without specific prior written
  28. * 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 winstl/toolhelp/sequence_base.hpp
  44. *
  45. * \brief [C++ only] Definition of the
  46. * \link winstl::th_sequence_base th_sequence_base\endlink class
  47. * (\ref group__library__windows_toolhelp "Windows ToolHelp" Library).
  48. */
  49. #ifndef WINSTL_INCL_WINSTL_TOOLHELP_HPP_SEQUENCE_BASE
  50. #define WINSTL_INCL_WINSTL_TOOLHELP_HPP_SEQUENCE_BASE
  51. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  52. # define WINSTL_VER_WINSTL_TOOLHELP_HPP_SEQUENCE_BASE_MAJOR 1
  53. # define WINSTL_VER_WINSTL_TOOLHELP_HPP_SEQUENCE_BASE_MINOR 1
  54. # define WINSTL_VER_WINSTL_TOOLHELP_HPP_SEQUENCE_BASE_REVISION 4
  55. # define WINSTL_VER_WINSTL_TOOLHELP_HPP_SEQUENCE_BASE_EDIT 14
  56. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  57. /* /////////////////////////////////////////////////////////////////////////
  58. * Includes
  59. */
  60. #ifndef WINSTL_INCL_WINSTL_H_WINSTL
  61. # include <winstl/winstl.h>
  62. #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
  63. #ifdef STLSOFT_CF_PRAGMA_ONCE_SUPPORT
  64. # pragma once
  65. #endif /* STLSOFT_CF_PRAGMA_ONCE_SUPPORT */
  66. #ifndef WINSTL_INCL_WINSTL_TOOLHELP_ERROR_HPP_SEQUENCE_EXCEPTION
  67. # include <winstl/toolhelp/error/exceptions.hpp>
  68. #endif /* !WINSTL_INCL_WINSTL_TOOLHELP_ERROR_HPP_SEQUENCE_EXCEPTION */
  69. #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER
  70. # include <stlsoft/util/std/iterator_helper.hpp>
  71. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER */
  72. #ifndef STLSOFT_INCL_H_TLHELP32
  73. # define STLSOFT_INCL_H_TLHELP32
  74. # include <tlhelp32.h>
  75. #endif /* !STLSOFT_INCL_H_TLHELP32 */
  76. /* /////////////////////////////////////////////////////////////////////////
  77. * Namespace
  78. */
  79. #ifndef _WINSTL_NO_NAMESPACE
  80. # if defined(_STLSOFT_NO_NAMESPACE) || \
  81. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  82. /* There is no stlsoft namespace, so must define ::winstl */
  83. namespace winstl
  84. {
  85. # else
  86. /* Define stlsoft::winstl_project */
  87. namespace stlsoft
  88. {
  89. namespace winstl_project
  90. {
  91. # endif /* _STLSOFT_NO_NAMESPACE */
  92. #endif /* !_WINSTL_NO_NAMESPACE */
  93. /* /////////////////////////////////////////////////////////////////////////
  94. * Classes
  95. */
  96. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  97. template<ss_typename_param_k V>
  98. struct th_sequence_value_traits;
  99. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  100. // NOTE: The following #defines could've been limited to 2, lower & upper
  101. // case only. But the heap list API specifies the first/next
  102. // functions as Heap32ListX, which is inconsistent with the
  103. // other 3 styles
  104. //
  105. // Each #define is #undef'd within the included file
  106. //
  107. // Example for module_sequence:
  108. // #define WINSTL_TH_API_SEQUENCE_VALUE_TRAITS_VALUE MODULEENTRY32
  109. // #define WINSTL_TH_API_SEQUENCE_VALUE_TRAITS_FIRST Module32First
  110. // #define WINSTL_TH_API_SEQUENCE_VALUE_TRAITS_NEXT Module32Next
  111. // #define WINSTL_TH_API_SEQUENCE_VALUE_TRAITS_FLAG TH32CS_SNAPMODULE
  112. // #define WINSTL_TH_API_SEQUENCE_VALUE_TRAITS_USE_PID
  113. /** \brief Iterator class for the th_sequence_base class template and its specialisations.
  114. *
  115. * \ingroup group__library__windows_toolhelp
  116. */
  117. template<ss_typename_param_k V>
  118. class th_sequence_const_iterator
  119. : public stlsoft_ns_qual(iterator_base)<winstl_ns_qual_std(input_iterator_tag)
  120. , V
  121. , ws_ptrdiff_t
  122. , V const*
  123. , V const&
  124. >
  125. {
  126. /// \name Member Types
  127. /// @{
  128. public:
  129. typedef th_sequence_const_iterator<V> class_type;
  130. typedef V value_type;
  131. typedef value_type const& const_reference;
  132. typedef HANDLE handle_type;
  133. typedef th_sequence_value_traits<value_type> traits_type;
  134. /// @}
  135. /// \name Construction
  136. /// @{
  137. public:
  138. /// \brief Constructs an instance based on a null instance of the requisite handle type.
  139. th_sequence_const_iterator()
  140. : m_snapshot(traits_type::null_handle())
  141. {
  142. // Do nothing
  143. }
  144. /// \brief Constructs an instance based on a snapshot handle.
  145. th_sequence_const_iterator(handle_type snapshot)
  146. : m_snapshot(snapshot)
  147. {
  148. WINSTL_ASSERT(m_snapshot != traits_type::invalid_handle());
  149. ::memset(&m_value, 0, sizeof(m_value));
  150. m_value.dwSize = sizeof(m_value);
  151. bool ok = traits_type::first(m_snapshot, m_value);
  152. if( !ok )
  153. {
  154. m_snapshot = traits_type::null_handle();
  155. }
  156. }
  157. /// \brief Copy constructor
  158. th_sequence_const_iterator(class_type const& rhs)
  159. : m_snapshot(rhs.m_snapshot)
  160. , m_value (rhs.m_value)
  161. {
  162. WINSTL_ASSERT(m_snapshot != traits_type::invalid_handle());
  163. }
  164. // NOTE: Default destructor is good enough
  165. // NOTE: Default copy assignment operator is good enough
  166. /// @}
  167. /// \name Forward Iterator methods
  168. /// @{
  169. public:
  170. const_reference operator *() const
  171. {
  172. return m_value;
  173. }
  174. class_type& operator ++()
  175. {
  176. bool ok = traits_type::next(m_snapshot, m_value);
  177. if( !ok )
  178. m_snapshot = traits_type::null_handle();
  179. return *this;
  180. }
  181. class_type operator ++(int)
  182. {
  183. class_type rhs(*this);
  184. ++*this;
  185. return rhs;
  186. }
  187. bool equal(class_type const& rhs) const
  188. {
  189. WINSTL_MESSAGE_ASSERT("Attempting to compare two non-endpoint iterators from different ranges", (NULL == m_snapshot || NULL == rhs.m_snapshot || m_snapshot == rhs.m_snapshot));
  190. return m_snapshot == rhs.m_snapshot;
  191. }
  192. bool operator ==(class_type const& rhs) const
  193. {
  194. return equal(rhs);
  195. }
  196. bool operator !=(class_type const& rhs) const
  197. {
  198. return !equal(rhs);
  199. }
  200. /// @}
  201. /// \name Members
  202. /// @{
  203. private:
  204. handle_type m_snapshot;
  205. value_type m_value;
  206. /// @}
  207. };
  208. /** \brief [IMPLEMENTATION] A utility class template that is used to
  209. * to block the non-default constructor for specialisations of
  210. * th_sequence_base that do not require the process Id.
  211. * \ingroup group__library__windows_toolhelp
  212. */
  213. template<typename V>
  214. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  215. struct sequence_doesnt_use_pid;
  216. #else /* ? STLSOFT_DOCUMENTATION_SKIP_SECTION */
  217. struct sequence_doesnt_use_pid {};
  218. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  219. /** \brief Class template for TOOLHELP STL collections.
  220. *
  221. * \ingroup group__library__windows_toolhelp
  222. */
  223. template< ss_typename_param_k V
  224. , ss_typename_param_k E = throw_exception_policy<toolhelp_exception>
  225. >
  226. class th_sequence_base
  227. {
  228. /// \name Member Types
  229. /// @{
  230. public:
  231. /// \brief The size type.
  232. typedef th_sequence_base<V> class_type;
  233. /// \brief The non-mutating (const) iterator type.
  234. typedef th_sequence_const_iterator<V> const_iterator;
  235. /// \brief The value type.
  236. typedef ss_typename_type_k const_iterator::value_type value_type;
  237. /// \brief The mutating (non-const) reference type.
  238. typedef ss_typename_type_k const_iterator::reference reference;
  239. /// \brief The non-mutating (const) type.
  240. typedef ss_typename_type_k const_iterator::const_reference const_reference;
  241. /// \brief The handle type.
  242. typedef ss_typename_type_k const_iterator::handle_type handle_type;
  243. /// \brief The traits type.
  244. typedef ss_typename_type_k const_iterator::traits_type traits_type;
  245. /// \brief The exception policy type.
  246. typedef E exception_policy;
  247. /// \brief The size type.
  248. typedef ws_size_t size_type;
  249. /// @}
  250. /// \name Construction
  251. /// @{
  252. public:
  253. /// \brief Constructs an instance on a TOOLHELP snapshot for the calling process.
  254. th_sequence_base()
  255. : m_snapshot(::CreateToolhelp32Snapshot(
  256. traits_type::flag()
  257. , 0
  258. ))
  259. {
  260. verify_construction();
  261. }
  262. /// \brief Constructs an instance on a TOOLHELP snapshot for the specified process.
  263. #if !defined(STLSOFT_COMPILER_IS_MSVC) || \
  264. _MSC_VER > 1200
  265. th_sequence_base(DWORD process_id, DWORD = sizeof(sequence_doesnt_use_pid<value_type>))
  266. #else /* ? compiler */
  267. th_sequence_base(DWORD process_id)
  268. #endif /* compiler */
  269. : m_snapshot(::CreateToolhelp32Snapshot(
  270. traits_type::flag()
  271. , process_id
  272. ))
  273. {
  274. verify_construction();
  275. }
  276. /// \brief Destructor
  277. ~th_sequence_base()
  278. {
  279. if(traits_type::invalid_handle() != m_snapshot)
  280. {
  281. ::CloseHandle(m_snapshot);
  282. }
  283. }
  284. /// @}
  285. /// \name Iteration
  286. /// @{
  287. public:
  288. /// \brief Begins the iteration.
  289. ///
  290. /// \return An iterator representing the start of the sequence.
  291. const_iterator begin() const
  292. {
  293. return const_iterator(m_snapshot);
  294. }
  295. /// \brief Ends the iteration.
  296. ///
  297. /// \return An iterator representing the end of the sequence.
  298. const_iterator end() const
  299. {
  300. return const_iterator();
  301. }
  302. /// @}
  303. /// \name Attributes
  304. /// @{
  305. public:
  306. /// \brief Indicates whether the sequence is empty.
  307. bool empty() const
  308. {
  309. // NOTE: Not necessarily efficient
  310. // First answer could be cached
  311. // This is also provided just as a convenience
  312. return (begin() == end());
  313. }
  314. /// @}
  315. /// \name Members
  316. /// @{
  317. private:
  318. handle_type m_snapshot;
  319. /// @}
  320. /// \name Not to be implemented
  321. /// @{
  322. private:
  323. th_sequence_base(class_type const&);
  324. class_type& operator =(class_type const&);
  325. /// @}
  326. void verify_construction()
  327. {
  328. if(traits_type::invalid_handle() == m_snapshot)
  329. {
  330. exception_policy xp;
  331. DWORD dwErr = ::GetLastError();
  332. xp(traits_type::create_snapshot_fail_message(), dwErr);
  333. }
  334. }
  335. };
  336. /* ////////////////////////////////////////////////////////////////////// */
  337. #ifndef _WINSTL_NO_NAMESPACE
  338. # if defined(_STLSOFT_NO_NAMESPACE) || \
  339. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  340. } // namespace winstl
  341. # else
  342. } // namespace winstl_project
  343. } // namespace stlsoft
  344. # endif /* _STLSOFT_NO_NAMESPACE */
  345. #endif /* !_WINSTL_NO_NAMESPACE */
  346. /* ////////////////////////////////////////////////////////////////////// */
  347. #endif /* WINSTL_INCL_WINSTL_TOOLHELP_HPP_SEQUENCE_BASE */
  348. /* ///////////////////////////// end of file //////////////////////////// */