This commit is contained in:
2026-03-23 20:54:41 +08:00
commit e13b3650e9
4596 changed files with 1015768 additions and 0 deletions

View File

@@ -0,0 +1,144 @@
//
// boost/process/v2/windows/default_launcher.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
//
// 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_V2_WINDOWS_AS_USER_LAUNCHER_HPP
#define BOOST_PROCESS_V2_WINDOWS_AS_USER_LAUNCHER_HPP
#include <boost/process/v2/detail/config.hpp>
#include <boost/process/v2/windows/default_launcher.hpp>
BOOST_PROCESS_V2_BEGIN_NAMESPACE
namespace windows
{
/// A windows launcher using CreateProcessAsUser instead of CreateProcess
struct as_user_launcher : default_launcher
{
/// The token to be used in CreateProcessAsUser.
HANDLE token;
as_user_launcher(HANDLE token = INVALID_HANDLE_VALUE) : token(token) {}
template<typename ExecutionContext, typename Args, typename ... Inits>
auto operator()(ExecutionContext & context,
const typename std::enable_if<std::is_convertible<
ExecutionContext&, net::execution_context&>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
{
error_code ec;
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
if (ec)
v2::detail::throw_error(ec, "as_user_launcher");
return proc;
}
template<typename ExecutionContext, typename Args, typename ... Inits>
auto operator()(ExecutionContext & context,
error_code & ec,
const typename std::enable_if<std::is_convertible<
ExecutionContext&, net::execution_context&>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
{
return (*this)(context.get_executor(), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
}
template<typename Executor, typename Args, typename ... Inits>
auto operator()(Executor exec,
const typename std::enable_if<
net::execution::is_executor<Executor>::value ||
net::is_executor<Executor>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> basic_process<Executor>
{
error_code ec;
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
if (ec)
detail::throw_error(ec, "as_user_launcher");
return proc;
}
template<typename Executor, typename Args, typename ... Inits>
auto operator()(Executor exec,
error_code & ec,
const typename std::enable_if<
net::execution::is_executor<Executor>::value ||
net::is_executor<Executor>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> basic_process<Executor>
{
auto command_line = this->build_command_line(executable, args);
ec = detail::on_setup(*this, executable, command_line, inits...);
if (ec)
{
detail::on_error(*this, executable, command_line, ec, inits...);
return basic_process<Executor>(exec);
}
if (!inherited_handles.empty())
{
set_handle_list(ec);
if (ec)
return basic_process<Executor>(exec);
}
auto ok = ::CreateProcessAsUserW(
token,
executable.empty() ? nullptr : executable.c_str(),
command_line.empty() ? nullptr : &command_line.front(),
process_attributes,
thread_attributes,
inherited_handles.empty() ? FALSE : TRUE,
creation_flags,
environment,
current_directory.empty() ? nullptr : current_directory.c_str(),
&startup_info.StartupInfo,
&process_information);
if (ok == 0)
{
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
detail::on_error(*this, executable, command_line, ec, inits...);
if (process_information.hProcess != INVALID_HANDLE_VALUE)
::CloseHandle(process_information.hProcess);
if (process_information.hThread != INVALID_HANDLE_VALUE)
::CloseHandle(process_information.hThread);
return basic_process<Executor>(exec);
} else
{
detail::on_success(*this, executable, command_line, inits...);
if (process_information.hThread != INVALID_HANDLE_VALUE)
::CloseHandle(process_information.hThread);
return basic_process<Executor>(exec,
this->process_information.dwProcessId,
this->process_information.hProcess);
}
}
};
}
BOOST_PROCESS_V2_END_NAMESPACE
#endif // BOOST_PROCESS_V2_WINDOWS_AS_USER_LAUNCHER_HPP

View File

@@ -0,0 +1,50 @@
//
// boost/process/v2/windows/default_launcher.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
//
// 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_V2_WINDOWS_CREATION_FLAGS_HPP
#define BOOST_PROCESS_V2_WINDOWS_CREATION_FLAGS_HPP
#include <boost/process/v2/windows/default_launcher.hpp>
BOOST_PROCESS_V2_BEGIN_NAMESPACE
namespace windows
{
/// An initializer to add to the dwFlags in the startup-info
/**
* @tparam Flags The flags to be set.
*/
template<DWORD Flags>
struct process_creation_flags
{
constexpr process_creation_flags () {}
error_code on_setup(windows::default_launcher & launcher,
const filesystem::path &,
const std::wstring &) const
{
launcher.creation_flags |= Flags;
return error_code {};
};
};
/// A flag to create a new process group. Necessary to allow interrupts for the subprocess.
constexpr static process_creation_flags<CREATE_NEW_PROCESS_GROUP> create_new_process_group;
constexpr static process_creation_flags<CREATE_BREAKAWAY_FROM_JOB> create_breakaway_from_job;
constexpr static process_creation_flags<CREATE_NEW_CONSOLE> create_new_console;
}
BOOST_PROCESS_V2_END_NAMESPACE
#endif // BOOST_PROCESS_V2_WINDOWS_CREATION_FLAGS_HPP

View File

@@ -0,0 +1,451 @@
//
// boost/process/v2/windows/default_launcher.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
//
// 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_V2_WINDOWS_DEFAULT_LAUNCHER_HPP
#define BOOST_PROCESS_V2_WINDOWS_DEFAULT_LAUNCHER_HPP
#include <boost/process/v2/cstring_ref.hpp>
#include <boost/process/v2/detail/config.hpp>
#include <boost/process/v2/detail/last_error.hpp>
#include <boost/process/v2/detail/throw_error.hpp>
#include <boost/process/v2/detail/utf8.hpp>
#include <boost/process/v2/error.hpp>
#include <numeric>
#include <memory>
#include <type_traits>
#include <windows.h>
#if defined(BOOST_PROCESS_V2_STANDALONE)
#include <asio/execution/executor.hpp>
#include <asio/is_executor.hpp>
#include <asio/execution_context.hpp>
#else
#include <boost/asio/execution/executor.hpp>
#include <boost/asio/is_executor.hpp>
#include <boost/asio/execution_context.hpp>
#endif
BOOST_PROCESS_V2_BEGIN_NAMESPACE
template<typename Executor>
struct basic_process;
namespace detail
{
struct base {};
struct derived : base {};
template<typename Launcher, typename Init>
inline error_code invoke_on_setup(Launcher & /*launcher*/, const filesystem::path &executable, std::wstring &cmd_line,
Init && /*init*/, base && )
{
return error_code{};
}
template<typename Launcher, typename Init>
inline auto invoke_on_setup(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
Init && init, derived && )
-> decltype(init.on_setup(launcher, executable, cmd_line))
{
return init.on_setup(launcher, executable, cmd_line);
}
template<typename Launcher, typename Init>
inline std::false_type probe_on_setup(
Launcher & launcher, Init && init, base && );
template<typename Launcher, typename Init>
inline auto probe_on_setup(Launcher & launcher, Init && init, derived && )
-> std::is_same<error_code, decltype(init.on_setup(launcher, std::declval<const filesystem::path &>(), std::declval<std::wstring &>()))>;
template<typename Launcher, typename Init>
using has_on_setup = decltype(probe_on_setup(std::declval<Launcher&>(), std::declval<Init>(), derived{}));
template<typename Launcher>
inline error_code on_setup(Launcher & /*launcher*/, const filesystem::path &/*executable*/, std::wstring &/*cmd_line*/)
{
return error_code{};
}
template<typename Launcher, typename Init1, typename ... Inits>
inline error_code on_setup(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
Init1 && init1, Inits && ... inits)
{
auto ec = invoke_on_setup(launcher, executable, cmd_line, init1, derived{});
if (ec)
return ec;
else
return on_setup(launcher, executable, cmd_line, inits...);
}
template<typename Launcher, typename Init>
inline void invoke_on_error(Launcher & /*launcher*/, const filesystem::path &/*executable*/, std::wstring &/*cmd_line*/,
const error_code & /*ec*/, Init && /*init*/, base && )
{
}
template<typename Launcher, typename Init>
inline auto invoke_on_error(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
const error_code & ec, Init && init, derived && )
-> decltype(init.on_error(launcher, executable, cmd_line, ec))
{
init.on_error(launcher, executable, cmd_line, ec);
}
template<typename Launcher, typename Init>
inline std::false_type probe_on_error(
Launcher & launcher, Init && init, base && );
template<typename Launcher, typename Init>
inline auto probe_on_error(Launcher & launcher, Init && init, derived && )
-> std::is_same<error_code, decltype(init.on_error(launcher, std::declval<const filesystem::path &>(), std::declval<std::wstring &>(), std::declval<error_code&>()))>;
template<typename Launcher, typename Init>
using has_on_error = decltype(probe_on_error(std::declval<Launcher&>(), std::declval<Init>(), derived{}));
template<typename Launcher>
inline void on_error(Launcher & /*launcher*/, const filesystem::path &/*executable*/, std::wstring &/*cmd_line*/,
const error_code & /*ec*/)
{
}
template<typename Launcher, typename Init1, typename ... Inits>
inline void on_error(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
const error_code & ec,
Init1 && init1,
Inits && ... inits)
{
invoke_on_error(launcher, executable, cmd_line, ec, init1, derived{});
on_error(launcher, executable, cmd_line, ec, inits...);
}
template<typename Launcher, typename Init>
inline void invoke_on_success(Launcher & /*launcher*/, const filesystem::path &/*executable*/, std::wstring &/*cmd_line*/,
Init && /*init*/, base && )
{
}
template<typename Launcher, typename Init>
inline auto invoke_on_success(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
Init && init, derived && )
-> decltype(init.on_success(launcher, executable, cmd_line))
{
init.on_success(launcher, executable, cmd_line);
}
template<typename Launcher, typename Init>
inline std::false_type probe_on_success(
Launcher & launcher, Init && init, base && );
template<typename Launcher, typename Init>
inline auto probe_on_success(Launcher & launcher, Init && init, derived && )
-> std::is_same<error_code, decltype(init.on_success(launcher, std::declval<const filesystem::path &>(), std::declval<std::wstring &>()))>;
template<typename Launcher, typename Init>
using has_on_success = decltype(probe_on_success(std::declval<Launcher&>(), std::declval<Init>(), derived{}));
template<typename Launcher>
inline void on_success(Launcher & /*launcher*/, const filesystem::path &/*executable*/, std::wstring &/*cmd_line*/)
{
}
template<typename Launcher, typename Init1, typename ... Inits>
inline void on_success(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
Init1 && init1, Inits && ... inits)
{
invoke_on_success(launcher, executable, cmd_line, init1, derived{});
on_success(launcher, executable, cmd_line, inits...);
}
template<typename Launcher, typename Init>
struct is_initializer : std::integral_constant<bool,
has_on_setup<Launcher, Init>::value ||
has_on_error<Launcher, Init>::value ||
has_on_success<Launcher, Init>::value>
{
};
template<typename Launcher, typename ... Inits>
struct all_are_initializers;
template<typename Launcher>
struct all_are_initializers<Launcher> : std::true_type {};
template<typename Launcher, typename Init>
struct all_are_initializers<Launcher, Init> : is_initializer<Launcher, Init> {};
template<typename Launcher, typename Init, typename ... Tail>
struct all_are_initializers<Launcher, Init, Tail...>
: std::integral_constant<bool, is_initializer<Launcher, Init>::value && all_are_initializers<Launcher, Tail...>::value>
{
};
}
template<typename Executor>
struct basic_process;
namespace windows
{
/// The default launcher for processes on windows.
struct default_launcher
{
//// The process_attributes passed to CreateProcess
SECURITY_ATTRIBUTES * process_attributes = nullptr;
//// The thread_attributes passed to CreateProcess
SECURITY_ATTRIBUTES * thread_attributes = nullptr;
/// The inhreited_handles option. bInheritHandles will be true if not empty..
std::vector<HANDLE> inherited_handles;
/// The creation flags of the process. Initializers may add to them; extended startupinfo is assumed.
DWORD creation_flags{EXTENDED_STARTUPINFO_PRESENT};
/// A pointer to the subprocess environment.
void * environment = nullptr;
/// The startup director. An empty path will get ignored.
filesystem::path current_directory{};
/// The full startup info passed to CreateProcess
STARTUPINFOEXW startup_info{{sizeof(STARTUPINFOEXW), nullptr, nullptr, nullptr,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr,
INVALID_HANDLE_VALUE,
INVALID_HANDLE_VALUE,
INVALID_HANDLE_VALUE},
nullptr};
/// Allow batch files to be executed, which might pose a security threat.
bool allow_batch_files = false;
/// The process_information that gets assigned after a call to CreateProcess
PROCESS_INFORMATION process_information{nullptr, nullptr, 0,0};
template<typename Executor, typename ... Inits>
using enable_init = typename std::enable_if<
detail::all_are_initializers<default_launcher, Inits...>::value,
basic_process<Executor>>::type;
default_launcher() = default;
template<typename ExecutionContext, typename Args, typename ... Inits>
auto operator()(ExecutionContext & context,
const typename std::enable_if<std::is_convertible<
ExecutionContext&, net::execution_context&>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> enable_init<typename ExecutionContext::executor_type, Inits...>
{
error_code ec;
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
if (ec)
v2::detail::throw_error(ec, "default_launcher");
return proc;
}
template<typename ExecutionContext, typename Args, typename ... Inits>
auto operator()(ExecutionContext & context,
error_code & ec,
const typename std::enable_if<std::is_convertible<
ExecutionContext&, net::execution_context&>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> enable_init<typename ExecutionContext::executor_type, Inits...>
{
return (*this)(context.get_executor(), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
}
template<typename Executor, typename Args, typename ... Inits>
auto operator()(Executor exec,
const typename std::enable_if<
net::execution::is_executor<Executor>::value
|| net::is_executor<Executor>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> enable_init<Executor, Inits...>
{
error_code ec;
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
if (ec)
detail::throw_error(ec, "default_launcher");
return proc;
}
template<typename Executor, typename Args, typename ... Inits>
auto operator()(Executor exec,
error_code & ec,
const typename std::enable_if<
net::execution::is_executor<Executor>::value ||
net::is_executor<Executor>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> enable_init<Executor, Inits...>
{
if (!allow_batch_files && ((executable.extension() == ".bat") || (executable.extension() == ".cmd")))
{
BOOST_PROCESS_V2_ASSIGN_EC(ec, ERROR_ACCESS_DENIED, system_category());
return basic_process<Executor>(exec);
}
auto command_line = this->build_command_line(executable, std::forward<Args>(args));
ec = detail::on_setup(*this, executable, command_line, inits...);
if (ec)
{
detail::on_error(*this, executable, command_line, ec, inits...);
return basic_process<Executor>(exec);
}
if (!inherited_handles.empty())
{
set_handle_list(ec);
if (ec)
return basic_process<Executor>(exec);
}
auto ok = ::CreateProcessW(
executable.empty() ? nullptr : executable.c_str(),
command_line.empty() ? nullptr : &command_line.front(),
process_attributes,
thread_attributes,
inherited_handles.empty() ? FALSE : TRUE,
creation_flags,
environment,
current_directory.empty() ? nullptr : current_directory.c_str(),
&startup_info.StartupInfo,
&process_information);
if (ok == 0)
{
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
detail::on_error(*this, executable, command_line, ec, inits...);
if (process_information.hProcess != INVALID_HANDLE_VALUE)
::CloseHandle(process_information.hProcess);
if (process_information.hThread != INVALID_HANDLE_VALUE)
::CloseHandle(process_information.hThread);
return basic_process<Executor>(exec);
}
else
{
detail::on_success(*this, executable, command_line, inits...);
if (process_information.hThread != INVALID_HANDLE_VALUE)
::CloseHandle(process_information.hThread);
return basic_process<Executor>(exec,
this->process_information.dwProcessId,
this->process_information.hProcess);
}
}
BOOST_PROCESS_V2_DECL static
std::size_t escaped_argv_length(basic_string_view<wchar_t> ws);
BOOST_PROCESS_V2_DECL static
std::size_t escape_argv_string(wchar_t * itr, std::size_t max_size,
basic_string_view<wchar_t> ws);
template<typename Argv>
static std::wstring build_command_line_impl(
const filesystem::path & pt,
const Argv & argv,
basic_string_view<wchar_t> args)
{
std::size_t req_size = std::accumulate(
std::begin(argv), std::end(argv), escaped_argv_length(pt.native()),
[](std::size_t sz, basic_string_view<wchar_t> arg) -> std::size_t
{
return sz + 1u + escaped_argv_length(arg);
});
std::wstring res;
res.resize(req_size, L' ');
wchar_t * itr = &res.front();
itr += escape_argv_string(itr, res.size(), pt.native());
for (const auto & a : argv)
{
itr++;
itr += escape_argv_string(itr, std::distance(itr, &res.back() + 1), a);
}
return res;
}
template<typename Argv>
static std::wstring build_command_line_impl(
const filesystem::path & pt,
const Argv & argv,
basic_string_view<char> args)
{
std::vector<std::wstring> argw;
argw.resize(std::distance(std::begin(argv), std::end(argv)));
std::transform(std::begin(argv), std::end(argv), argw.begin(),
[](basic_string_view <char> arg)
{
return detail::conv_string<wchar_t>(arg.data(), arg.size());
});
return build_command_line_impl(pt, argw, L"");
}
template<typename Args,
typename Char = decltype(*std::begin(std::declval<Args>()))>
static std::wstring build_command_line(const filesystem::path & pt, const Args & args)
{
if (std::begin(args) == std::end(args))
{
std::wstring buffer;
buffer.resize(escaped_argv_length(pt.native()));
if (!buffer.empty())
escape_argv_string(&buffer.front(), buffer.size(), pt.native());
return buffer;
}
return build_command_line_impl(pt, args, *std::begin(args));
}
static std::wstring build_command_line(const filesystem::path & pt, const wchar_t * args)
{
return args;
}
struct lpproc_thread_closer
{
void operator()(::LPPROC_THREAD_ATTRIBUTE_LIST l)
{
::DeleteProcThreadAttributeList(l);
::HeapFree(GetProcessHeap(), 0, l);
}
};
std::unique_ptr<std::remove_pointer<LPPROC_THREAD_ATTRIBUTE_LIST>::type, lpproc_thread_closer> proc_attribute_list_storage;
BOOST_PROCESS_V2_DECL LPPROC_THREAD_ATTRIBUTE_LIST get_thread_attribute_list(error_code & ec);
BOOST_PROCESS_V2_DECL void set_handle_list(error_code & ec);
};
}
BOOST_PROCESS_V2_END_NAMESPACE
#endif //BOOST_PROCESS_V2_WINDOWS_DEFAULT_LAUNCHER_HPP

View File

@@ -0,0 +1,53 @@
//
// boost/process/v2/windows/default_launcher.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
//
// 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_V2_WINDOWS_SHOW_WINDOW_HPP
#define BOOST_PROCESS_V2_WINDOWS_SHOW_WINDOW_HPP
#include <boost/process/v2/windows/default_launcher.hpp>
BOOST_PROCESS_V2_BEGIN_NAMESPACE
namespace windows
{
/// A templated initializer to add wShowWindow flags.
template<DWORD Flags>
struct process_show_window
{
constexpr process_show_window() {}
error_code on_setup(windows::default_launcher & launcher,
const filesystem::path &,
const std::wstring &) const
{
launcher.startup_info.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW;
launcher.startup_info.StartupInfo.wShowWindow |= Flags;
return error_code {};
};
};
///Hides the window and activates another window.
constexpr static process_show_window<SW_HIDE > show_window_hide;
///Activates the window and displays it as a maximized window.
constexpr static process_show_window<SW_SHOWMAXIMIZED > show_window_maximized;
///Activates the window and displays it as a minimized window.
constexpr static process_show_window<SW_SHOWMINIMIZED > show_window_minimized;
///Displays the window as a minimized window. This value is similar to `minimized`, except the window is not activated.
constexpr static process_show_window<SW_SHOWMINNOACTIVE> show_window_minimized_not_active;
///Displays a window in its most recent size and position. This value is similar to show_normal`, except that the window is not activated.
constexpr static process_show_window<SW_SHOWNOACTIVATE > show_window_not_active;
///Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time.
constexpr static process_show_window<SW_SHOWNORMAL > show_window_normal;
}
BOOST_PROCESS_V2_END_NAMESPACE
#endif // BOOST_PROCESS_V2_WINDOWS_SHOW_WINDOW_HPP

View File

@@ -0,0 +1,140 @@
//
// boost/process/v2/windows/default_launcher.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
//
// 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_V2_WINDOWS_WITH_LOGON_LAUNCHER_HPP
#define BOOST_PROCESS_V2_WINDOWS_WITH_LOGON_LAUNCHER_HPP
#include <boost/process/v2/windows/default_launcher.hpp>
BOOST_PROCESS_V2_BEGIN_NAMESPACE
namespace windows
{
/// A windows launcher using CreateProcessWithLogon instead of CreateProcess
struct with_logon_launcher : default_launcher
{
std::wstring username, password, domain;
DWORD logon_flags{0u};
with_logon_launcher(std::wstring username = L"",
std::wstring password = L"",
std::wstring domain = L"",
DWORD logon_flags = 0u) :
username(std::move(username)),
password(std::move(password)),
domain(std::move(domain)),
logon_flags(logon_flags)
{
}
template<typename ExecutionContext, typename Args, typename ... Inits>
auto operator()(ExecutionContext & context,
error_code & ec,
const typename std::enable_if<std::is_convertible<
ExecutionContext&, net::execution_context&>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
{
return (*this)(context.get_executor(), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
}
template<typename ExecutionContext, typename Args, typename ... Inits>
auto operator()(ExecutionContext & context,
const typename std::enable_if<std::is_convertible<
ExecutionContext&, net::execution_context&>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
{
return (*this)(context.get_executor(), executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
}
template<typename Executor, typename Args, typename ... Inits>
auto operator()(Executor exec,
const typename std::enable_if<
net::execution::is_executor<Executor>::value ||
net::is_executor<Executor>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> basic_process<Executor>
{
error_code ec;
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
if (ec)
v2::detail::throw_error(ec, "with_logon_launcher");
return proc;
}
template<typename Executor, typename Args, typename ... Inits>
auto operator()(Executor exec,
error_code & ec,
const typename std::enable_if<
net::execution::is_executor<Executor>::value ||
net::is_executor<Executor>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> basic_process<Executor>
{
auto command_line = this->build_command_line(executable, args);
ec = detail::on_setup(*this, executable, command_line, inits...);
if (ec)
{
detail::on_error(*this, executable, command_line, ec, inits...);
return basic_process<Executor>(exec);
}
auto ok = ::CreateProcessWithLogonW(
username.c_str(),
domain.empty() ? nullptr : domain.c_str(),
password.c_str(),
logon_flags,
executable.empty() ? nullptr : executable.c_str(),
command_line.empty() ? nullptr : &command_line.front(),
creation_flags,
environment,
current_directory.empty() ? nullptr : current_directory.c_str(),
&startup_info.StartupInfo,
&process_information);
if (ok == 0)
{
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
detail::on_error(*this, executable, command_line, ec, inits...);
if (process_information.hProcess != INVALID_HANDLE_VALUE)
::CloseHandle(process_information.hProcess);
if (process_information.hThread != INVALID_HANDLE_VALUE)
::CloseHandle(process_information.hThread);
return basic_process<Executor>(exec);
} else
{
detail::on_success(*this, executable, command_line, inits...);
if (process_information.hThread != INVALID_HANDLE_VALUE)
::CloseHandle(process_information.hThread);
return basic_process<Executor>(exec,
this->process_information.dwProcessId,
this->process_information.hProcess);
}
}
};
}
BOOST_PROCESS_V2_END_NAMESPACE
#endif // BOOST_PROCESS_V2_WINDOWS_WITH_LOGON_LAUNCHER_HPP

View File

@@ -0,0 +1,135 @@
//
// boost/process/v2/windows/default_launcher.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
//
// 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_V2_WINDOWS_WITH_TOKEN_LAUNCHER_HPP
#define BOOST_PROCESS_V2_WINDOWS_WITH_TOKEN_LAUNCHER_HPP
#include <boost/process/v2/windows/default_launcher.hpp>
BOOST_PROCESS_V2_BEGIN_NAMESPACE
namespace windows
{
/// A windows launcher using CreateProcessWithToken instead of CreateProcess
struct with_token_launcher : default_launcher
{
HANDLE token;
DWORD logon_flags;
with_token_launcher(HANDLE token = INVALID_HANDLE_VALUE,
DWORD logon_flags = 0u) : token(token), logon_flags(logon_flags) {}
template<typename ExecutionContext, typename Args, typename ... Inits>
auto operator()(ExecutionContext & context,
const typename std::enable_if<std::is_convertible<
ExecutionContext&, net::execution_context&>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
{
error_code ec;
auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
if (ec)
v2::detail::throw_error(ec, "with_token_launcher");
return proc;
}
template<typename ExecutionContext, typename Args, typename ... Inits>
auto operator()(ExecutionContext & context,
error_code & ec,
const typename std::enable_if<std::is_convertible<
ExecutionContext&, net::execution_context&>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
{
return (*this)(context.get_executor(), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
}
template<typename Executor, typename Args, typename ... Inits>
auto operator()(Executor exec,
const typename std::enable_if<
net::execution::is_executor<Executor>::value ||
net::is_executor<Executor>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> basic_process<Executor>
{
error_code ec;
auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
if (ec)
detail::throw_error(ec, "with_token_launcher");
return proc;
}
template<typename Executor, typename Args, typename ... Inits>
auto operator()(Executor exec,
error_code & ec,
const typename std::enable_if<
net::execution::is_executor<Executor>::value ||
net::is_executor<Executor>::value,
filesystem::path >::type & executable,
Args && args,
Inits && ... inits ) -> basic_process<Executor>
{
auto command_line = this->build_command_line(executable, args);
ec = detail::on_setup(*this, executable, command_line, inits...);
if (ec)
{
detail::on_error(*this, executable, command_line, ec, inits...);
return basic_process<Executor>(exec);
}
auto ok = ::CreateProcessWithTokenW(
token,
logon_flags,
executable.empty() ? nullptr : executable.c_str(),
command_line.empty() ? nullptr : &command_line.front(),
creation_flags,
environment,
current_directory.empty() ? nullptr : current_directory.c_str(),
&startup_info.StartupInfo,
&process_information);
if (ok == 0)
{
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
detail::on_error(*this, executable, command_line, ec, inits...);
if (process_information.hProcess != INVALID_HANDLE_VALUE)
::CloseHandle(process_information.hProcess);
if (process_information.hThread != INVALID_HANDLE_VALUE)
::CloseHandle(process_information.hThread);
return basic_process<Executor>(exec);
} else
{
detail::on_success(*this, executable, command_line, inits...);
if (process_information.hThread != INVALID_HANDLE_VALUE)
::CloseHandle(process_information.hThread);
return basic_process<Executor>(exec,
this->process_information.dwProcessId,
this->process_information.hProcess);
}
}
};
}
BOOST_PROCESS_V2_END_NAMESPACE
#endif // BOOST_PROCESS_V2_WINDOWS_WITH_TOKEN_LAUNCHER_HPP