From f2ecdc70ef854c17744247fbfcd3435464cb6240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Wed, 3 Jun 2020 21:37:02 +0200 Subject: [PATCH] Fixes #99 ("Error in win32_api.hpp"): - Careful use of Boost.Winapi and use of SetFilePointer instead of SetFilePointerEx (which requires a _LARGE_INTEGER by value that difficults the use of windows.h in certain circustances) - Added tests to verify windows.h inclusion without BOOST_USE_WINDOWS_H does not break things --- doc/interprocess.qbk | 14 ++++ .../interprocess/detail/os_file_functions.hpp | 8 +- .../boost/interprocess/detail/win32_api.hpp | 39 ++++----- .../interprocess/sync/windows/named_sync.hpp | 2 +- test/include_but_no_use_windows_h.cpp | 33 ++++++++ ...dows_eventlog_stamp_shared_memory_test.cpp | 84 +++++++++++++++++++ 6 files changed, 154 insertions(+), 26 deletions(-) create mode 100644 test/include_but_no_use_windows_h.cpp create mode 100644 test/windows_eventlog_stamp_shared_memory_test.cpp diff --git a/doc/interprocess.qbk b/doc/interprocess.qbk index cc2a143..1dbb1be 100644 --- a/doc/interprocess.qbk +++ b/doc/interprocess.qbk @@ -6763,6 +6763,20 @@ thank them: [section:release_notes Release Notes] +[section:release_notes_boost_1_74_00 Boost 1.74 Release] + +* [*ABI breaking]: Option `BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED` is now the default value. + You can obtain the pre-Boost 1.73 behaviour defining `BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED`. + The old and broken pre-Boost 1.54 behaviour (`BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME`) is no + longer available. + +* Fixed bugs: + * [@https://github.com/boostorg/interprocess/issues/89 GitHub #89 (['"priv_size_from_mapping_size() calculates wrong value"])]. + * [@https://github.com/boostorg/interprocess/issues/99 GitHub #99 (['"Error in win32_api.hpp"])]. + * [@https://github.com/boostorg/interprocess/issues/89 GitHub #105 (['"Build failure with clang on Windows"])]. + +[endsect] + [section:release_notes_boost_1_71_00 Boost 1.71 Release] * Fixed bugs: diff --git a/include/boost/interprocess/detail/os_file_functions.hpp b/include/boost/interprocess/detail/os_file_functions.hpp index 7a05b5e..17c5c94 100644 --- a/include/boost/interprocess/detail/os_file_functions.hpp +++ b/include/boost/interprocess/detail/os_file_functions.hpp @@ -167,7 +167,7 @@ inline bool truncate_file (file_handle_t hnd, std::size_t size) } if(offset_t(size) > filesize){ - if(!winapi::set_file_pointer_ex(hnd, filesize, 0, winapi::file_begin)){ + if(!winapi::set_file_pointer(hnd, filesize, 0, winapi::file_begin)){ return false; } //We will write zeros in the end of the file @@ -186,7 +186,7 @@ inline bool truncate_file (file_handle_t hnd, std::size_t size) } } else{ - if(!winapi::set_file_pointer_ex(hnd, size, 0, winapi::file_begin)){ + if(!winapi::set_file_pointer(hnd, size, 0, winapi::file_begin)){ return false; } if(!winapi::set_end_of_file(hnd)){ @@ -200,10 +200,10 @@ inline bool get_file_size(file_handle_t hnd, offset_t &size) { return winapi::get_file_size(hnd, size); } inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos) -{ return winapi::set_file_pointer_ex(hnd, off, 0, (unsigned long) pos); } +{ return winapi::set_file_pointer(hnd, off, 0, (unsigned long) pos); } inline bool get_file_pointer(file_handle_t hnd, offset_t &off) -{ return winapi::set_file_pointer_ex(hnd, 0, &off, winapi::file_current); } +{ return winapi::set_file_pointer(hnd, 0, &off, winapi::file_current); } inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata) { diff --git a/include/boost/interprocess/detail/win32_api.hpp b/include/boost/interprocess/detail/win32_api.hpp index 1681ef8..76bd159 100644 --- a/include/boost/interprocess/detail/win32_api.hpp +++ b/include/boost/interprocess/detail/win32_api.hpp @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include #include @@ -279,6 +279,7 @@ enum section_information_class #include #include #include +#include #include #include #include @@ -303,11 +304,11 @@ namespace boost { namespace ipwinapiext { typedef boost::winapi::LONG_ LSTATUS; -#ifndef BOOST_USE_WINDOWS_H -typedef boost::winapi::LARGE_INTEGER_ LARGE_INTEGER_EXT; -#else -typedef LARGE_INTEGER LARGE_INTEGER_EXT; -#endif +//#ifndef BOOST_USE_WINDOWS_H +//typedef boost::winapi::LARGE_INTEGER_ LARGE_INTEGER_EXT; +//#else +//typedef LARGE_INTEGER LARGE_INTEGER_EXT; +//#endif }} //namespace boost::ipwinapiext @@ -320,8 +321,6 @@ BOOST_SYMBOL_IMPORT BOOST_WINAPI_DETAIL_VOID BOOST_WINAPI_WINAPI_CC SetLastError //File management BOOST_SYMBOL_IMPORT boost::winapi::DWORD_ BOOST_WINAPI_WINAPI_CC GetFileType(boost::winapi::HANDLE_ hTemplateFile); -BOOST_SYMBOL_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC SetFilePointerEx( boost::winapi::HANDLE_ hFile, boost::ipwinapiext::LARGE_INTEGER_EXT liDistanceToMove - , ::_LARGE_INTEGER *lpNewFilePointer, boost::winapi::DWORD_ dwMoveMethod); BOOST_SYMBOL_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC FlushFileBuffers(boost::winapi::HANDLE_ hFile); //Virtual Memory BOOST_SYMBOL_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC VirtualLock(boost::winapi::LPVOID_ lpAddress, boost::winapi::SIZE_T_ dwSize); @@ -365,14 +364,6 @@ BOOST_FORCEINLINE BOOST_WINAPI_DETAIL_VOID SetLastError(boost::winapi::DWORD_ dw BOOST_FORCEINLINE boost::winapi::DWORD_ GetFileType(boost::winapi::HANDLE_ hTemplateFile) { return ::GetFileType(hTemplateFile); } -BOOST_FORCEINLINE boost::winapi::BOOL_ SetFilePointerEx(boost::winapi::HANDLE_ hFile, boost::winapi::LARGE_INTEGER_ liDistanceToMove - , boost::winapi::PLARGE_INTEGER_ lpNewFilePointer, boost::winapi::DWORD_ dwMoveMethod) -{ - boost::ipwinapiext::LARGE_INTEGER_EXT largeInt; - largeInt.QuadPart = liDistanceToMove.QuadPart; - return ::SetFilePointerEx(hFile, largeInt, reinterpret_cast< ::_LARGE_INTEGER* >(lpNewFilePointer), dwMoveMethod); -} - BOOST_FORCEINLINE boost::winapi::BOOL_ FlushFileBuffers(boost::winapi::HANDLE_ hFile) { return ::FlushFileBuffers(hFile); } @@ -741,7 +732,7 @@ class interprocess_all_access_security inline void * create_file_mapping (void * handle, unsigned long access, ::boost::ulong_long_type file_offset, const char * name, interprocess_security_attributes *psec) { - const unsigned long high_size(file_offset >> 32), low_size((boost::uint32_t)file_offset); + const boost::winapi::DWORD_ high_size(file_offset >> 32), low_size((boost::winapi::DWORD_)file_offset); return CreateFileMappingA (handle, psec, access, high_size, low_size, name); } @@ -806,10 +797,16 @@ inline unsigned long get_temp_path(unsigned long length, char *buffer) inline int set_end_of_file(void *handle) { return 0 != boost::winapi::SetEndOfFile(handle); } -inline bool set_file_pointer_ex(void *handle, __int64 distance, __int64 *new_file_pointer, unsigned long move_method) +inline bool set_file_pointer(void *handle, __int64 distance, __int64 *new_file_pointer, unsigned long move_method) { - boost::winapi::LARGE_INTEGER_ d; d.QuadPart = distance; - return 0 != boost::ipwinapiext::SetFilePointerEx(handle, d, (boost::winapi::LARGE_INTEGER_*)new_file_pointer, move_method); + long highPart = distance >> 32u; + boost::winapi::DWORD_ r = boost::winapi::SetFilePointer(handle, (unsigned long)distance, &highPart, move_method); + bool br = r != boost::winapi::INVALID_SET_FILE_POINTER_ || boost::winapi::GetLastError() != 0; + if (br && new_file_pointer){ + *new_file_pointer = (unsigned __int64)r + ((__int64)highPart << 32); + } + + return br; } inline bool lock_file_ex(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped *overlapped) @@ -1150,7 +1147,7 @@ class nt_query_mem_deleter offsetof(ntquery_mem_t, name.Name.Buffer); // Timestamp process id atomic count static const std::size_t rename_suffix = - (SystemTimeOfDayInfoLength + sizeof(unsigned long) + sizeof(boost::uint32_t))*2; + (SystemTimeOfDayInfoLength + sizeof(unsigned long) + sizeof(boost::winapi::DWORD_))*2; public: explicit nt_query_mem_deleter(std::size_t object_name_information_size) diff --git a/include/boost/interprocess/sync/windows/named_sync.hpp b/include/boost/interprocess/sync/windows/named_sync.hpp index cf19335..1425b4d 100644 --- a/include/boost/interprocess/sync/windows/named_sync.hpp +++ b/include/boost/interprocess/sync/windows/named_sync.hpp @@ -83,7 +83,7 @@ inline void windows_named_sync::close(windows_named_sync_interface &sync_interfa winapi::interprocess_overlapped overlapped; if(winapi::lock_file_ex (m_file_hnd, winapi::lockfile_exclusive_lock, 0, sizeof_file_info, 0, &overlapped)){ - if(winapi::set_file_pointer_ex(m_file_hnd, sizeof(sync_id::internal_type), 0, winapi::file_begin)){ + if(winapi::set_file_pointer(m_file_hnd, sizeof(sync_id::internal_type), 0, winapi::file_begin)){ const void *buf = sync_interface.buffer_with_final_data_to_file(); unsigned long written_or_read = 0; diff --git a/test/include_but_no_use_windows_h.cpp b/test/include_but_no_use_windows_h.cpp new file mode 100644 index 0000000..003701d --- /dev/null +++ b/test/include_but_no_use_windows_h.cpp @@ -0,0 +1,33 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include + +#ifdef BOOST_INTERPROCESS_WINDOWS +#include + +#include + +using namespace boost::interprocess; + +int main () +{ + windows_shared_memory dummy; + static_cast(dummy); + return 0; +} + +#else + +int main() +{ + return 0; +} + +#endif diff --git a/test/windows_eventlog_stamp_shared_memory_test.cpp b/test/windows_eventlog_stamp_shared_memory_test.cpp new file mode 100644 index 0000000..f877463 --- /dev/null +++ b/test/windows_eventlog_stamp_shared_memory_test.cpp @@ -0,0 +1,84 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. 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) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#define BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED +#include +#include +#include +#include "named_creation_template.hpp" +#include //for strcmp, memset +#include //for cout +#include +#include "get_process_id_name.hpp" + +using namespace boost::interprocess; + +static const std::size_t ShmSize = 1000; +static const char * ShmName = test::get_process_id_name(); + +struct eraser +{ + ~eraser() + { + shared_memory_object::remove(ShmName); + } +}; + +typedef ipcdetail::managed_open_or_create_impl shared_memory; + +//This wrapper is necessary to have a common constructor +//in generic named_creation_template functions +class shared_memory_creation_test_wrapper + : public eraser + , public shared_memory +{ + + public: + shared_memory_creation_test_wrapper(create_only_t) + : shared_memory(create_only, ShmName, ShmSize, read_write, 0, permissions()) + {} + + shared_memory_creation_test_wrapper(open_only_t) + : shared_memory(open_only, ShmName, read_write, 0) + {} + + shared_memory_creation_test_wrapper(open_or_create_t) + : shared_memory(open_or_create, ShmName, ShmSize, read_write, 0, permissions()) + {} +}; + + +int main () +{ + try{ + shared_memory_object::remove(ShmName); + test::test_named_creation(); + + //Create and get name, size and address + { + shared_memory_object::remove(ShmName); + shared_memory shm1(create_only, ShmName, ShmSize, read_write, 0, permissions()); + + //Overwrite all memory + std::memset(shm1.get_user_address(), 0, shm1.get_user_size()); + + //Now test move semantics + shared_memory move_ctor(boost::move(shm1)); + shared_memory move_assign; + move_assign = boost::move(move_ctor); + } + } + catch(std::exception &ex){ + shared_memory_object::remove(ShmName); + std::cout << ex.what() << std::endl; + return 1; + } + shared_memory_object::remove(ShmName); + return 0; +}