From 798f2a98e893e3a35ceec081a00f89429d990686 Mon Sep 17 00:00:00 2001 From: Christopher Kohlhoff Date: Thu, 10 Dec 2015 22:28:03 +1100 Subject: [PATCH] Add support for Windows 8.1 store apps. --- include/boost/asio/detail/config.hpp | 36 +++-- include/boost/asio/detail/impl/socket_ops.ipp | 9 +- include/boost/asio/detail/impl/win_event.ipp | 8 ++ include/boost/asio/detail/impl/win_mutex.ipp | 5 + .../asio/detail/impl/win_static_mutex.ipp | 18 +++ include/boost/asio/detail/impl/win_thread.ipp | 8 +- .../asio/detail/local_free_on_block_exit.hpp | 2 + include/boost/asio/detail/socket_types.hpp | 8 +- include/boost/asio/detail/thread.hpp | 8 +- include/boost/asio/detail/win_event.hpp | 4 + include/boost/asio/detail/win_thread.hpp | 8 +- include/boost/asio/detail/winapi_thread.hpp | 124 ++++++++++++++++++ 12 files changed, 215 insertions(+), 23 deletions(-) create mode 100644 include/boost/asio/detail/winapi_thread.hpp diff --git a/include/boost/asio/detail/config.hpp b/include/boost/asio/detail/config.hpp index 0f9e52d5..d960e5a7 100644 --- a/include/boost/asio/detail/config.hpp +++ b/include/boost/asio/detail/config.hpp @@ -515,25 +515,41 @@ # endif // !defined(BOOST_ASIO_DISABLE_STD_MUTEX_AND_CONDVAR) #endif // !defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) -// WinRT target. -#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) -# if defined(__cplusplus_winrt) +// Windows App target. Windows but with a limited API. +#if !defined(BOOST_ASIO_WINDOWS_APP) +# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0603) # include # if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) \ && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -# define BOOST_ASIO_WINDOWS_RUNTIME 1 +# define BOOST_ASIO_WINDOWS_APP 1 # endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) // && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -# endif // defined(__cplusplus_winrt) +# endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0603) +#endif // !defined(BOOST_ASIO_WINDOWS_APP) + +// Legacy WinRT target. Windows App is preferred. +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) +# if !defined(BOOST_ASIO_WINDOWS_APP) +# if defined(__cplusplus_winrt) +# include +# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) \ + && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# define BOOST_ASIO_WINDOWS_RUNTIME 1 +# endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) + // && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# endif // defined(__cplusplus_winrt) +# endif // !defined(BOOST_ASIO_WINDOWS_APP) #endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) -// Windows target. Excludes WinRT. +// Windows target. Excludes WinRT but includes Windows App targets. #if !defined(BOOST_ASIO_WINDOWS) # if !defined(BOOST_ASIO_WINDOWS_RUNTIME) # if defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_WINDOWS) # define BOOST_ASIO_WINDOWS 1 # elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) # define BOOST_ASIO_WINDOWS 1 +# elif defined(BOOST_ASIO_WINDOWS_APP) +# define BOOST_ASIO_WINDOWS 1 # endif // defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_WINDOWS) # endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) #endif // !defined(BOOST_ASIO_WINDOWS) @@ -601,11 +617,11 @@ #if !defined(BOOST_ASIO_HAS_IOCP) # if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) # if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) -# if !defined(UNDER_CE) +# if !defined(UNDER_CE) && !defined(BOOST_ASIO_WINDOWS_APP) # if !defined(BOOST_ASIO_DISABLE_IOCP) # define BOOST_ASIO_HAS_IOCP 1 # endif // !defined(BOOST_ASIO_DISABLE_IOCP) -# endif // !defined(UNDER_CE) +# endif // !defined(UNDER_CE) && !defined(BOOST_ASIO_WINDOWS_APP) # endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) # endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) #endif // !defined(BOOST_ASIO_HAS_IOCP) @@ -721,9 +737,9 @@ #if !defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) # if !defined(BOOST_ASIO_DISABLE_WINDOWS_OBJECT_HANDLE) # if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) -# if !defined(UNDER_CE) +# if !defined(UNDER_CE) && !defined(BOOST_ASIO_WINDOWS_APP) # define BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE 1 -# endif // !defined(UNDER_CE) +# endif // !defined(UNDER_CE) && !defined(BOOST_ASIO_WINDOWS_APP) # endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) # endif // !defined(BOOST_ASIO_DISABLE_WINDOWS_OBJECT_HANDLE) #endif // !defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) diff --git a/include/boost/asio/detail/impl/socket_ops.ipp b/include/boost/asio/detail/impl/socket_ops.ipp index dc068e0e..301e94dc 100644 --- a/include/boost/asio/detail/impl/socket_ops.ipp +++ b/include/boost/asio/detail/impl/socket_ops.ipp @@ -1634,7 +1634,8 @@ int getpeername(socket_type s, socket_addr_type* addr, return socket_error_retval; } -#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +#if defined(BOOST_ASIO_WINDOWS) && !defined(BOOST_ASIO_WINDOWS_APP) \ + || defined(__CYGWIN__) if (cached) { // Check if socket is still connected. @@ -1655,9 +1656,11 @@ int getpeername(socket_type s, socket_addr_type* addr, ec = boost::system::error_code(); return 0; } -#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +#else // defined(BOOST_ASIO_WINDOWS) && !defined(BOOST_ASIO_WINDOWS_APP) + // || defined(__CYGWIN__) (void)cached; -#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +#endif // defined(BOOST_ASIO_WINDOWS) && !defined(BOOST_ASIO_WINDOWS_APP) + // || defined(__CYGWIN__) clear_last_error(); int result = error_wrapper(call_getpeername( diff --git a/include/boost/asio/detail/impl/win_event.ipp b/include/boost/asio/detail/impl/win_event.ipp index 0fffbce9..54bdcec6 100644 --- a/include/boost/asio/detail/impl/win_event.ipp +++ b/include/boost/asio/detail/impl/win_event.ipp @@ -32,7 +32,11 @@ namespace detail { win_event::win_event() : state_(0) { +#if defined(BOOST_ASIO_WINDOWS_APP) + events_[0] = ::CreateEventEx(0, 0, CREATE_EVENT_MANUAL_RESET, 0); +#else // defined(BOOST_ASIO_WINDOWS_APP) events_[0] = ::CreateEvent(0, true, false, 0); +#endif // defined(BOOST_ASIO_WINDOWS_APP) if (!events_[0]) { DWORD last_error = ::GetLastError(); @@ -41,7 +45,11 @@ win_event::win_event() boost::asio::detail::throw_error(ec, "event"); } +#if defined(BOOST_ASIO_WINDOWS_APP) + events_[1] = ::CreateEventEx(0, 0, 0, 0); +#else // defined(BOOST_ASIO_WINDOWS_APP) events_[1] = ::CreateEvent(0, false, false, 0); +#endif // defined(BOOST_ASIO_WINDOWS_APP) if (!events_[1]) { DWORD last_error = ::GetLastError(); diff --git a/include/boost/asio/detail/impl/win_mutex.ipp b/include/boost/asio/detail/impl/win_mutex.ipp index 60ce9dd5..be1d1b81 100644 --- a/include/boost/asio/detail/impl/win_mutex.ipp +++ b/include/boost/asio/detail/impl/win_mutex.ipp @@ -44,6 +44,8 @@ int win_mutex::do_init() // we'll just call the Windows API and hope. # if defined(UNDER_CE) ::InitializeCriticalSection(&crit_section_); +# elif defined(BOOST_ASIO_WINDOWS_APP) + ::InitializeCriticalSectionEx(&crit_section_, 0x80000000, 0); # else if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000)) return ::GetLastError(); @@ -54,6 +56,9 @@ int win_mutex::do_init() { # if defined(UNDER_CE) ::InitializeCriticalSection(&crit_section_); +# elif defined(BOOST_ASIO_WINDOWS_APP) + if (!::InitializeCriticalSectionEx(&crit_section_, 0, 0)) + return ::GetLastError(); # else if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000)) return ::GetLastError(); diff --git a/include/boost/asio/detail/impl/win_static_mutex.ipp b/include/boost/asio/detail/impl/win_static_mutex.ipp index 02b44b5d..14a08efd 100644 --- a/include/boost/asio/detail/impl/win_static_mutex.ipp +++ b/include/boost/asio/detail/impl/win_static_mutex.ipp @@ -50,13 +50,23 @@ int win_static_mutex::do_init() mutex_name, 128, L"asio-58CCDC44-6264-4842-90C2-F3C545CB8AA7-%u-%p", static_cast(::GetCurrentProcessId()), this); +#if defined(BOOST_ASIO_WINDOWS_APP) + HANDLE mutex = ::CreateMutexExW(0, mutex_name, CREATE_MUTEX_INITIAL_OWNER, 0); +#else // defined(BOOST_ASIO_WINDOWS_APP) HANDLE mutex = ::CreateMutexW(0, TRUE, mutex_name); +#endif // defined(BOOST_ASIO_WINDOWS_APP) DWORD last_error = ::GetLastError(); if (mutex == 0) return ::GetLastError(); if (last_error == ERROR_ALREADY_EXISTS) + { +#if defined(BOOST_ASIO_WINDOWS_APP) + ::WaitForSingleObjectEx(mutex, INFINITE, false); +#else // defined(BOOST_ASIO_WINDOWS_APP) ::WaitForSingleObject(mutex, INFINITE); +#endif // defined(BOOST_ASIO_WINDOWS_APP) + } if (initialised_) { @@ -84,6 +94,14 @@ int win_static_mutex::do_init() { # if defined(UNDER_CE) ::InitializeCriticalSection(&crit_section_); +# elif defined(BOOST_ASIO_WINDOWS_APP) + if (!::InitializeCriticalSectionEx(&crit_section_, 0, 0)) + { + last_error = ::GetLastError(); + ::ReleaseMutex(mutex); + ::CloseHandle(mutex); + return last_error; + } # else if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000)) { diff --git a/include/boost/asio/detail/impl/win_thread.ipp b/include/boost/asio/detail/impl/win_thread.ipp index 727c122e..138257aa 100644 --- a/include/boost/asio/detail/impl/win_thread.ipp +++ b/include/boost/asio/detail/impl/win_thread.ipp @@ -17,7 +17,9 @@ #include -#if defined(BOOST_ASIO_WINDOWS) && !defined(UNDER_CE) +#if defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_APP) \ + && !defined(UNDER_CE) #include #include @@ -136,6 +138,8 @@ void __stdcall apc_function(ULONG_PTR) {} #include -#endif // defined(BOOST_ASIO_WINDOWS) && !defined(UNDER_CE) +#endif // defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_APP) + // && !defined(UNDER_CE) #endif // BOOST_ASIO_DETAIL_IMPL_WIN_THREAD_IPP diff --git a/include/boost/asio/detail/local_free_on_block_exit.hpp b/include/boost/asio/detail/local_free_on_block_exit.hpp index 47b5dafc..a3b597e8 100644 --- a/include/boost/asio/detail/local_free_on_block_exit.hpp +++ b/include/boost/asio/detail/local_free_on_block_exit.hpp @@ -18,6 +18,7 @@ #include #if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +#if !defined(BOOST_ASIO_WINDOWS_APP) #include #include @@ -54,6 +55,7 @@ private: #include +#endif // !defined(BOOST_ASIO_WINDOWS_APP) #endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) #endif // BOOST_ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP diff --git a/include/boost/asio/detail/socket_types.hpp b/include/boost/asio/detail/socket_types.hpp index f4be9377..e8c71093 100644 --- a/include/boost/asio/detail/socket_types.hpp +++ b/include/boost/asio/detail/socket_types.hpp @@ -37,7 +37,9 @@ # endif // defined(WINAPI_FAMILY) # include # include -# include +# if !defined(BOOST_ASIO_WINDOWS_APP) +# include +# endif // !defined(BOOST_ASIO_WINDOWS_APP) # if defined(BOOST_ASIO_WSPIAPI_H_DEFINED) # undef _WSPIAPI_H_ # undef BOOST_ASIO_WSPIAPI_H_DEFINED @@ -47,7 +49,9 @@ # pragma comment(lib, "ws2.lib") # elif defined(_MSC_VER) || defined(__BORLANDC__) # pragma comment(lib, "ws2_32.lib") -# pragma comment(lib, "mswsock.lib") +# if !defined(BOOST_ASIO_WINDOWS_APP) +# pragma comment(lib, "mswsock.lib") +# endif // !defined(BOOST_ASIO_WINDOWS_APP) # endif // defined(_MSC_VER) || defined(__BORLANDC__) # endif // !defined(BOOST_ASIO_NO_DEFAULT_LINKED_LIBS) # include diff --git a/include/boost/asio/detail/thread.hpp b/include/boost/asio/detail/thread.hpp index adc5a557..1076e645 100644 --- a/include/boost/asio/detail/thread.hpp +++ b/include/boost/asio/detail/thread.hpp @@ -20,8 +20,8 @@ #if !defined(BOOST_ASIO_HAS_THREADS) # include #elif defined(BOOST_ASIO_WINDOWS) -# if defined(UNDER_CE) -# include +# if defined(BOOST_ASIO_WINDOWS_APP) || defined(UNDER_CE) +# include # else # include # endif @@ -40,8 +40,8 @@ namespace detail { #if !defined(BOOST_ASIO_HAS_THREADS) typedef null_thread thread; #elif defined(BOOST_ASIO_WINDOWS) -# if defined(UNDER_CE) -typedef wince_thread thread; +# if defined(BOOST_ASIO_WINDOWS_APP) || defined(UNDER_CE) +typedef winapi_thread thread; # else typedef win_thread thread; # endif diff --git a/include/boost/asio/detail/win_event.hpp b/include/boost/asio/detail/win_event.hpp index ff4df5be..d9aba6cb 100644 --- a/include/boost/asio/detail/win_event.hpp +++ b/include/boost/asio/detail/win_event.hpp @@ -102,7 +102,11 @@ public: { state_ += 2; lock.unlock(); +#if defined(BOOST_ASIO_WINDOWS_APP) + ::WaitForMultipleObjectsEx(2, events_, false, INFINITE, false); +#else // defined(BOOST_ASIO_WINDOWS_APP) ::WaitForMultipleObjects(2, events_, false, INFINITE); +#endif // defined(BOOST_ASIO_WINDOWS_APP) lock.lock(); state_ -= 2; } diff --git a/include/boost/asio/detail/win_thread.hpp b/include/boost/asio/detail/win_thread.hpp index e4654300..44bf8da5 100644 --- a/include/boost/asio/detail/win_thread.hpp +++ b/include/boost/asio/detail/win_thread.hpp @@ -17,7 +17,9 @@ #include -#if defined(BOOST_ASIO_WINDOWS) && !defined(UNDER_CE) +#if defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_APP) \ + && !defined(UNDER_CE) #include #include @@ -136,6 +138,8 @@ private: # include #endif // defined(BOOST_ASIO_HEADER_ONLY) -#endif // defined(BOOST_ASIO_WINDOWS) && !defined(UNDER_CE) +#endif // defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_APP) + // && !defined(UNDER_CE) #endif // BOOST_ASIO_DETAIL_WIN_THREAD_HPP diff --git a/include/boost/asio/detail/winapi_thread.hpp b/include/boost/asio/detail/winapi_thread.hpp new file mode 100644 index 00000000..ce4050b2 --- /dev/null +++ b/include/boost/asio/detail/winapi_thread.hpp @@ -0,0 +1,124 @@ +// +// detail/winapi_thread.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// 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) +// + +#ifndef BOOST_ASIO_DETAIL_WINAPI_THREAD_HPP +#define BOOST_ASIO_DETAIL_WINAPI_THREAD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include + +#if defined(BOOST_ASIO_WINDOWS) +#if defined(BOOST_ASIO_WINDOWS_APP) || defined(UNDER_CE) + +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace asio { +namespace detail { + +DWORD WINAPI winapi_thread_function(LPVOID arg); + +class winapi_thread + : private noncopyable +{ +public: + // Constructor. + template + winapi_thread(Function f, unsigned int = 0) + { + std::auto_ptr arg(new func(f)); + DWORD thread_id = 0; + thread_ = ::CreateThread(0, 0, winapi_thread_function, + arg.get(), 0, &thread_id); + if (!thread_) + { + DWORD last_error = ::GetLastError(); + boost::system::error_code ec(last_error, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "thread"); + } + arg.release(); + } + + // Destructor. + ~winapi_thread() + { + ::CloseHandle(thread_); + } + + // Wait for the thread to exit. + void join() + { +#if defined(BOOST_ASIO_WINDOWS_APP) + ::WaitForSingleObjectEx(thread_, INFINITE, false); +#else // defined(BOOST_ASIO_WINDOWS_APP) + ::WaitForSingleObject(thread_, INFINITE); +#endif // defined(BOOST_ASIO_WINDOWS_APP) + } + +private: + friend DWORD WINAPI winapi_thread_function(LPVOID arg); + + class func_base + { + public: + virtual ~func_base() {} + virtual void run() = 0; + }; + + template + class func + : public func_base + { + public: + func(Function f) + : f_(f) + { + } + + virtual void run() + { + f_(); + } + + private: + Function f_; + }; + + ::HANDLE thread_; +}; + +inline DWORD WINAPI winapi_thread_function(LPVOID arg) +{ + std::auto_ptr func( + static_cast(arg)); + func->run(); + return 0; +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include + +#endif // defined(BOOST_ASIO_WINDOWS_APP) || defined(UNDER_CE) +#endif // defined(BOOST_ASIO_WINDOWS) + +#endif // BOOST_ASIO_DETAIL_WINAPI_THREAD_HPP