PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/FolderSizeWin32/FolderSizeWin32/win32.hpp

#
C++ Header | 556 lines | 397 code | 79 blank | 80 comment | 11 complexity | 46492d8b0f482e94bf80e08f469c7fbb MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Mĺrten Rĺnge.
  4. *
  5. * This source code is subject to terms and conditions of the Microsoft Public License. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Microsoft Public License, please send an email to
  8. * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Microsoft Public License.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. *
  14. * ***************************************************************************/
  15. // ----------------------------------------------------------------------------
  16. #pragma once
  17. // ----------------------------------------------------------------------------
  18. #include <windows.h>
  19. // ----------------------------------------------------------------------------
  20. #include <functional>
  21. #include <memory>
  22. #include <string>
  23. #include <type_traits>
  24. // ----------------------------------------------------------------------------
  25. #include <boost/noncopyable.hpp>
  26. #include <boost/optional.hpp>
  27. // ----------------------------------------------------------------------------
  28. #include "utility.hpp"
  29. // ----------------------------------------------------------------------------
  30. #define WIN32_INLINE inline
  31. // ----------------------------------------------------------------------------
  32. namespace win32
  33. {
  34. // -------------------------------------------------------------------------
  35. // -------------------------------------------------------------------------
  36. typedef std::basic_string<TCHAR> tstring;
  37. // -------------------------------------------------------------------------
  38. // -------------------------------------------------------------------------
  39. extern bool const windows7_or_later ;
  40. // -------------------------------------------------------------------------
  41. // -------------------------------------------------------------------------
  42. template<typename TValueType>
  43. TValueType const get_windows7_dependent_value (
  44. TValueType const & windows7_value
  45. , TValueType const & legacy_value
  46. )
  47. {
  48. if (windows7_or_later)
  49. {
  50. return windows7_value;
  51. }
  52. else
  53. {
  54. return legacy_value;
  55. }
  56. }
  57. // -------------------------------------------------------------------------
  58. // -------------------------------------------------------------------------
  59. void trace_string (tstring const & value);
  60. void trace_string (LPCTSTR const value);
  61. void debug_string (tstring const & value);
  62. void debug_string (LPCTSTR const value);
  63. #define WIN32_PRELUDE _T (__FUNCTION__) _T (" : ")
  64. #ifdef _DEBUG
  65. # define WIN32_DEBUG_STRING(expr) (::win32::debug_string (expr))
  66. #else
  67. # define WIN32_DEBUG_STRING(expr)
  68. #endif
  69. // -------------------------------------------------------------------------
  70. // -------------------------------------------------------------------------
  71. typedef unsigned __int64 file_time ;
  72. file_time const ticks_per_day = 24 * 60 * 60 * (1000000000ui64 / 100ui64);
  73. // -------------------------------------------------------------------------
  74. file_time const to_file_time (FILETIME const ft) throw ();
  75. FILETIME const get_current_time () throw ();
  76. // -------------------------------------------------------------------------
  77. // -------------------------------------------------------------------------
  78. tstring const get_window_text (HWND const hwnd);
  79. // -------------------------------------------------------------------------
  80. // -------------------------------------------------------------------------
  81. struct handle : boost::noncopyable
  82. {
  83. explicit handle (HANDLE const hnd) throw ();
  84. handle (handle const &&);
  85. ~handle () throw ();
  86. bool const is_valid () const throw ();
  87. HANDLE const value;
  88. };
  89. // -------------------------------------------------------------------------
  90. // -------------------------------------------------------------------------
  91. struct dll : boost::noncopyable
  92. {
  93. explicit dll (LPCTSTR const dll_name) throw ();
  94. dll (const dll &&);
  95. ~dll () throw ();
  96. bool const is_valid () const throw ();
  97. HMODULE const value;
  98. };
  99. // -------------------------------------------------------------------------
  100. // -------------------------------------------------------------------------
  101. template<typename TFunctionPtr>
  102. struct function_pointer : boost::noncopyable
  103. {
  104. function_pointer (HMODULE module, LPCSTR const function_name)
  105. : value (reinterpret_cast<TFunctionPtr> (GetProcAddress (module, function_name)))
  106. {
  107. }
  108. function_pointer (function_pointer const &&);
  109. bool const is_valid () const throw ()
  110. {
  111. return value != nullptr;
  112. }
  113. TFunctionPtr const value;
  114. };
  115. // -------------------------------------------------------------------------
  116. // -------------------------------------------------------------------------
  117. struct thread : boost::noncopyable
  118. {
  119. typedef std::tr1::function<unsigned int ()> proc;
  120. thread (
  121. tstring const & thread_name
  122. , proc const del);
  123. thread (thread const &&);
  124. bool const join (unsigned int const ms) const throw ();
  125. bool const is_terminated () const throw ();
  126. private:
  127. static void raw_proc (void * ptr) throw ();
  128. tstring const thread_name;
  129. bool volatile terminated;
  130. public:
  131. proc const procedure;
  132. handle const value;
  133. };
  134. // -------------------------------------------------------------------------
  135. // -------------------------------------------------------------------------
  136. struct find_file : boost::noncopyable
  137. {
  138. explicit find_file (tstring const & path);
  139. find_file (find_file const &&);
  140. ~find_file () throw ();
  141. bool const is_valid () const throw ();
  142. bool const find_next () throw ();
  143. bool const is_directory () const throw ();
  144. big_size const get_size () const throw ();
  145. FILETIME const get_creation_time () const throw ();
  146. FILETIME const get_last_access_time () const throw ();
  147. FILETIME const find_file::get_last_write_time () const throw ();
  148. DWORD const get_reparse_point_tag () const throw ();
  149. DWORD const get_file_attributes () const throw ();
  150. LPCTSTR const get_name () const throw ();
  151. private:
  152. WIN32_FIND_DATA find_data;
  153. HANDLE const find_file_handle;
  154. };
  155. // -------------------------------------------------------------------------
  156. // -------------------------------------------------------------------------
  157. template<typename ValueType>
  158. struct thread_safe_scoped_ptr
  159. {
  160. explicit thread_safe_scoped_ptr (ValueType * const ptr = nullptr) throw ()
  161. : m_ptr (ptr)
  162. {
  163. }
  164. std::auto_ptr<ValueType> reset (ValueType * const ptr = nullptr) throw ()
  165. {
  166. auto pointer = m_ptr;
  167. while (
  168. pointer != InterlockedCompareExchangePointer (
  169. &m_ptr
  170. , ptr
  171. , pointer
  172. ))
  173. {
  174. pointer = m_ptr;
  175. }
  176. return std::auto_ptr<ValueType> (reinterpret_cast<ValueType*> (pointer));
  177. }
  178. private:
  179. void * volatile m_ptr;
  180. };
  181. // -------------------------------------------------------------------------
  182. // -------------------------------------------------------------------------
  183. namespace event_type
  184. {
  185. enum type
  186. {
  187. auto_reset ,
  188. manual_reset ,
  189. enum_count ,
  190. };
  191. }
  192. // -------------------------------------------------------------------------
  193. // -------------------------------------------------------------------------
  194. struct event : boost::noncopyable
  195. {
  196. explicit event (event_type::type const event_type);
  197. event (event const &&);
  198. void set () throw ();
  199. handle const value;
  200. };
  201. // -------------------------------------------------------------------------
  202. // -------------------------------------------------------------------------
  203. struct paint_device_context : boost::noncopyable
  204. {
  205. explicit paint_device_context (HWND const hwnd) throw ();
  206. paint_device_context (paint_device_context const &&);
  207. ~paint_device_context () throw ();
  208. PAINTSTRUCT const paint_struct ;
  209. HWND const hwnd ;
  210. HDC const hdc ;
  211. };
  212. // -------------------------------------------------------------------------
  213. // -------------------------------------------------------------------------
  214. struct window_device_context : boost::noncopyable
  215. {
  216. explicit window_device_context (HWND const hwnd) throw ();
  217. window_device_context (window_device_context const &&);
  218. ~window_device_context () throw ();
  219. HWND const hwnd;
  220. HDC const hdc;
  221. };
  222. // -------------------------------------------------------------------------
  223. // -------------------------------------------------------------------------
  224. struct device_context : boost::noncopyable
  225. {
  226. explicit device_context (HDC const dc) throw ();
  227. device_context (device_context const &&);
  228. ~device_context () throw ();
  229. HDC const value;
  230. };
  231. // -------------------------------------------------------------------------
  232. // -------------------------------------------------------------------------
  233. template<typename TGdiObject>
  234. struct gdi_object : boost::noncopyable
  235. {
  236. explicit gdi_object (TGdiObject const obj) throw ()
  237. : value (obj)
  238. {
  239. }
  240. gdi_object (gdi_object const &&);
  241. bool const is_valid () const throw ()
  242. {
  243. return value != nullptr;
  244. }
  245. ~gdi_object () throw ()
  246. {
  247. if (value)
  248. {
  249. auto deleted_result = DeleteObject (value);
  250. UNUSED_VARIABLE (deleted_result);
  251. }
  252. }
  253. TGdiObject const value;
  254. };
  255. // -------------------------------------------------------------------------
  256. // -------------------------------------------------------------------------
  257. struct select_object : boost::noncopyable
  258. {
  259. select_object (HDC const dc, HGDIOBJ obj) throw ();
  260. select_object (select_object const &&);
  261. ~select_object () throw ();
  262. HDC const dc ;
  263. HGDIOBJ const previously_selected_object ;
  264. };
  265. // -------------------------------------------------------------------------
  266. void gradient_fill (
  267. HDC const hdc
  268. , RECT const & rect
  269. , COLORREF const top_color
  270. , COLORREF const bottom_color
  271. );
  272. // -------------------------------------------------------------------------
  273. // -------------------------------------------------------------------------
  274. gdi_object<HFONT> const create_font (LPCTSTR const font_family, int const height);
  275. // -------------------------------------------------------------------------
  276. namespace standard_font
  277. {
  278. enum type
  279. {
  280. caption ,
  281. menu ,
  282. status ,
  283. message ,
  284. enum_count ,
  285. };
  286. }
  287. // -------------------------------------------------------------------------
  288. gdi_object<HFONT> const create_standard_font (
  289. standard_font::type const font_type
  290. , int const height
  291. );
  292. gdi_object<HFONT> const create_standard_font (
  293. standard_font::type const font_type
  294. );
  295. // -------------------------------------------------------------------------
  296. // -------------------------------------------------------------------------
  297. tstring const load_string_resource (int const resource_id);
  298. tstring const load_string_resource (int const resource_id, LPCTSTR const default_value);
  299. gdi_object<HBITMAP> const load_bitmap_resource (int const resource_id);
  300. SIZE const get_bitmap_size (HDC const hdc, HBITMAP const bitmap);
  301. // -------------------------------------------------------------------------
  302. // -------------------------------------------------------------------------
  303. RECT const zero_rect ();
  304. bool const is_inside (RECT const & rect, POINT const & point) throw ();
  305. boost::optional<RECT> const intersect (RECT const & left, RECT const & right) throw ();
  306. // -------------------------------------------------------------------------
  307. // -------------------------------------------------------------------------
  308. POINT const get_client_mouse_coordinate (HWND const hwnd, LPARAM const lParam);
  309. POINT const get_mouse_coordinate (LPARAM const lParam);
  310. // -------------------------------------------------------------------------
  311. // -------------------------------------------------------------------------
  312. namespace detail
  313. {
  314. template<typename TValue, int size>
  315. struct atomic_impl;
  316. template<typename TValue>
  317. struct atomic_impl<TValue, 8>
  318. {
  319. static_assert (
  320. std::tr1::is_pod<TValue>::value,
  321. "TValue must be pod-type"
  322. );
  323. static_assert (
  324. sizeof (long long) == 8,
  325. "sizeof (long long) must be 8"
  326. );
  327. atomic_impl () throw ()
  328. : m_value (0)
  329. {
  330. }
  331. atomic_impl (TValue const value) throw ()
  332. : m_value ((long long)value)
  333. {
  334. }
  335. WIN32_INLINE TValue const get () const throw ()
  336. {
  337. return (TValue) (
  338. _InterlockedCompareExchange64 (
  339. const_cast<long long volatile*>(&m_value)
  340. , 0
  341. , 0
  342. ));
  343. }
  344. WIN32_INLINE bool const compare_and_exchange (
  345. TValue const new_value,
  346. TValue const compare_value
  347. ) throw ()
  348. {
  349. auto new_value_ = (long long)new_value;
  350. auto compare_value_ = (long long)compare_value;
  351. return
  352. _InterlockedCompareExchange64 (
  353. &m_value
  354. , new_value_
  355. , compare_value_
  356. )
  357. == compare_value_;
  358. }
  359. private:
  360. __declspec (align (8))
  361. volatile long long m_value;
  362. };
  363. template<typename TValue>
  364. struct atomic_impl<TValue, 4>
  365. {
  366. static_assert (
  367. std::tr1::is_pod<TValue>::value,
  368. "TValue must be pod-type"
  369. );
  370. static_assert (
  371. sizeof (long) == 4,
  372. "sizeof (long) must be 4"
  373. );
  374. atomic_impl () throw ()
  375. : m_value (0)
  376. {
  377. }
  378. explicit atomic_impl (TValue const value) throw ()
  379. : m_value ((long)value)
  380. {
  381. }
  382. WIN32_INLINE TValue const get () const throw ()
  383. {
  384. // No interlocked needed on 32bit as memory bus is 32 bit and m_value is aligned
  385. // Also VS2005+ puts in a memory barrier implicitly on volatile
  386. // (even though it's not mandated by the standard)
  387. return (TValue) m_value;
  388. }
  389. WIN32_INLINE bool const compare_and_exchange (
  390. TValue const new_value,
  391. TValue const compare_value
  392. ) throw ()
  393. {
  394. auto new_value_ = (long)new_value;
  395. auto compare_value_ = (long)compare_value;
  396. return
  397. _InterlockedCompareExchange (
  398. &m_value
  399. , new_value_
  400. , compare_value_
  401. )
  402. == compare_value_;
  403. }
  404. private:
  405. __declspec (align (4))
  406. volatile long m_value;
  407. };
  408. }
  409. // -------------------------------------------------------------------------
  410. // -------------------------------------------------------------------------
  411. template<typename TValue>
  412. struct atomic
  413. {
  414. static_assert (
  415. std::tr1::is_pod<TValue>::value,
  416. "TValue must be pod-type"
  417. );
  418. atomic () throw ()
  419. {
  420. }
  421. explicit atomic (TValue const value) throw ()
  422. : m_value (value)
  423. {
  424. }
  425. WIN32_INLINE TValue const get () const throw ()
  426. {
  427. return m_value.get ();
  428. }
  429. WIN32_INLINE bool const compare_and_exchange (
  430. TValue const new_value,
  431. TValue const compare_value
  432. ) throw ()
  433. {
  434. return m_value.compare_and_exchange (
  435. new_value,
  436. compare_value
  437. );
  438. }
  439. template<typename TFunctor>
  440. WIN32_INLINE TValue const update (TFunctor const functor) throw ()
  441. {
  442. auto current_value = TValue ();
  443. auto new_value = TValue ();
  444. do
  445. {
  446. current_value = m_value.get ();
  447. new_value = functor (current_value);
  448. }
  449. while (!m_value.compare_and_exchange (new_value, current_value));
  450. return new_value;
  451. }
  452. WIN32_INLINE TValue const inplace_add (TValue const value) throw ()
  453. {
  454. return update ([=] (TValue const v) { return value + v; });
  455. }
  456. WIN32_INLINE TValue const inplace_max (TValue const value) throw ()
  457. {
  458. return update ([=] (TValue const v) { return max_impl (value, v); });
  459. }
  460. WIN32_INLINE TValue const inplace_min (TValue const value) throw ()
  461. {
  462. return update ([=] (TValue const v) { return min_impl (value, v); });
  463. }
  464. private:
  465. WIN32_INLINE static TValue max_impl (TValue const left, TValue const right) throw ()
  466. {
  467. return left < right ? right : left;
  468. }
  469. WIN32_INLINE static TValue min_impl (TValue const left, TValue const right) throw ()
  470. {
  471. return left < right ? left : right;
  472. }
  473. detail::atomic_impl<TValue, sizeof (TValue)> m_value;
  474. };
  475. // -------------------------------------------------------------------------
  476. }
  477. // ----------------------------------------------------------------------------