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.

517 lines
14 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: winstl/error/exceptions.hpp
  3. *
  4. * Purpose: windows_exception class, and its policy class
  5. *
  6. * Created: 19th June 2004
  7. * Updated: 23rd February 2011
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 2004-2011, Matthew Wilson and Synesis Software
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright notice, this
  18. * list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  23. * any contributors may be used to endorse or promote products derived from
  24. * this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * ////////////////////////////////////////////////////////////////////// */
  39. /** \file winstl/error/exceptions.hpp
  40. *
  41. * \brief [C++ only] Definition of the winstl::windows_exception and
  42. * winstl::resource_exception exception classes, and the
  43. * winstl::windows_exception_policy and winstl::resource_exception_policy
  44. * exception policy classes
  45. * (\ref group__library__error "Error" Library).
  46. */
  47. #ifndef WINSTL_INCL_WINSTL_ERROR_HPP_EXCEPTIONS
  48. #define WINSTL_INCL_WINSTL_ERROR_HPP_EXCEPTIONS
  49. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  50. # define WINSTL_VER_WINSTL_ERROR_HPP_EXCEPTIONS_MAJOR 4
  51. # define WINSTL_VER_WINSTL_ERROR_HPP_EXCEPTIONS_MINOR 5
  52. # define WINSTL_VER_WINSTL_ERROR_HPP_EXCEPTIONS_REVISION 1
  53. # define WINSTL_VER_WINSTL_ERROR_HPP_EXCEPTIONS_EDIT 63
  54. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  55. /* /////////////////////////////////////////////////////////////////////////
  56. * Compatibility
  57. */
  58. /*
  59. [DocumentationStatus:Ready]
  60. */
  61. /* /////////////////////////////////////////////////////////////////////////
  62. * Includes
  63. */
  64. #ifndef WINSTL_INCL_WINSTL_H_WINSTL
  65. # include <winstl/winstl.h>
  66. #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
  67. #ifndef STLSOFT_INCL_STLSOFT_ERROR_HPP_EXCEPTIONS
  68. # include <stlsoft/error/exceptions.hpp> // for null_exception_policy
  69. #endif /* !STLSOFT_INCL_STLSOFT_ERROR_HPP_EXCEPTIONS */
  70. #ifndef WINSTL_INCL_WINSTL_ERROR_H_ERROR_FUNCTIONS
  71. # include <winstl/error/error_functions.h>
  72. #endif /* !WINSTL_INCL_WINSTL_ERROR_H_ERROR_FUNCTIONS */
  73. #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_EXCEPTION_STRING
  74. # include <stlsoft/util/exception_string.hpp>
  75. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_EXCEPTION_STRING */
  76. #ifndef STLSOFT_INCL_STLSOFT_SMARTPTR_HPP_SCOPED_HANDLE
  77. # include <stlsoft/smartptr/scoped_handle.hpp>
  78. #endif /* !STLSOFT_INCL_STLSOFT_SMARTPTR_HPP_SCOPED_HANDLE */
  79. #ifndef STLSOFT_INCL_H_STRING
  80. # define STLSOFT_INCL_H_STRING
  81. # include <string.h>
  82. #endif /* !STLSOFT_INCL_H_STRING */
  83. /* /////////////////////////////////////////////////////////////////////////
  84. * Namespace
  85. */
  86. #ifndef _WINSTL_NO_NAMESPACE
  87. # if defined(_STLSOFT_NO_NAMESPACE) || \
  88. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  89. /* There is no stlsoft namespace, so must define ::winstl */
  90. namespace winstl
  91. {
  92. # else
  93. /* Define stlsoft::winstl_project */
  94. namespace stlsoft
  95. {
  96. namespace winstl_project
  97. {
  98. # endif /* _STLSOFT_NO_NAMESPACE */
  99. #endif /* !_WINSTL_NO_NAMESPACE */
  100. /* /////////////////////////////////////////////////////////////////////////
  101. * Classes
  102. */
  103. /** \brief General exception class for Windows operating system failures.
  104. *
  105. * \ingroup group__library__error
  106. *
  107. */
  108. class windows_exception
  109. : public stlsoft_ns_qual(os_exception)
  110. {
  111. /// \name Member Types
  112. /// @{
  113. protected:
  114. typedef stlsoft_ns_qual(exception_string) string_type;
  115. public:
  116. /// The parent class type
  117. typedef stlsoft_ns_qual(os_exception) parent_class_type;
  118. /// The error code type
  119. typedef ws_dword_t error_code_type;
  120. /// The class type
  121. typedef windows_exception class_type;
  122. /// The size type
  123. typedef ws_size_t size_type;
  124. /// @}
  125. /// \name Construction
  126. /// @{
  127. public:
  128. /// \brief Constructs an instance from the given error code
  129. ss_explicit_k windows_exception(error_code_type err)
  130. : m_reason()
  131. , m_strerror(NULL)
  132. , m_errorCode(err)
  133. {}
  134. /// \brief Copy constructor
  135. windows_exception(class_type const& rhs)
  136. : m_reason(rhs.m_reason)
  137. , m_strerror(NULL)
  138. , m_errorCode(rhs.m_errorCode)
  139. {}
  140. /// \brief Constructs an instance from the given message and error code
  141. windows_exception(char const* reason, error_code_type err)
  142. : m_reason(class_type::create_reason_(reason, err))
  143. , m_strerror(NULL)
  144. , m_errorCode(err)
  145. {}
  146. /// \brief Constructs an instance from the given message and error code
  147. windows_exception(char const* reason)
  148. : m_reason(reason)
  149. , m_strerror(NULL)
  150. , m_errorCode(ERROR_SUCCESS)
  151. {}
  152. protected:
  153. /// \brief
  154. windows_exception(string_type const& reason, error_code_type err)
  155. : m_reason(reason)
  156. , m_strerror(NULL)
  157. , m_errorCode(err)
  158. {}
  159. public:
  160. virtual ~windows_exception() stlsoft_throw_0()
  161. {
  162. if( NULL != m_strerror &&
  163. m_reason.c_str() != m_strerror)
  164. {
  165. format_message_free_buff(m_strerror);
  166. }
  167. }
  168. /// @}
  169. /// \name Accessors
  170. /// @{
  171. public:
  172. virtual char const* what() const stlsoft_throw_0()
  173. {
  174. if(!m_reason.empty())
  175. {
  176. return m_reason.c_str();
  177. }
  178. else
  179. {
  180. return this->strerror();
  181. }
  182. }
  183. /// The error code associated with the exception
  184. error_code_type get_error_code() const
  185. {
  186. return m_errorCode;
  187. }
  188. /// [DEPRECATED] The error code associated with the exception
  189. ///
  190. /// \deprecated Use get_error_code() instead.
  191. error_code_type last_error() const
  192. {
  193. return get_error_code();
  194. }
  195. char const* strerror() const
  196. {
  197. if(NULL == m_strerror)
  198. {
  199. if(is_memory_error_(m_errorCode))
  200. {
  201. return "Out of memory";
  202. }
  203. else
  204. {
  205. char*& s = stlsoft_ns_qual(remove_const)(this->m_strerror);
  206. if(0 == format_message(FORMAT_MESSAGE_IGNORE_INSERTS, NULL, m_errorCode, &s))
  207. {
  208. return "Windows system error";
  209. }
  210. }
  211. }
  212. return m_strerror;
  213. }
  214. /// @}
  215. /// \name Implementation
  216. /// @{
  217. private:
  218. static bool is_memory_error_(error_code_type code)
  219. {
  220. switch(code)
  221. {
  222. default:
  223. return false;
  224. #ifdef _HRESULT_DEFINED
  225. case static_cast<error_code_type>(E_OUTOFMEMORY):
  226. #else /* ? _HRESULT_DEFINED */
  227. case static_cast<error_code_type>(0x8007000EL):
  228. #endif /* _HRESULT_DEFINED */
  229. case static_cast<error_code_type>(ERROR_OUTOFMEMORY):
  230. return true;
  231. }
  232. }
  233. static string_type create_reason_(char const* reason, error_code_type err)
  234. {
  235. if( is_memory_error_(err) ||
  236. NULL == reason ||
  237. '\0' == reason[0])
  238. {
  239. return string_type();
  240. }
  241. else
  242. {
  243. #if 0
  244. size_type const len = ::strlen(reason);
  245. stlsoft_ns_qual(exception_string_creator) creator(len + 100u);
  246. creator.append(reason);
  247. char* s;
  248. if(0 != format_message(FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, &s))
  249. {
  250. stlsoft_ns_qual(scoped_handle)<char*> scoper(s, format_message_free_buff);
  251. creator.append(": ").append(s);
  252. }
  253. return creator.create();
  254. #else /* ? 0 */
  255. string_type r(reason);
  256. char* s;
  257. if(0 != format_message(FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, &s))
  258. {
  259. #if 0
  260. stlsoft_ns_qual(scoped_handle)<char*> scoper(s, format_message_free_buff);
  261. #else /* ? 0 */
  262. // Workaround for Intel compile error
  263. void (*pfn)(ws_char_a_t*) = format_message_free_buff;
  264. stlsoft_ns_qual(scoped_handle)<char*> scoper(s, pfn);
  265. #endif /* 0 */
  266. return r + ": " + s;
  267. }
  268. else
  269. {
  270. return r;
  271. }
  272. #endif /* 0 */
  273. }
  274. }
  275. /// @}
  276. /// \name Member Variables
  277. /// @{
  278. private:
  279. const string_type m_reason;
  280. char* m_strerror;
  281. const error_code_type m_errorCode;
  282. /// @}
  283. /// \name Not to be implemented
  284. /// @{
  285. private:
  286. class_type& operator =(class_type const&);
  287. /// @}
  288. };
  289. /** \brief Indicates that a resource could not be located.
  290. *
  291. * \ingroup group__library__error
  292. *
  293. * \see winstl::applet_module |
  294. * winstl::basic_resource_string
  295. */
  296. class resource_exception
  297. : public windows_exception
  298. {
  299. /// \name Member Types
  300. /// @{
  301. public:
  302. typedef windows_exception parent_class_type;
  303. typedef resource_exception class_type;
  304. /// @}
  305. /// \name Construction
  306. /// @{
  307. public:
  308. resource_exception( char const* reason
  309. , error_code_type err
  310. , LPCTSTR resourceId = NULL
  311. , LPCTSTR resourceType = NULL)
  312. : parent_class_type(reason, err)
  313. , m_resourceId(resourceId)
  314. , m_resourceType(resourceType)
  315. {}
  316. /// @}
  317. /// \name Members
  318. /// @{
  319. public:
  320. LPCTSTR get_resource_id() const
  321. {
  322. return m_resourceId;
  323. }
  324. LPCTSTR get_resource_type() const
  325. {
  326. return m_resourceType;
  327. }
  328. /// @}
  329. /// \name Members
  330. /// @{
  331. private:
  332. const LPCTSTR m_resourceId;
  333. const LPCTSTR m_resourceType;
  334. /// @}
  335. /// \name Not to be implemented
  336. /// @{
  337. private:
  338. class_type& operator =(class_type const&);
  339. /// @}
  340. };
  341. /** \brief Indicates that a access condition was encountered.
  342. *
  343. * \ingroup group__library__error
  344. */
  345. class access_exception
  346. : public windows_exception
  347. {
  348. /// \name Member Types
  349. /// @{
  350. public:
  351. typedef windows_exception parent_class_type;
  352. typedef access_exception class_type;
  353. typedef parent_class_type::error_code_type error_code_type;
  354. /// @}
  355. /// \name Construction
  356. /// @{
  357. public:
  358. access_exception( char const* reason
  359. , error_code_type err)
  360. : parent_class_type(reason, err)
  361. {}
  362. access_exception(error_code_type err)
  363. : parent_class_type(err)
  364. {}
  365. /// @}
  366. /// \name Not to be implemented
  367. /// @{
  368. private:
  369. class_type& operator =(class_type const&);
  370. /// @}
  371. };
  372. /* /////////////////////////////////////////////////////////////////////////
  373. * Policies
  374. */
  375. /** \brief A policy class that throws a windows_exception class.
  376. *
  377. * \ingroup group__library__error
  378. *
  379. */
  380. // [[synesis:class:exception-policy: windows_exception_policy]]
  381. struct windows_exception_policy
  382. {
  383. /// \name Member Types
  384. /// @{
  385. public:
  386. /// The thrown type
  387. typedef windows_exception thrown_type;
  388. typedef ws_dword_t error_code_type;
  389. /// @}
  390. /// \name Operators
  391. /// @{
  392. public:
  393. /// Function call operator, taking no parameters
  394. void operator ()() const
  395. {
  396. STLSOFT_THROW_X(thrown_type(::GetLastError()));
  397. }
  398. /// Function call operator, taking one parameter
  399. void operator ()(error_code_type err) const
  400. {
  401. STLSOFT_THROW_X(thrown_type(err));
  402. }
  403. /// Function call operator, taking two parameters
  404. void operator ()(char const* reason, error_code_type err) const
  405. {
  406. STLSOFT_THROW_X(thrown_type(reason, err));
  407. }
  408. /// @}
  409. };
  410. /** \brief A policy class that throws a resource_exception class.
  411. *
  412. * \ingroup group__library__error
  413. *
  414. */
  415. // [[synesis:class:exception-policy: resource_exception_policy]]
  416. struct resource_exception_policy
  417. {
  418. /// \name Member Types
  419. /// @{
  420. public:
  421. /// The thrown type
  422. typedef resource_exception thrown_type;
  423. typedef ws_dword_t error_code_type;
  424. /// @}
  425. /// \name Operators
  426. /// @{
  427. public:
  428. /// Function call operator, taking two parameters
  429. void operator ()(char const* reason, error_code_type err) const
  430. {
  431. STLSOFT_THROW_X(thrown_type(reason, err));
  432. }
  433. /// Function call operator, taking three parameters
  434. void operator ()(char const* reason, error_code_type err, LPCTSTR resourceId) const
  435. {
  436. STLSOFT_THROW_X(thrown_type(reason, err, resourceId));
  437. }
  438. /// Function call operator, taking four parameters
  439. void operator ()(char const* reason, error_code_type err, LPCTSTR resourceId, LPCTSTR resourceType) const
  440. {
  441. STLSOFT_THROW_X(thrown_type(reason, err, resourceId, resourceType));
  442. }
  443. /// @}
  444. };
  445. ////////////////////////////////////////////////////////////////////////////
  446. // Unit-testing
  447. #ifdef STLSOFT_UNITTEST
  448. # include "./unittest/exceptions_unittest_.h"
  449. #endif /* STLSOFT_UNITTEST */
  450. /* ////////////////////////////////////////////////////////////////////// */
  451. #ifndef _WINSTL_NO_NAMESPACE
  452. # if defined(_STLSOFT_NO_NAMESPACE) || \
  453. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  454. } // namespace winstl
  455. # else
  456. } // namespace winstl_project
  457. } // namespace stlsoft
  458. # endif /* _STLSOFT_NO_NAMESPACE */
  459. #endif /* !_WINSTL_NO_NAMESPACE */
  460. /* ////////////////////////////////////////////////////////////////////// */
  461. #endif /* !WINSTL_INCL_WINSTL_ERROR_HPP_EXCEPTIONS */
  462. /* ///////////////////////////// end of file //////////////////////////// */