Skip to content

Instantly share code, notes, and snippets.

@martinmoene
Created May 17, 2018 13:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save martinmoene/62db7bdda6bfcbbb4d23ced089929170 to your computer and use it in GitHub Desktop.
Save martinmoene/62db7bdda6bfcbbb4d23ced089929170 to your computer and use it in GitHub Desktop.
Kenny Kerr. Windows with C++ - C++ and the Windows API. July 2011.
/**
* \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
*/
/**
* \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