update boost

This commit is contained in:
2023-11-24 12:56:13 -06:00
parent cfc99971af
commit 19d727037a
9260 changed files with 849256 additions and 299957 deletions

View File

@@ -7,6 +7,7 @@
#define BOOST_PROCESS_DETAIL_WINDOWS_ASIO_FWD_HPP_
#include <memory>
#include <boost/asio/ts/netfwd.hpp>
namespace boost { namespace asio {
@@ -19,43 +20,19 @@ template<typename Allocator>
class basic_streambuf;
typedef basic_streambuf<std::allocator<char>> streambuf;
class io_context;
class executor;
template <typename Handler>
class basic_yield_context;
namespace windows {
#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
class stream_handle_service;
template <typename StreamHandleService>
class basic_stream_handle;
typedef basic_stream_handle<stream_handle_service> stream_handle;
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
template <typename Executor>
class basic_stream_handle;
typedef basic_stream_handle<executor> stream_handle;
typedef basic_stream_handle<any_io_executor> stream_handle;
#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
class object_handle_service;
template <typename ObjectHandleService>
class basic_object_handle;
typedef basic_object_handle<object_handle_service> object_handle;
#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
template <typename Executor>
class basic_object_handle;
typedef basic_object_handle<executor> object_handle;
#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */
typedef basic_object_handle<any_io_executor> object_handle;
} //windows
} //asio

View File

@@ -17,19 +17,20 @@
#include <boost/asio/write.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/used_handles.hpp>
#include <boost/process/detail/windows/async_handler.hpp>
#include <boost/process/detail/windows/asio_fwd.hpp>
#include <boost/process/async_pipe.hpp>
#include <memory>
#include <future>
namespace boost { namespace process { namespace detail { namespace windows {
template<typename Buffer>
struct async_in_buffer : ::boost::process::detail::windows::handler_base_ext,
::boost::process::detail::windows::require_io_context
::boost::process::detail::windows::require_io_context,
::boost::process::detail::uses_handles
{
Buffer & buf;
@@ -42,6 +43,11 @@ struct async_in_buffer : ::boost::process::detail::windows::handler_base_ext,
std::shared_ptr<boost::process::async_pipe> pipe;
::boost::winapi::HANDLE_ get_used_handles() const
{
return std::move(*pipe).source().native_handle();
}
async_in_buffer(Buffer & buf) : buf(buf)
{
}

View File

@@ -16,6 +16,7 @@
#include <boost/winapi/error_codes.hpp>
#include <boost/asio/read.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/used_handles.hpp>
#include <boost/process/detail/windows/asio_fwd.hpp>
#include <istream>
@@ -108,12 +109,18 @@ struct async_out_buffer : ::boost::process::detail::windows::handler_base_ext,
template<int p1, int p2, typename Type>
struct async_out_future : ::boost::process::detail::windows::handler_base_ext,
::boost::process::detail::windows::require_io_context
::boost::process::detail::windows::require_io_context,
::boost::process::detail::uses_handles
{
std::shared_ptr<boost::process::async_pipe> pipe;
std::shared_ptr<std::promise<Type>> promise = std::make_shared<std::promise<Type>>();
std::shared_ptr<boost::asio::streambuf> buffer = std::make_shared<boost::asio::streambuf>();
::boost::winapi::HANDLE_ get_used_handles() const
{
return std::move(*pipe).sink().native_handle();
}
async_out_future(std::future<Type> & fut)
{

View File

@@ -40,23 +40,31 @@ class async_pipe
{
::boost::asio::windows::stream_handle _source;
::boost::asio::windows::stream_handle _sink ;
public:
typedef ::boost::winapi::HANDLE_ native_handle_type;
typedef ::boost::asio::windows::stream_handle handle_type;
inline async_pipe(boost::asio::io_context & ios,
const std::string & name = make_pipe_name())
: async_pipe(ios, ios, name) {}
inline async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink,
const std::string & name = make_pipe_name());
const std::string & name, bool private_);
public:
typedef ::boost::winapi::HANDLE_ native_handle_type;
typedef ::boost::asio::windows::stream_handle handle_type;
typedef typename handle_type::executor_type executor_type;
async_pipe(boost::asio::io_context & ios) : async_pipe(ios, ios, make_pipe_name(), true) {}
async_pipe(boost::asio::io_context & ios_source, boost::asio::io_context & ios_sink)
: async_pipe(ios_source, ios_sink, make_pipe_name(), true) {}
async_pipe(boost::asio::io_context & ios, const std::string & name)
: async_pipe(ios, ios, name, false) {}
async_pipe(boost::asio::io_context & ios_source, boost::asio::io_context & ios_sink, const std::string & name)
: async_pipe(ios_source, ios_sink, name, false) {}
inline async_pipe(const async_pipe& rhs);
async_pipe(async_pipe&& rhs) : _source(std::move(rhs._source)), _sink(std::move(rhs._sink))
{
rhs._source.assign (::boost::winapi::INVALID_HANDLE_VALUE_);
rhs._sink .assign (::boost::winapi::INVALID_HANDLE_VALUE_);
}
template<class CharT, class Traits = std::char_traits<CharT>>
explicit async_pipe(::boost::asio::io_context & ios_source,
@@ -191,13 +199,15 @@ public:
handle_type source(::boost::asio::io_context& ios) &&
{
::boost::asio::windows::stream_handle stolen(ios.get_executor(), _source.native_handle());
_source.assign(::boost::winapi::INVALID_HANDLE_VALUE_);
boost::system::error_code ec;
_source.assign(::boost::winapi::INVALID_HANDLE_VALUE_, ec);
return stolen;
}
handle_type sink (::boost::asio::io_context& ios) &&
{
::boost::asio::windows::stream_handle stolen(ios.get_executor(), _sink.native_handle());
_sink.assign(::boost::winapi::INVALID_HANDLE_VALUE_);
boost::system::error_code ec;
_sink.assign(::boost::winapi::INVALID_HANDLE_VALUE_, ec);
return stolen;
}
@@ -235,12 +245,11 @@ public:
}
};
async_pipe::async_pipe(const async_pipe& p) :
_source(const_cast<handle_type&>(p._source).get_executor()),
_sink (const_cast<handle_type&>(p._sink).get_executor())
{
auto proc = ::boost::winapi::GetCurrentProcess();
::boost::winapi::HANDLE_ source;
@@ -266,14 +275,16 @@ async_pipe::async_pipe(const async_pipe& p) :
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
_source.assign(source);
_sink. assign(sink);
if (source != ::boost::winapi::INVALID_HANDLE_VALUE_)
_source.assign(source);
if (sink != ::boost::winapi::INVALID_HANDLE_VALUE_)
_sink. assign(sink);
}
async_pipe::async_pipe(boost::asio::io_context & ios_source,
boost::asio::io_context & ios_sink,
const std::string & name) : _source(ios_source), _sink(ios_sink)
const std::string & name, bool private_) : _source(ios_source), _sink(ios_sink)
{
static constexpr int FILE_FLAG_OVERLAPPED_ = 0x40000000; //temporary
@@ -285,7 +296,7 @@ async_pipe::async_pipe(boost::asio::io_context & ios_source,
#endif
::boost::winapi::PIPE_ACCESS_INBOUND_
| FILE_FLAG_OVERLAPPED_, //write flag
0, 1, 8192, 8192, 0, nullptr);
0, private_ ? 1 : ::boost::winapi::PIPE_UNLIMITED_INSTANCES_, 8192, 8192, 0, nullptr);
if (source == boost::winapi::INVALID_HANDLE_VALUE_)
@@ -310,6 +321,44 @@ async_pipe::async_pipe(boost::asio::io_context & ios_source,
_sink.assign(sink);
}
template<class CharT, class Traits>
async_pipe& async_pipe::operator=(const basic_pipe<CharT, Traits> & p)
{
auto proc = ::boost::winapi::GetCurrentProcess();
::boost::winapi::HANDLE_ source;
::boost::winapi::HANDLE_ sink;
//cannot get the handle from a const object.
auto source_in = p.native_source();
auto sink_in = p.native_sink();
if (source_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, source_in.native_handle(), proc, &source, 0,
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
if (sink_in == ::boost::winapi::INVALID_HANDLE_VALUE_)
sink = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
proc, sink_in.native_handle(), proc, &sink, 0,
static_cast<::boost::winapi::BOOL_>(true),
::boost::winapi::DUPLICATE_SAME_ACCESS_))
throw_last_error("Duplicate Pipe Failed");
//so we also assign the io_context
if (source != ::boost::winapi::INVALID_HANDLE_VALUE_)
_source.assign(source);
if (sink != ::boost::winapi::INVALID_HANDLE_VALUE_)
_sink.assign(sink);
return *this;
}
async_pipe& async_pipe::operator=(const async_pipe & p)
{
auto proc = ::boost::winapi::GetCurrentProcess();
@@ -321,6 +370,8 @@ async_pipe& async_pipe::operator=(const async_pipe & p)
auto &source_in = const_cast<::boost::asio::windows::stream_handle &>(p._source);
auto &sink_in = const_cast<::boost::asio::windows::stream_handle &>(p._sink);
source_in.get_executor();
if (source_in.native_handle() == ::boost::winapi::INVALID_HANDLE_VALUE_)
source = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if (!::boost::winapi::DuplicateHandle(
@@ -338,24 +389,23 @@ async_pipe& async_pipe::operator=(const async_pipe & p)
throw_last_error("Duplicate Pipe Failed");
//so we also assign the io_context
_source = ::boost::asio::windows::stream_handle(source_in.get_executor(), source);
_sink = ::boost::asio::windows::stream_handle(source_in.get_executor(), sink);
if (source != ::boost::winapi::INVALID_HANDLE_VALUE_)
_source = ::boost::asio::windows::stream_handle(source_in.get_executor(), source);
else
_source = ::boost::asio::windows::stream_handle(source_in.get_executor());
if (sink != ::boost::winapi::INVALID_HANDLE_VALUE_)
_sink = ::boost::asio::windows::stream_handle(source_in.get_executor(), sink);
else
_sink = ::boost::asio::windows::stream_handle(source_in.get_executor());
return *this;
}
async_pipe& async_pipe::operator=(async_pipe && rhs)
{
if (_source.native_handle() != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_source.native_handle());
if (_sink.native_handle() != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_sink.native_handle());
_source.assign(rhs._source.native_handle());
_sink .assign(rhs._sink .native_handle());
rhs._source.assign(::boost::winapi::INVALID_HANDLE_VALUE_);
rhs._sink .assign(::boost::winapi::INVALID_HANDLE_VALUE_);
_source = std::move(rhs._source);
_sink = std::move(rhs._sink);
return *this;
}

View File

@@ -30,14 +30,17 @@ inline std::string build_args(const std::string & exe, std::vector<std::string>
{
std::string st = exe;
//put in quotes if it has spaces
//put in quotes if it has spaces or double quotes
if(!exe.empty())
{
boost::replace_all(st, "\"", "\\\"");
auto it = st.find_first_of(" \"");
auto it = std::find(st.begin(), st.end(), ' ');
if (it != st.end())//contains spaces.
if(it != st.npos)//contains spaces.
{
// double existing quotes
boost::replace_all(st, "\"", "\"\"");
// surround with quotes
st.insert(st.begin(), '"');
st += '"';
}
@@ -45,18 +48,21 @@ inline std::string build_args(const std::string & exe, std::vector<std::string>
for (auto & arg : data)
{
boost::replace_all(arg, "\"", "\\\"");
auto it = std::find(arg.begin(), arg.end(), ' ');//contains space?
if (it != arg.end())//ok, contains spaces.
if(!arg.empty())
{
//the first one is put directly onto the output,
//because then I don't have to copy the whole string
arg.insert(arg.begin(), '"');
arg += '"'; //thats the post one.
auto it = arg.find_first_of(" \"");//contains space or double quotes?
if(it != arg.npos)//yes
{
// double existing quotes
boost::replace_all(arg, "\"", "\"\"");
// surround with quotes
arg.insert(arg.begin(), '"');
arg += '"';
}
}
if (!st.empty())//first one does not need a preceeding space
if (!st.empty())//first one does not need a preceding space
st += ' ';
st += arg;
@@ -68,33 +74,39 @@ inline std::wstring build_args(const std::wstring & exe, std::vector<std::wstrin
{
std::wstring st = exe;
//put in quotes if it has spaces
//put in quotes if it has spaces or double quotes
if(!exe.empty())
{
boost::replace_all(st, L"\"", L"\\\"");
auto it = st.find_first_of(L" \"");
auto it = std::find(st.begin(), st.end(), L' ');
if (it != st.end())//contains spaces.
if(it != st.npos)//contains spaces or double quotes.
{
// double existing quotes
boost::replace_all(st, L"\"", L"\"\"");
// surround with quotes
st.insert(st.begin(), L'"');
st += L'"';
}
}
for (auto & arg : data)
for(auto & arg : data)
{
boost::replace_all(arg, L"\"", L"\\\"");
auto it = std::find(arg.begin(), arg.end(), L' ');//contains space?
if (it != arg.end())//ok, contains spaces.
if(!arg.empty())
{
//the first one is put directly onto the output,
//because then I don't have to copy the whole string
arg.insert(arg.begin(), L'"');
arg += L'"'; //thats the post one.
auto it = arg.find_first_of(L" \"");//contains space or double quotes?
if(it != arg.npos)//yes
{
// double existing quotes
boost::replace_all(arg, L"\"", L"\"\"");
// surround with quotes
arg.insert(arg.begin(), L'"');
arg += '"';
}
}
if (!st.empty())//first one does not need a preceeding space
if (!st.empty())//first one does not need a preceding space
st += L' ';
st += arg;
@@ -147,8 +159,13 @@ struct exe_cmd_init : handler_base_ext
return exe_cmd_init<Char>(std::move(sh), std::move(args_));
}
#ifdef BOOST_PROCESS_USE_STD_FS
static std:: string get_shell(char) {return shell(). string(); }
static std::wstring get_shell(wchar_t) {return shell().wstring(); }
#else
static std:: string get_shell(char) {return shell(). string(codecvt()); }
static std::wstring get_shell(wchar_t) {return shell().wstring(codecvt());}
#endif
static exe_cmd_init<Char> cmd_shell(string_type&& cmd)
{

View File

@@ -98,7 +98,7 @@ public:
return static_cast<int_type>(read_len);
}
bool is_open()
bool is_open() const
{
return (_source != ::boost::winapi::INVALID_HANDLE_VALUE_) ||
(_sink != ::boost::winapi::INVALID_HANDLE_VALUE_);
@@ -152,13 +152,13 @@ basic_pipe<Char, Traits>::basic_pipe(const std::string & name)
name_.c_str(),
::boost::winapi::PIPE_ACCESS_INBOUND_
| FILE_FLAG_OVERLAPPED_, //write flag
0, 1, 8192, 8192, 0, nullptr);
0, ::boost::winapi::PIPE_UNLIMITED_INSTANCES_, 8192, 8192, 0, nullptr);
if (source == boost::winapi::INVALID_HANDLE_VALUE_)
::boost::process::detail::throw_last_error("create_named_pipe() failed");
::boost::winapi::HANDLE_ sink = boost::winapi::create_file(
name.c_str(),
name_.c_str(),
::boost::winapi::GENERIC_WRITE_, 0, nullptr,
OPEN_EXISTING_,
FILE_FLAG_OVERLAPPED_, //to allow read

View File

@@ -17,7 +17,7 @@
namespace boost { namespace process { namespace detail { namespace windows {
typedef int pid_t;
typedef ::boost::winapi::DWORD_ pid_t;
struct child_handle
{
@@ -66,7 +66,7 @@ struct child_handle
pid_t id() const
{
return static_cast<int>(proc_info.dwProcessId);
return static_cast<pid_t>(proc_info.dwProcessId);
}
typedef ::boost::winapi::HANDLE_ process_handle_t;
@@ -81,7 +81,7 @@ struct child_handle
{
::boost::winapi::BOOL_ value;
if (!::boost::winapi::IsProcessInJob(proc_info.hProcess, nullptr, &value))
throw_last_error("IsProcessinJob Failed");
throw_last_error("IsProcessInJob Failed");
return value!=0;
}
bool in_group(std::error_code &ec) const noexcept

View File

@@ -73,8 +73,8 @@ inline auto native_environment_impl<Char>::get(const pointer_type id) -> string_
if (size == sizeof(buf)) //the return size gives the size without the null, so I know this went wrong
{
/*limit defined here https://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx
* but I used 32768 so it is a multiple of 4096.
/* limit defined here https://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx
* but I used 32768, so it is a multiple of 4096.
*/
constexpr static std::size_t max_size = 32768;
//Handle variables longer then buf.
@@ -90,12 +90,12 @@ inline auto native_environment_impl<Char>::get(const pointer_type id) -> string_
::boost::process::detail::throw_last_error("GetEnvironmentVariable() failed");
else
return std::basic_string<Char>(
buf.data(), buf.data()+ size + 1);
buf.data(), buf.data()+ size);
}
}
return std::basic_string<Char>(buf, buf+size+1);
return std::basic_string<Char>(buf, buf+size);
}
template<typename Char>
@@ -232,6 +232,8 @@ basic_environment_impl<Char>::basic_environment_impl(const native_environment_im
template<typename Char>
inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type
{
if (id.size() >= _data.size()) //ok, so it is impossible id is in there.
return string_type(_data.data());
if (std::equal(id.begin(), id.end(), _data.begin()) && (_data[id.size()] == equal_sign<Char>()))
return string_type(_data.data()); //null-char is handled by the string.
@@ -271,7 +273,7 @@ template<typename Char>
inline void basic_environment_impl<Char>::reset(const string_type &id)
{
//ok, we need to check the size of data first
if (id.size() >= _data.size()) //ok, so it's impossible id is in there.
if (id.size() >= _data.size()) //ok, so it is impossible id is in there.
return;
//check if it's the first one, spares us the search.

View File

@@ -10,7 +10,8 @@
#include <boost/winapi/handles.hpp>
#include <boost/winapi/file_management.hpp>
#include <string>
#include <boost/filesystem/path.hpp>
#include <boost/process/filesystem.hpp>
#include <boost/core/exchange.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
@@ -39,7 +40,7 @@ struct file_descriptor
}
file_descriptor() = default;
file_descriptor(const boost::filesystem::path& p, mode_t mode = read_write)
file_descriptor(const boost::process::filesystem::path& p, mode_t mode = read_write)
: file_descriptor(p.native(), mode)
{
}
@@ -90,10 +91,19 @@ struct file_descriptor
}
file_descriptor(const file_descriptor & ) = delete;
file_descriptor(file_descriptor && ) = default;
file_descriptor(file_descriptor &&other)
: _handle( boost::exchange(other._handle, ::boost::winapi::INVALID_HANDLE_VALUE_) )
{
}
file_descriptor& operator=(const file_descriptor & ) = delete;
file_descriptor& operator=(file_descriptor && ) = default;
file_descriptor& operator=(file_descriptor &&other)
{
if (_handle != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_handle);
_handle = boost::exchange(other._handle, ::boost::winapi::INVALID_HANDLE_VALUE_);
return *this;
}
~file_descriptor()
{

View File

@@ -13,16 +13,20 @@
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/used_handles.hpp>
#include <boost/process/detail/windows/file_descriptor.hpp>
#include <io.h>
namespace boost { namespace process { namespace detail { namespace windows {
struct file_in : public ::boost::process::detail::handler_base
struct file_in : public ::boost::process::detail::handler_base,
::boost::process::detail::uses_handles
{
file_descriptor file;
::boost::winapi::HANDLE_ handle = file.handle();
::boost::winapi::HANDLE_ get_used_handles() const { return handle; }
template<typename T>
file_in(T&& t) : file(std::forward<T>(t), file_descriptor::read) {}
file_in(FILE * f) : handle(reinterpret_cast<::boost::winapi::HANDLE_>(_get_osfhandle(_fileno(f)))) {}

View File

@@ -14,16 +14,21 @@
#include <boost/winapi/handles.hpp>
#include <boost/winapi/handle_info.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/used_handles.hpp>
#include <boost/process/detail/windows/file_descriptor.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
template<int p1, int p2>
struct file_out : public ::boost::process::detail::handler_base
struct file_out : public ::boost::process::detail::handler_base,
::boost::process::detail::uses_handles
{
file_descriptor file;
::boost::winapi::HANDLE_ handle = file.handle();
::boost::winapi::HANDLE_ get_used_handles() const { return handle; }
template<typename T>
file_out(T&& t) : file(std::forward<T>(t), file_descriptor::write) {}
file_out(FILE * f) : handle(reinterpret_cast<void*>(_get_osfhandle(_fileno(f)))) {}

View File

@@ -6,9 +6,10 @@
#ifndef BOOST_PROCESS_DETAIL_WINDOWS_GROUP_REF_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_GROUP_REF_HPP_
#include <boost/winapi/process.hpp>
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/windows/group_handle.hpp>
#include <boost/winapi/process.hpp>
#include <boost/process/detail/used_handles.hpp>
#include <boost/process/detail/windows/handler.hpp>
namespace boost { namespace process {
@@ -17,10 +18,12 @@ namespace detail { namespace windows {
struct group_ref : handler_base_ext
struct group_ref : handler_base_ext, ::boost::process::detail::uses_handles
{
::boost::winapi::HANDLE_ handle;
::boost::winapi::HANDLE_ get_used_handles() const { return handle; }
explicit group_ref(group_handle &g) :
handle(g.handle())
{}

View File

@@ -0,0 +1,262 @@
// Copyright (c) 2018 Klemens D. Morgenstern
//
// 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_PROCESS_DETAIL_WINDOWS_HANDLE_WORKAROUND_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_HANDLE_WORKAROUND_HPP_
#include <boost/winapi/basic_types.hpp>
#include <boost/winapi/dll.hpp>
#include <boost/winapi/access_rights.hpp>
//#define BOOST_USE_WINDOWS_H 1
#if defined( BOOST_USE_WINDOWS_H )
#include <winternl.h>
#endif
namespace boost { namespace process { namespace detail { namespace windows { namespace workaround
{
typedef struct _SYSTEM_HANDLE_ENTRY_
{
::boost::winapi::ULONG_ OwnerPid;
::boost::winapi::BYTE_ ObjectType;
::boost::winapi::BYTE_ HandleFlags;
::boost::winapi::USHORT_ HandleValue;
::boost::winapi::PVOID_ ObjectPointer;
::boost::winapi::ULONG_ AccessMask;
} SYSTEM_HANDLE_ENTRY_, *PSYSTEM_HANDLE_ENTRY_;
typedef struct _SYSTEM_HANDLE_INFORMATION_
{
::boost::winapi::ULONG_ Count;
SYSTEM_HANDLE_ENTRY_ Handle[1];
} SYSTEM_HANDLE_INFORMATION_, *PSYSTEM_HANDLE_INFORMATION_;
#if defined( BOOST_USE_WINDOWS_H )
using UNICODE_STRING_ = ::UNICODE_STRING;
using GENERIC_MAPPING_ = ::GENERIC_MAPPING;
using OBJECT_INFORMATION_CLASS_ = ::OBJECT_INFORMATION_CLASS;
constexpr static OBJECT_INFORMATION_CLASS_ ObjectTypeInformation = ::OBJECT_INFORMATION_CLASS::ObjectTypeInformation;
typedef struct _OBJECT_TYPE_INFORMATION_ {
UNICODE_STRING TypeName;
ULONG TotalNumberOfObjects;
ULONG TotalNumberOfHandles;
ULONG TotalPagedPoolUsage;
ULONG TotalNonPagedPoolUsage;
ULONG TotalNamePoolUsage;
ULONG TotalHandleTableUsage;
ULONG HighWaterNumberOfObjects;
ULONG HighWaterNumberOfHandles;
ULONG HighWaterPagedPoolUsage;
ULONG HighWaterNonPagedPoolUsage;
ULONG HighWaterNamePoolUsage;
ULONG HighWaterHandleTableUsage;
ULONG InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ULONG ValidAccessMask;
BOOLEAN SecurityRequired;
BOOLEAN MaintainHandleCount;
UCHAR TypeIndex;
CHAR ReservedByte;
ULONG PoolType;
ULONG DefaultPagedPoolCharge;
ULONG DefaultNonPagedPoolCharge;
} OBJECT_TYPE_INFORMATION_, *POBJECT_TYPE_INFORMATION_;
#else
typedef enum _OBJECT_INFORMATION_CLASS_
{
ObjectBasicInformation,
ObjectNameInformation,
ObjectTypeInformation,
ObjectAllInformation,
ObjectDataInformation
} OBJECT_INFORMATION_CLASS_, *POBJECT_INFORMATION_CLASS_;
typedef struct _UNICODE_STRING_ {
::boost::winapi::USHORT_ Length;
::boost::winapi::USHORT_ MaximumLength;
::boost::winapi::LPWSTR_ Buffer;
} UNICODE_STRING_, *PUNICODE_STRING_;
typedef struct _GENERIC_MAPPING_ {
::boost::winapi::ACCESS_MASK_ GenericRead;
::boost::winapi::ACCESS_MASK_ GenericWrite;
::boost::winapi::ACCESS_MASK_ GenericExecute;
::boost::winapi::ACCESS_MASK_ GenericAll;
} GENERIC_MAPPING_;
#endif
typedef struct _OBJECT_BASIC_INFORMATION {
::boost::winapi::ULONG_ Attributes;
::boost::winapi::ACCESS_MASK_ GrantedAccess;
::boost::winapi::ULONG_ HandleCount;
::boost::winapi::ULONG_ PointerCount;
::boost::winapi::ULONG_ PagedPoolUsage;
::boost::winapi::ULONG_ NonPagedPoolUsage;
::boost::winapi::ULONG_ Reserved[3];
::boost::winapi::ULONG_ NameInformationLength;
::boost::winapi::ULONG_ TypeInformationLength;
::boost::winapi::ULONG_ SecurityDescriptorLength;
::boost::winapi::LARGE_INTEGER_ CreateTime;
} OBJECT_BASIC_INFORMATION_, *POBJECT_BASIC_INFORMATION_;
typedef struct _OBJECT_NAME_INFORMATION {
UNICODE_STRING_ Name;
} OBJECT_NAME_INFORMATION_, *POBJECT_NAME_INFORMATION_;
#if defined( BOOST_USE_WINDOWS_H )
extern "C"
{
using SYSTEM_INFORMATION_CLASS_ = ::SYSTEM_INFORMATION_CLASS;
constexpr static SYSTEM_INFORMATION_CLASS_ SystemHandleInformation_ = static_cast<SYSTEM_INFORMATION_CLASS_>(16);
inline ::boost::winapi::NTSTATUS_ nt_system_query_information(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
void * SystemInformation,
::boost::winapi::ULONG_ SystemInformationLength,
::boost::winapi::PULONG_ ReturnLength)
{
return ::NtQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
}
inline ::boost::winapi::NTSTATUS_ nt_query_object(
::boost::winapi::HANDLE_ Handle,
OBJECT_INFORMATION_CLASS_ ObjectInformationClass,
::boost::winapi::PVOID_ ObjectInformation,
::boost::winapi::ULONG_ ObjectInformationLength,
::boost::winapi::PULONG_ ReturnLength
)
{
return ::NtQueryObject(Handle, ObjectInformationClass, ObjectInformation, ObjectInformationLength, ReturnLength);
}
}
#else
//this import workaround is to keep it a header-only library. and enums cannot be imported from the winapi.
extern "C"
{
typedef enum _SYSTEM_INFORMATION_CLASS_
{
SystemBasicInformation_ = 0,
SystemProcessorInformation_ = 1,
SystemPerformanceInformation_ = 2,
SystemTimeOfDayInformation_ = 3,
SystemProcessInformation_ = 5,
SystemProcessorPerformanceInformation_ = 8,
SystemHandleInformation_ = 16,
SystemPagefileInformation_ = 18,
SystemInterruptInformation_ = 23,
SystemExceptionInformation_ = 33,
SystemRegistryQuotaInformation_ = 37,
SystemLookasideInformation_ = 45
} SYSTEM_INFORMATION_CLASS_;
typedef struct _OBJECT_TYPE_INFORMATION_ {
UNICODE_STRING_ TypeName;
::boost::winapi::ULONG_ TotalNumberOfObjects;
::boost::winapi::ULONG_ TotalNumberOfHandles;
::boost::winapi::ULONG_ TotalPagedPoolUsage;
::boost::winapi::ULONG_ TotalNonPagedPoolUsage;
::boost::winapi::ULONG_ TotalNamePoolUsage;
::boost::winapi::ULONG_ TotalHandleTableUsage;
::boost::winapi::ULONG_ HighWaterNumberOfObjects;
::boost::winapi::ULONG_ HighWaterNumberOfHandles;
::boost::winapi::ULONG_ HighWaterPagedPoolUsage;
::boost::winapi::ULONG_ HighWaterNonPagedPoolUsage;
::boost::winapi::ULONG_ HighWaterNamePoolUsage;
::boost::winapi::ULONG_ HighWaterHandleTableUsage;
::boost::winapi::ULONG_ InvalidAttributes;
GENERIC_MAPPING_ GenericMapping;
::boost::winapi::ULONG_ ValidAccessMask;
::boost::winapi::BOOLEAN_ SecurityRequired;
::boost::winapi::BOOLEAN_ MaintainHandleCount;
::boost::winapi::UCHAR_ TypeIndex;
::boost::winapi::CHAR_ ReservedByte;
::boost::winapi::ULONG_ PoolType;
::boost::winapi::ULONG_ DefaultPagedPoolCharge;
::boost::winapi::ULONG_ DefaultNonPagedPoolCharge;
} OBJECT_TYPE_INFORMATION_, *POBJECT_TYPE_INFORMATION_;
/*
NTSTATUS NtQuerySystemInformation(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength
);
*/
typedef ::boost::winapi::NTSTATUS_ (*nt_system_query_information_p )(
SYSTEM_INFORMATION_CLASS_,
void *,
::boost::winapi::ULONG_,
::boost::winapi::PULONG_);
/*
NTSYSCALLAPI NTSTATUS NtQueryObject(
HANDLE Handle,
OBJECT_INFORMATION_CLASS ObjectInformationClass,
PVOID ObjectInformation,
ULONG ObjectInformationLength,
PULONG ReturnLength
);
*/
typedef ::boost::winapi::NTSTATUS_ (*nt_query_object_p )(
::boost::winapi::HANDLE_,
OBJECT_INFORMATION_CLASS_,
void *,
::boost::winapi::ULONG_,
::boost::winapi::PULONG_);
}
inline ::boost::winapi::NTSTATUS_ nt_system_query_information(
SYSTEM_INFORMATION_CLASS_ SystemInformationClass,
void *SystemInformation,
::boost::winapi::ULONG_ SystemInformationLength,
::boost::winapi::PULONG_ ReturnLength)
{
static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle(L"Ntdll.dll");
static nt_system_query_information_p f = reinterpret_cast<nt_system_query_information_p>(::boost::winapi::get_proc_address(h, "NtQuerySystemInformation"));
return (*f)(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
}
inline ::boost::winapi::BOOL_ nt_query_object(
::boost::winapi::HANDLE_ Handle,
OBJECT_INFORMATION_CLASS_ ObjectInformationClass,
void *ObjectInformation,
::boost::winapi::ULONG_ ObjectInformationLength,
::boost::winapi::PULONG_ ReturnLength)
{
static ::boost::winapi::HMODULE_ h = ::boost::winapi::get_module_handle(L"Ntdll.dll");
static nt_query_object_p f = reinterpret_cast<nt_query_object_p>(::boost::winapi::get_proc_address(h, "NtQueryObject"));
return (*f)(Handle, ObjectInformationClass, ObjectInformation, ObjectInformationLength, ReturnLength);
}
#endif
}}}}}
#endif /* BOOST_PROCESS_DETAIL_WINDOWS_JOB_WORKAROUND_HPP_ */

View File

@@ -0,0 +1,178 @@
// Copyright (c) 2019 Klemens D. Morgenstern
//
// 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_PROCESS_DETAIL_WINDOWS_HANDLES_HPP_
#define BOOST_PROCESS_DETAIL_WINDOWS_HANDLES_HPP_
#include <vector>
#include <system_error>
#include <boost/process/detail/windows/handle_workaround.hpp>
#include <boost/process/detail/windows/handler.hpp>
#include <boost/winapi/get_current_process_id.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/winapi/handle_info.hpp>
namespace boost { namespace process { namespace detail {
template<typename Executor, typename Function>
void foreach_used_handle(Executor &exec, Function &&func);
namespace windows {
using native_handle_type = ::boost::winapi::HANDLE_ ;
inline std::vector<native_handle_type> get_handles(std::error_code & ec)
{
auto pid = ::boost::winapi::GetCurrentProcessId();
std::vector<char> buffer(2048);
constexpr static auto STATUS_INFO_LENGTH_MISMATCH_ = static_cast<::boost::winapi::NTSTATUS_>(0xC0000004l);
auto info_pointer = reinterpret_cast<workaround::SYSTEM_HANDLE_INFORMATION_*>(buffer.data());
::boost::winapi::NTSTATUS_ nt_status = STATUS_INFO_LENGTH_MISMATCH_;
for (;
nt_status == STATUS_INFO_LENGTH_MISMATCH_;
nt_status = workaround::nt_system_query_information(
workaround::SystemHandleInformation_,
info_pointer, static_cast<::boost::winapi::ULONG_>(buffer.size()),
nullptr))
{
buffer.resize(buffer.size() * 2);
info_pointer = reinterpret_cast<workaround::SYSTEM_HANDLE_INFORMATION_*>(buffer.data());
}
if (nt_status < 0 || nt_status > 0x7FFFFFFF)
{
ec = ::boost::process::detail::get_last_error();
return {};
}
else
ec.clear();
std::vector<native_handle_type> res;
for (auto itr = info_pointer->Handle; itr != (info_pointer->Handle + info_pointer->Count); itr++)
{
if (itr->OwnerPid == pid)
res.push_back(reinterpret_cast<native_handle_type>(static_cast<std::uintptr_t>(itr->HandleValue)));
}
return res;
}
inline std::vector<native_handle_type> get_handles()
{
std::error_code ec;
auto res = get_handles(ec);
if (ec)
boost::process::detail::throw_error(ec, "NtQuerySystemInformation failed");
return res;
}
inline bool is_stream_handle(native_handle_type handle, std::error_code & ec)
{
::boost::winapi::ULONG_ actual_size;
auto nt_status = workaround::nt_query_object(
handle,
workaround::ObjectTypeInformation,
NULL,
0, &actual_size);
std::vector<char> vec;
vec.resize(actual_size);
workaround::OBJECT_TYPE_INFORMATION_ * type_info_p = reinterpret_cast<workaround::OBJECT_TYPE_INFORMATION_*>(vec.data());
nt_status = workaround::nt_query_object(
handle,
workaround::ObjectTypeInformation,
type_info_p,
actual_size, &actual_size);
if (nt_status < 0 || nt_status > 0x7FFFFFFF)
{
ec = ::boost::process::detail::get_last_error();
return false;
}
else
ec.clear();
auto &nm = type_info_p->TypeName.Buffer;
return type_info_p->TypeName.Length >= 5 &&
nm[0] == L'F' &&
nm[1] == L'i' &&
nm[2] == L'l' &&
nm[3] == L'e' &&
nm[4] == L'\0';
}
inline bool is_stream_handle(native_handle_type handle)
{
std::error_code ec;
auto res = is_stream_handle(handle, ec);
if (ec)
boost::process::detail::throw_error(ec, "NtQueryObject failed");
return res;
}
struct limit_handles_ : handler_base_ext
{
mutable std::vector<::boost::winapi::HANDLE_> handles_with_inherit_flag;
template<typename Executor>
void on_setup(Executor & exec) const
{
auto all_handles = get_handles();
foreach_used_handle(exec,
[&](::boost::winapi::HANDLE_ handle)
{
auto itr = std::find(all_handles.begin(), all_handles .end(), handle);
::boost::winapi::DWORD_ flags = 0u;
if (itr != all_handles.end())
*itr = ::boost::winapi::INVALID_HANDLE_VALUE_;
else if ((::boost::winapi::GetHandleInformation(*itr, &flags) != 0)
&&((flags & ::boost::winapi::HANDLE_FLAG_INHERIT_) == 0)) //it is NOT inherited anyhow, so ignore too
*itr = ::boost::winapi::INVALID_HANDLE_VALUE_;
});
auto part_itr = std::partition(all_handles.begin(), all_handles.end(),
[](::boost::winapi::HANDLE_ handle) {return handle != ::boost::winapi::INVALID_HANDLE_VALUE_;});
all_handles.erase(part_itr, all_handles.end()); //remove invalid handles
handles_with_inherit_flag = std::move(all_handles);
for (auto handle : handles_with_inherit_flag)
::boost::winapi::SetHandleInformation(handle, ::boost::winapi::HANDLE_FLAG_INHERIT_, 0);
}
template<typename Executor>
void on_error(Executor & exec, const std::error_code & ec) const
{
for (auto handle : handles_with_inherit_flag)
::boost::winapi::SetHandleInformation(handle, ::boost::winapi::HANDLE_FLAG_INHERIT_, ::boost::winapi::HANDLE_FLAG_INHERIT_);
}
template<typename Executor>
void on_success(Executor & exec) const
{
for (auto handle : handles_with_inherit_flag)
::boost::winapi::SetHandleInformation(handle, ::boost::winapi::HANDLE_FLAG_INHERIT_, ::boost::winapi::HANDLE_FLAG_INHERIT_);
}
};
}}}}
#endif //PROCESS_HANDLES_HPP

View File

@@ -8,7 +8,9 @@
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/async_handler.hpp>
#include <boost/process/detail/windows/is_running.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/windows/object_handle.hpp>
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
@@ -114,6 +116,15 @@ struct io_context_ref : boost::process::detail::handler_base
wait_handler wh(std::move(funcs), ios, process_handle, exec.exit_status);
::boost::winapi::DWORD_ code;
if(::boost::winapi::GetExitCodeProcess(process_handle, &code)
&& code != still_active)
{
::boost::asio::post(wh.handle->get_executor(), std::move(wh));
return;
}
auto handle_p = wh.handle.get();
handle_p->async_wait(std::move(wh));
}
@@ -130,12 +141,13 @@ struct io_context_ref : boost::process::detail::handler_base
boost::asio::io_context & ios, void * handle,
const std::shared_ptr<std::atomic<int>> &exit_status)
: funcs(std::move(funcs)),
handle(new boost::asio::windows::object_handle(ios.get_executor(), handle)),
handle(new boost::asio::windows::object_handle(
asio::prefer(ios.get_executor(), asio::execution::outstanding_work.tracked), handle)),
exit_status(exit_status)
{
}
void operator()(const boost::system::error_code & ec_in)
void operator()(const boost::system::error_code & ec_in = {})
{
std::error_code ec;
if (ec_in)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2106 Klemens D. Morgenstern
// Copyright (c) 2016 Klemens D. Morgenstern
//
// 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)
@@ -7,6 +7,7 @@
#define BOOST_PROCESS_WINDOWS_IS_RUNNING_HPP
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/windows/child_handle.hpp>
#include <system_error>
#include <cstdlib>
#include <boost/winapi/process.hpp>

View File

@@ -14,14 +14,18 @@
#include <boost/winapi/handles.hpp>
#include <boost/winapi/handle_info.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/used_handles.hpp>
#include <boost/process/detail/windows/file_descriptor.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
struct null_in : public ::boost::process::detail::handler_base
struct null_in : public ::boost::process::detail::handler_base, ::boost::process::detail::uses_handles
{
file_descriptor source{"NUL", file_descriptor::read};
::boost::winapi::HANDLE_ get_used_handles() const { return source.handle(); }
public:
template <class WindowsExecutor>
void on_setup(WindowsExecutor &e) const

View File

@@ -14,15 +14,18 @@
#include <boost/winapi/handles.hpp>
#include <boost/winapi/handle_info.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/used_handles.hpp>
#include <boost/process/detail/windows/file_descriptor.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
template<int p1, int p2>
struct null_out : public ::boost::process::detail::handler_base
struct null_out : public ::boost::process::detail::handler_base, ::boost::process::detail::uses_handles
{
file_descriptor sink {"NUL", file_descriptor::write}; //works because it gets destroyed AFTER launch.
::boost::winapi::HANDLE_ get_used_handles() const { return sink.handle(); }
template <typename WindowsExecutor>
void on_setup(WindowsExecutor &e) const;
};

View File

@@ -6,13 +6,20 @@
#ifndef BOOST_PROCESS_WINDOWS_ON_EXIT_HPP_
#define BOOST_PROCESS_WINDOWS_ON_EXIT_HPP_
#include <boost/process/async.hpp>
#include <boost/process/detail/config.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/process/detail/windows/async_handler.hpp>
#include <boost/asio/execution.hpp>
#include <system_error>
#include <functional>
namespace boost { namespace process { namespace detail { namespace windows {
namespace boost { namespace process { namespace detail {
template<typename Tuple>
inline asio::io_context& get_io_context(const Tuple & tup);
namespace windows {
struct on_exit_ : boost::process::detail::windows::async_handler
{
@@ -23,10 +30,12 @@ struct on_exit_ : boost::process::detail::windows::async_handler
}
template<typename Executor>
std::function<void(int, const std::error_code&)> on_exit_handler(Executor&)
std::function<void(int, const std::error_code&)> on_exit_handler(Executor& exec)
{
auto v = boost::asio::prefer(boost::process::detail::get_io_context(exec.seq).get_executor(),
boost::asio::execution::outstanding_work.tracked);
auto handler_ = this->handler;
return [handler_](int exit_code, const std::error_code & ec)
return [v, handler_](int exit_code, const std::error_code & ec)
{
handler_(static_cast<int>(exit_code), ec);
};

View File

@@ -12,14 +12,19 @@
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/process/detail/used_handles.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/system/error_code.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
struct pipe_in : public ::boost::process::detail::handler_base
struct pipe_in : public ::boost::process::detail::handler_base, ::boost::process::detail::uses_handles
{
::boost::winapi::HANDLE_ handle;
::boost::winapi::HANDLE_ get_used_handles() const { return handle; }
pipe_in(::boost::winapi::HANDLE_ handle) : handle(handle) {}
template<typename T> //async_pipe

View File

@@ -13,17 +13,20 @@
#include <boost/winapi/process.hpp>
#include <boost/winapi/handles.hpp>
#include <boost/process/detail/used_handles.hpp>
#include <boost/process/detail/handler_base.hpp>
#include <boost/system/error_code.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
template<int p1, int p2>
struct pipe_out : public ::boost::process::detail::handler_base
struct pipe_out : public ::boost::process::detail::handler_base, ::boost::process::detail::uses_handles
{
::boost::winapi::HANDLE_ handle;
::boost::winapi::HANDLE_ get_used_handles() const { return handle; }
pipe_out(::boost::winapi::HANDLE_ handle) : handle(handle) {}
template<typename T>
pipe_out(T & p) : handle(p.native_sink())

View File

@@ -11,8 +11,7 @@
#define BOOST_PROCESS_WINDOWS_SEARCH_PATH_HPP
#include <boost/process/detail/config.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/process/filesystem.hpp>
#include <boost/system/error_code.hpp>
#include <string>
#include <stdexcept>
@@ -24,9 +23,9 @@
namespace boost { namespace process { namespace detail { namespace windows {
inline boost::filesystem::path search_path(
const boost::filesystem::path &filename,
const std::vector<boost::filesystem::path> &path)
inline boost::process::filesystem::path search_path(
const boost::process::filesystem::path &filename,
const std::vector<boost::process::filesystem::path> &path)
{
const ::boost::process::wnative_environment ne{};
typedef typename ::boost::process::wnative_environment::const_entry_type value_type;
@@ -36,7 +35,9 @@ inline boost::filesystem::path search_path(
[&](const value_type & e)
{return id == ::boost::to_upper_copy(e.get_name(), ::boost::process::detail::process_locale());});
auto extensions_in = itr->to_vector();
std::vector<std::wstring> extensions_in;
if (itr != ne.cend())
extensions_in = itr->to_vector();
std::vector<std::wstring> extensions((extensions_in.size() * 2) + 1);
@@ -55,19 +56,23 @@ inline boost::filesystem::path search_path(
for (auto & ext : extensions)
boost::to_lower(ext);
for (const boost::filesystem::path & pp_ : path)
for (const boost::process::filesystem::path & pp_ : path)
{
auto p = pp_ / filename;
for (boost::filesystem::path ext : extensions)
for (boost::process::filesystem::path ext : extensions)
{
boost::filesystem::path pp = p;
pp += ext;
boost::process::filesystem::path pp_ext = p;
pp_ext += ext;
#if defined(BOOST_PROCESS_USE_STD_FS)
std::error_code ec;
#else
boost::system::error_code ec;
bool file = boost::filesystem::is_regular_file(pp, ec);
#endif
bool file = boost::process::filesystem::is_regular_file(pp_ext, ec);
if (!ec && file &&
::boost::winapi::sh_get_file_info(pp.native().c_str(), 0, 0, 0, ::boost::winapi::SHGFI_EXETYPE_))
::boost::winapi::sh_get_file_info(pp_ext.native().c_str(), 0, 0, 0, ::boost::winapi::SHGFI_EXETYPE_))
{
return pp;
return pp_ext;
}
}
}

View File

@@ -12,29 +12,29 @@
#include <boost/process/detail/config.hpp>
#include <system_error>
#include <boost/filesystem/path.hpp>
#include <boost/process/filesystem.hpp>
#include <boost/winapi/basic_types.hpp>
#include <boost/winapi/get_system_directory.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
inline boost::filesystem::path shell_path()
inline boost::process::filesystem::path shell_path()
{
::boost::winapi::WCHAR_ sysdir[260];
unsigned int size = ::boost::winapi::get_system_directory(sysdir, sizeof(sysdir));
if (!size)
throw_last_error("GetSystemDirectory() failed");
boost::filesystem::path p = sysdir;
boost::process::filesystem::path p = sysdir;
return p / "cmd.exe";
}
inline boost::filesystem::path shell_path(std::error_code &ec) noexcept
inline boost::process::filesystem::path shell_path(std::error_code &ec) noexcept
{
::boost::winapi::WCHAR_ sysdir[260];
unsigned int size = ::boost::winapi::get_system_directory(sysdir, sizeof(sysdir));
boost::filesystem::path p;
boost::process::filesystem::path p;
if (!size)
ec = std::error_code(
::boost::winapi::GetLastError(),

View File

@@ -27,7 +27,7 @@ inline bool wait_impl(const group_handle & p, std::error_code & ec, std::chrono:
while (workaround::get_queued_completion_status(
p._io_port, &completion_code,
&completion_key, &overlapped, wait_time))
&completion_key, &overlapped, static_cast<::boost::winapi::DWORD_>(wait_time)))
{
if (reinterpret_cast<::boost::winapi::HANDLE_>(completion_key) == p._job_object &&
completion_code == workaround::JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO_)
@@ -48,11 +48,11 @@ inline bool wait_impl(const group_handle & p, std::error_code & ec, std::chrono:
return false; //correct, nothing left.
}
//reduce the remaining wait time -> in case interrupted by something else
if (wait_time != ::boost::winapi::infinite)
if (wait_time != static_cast<int>(::boost::winapi::infinite))
{
auto now = std::chrono::system_clock::now();
auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
wait_time -= diff.count();
wait_time -= static_cast<std::chrono::system_clock::rep>(diff.count());
start_time = now;
if (wait_time <= 0)
return true; //timeout with other source