Created
May 17, 2018 13:49
-
-
Save martinmoene/62db7bdda6bfcbbb4d23ced089929170 to your computer and use it in GitHub Desktop.
Kenny Kerr. Windows with C++ - C++ and the Windows API. July 2011.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* \file win/check_result.h | |
* | |
* \brief Windows API. | |
* \author Kenny Kerr, Martin Moene | |
* \date 3 February 2016 | |
* \since 0.0.0 | |
* | |
* From: Kenny Kerr. Windows with C++ - C++ and the Windows API. July 2011. | |
* https://msdn.microsoft.com/%20magazine/hh288076 | |
*/ | |
#ifndef G_CORE_WIN_CHECK_RESULT_H_INCLUDED | |
#define G_CORE_WIN_CHECK_RESULT_H_INCLUDED | |
#include <string> | |
#include <stdexcept> | |
#include <windows.h> | |
namespace win { | |
namespace detail { | |
inline std::string api_message( long result ) | |
{ | |
LPVOID lpMsgBuf; | |
FormatMessage( | |
FORMAT_MESSAGE_ALLOCATE_BUFFER | | |
FORMAT_MESSAGE_FROM_SYSTEM | | |
FORMAT_MESSAGE_IGNORE_INSERTS, | |
NULL, | |
result, | |
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language | |
(LPTSTR) &lpMsgBuf, | |
0, | |
NULL | |
); | |
const std::string text( static_cast<char const *>( lpMsgBuf ) ); | |
LocalFree( lpMsgBuf ); | |
// strip trailing '.\r\n': | |
const int strip_count = 3; | |
return text.length() <= strip_count ? "" : text.substr( 0, text.length() - strip_count ); | |
} | |
inline std::string message( long result, std::string text ) | |
{ | |
return "Windows API error status (" + std::to_string(result) + "): " | |
+ api_message(result) + ( text.empty() ? "" : " (" + text + ")" ); | |
} | |
} // namespace detail | |
struct check_failed : public std::runtime_error | |
{ | |
explicit check_failed( long result, std::string text = "" ) | |
: std::runtime_error( detail::message( result, text ) ) | |
, error( result ) {} | |
const long error; | |
}; | |
inline void check_bool( BOOL result ) | |
{ | |
if ( ! result ) | |
{ | |
throw check_failed( GetLastError() ); | |
} | |
} | |
inline void check_bool( bool result ) | |
{ | |
if ( ! result ) | |
{ | |
throw check_failed( GetLastError() ); | |
} | |
} | |
inline void check_hr( HRESULT result ) | |
{ | |
if ( S_OK != result ) | |
{ | |
throw check_failed( result ); | |
} | |
} | |
template <typename T> | |
inline void check( T expected, T actual ) | |
{ | |
if ( expected != actual ) | |
{ | |
throw check_failed( actual, "expected: " + std::to_string( expected ) ); | |
} | |
} | |
} // namespace win | |
#endif G_CORE_WIN_CHECK_RESULT_H_INCLUDED | |
/* | |
* end of file | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* \file win/unique_handle.h | |
* | |
* \brief Windows API. | |
* \author Kenny Kerr, Martin Moene | |
* \date 3 February 2016 | |
* \since 0.0.0 | |
* | |
* From: Kenny Kerr. Windows with C++ - C++ and the Windows API. July 2011. | |
* https://msdn.microsoft.com/%20magazine/hh288076 | |
*/ | |
#ifndef G_CORE_WIN_UNIQUE_HANDLE_H_INCLUDED | |
#define G_CORE_WIN_UNIQUE_HANDLE_H_INCLUDED | |
#include <windows.h> | |
#if ( __cplusplus >= 201103L ) | |
# define win_CPP11_OR_GREATER 1 | |
#endif | |
#if win_CPP11_OR_GREATER | |
# define win_NOEXCEPT noexcept | |
#else | |
# define win_NOEXCEPT throw() | |
#endif | |
namespace win { | |
namespace detail { | |
struct afxmodule_traits | |
{ | |
static HINSTANCE invalid() win_NOEXCEPT | |
{ | |
return nullptr; | |
} | |
static void close( HINSTANCE value ) win_NOEXCEPT | |
{ | |
AfxFreeLibrary( value ); | |
} | |
}; | |
struct module_traits | |
{ | |
static HMODULE invalid() win_NOEXCEPT | |
{ | |
return nullptr; | |
} | |
static void close( HMODULE value ) win_NOEXCEPT | |
{ | |
FreeLibrary( value ); | |
} | |
}; | |
struct cursor_traits | |
{ | |
static HCURSOR invalid() win_NOEXCEPT | |
{ | |
return NULL; | |
} | |
static void close( HCURSOR value ) win_NOEXCEPT | |
{ | |
DestroyCursor( value ); | |
} | |
}; | |
struct file_traits | |
{ | |
static HANDLE invalid() win_NOEXCEPT | |
{ | |
return INVALID_HANDLE_VALUE; | |
} | |
static void close( HANDLE value ) win_NOEXCEPT | |
{ | |
CloseHandle( value ); | |
} | |
}; | |
struct handle_traits | |
{ | |
static HANDLE invalid() win_NOEXCEPT | |
{ | |
return nullptr; | |
} | |
static void close( HANDLE value ) win_NOEXCEPT | |
{ | |
CloseHandle( value ); | |
} | |
}; | |
struct mutex_traits | |
{ | |
static HANDLE invalid() win_NOEXCEPT | |
{ | |
return nullptr; | |
} | |
static void close( HANDLE value ) win_NOEXCEPT | |
{ | |
ReleaseMutex( value ); | |
} | |
}; | |
struct socket_traits | |
{ | |
static SOCKET invalid() win_NOEXCEPT | |
{ | |
return INVALID_SOCKET; | |
} | |
static void close( SOCKET value ) win_NOEXCEPT | |
{ | |
closesocket( value ); | |
} | |
}; | |
} // namespace detail | |
template <typename T, typename Traits> | |
class unique_handle | |
{ | |
typedef void ( unique_handle::*safe_bool )() const; | |
void this_type_does_not_support_comparisons() const {} | |
public: | |
typedef T value_type; | |
explicit unique_handle( T value = Traits::invalid() ) win_NOEXCEPT | |
: m_value( value ) {} | |
~unique_handle() win_NOEXCEPT | |
{ | |
close(); | |
} | |
unique_handle( unique_handle && other ) win_NOEXCEPT | |
: m_value( other.release() ) {} | |
unique_handle & operator=( unique_handle && other ) win_NOEXCEPT | |
{ | |
reset( other.release() ); | |
return *this; | |
} | |
// simulate C++11 explicit bool() | |
operator safe_bool() const win_NOEXCEPT | |
{ | |
return Traits::invalid() != m_value | |
? &unique_handle::this_type_does_not_support_comparisons | |
: nullptr; | |
} | |
T get() const win_NOEXCEPT | |
{ | |
return m_value; | |
} | |
bool reset( T value = Traits::invalid() ) win_NOEXCEPT | |
{ | |
if ( m_value != value ) | |
{ | |
close(); | |
m_value = value; | |
} | |
return *this; | |
} | |
T release() win_NOEXCEPT | |
{ | |
auto value = m_value; | |
m_value = Traits::invalid(); | |
return value; | |
} | |
private: | |
unique_handle( unique_handle const & ); // = delete; | |
unique_handle & operator=( unique_handle const & ); // = delete; | |
bool operator==(unique_handle const &); | |
bool operator!=(unique_handle const &); | |
void close() win_NOEXCEPT | |
{ | |
if ( *this ) | |
{ | |
Traits::close( m_value ); | |
} | |
} | |
T m_value; | |
}; | |
typedef unique_handle< HINSTANCE, detail::afxmodule_traits> afxmodule; | |
typedef unique_handle< HCURSOR , detail::cursor_traits > cursor; | |
typedef unique_handle< HANDLE , detail::file_traits > file; | |
typedef unique_handle< HANDLE , detail::handle_traits > handle; | |
typedef unique_handle< HMODULE , detail::module_traits > module; | |
typedef unique_handle< HANDLE , detail::mutex_traits > mutex; | |
typedef unique_handle< SOCKET , detail::socket_traits > socket; | |
} // namespace win | |
#endif // G_CORE_WIN_UNIQUE_HANDLE_H_INCLUDED | |
/* | |
* end of file | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment