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.

381 lines
13 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: winstl/system/process_module_sequence.hpp
  3. *
  4. * Purpose: Process Id sequence class.
  5. *
  6. * Created: 24th June 2005
  7. * Updated: 10th August 2009
  8. *
  9. * Thanks to: Adi Shavit for spotting a small inefficiency in the
  10. * resize()-ing, during the review of Extended STL volume 1
  11. * (see http://extendedstl.com/).
  12. *
  13. * Home: http://stlsoft.org/
  14. *
  15. * Copyright (c) 2005-2009, 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 winstl/system/process_module_sequence.hpp
  44. *
  45. * \brief [C++ only] Definition of the winstl::process_module_sequence
  46. * class
  47. * (\ref group__library__system "System" Library).
  48. */
  49. #ifndef WINSTL_INCL_WINSTL_SYSTEM_HPP_PROCESS_MODULE_SEQUENCE
  50. #define WINSTL_INCL_WINSTL_SYSTEM_HPP_PROCESS_MODULE_SEQUENCE
  51. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  52. # define WINSTL_VER_WINSTL_SYSTEM_HPP_PROCESS_MODULE_SEQUENCE_MAJOR 2
  53. # define WINSTL_VER_WINSTL_SYSTEM_HPP_PROCESS_MODULE_SEQUENCE_MINOR 2
  54. # define WINSTL_VER_WINSTL_SYSTEM_HPP_PROCESS_MODULE_SEQUENCE_REVISION 2
  55. # define WINSTL_VER_WINSTL_SYSTEM_HPP_PROCESS_MODULE_SEQUENCE_EDIT 48
  56. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  57. /* /////////////////////////////////////////////////////////////////////////
  58. * Compatibility
  59. */
  60. /*
  61. [Incompatibilies-start]
  62. STLSOFT_COMPILER_IS_COMO:
  63. [Incompatibilies-end]
  64. */
  65. /* /////////////////////////////////////////////////////////////////////////
  66. * Includes
  67. */
  68. #ifndef WINSTL_INCL_WINSTL_H_WINSTL
  69. # include <winstl/winstl.h>
  70. #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
  71. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  72. # ifndef WINSTL_INCL_WINSTL_ERROR_HPP_WINDOWS_EXCEPTIONS
  73. # include <winstl/error/exceptions.hpp>
  74. # endif /* !WINSTL_INCL_WINSTL_ERROR_HPP_WINDOWS_EXCEPTIONS */
  75. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  76. #ifndef WINSTL_INCL_WINSTL_MEMORY_HPP_PROCESSHEAP_ALLOCATOR
  77. # include <winstl/memory/processheap_allocator.hpp>
  78. #endif /* !WINSTL_INCL_WINSTL_MEMORY_HPP_PROCESSHEAP_ALLOCATOR */
  79. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER
  80. # include <stlsoft/memory/auto_buffer.hpp>
  81. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER */
  82. #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS
  83. # include <stlsoft/collections/util/collections.hpp>
  84. #endif /* !STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS */
  85. #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER
  86. # include <stlsoft/util/std/iterator_helper.hpp>
  87. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER */
  88. #if !defined(_PSAPI_H_) && \
  89. !defined(_PSAPI_H)
  90. # ifndef WINSTL_INCL_WINSTL_DL_HPP_DL_CALL
  91. # include <winstl/dl/dl_call.hpp>
  92. # endif /* !WINSTL_INCL_WINSTL_DL_HPP_DL_CALL */
  93. #endif /* psapi */
  94. #if !defined(STLSOFT_UNITTEST)
  95. # include <algorithm>
  96. #endif /* !STLSOFT_UNITTEST */
  97. /* /////////////////////////////////////////////////////////////////////////
  98. * Namespace
  99. */
  100. #ifndef _WINSTL_NO_NAMESPACE
  101. # if defined(_STLSOFT_NO_NAMESPACE) || \
  102. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  103. /* There is no stlsoft namespace, so must define ::winstl */
  104. namespace winstl
  105. {
  106. # else
  107. /* Define stlsoft::winstl_project */
  108. namespace stlsoft
  109. {
  110. namespace winstl_project
  111. {
  112. # endif /* _STLSOFT_NO_NAMESPACE */
  113. #endif /* !_WINSTL_NO_NAMESPACE */
  114. /* /////////////////////////////////////////////////////////////////////////
  115. * Classes
  116. */
  117. /** \brief Process module (constituent DLLs) sequence
  118. *
  119. * \ingroup group__library__system
  120. */
  121. class process_module_sequence
  122. : public stlsoft_ns_qual(stl_collection_tag)
  123. {
  124. /// \name Member Types
  125. /// @{
  126. public:
  127. /// The value type
  128. typedef HMODULE value_type;
  129. /// The allocator type
  130. typedef processheap_allocator<value_type> allocator_type;
  131. /// The class type
  132. typedef process_module_sequence class_type;
  133. /// The non-mutating (const) pointer type
  134. typedef value_type const* const_pointer;
  135. /// The non-mutating (const) reference type
  136. typedef value_type const& const_reference;
  137. /// The non-mutating (const) iterator type
  138. typedef stlsoft_ns_qual(pointer_iterator)< value_type
  139. , const_pointer
  140. , const_reference
  141. >::type const_iterator;
  142. /// The size type
  143. typedef ws_size_t size_type;
  144. /// The difference type
  145. typedef ws_ptrdiff_t difference_type;
  146. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  147. /// The non-mutating (const) reverse iterator type
  148. typedef stlsoft_ns_qual(const_reverse_bidirectional_iterator_base)< const_iterator
  149. , value_type
  150. , const_reference
  151. , const_pointer
  152. , difference_type
  153. > const_reverse_iterator;
  154. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  155. /// @}
  156. /// \name Construction
  157. /// @{
  158. public:
  159. /// Constructs a sequence from the current modules in the given process
  160. ss_explicit_k process_module_sequence(HANDLE hProcess);
  161. /// Copies the contents of the sequence
  162. process_module_sequence(class_type const& rhs);
  163. /// Releases the storage associated with the process id list
  164. ~process_module_sequence() stlsoft_throw_0();
  165. /// @}
  166. /// \name Iteration
  167. /// @{
  168. public:
  169. /// Begins the iteration
  170. ///
  171. /// \return An iterator representing the start of the sequence
  172. const_iterator begin() const;
  173. /// Ends the iteration
  174. ///
  175. /// \return An iterator representing the end of the sequence
  176. const_iterator end() const;
  177. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  178. /// Begins the reverse iteration
  179. ///
  180. /// \return An iterator representing the start of the reverse sequence
  181. const_reverse_iterator rbegin() const;
  182. /// Ends the reverse iteration
  183. ///
  184. /// \return An iterator representing the end of the reverse sequence
  185. const_reverse_iterator rend() const;
  186. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  187. /// @}
  188. /// \name Element Access
  189. /// @{
  190. public:
  191. /// Returns a reference to the element at the given index
  192. ///
  193. /// \param index The required index. Behaviour is undefined, if not within the range [0, size())
  194. const_reference operator [](size_type index) const;
  195. /// @}
  196. /// \name Attributes
  197. /// @{
  198. public:
  199. /// Indicates whether the sequence is empty
  200. ws_bool_t empty() const;
  201. /// Returns the number of identifiers in the sequence
  202. size_type size() const;
  203. /// @}
  204. /// \name Members
  205. /// @{
  206. private:
  207. typedef stlsoft_ns_qual(auto_buffer_old)< value_type
  208. , allocator_type
  209. , 64
  210. > buffer_type_;
  211. buffer_type_ m_modules;
  212. /// @}
  213. /// \name Not to be implemented
  214. /// @{
  215. private:
  216. class_type& operator =(class_type const&);
  217. /// @}
  218. };
  219. ////////////////////////////////////////////////////////////////////////////
  220. // Unit-testing
  221. #ifdef STLSOFT_UNITTEST
  222. # include "./unittest/process_module_sequence_unittest_.h"
  223. #endif /* STLSOFT_UNITTEST */
  224. /* /////////////////////////////////////////////////////////////////////////
  225. * Implementation
  226. */
  227. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  228. inline process_module_sequence::process_module_sequence(HANDLE hProcess)
  229. : m_modules(buffer_type_::internal_size())
  230. {
  231. DWORD cbReturned;
  232. for(;;)
  233. {
  234. #if defined(_PSAPI_H_) || \
  235. defined(_PSAPI_H)
  236. if(!::EnumProcessModules(hProcess, &m_modules[0], sizeof(value_type) * m_modules.size(), &cbReturned))
  237. #else /* ? psapi */
  238. if(!dl_call<BOOL>( "PSAPI.DLL"
  239. , WINSTL_DL_CALL_WINx_STDCALL_LITERAL("EnumProcessModules")
  240. , hProcess
  241. , &m_modules[0]
  242. , sizeof(value_type) * m_modules.size()
  243. , &cbReturned))
  244. #endif /* psapi */
  245. {
  246. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  247. STLSOFT_THROW_X(windows_exception("Failed to enumerate processes", ::GetLastError()));
  248. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  249. m_modules.resize(0);
  250. break;
  251. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  252. }
  253. else
  254. {
  255. const ws_size_t n = cbReturned / sizeof(value_type);
  256. if(n < m_modules.size())
  257. {
  258. m_modules.resize(n);
  259. break;
  260. }
  261. else
  262. {
  263. const size_type size = m_modules.size();
  264. m_modules.resize(1); // Read "Extended STL, volume 1" to find out what this is for
  265. if(!m_modules.resize(2 * size))
  266. {
  267. // This will only ever be executed when compiled in the
  268. // absence of throwing bad_alloc on memory exhaustion
  269. m_modules.resize(0);
  270. break;
  271. }
  272. }
  273. }
  274. }
  275. }
  276. inline process_module_sequence::process_module_sequence(process_module_sequence const& rhs)
  277. : m_modules(rhs.m_modules.size())
  278. {
  279. stlsoft_ns_qual_std(copy)(rhs.m_modules.begin(), rhs.m_modules.end(), m_modules.begin());
  280. }
  281. inline process_module_sequence::~process_module_sequence() stlsoft_throw_0()
  282. {}
  283. inline process_module_sequence::const_iterator process_module_sequence::begin() const
  284. {
  285. return &*m_modules.begin();
  286. }
  287. inline process_module_sequence::const_iterator process_module_sequence::end() const
  288. {
  289. return &*m_modules.end();
  290. }
  291. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  292. inline process_module_sequence::const_reverse_iterator process_module_sequence::rbegin() const
  293. {
  294. return const_reverse_iterator(end());
  295. }
  296. inline process_module_sequence::const_reverse_iterator process_module_sequence::rend() const
  297. {
  298. return const_reverse_iterator(begin());
  299. }
  300. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  301. inline process_module_sequence::const_reference process_module_sequence::operator [](process_module_sequence::size_type index) const
  302. {
  303. WINSTL_MESSAGE_ASSERT("Index out of range", index < size());
  304. return m_modules[index];
  305. }
  306. inline ws_bool_t process_module_sequence::empty() const
  307. {
  308. return m_modules.empty();
  309. }
  310. inline process_module_sequence::size_type process_module_sequence::size() const
  311. {
  312. return m_modules.size();
  313. }
  314. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  315. /* /////////////////////////////////////////////////////////////////////////
  316. * Namespace
  317. */
  318. #ifndef _WINSTL_NO_NAMESPACE
  319. # if defined(_STLSOFT_NO_NAMESPACE) || \
  320. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  321. } // namespace winstl
  322. # else
  323. } // namespace winstl_project
  324. } // namespace stlsoft
  325. # endif /* _STLSOFT_NO_NAMESPACE */
  326. #endif /* !_WINSTL_NO_NAMESPACE */
  327. /* ////////////////////////////////////////////////////////////////////// */
  328. #endif /* !WINSTL_INCL_WINSTL_SYSTEM_HPP_PROCESS_MODULE_SEQUENCE */
  329. /* ///////////////////////////// end of file //////////////////////////// */