From 96407384c48eefd85a4654c67cdb306e8b61e52a Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Mon, 22 Feb 2016 23:24:30 +0300 Subject: [PATCH] Fixed an exception when checking if the semaphore counter is zero. Moved UTF conversion function to code_conversion.cpp. Moved access permission constants to Boost.WinAPI. --- src/code_conversion.cpp | 35 +++++++++++++++++++ src/windows/ipc_reliable_message_queue.cpp | 7 ++-- src/windows/ipc_sync_wrappers.cpp | 35 ++++--------------- src/windows/mapped_shared_memory.cpp | 7 ++-- src/windows/utf_code_conversion.hpp | 40 ++++++++++++++++++++++ 5 files changed, 87 insertions(+), 37 deletions(-) create mode 100644 src/windows/utf_code_conversion.hpp diff --git a/src/code_conversion.cpp b/src/code_conversion.cpp index 3b05f21..13df238 100644 --- a/src/code_conversion.cpp +++ b/src/code_conversion.cpp @@ -21,6 +21,11 @@ #include #include #include +#if defined(BOOST_WINDOWS) +#include +#include +#include +#endif #include namespace boost { @@ -199,6 +204,36 @@ BOOST_LOG_API void code_convert_impl(const char32_t* str1, std::size_t len, std: #endif // !defined(BOOST_LOG_NO_CXX11_CODECVT_FACETS) +#if defined(BOOST_WINDOWS) + +//! Converts UTF-8 to UTF-16 +std::wstring utf8_to_utf16(const char* str) +{ + std::size_t utf8_len = std::strlen(str); + if (utf8_len == 0) + return std::wstring(); + else if (BOOST_UNLIKELY(utf8_len > static_cast< std::size_t >((std::numeric_limits< int >::max)()))) + BOOST_LOG_THROW_DESCR(bad_alloc, "Multibyte string too long"); + + int len = boost::detail::winapi::MultiByteToWideChar(boost::detail::winapi::CP_UTF8_, boost::detail::winapi::MB_ERR_INVALID_CHARS_, str, static_cast< int >(utf8_len), NULL, 0); + if (BOOST_LIKELY(len > 0)) + { + std::wstring wstr; + wstr.resize(len); + + len = boost::detail::winapi::MultiByteToWideChar(boost::detail::winapi::CP_UTF8_, boost::detail::winapi::MB_ERR_INVALID_CHARS_, str, static_cast< int >(utf8_len), &wstr[0], len); + if (BOOST_LIKELY(len > 0)) + { + return wstr; + } + } + + BOOST_LOG_THROW_DESCR(conversion_error, "Failed to convert UTF-8 to UTF-16"); + BOOST_LOG_UNREACHABLE_RETURN(std::wstring()); +} + +#endif // defined(BOOST_WINDOWS) + } // namespace aux BOOST_LOG_CLOSE_NAMESPACE // namespace log diff --git a/src/windows/ipc_reliable_message_queue.cpp b/src/windows/ipc_reliable_message_queue.cpp index d4f87f3..3f55820 100644 --- a/src/windows/ipc_reliable_message_queue.cpp +++ b/src/windows/ipc_reliable_message_queue.cpp @@ -40,6 +40,7 @@ #include // SwitchToThread #include "windows/ipc_sync_wrappers.hpp" #include "windows/mapped_shared_memory.hpp" +#include "windows/utf_code_conversion.hpp" #include "murmur3.hpp" #include "bit_tools.hpp" #include @@ -215,7 +216,7 @@ public: m_block_size_log2(0u), m_name(name) { - const std::wstring wname = boost::log::ipc::aux::utf8_to_utf16(name); + const std::wstring wname = boost::log::aux::utf8_to_utf16(name); const std::size_t shmem_size = estimate_region_size(capacity, block_size); m_shared_memory.create(wname.c_str(), shmem_size, perms); m_shared_memory.map(); @@ -238,7 +239,7 @@ public: m_block_size_log2(0u), m_name(name) { - const std::wstring wname = boost::log::ipc::aux::utf8_to_utf16(name); + const std::wstring wname = boost::log::aux::utf8_to_utf16(name); const std::size_t shmem_size = estimate_region_size(capacity, block_size); const bool created = m_shared_memory.create_or_open(wname.c_str(), shmem_size, perms); m_shared_memory.map(); @@ -262,7 +263,7 @@ public: m_block_size_log2(0u), m_name(name) { - const std::wstring wname = boost::log::ipc::aux::utf8_to_utf16(name); + const std::wstring wname = boost::log::aux::utf8_to_utf16(name); m_shared_memory.open(wname.c_str()); m_shared_memory.map(); diff --git a/src/windows/ipc_sync_wrappers.cpp b/src/windows/ipc_sync_wrappers.cpp index 0822079..842c5c5 100644 --- a/src/windows/ipc_sync_wrappers.cpp +++ b/src/windows/ipc_sync_wrappers.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include "unique_ptr.hpp" #include "windows/ipc_sync_wrappers.hpp" #include @@ -52,32 +53,6 @@ namespace ipc { namespace aux { -//! Converts UTF-8 to UTF-16 -std::wstring utf8_to_utf16(const char* str) -{ - std::size_t utf8_len = std::strlen(str); - if (utf8_len == 0) - return std::wstring(); - else if (BOOST_UNLIKELY(utf8_len > static_cast< std::size_t >((std::numeric_limits< int >::max)()))) - BOOST_LOG_THROW_DESCR(bad_alloc, "Multibyte string too long"); - - int len = boost::detail::winapi::MultiByteToWideChar(boost::detail::winapi::CP_UTF8_, boost::detail::winapi::MB_ERR_INVALID_CHARS_, str, static_cast< int >(utf8_len), NULL, 0); - if (BOOST_LIKELY(len > 0)) - { - std::wstring wstr; - wstr.resize(len); - - len = boost::detail::winapi::MultiByteToWideChar(boost::detail::winapi::CP_UTF8_, boost::detail::winapi::MB_ERR_INVALID_CHARS_, str, static_cast< int >(utf8_len), &wstr[0], len); - if (BOOST_LIKELY(len > 0)) - { - return wstr; - } - } - - BOOST_LOG_THROW_DESCR(conversion_error, "Failed to convert UTF-8 to UTF-16"); - BOOST_LOG_UNREACHABLE_RETURN(std::wstring()); -} - void interprocess_event::create(const wchar_t* name, bool manual_reset, permissions const& perms) { #if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6 @@ -167,7 +142,7 @@ void interprocess_semaphore::create_or_open(const wchar_t* name, permissions con (std::numeric_limits< boost::detail::winapi::LONG_ >::max)(), // max count name, 0u, // flags - boost::detail::winapi::SYNCHRONIZE_ | boost::detail::winapi::SEMAPHORE_MODIFY_STATE_ + boost::detail::winapi::SYNCHRONIZE_ | boost::detail::winapi::SEMAPHORE_MODIFY_STATE_ | boost::detail::winapi::SEMAPHORE_QUERY_STATE_ ); #else boost::detail::winapi::HANDLE_ h = boost::detail::winapi::CreateSemaphoreW @@ -197,7 +172,7 @@ void interprocess_semaphore::create_or_open(const wchar_t* name, permissions con void interprocess_semaphore::open(const wchar_t* name) { - boost::detail::winapi::HANDLE_ h = boost::detail::winapi::OpenSemaphoreW(boost::detail::winapi::SYNCHRONIZE_ | boost::detail::winapi::SEMAPHORE_MODIFY_STATE_, false, name); + boost::detail::winapi::HANDLE_ h = boost::detail::winapi::OpenSemaphoreW(boost::detail::winapi::SYNCHRONIZE_ | boost::detail::winapi::SEMAPHORE_MODIFY_STATE_ | boost::detail::winapi::SEMAPHORE_QUERY_STATE_, false, name); if (BOOST_UNLIKELY(h == NULL)) { const boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError(); @@ -241,7 +216,9 @@ bool interprocess_semaphore::is_semaphore_zero_count_nt_query_semaphore(boost::d ); if (BOOST_UNLIKELY(err != 0u)) { - BOOST_LOG_THROW_DESCR_PARAMS(boost::log::system_error, "Failed to test an interprocess semaphore object for zero count", (ERROR_INVALID_HANDLE)); + char buf[sizeof(unsigned int) * 2u + 4u]; + boost::log::aux::snprintf(buf, sizeof(buf), "0x%08x", static_cast< unsigned int >(err)); + BOOST_LOG_THROW_DESCR_PARAMS(boost::log::system_error, std::string("Failed to test an interprocess semaphore object for zero count, NT status: ") + buf, (ERROR_INVALID_HANDLE)); } return info.current_count == 0u; diff --git a/src/windows/mapped_shared_memory.cpp b/src/windows/mapped_shared_memory.cpp index 24011e8..7ce1282 100644 --- a/src/windows/mapped_shared_memory.cpp +++ b/src/windows/mapped_shared_memory.cpp @@ -41,9 +41,6 @@ namespace ipc { namespace aux { -//! A special permission that is required to be able to read the shared memory segment size -BOOST_CONSTEXPR_OR_CONST boost::detail::winapi::DWORD_ SECTION_QUERY_ = 0x00000001; - boost::atomic< mapped_shared_memory::nt_query_section_t > mapped_shared_memory::nt_query_section(static_cast< mapped_shared_memory::nt_query_section_t >(NULL)); mapped_shared_memory::~mapped_shared_memory() @@ -136,7 +133,7 @@ void mapped_shared_memory::open(const wchar_t* name) BOOST_ASSERT(m_handle == NULL); // Note: FILE_MAP_WRITE implies reading permission as well - boost::detail::winapi::HANDLE_ h = boost::detail::winapi::OpenFileMappingW(boost::detail::winapi::FILE_MAP_WRITE_ | SECTION_QUERY_, false, name); + boost::detail::winapi::HANDLE_ h = boost::detail::winapi::OpenFileMappingW(boost::detail::winapi::FILE_MAP_WRITE_ | boost::detail::winapi::SECTION_QUERY_, false, name); if (BOOST_UNLIKELY(h == NULL)) { @@ -167,7 +164,7 @@ void mapped_shared_memory::map() m_mapped_address = boost::detail::winapi::MapViewOfFile ( m_handle, - boost::detail::winapi::FILE_MAP_WRITE_ | SECTION_QUERY_, + boost::detail::winapi::FILE_MAP_WRITE_ | boost::detail::winapi::SECTION_QUERY_, 0u, 0u, m_size diff --git a/src/windows/utf_code_conversion.hpp b/src/windows/utf_code_conversion.hpp new file mode 100644 index 0000000..a7f4c10 --- /dev/null +++ b/src/windows/utf_code_conversion.hpp @@ -0,0 +1,40 @@ +/* + * Copyright Andrey Semashev 2016. + * Distributed under the Boost Software License, Version 1.0. + * (See accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ +/*! + * \file windows/utf_code_conversion.hpp + * \author Andrey Semashev + * \date 22.02.2016 + * + * \brief This header is the Boost.Log library implementation, see the library documentation + * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html. + */ + +#ifndef BOOST_LOG_WINDOWS_UTF_CODE_CONVERSION_HPP_INCLUDED_ +#define BOOST_LOG_WINDOWS_UTF_CODE_CONVERSION_HPP_INCLUDED_ + +#include +#include +#include + +namespace boost { + +BOOST_LOG_OPEN_NAMESPACE + +namespace aux { + +//! Converts UTF-8 to UTF-16 +std::wstring utf8_to_utf16(const char* str); + +} // namespace aux + +BOOST_LOG_CLOSE_NAMESPACE // namespace log + +} // namespace boost + +#include + +#endif // BOOST_LOG_WINDOWS_UTF_CODE_CONVERSION_HPP_INCLUDED_