aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--include/winapi/process.hpp2
-rw-r--r--src/process.cpp31
-rw-r--r--test/unit_tests/process.cpp7
3 files changed, 40 insertions, 0 deletions
diff --git a/include/winapi/process.hpp b/include/winapi/process.hpp
index d52ad0a..05411cd 100644
--- a/include/winapi/process.hpp
+++ b/include/winapi/process.hpp
@@ -24,6 +24,8 @@ public:
static Process create(const CommandLine&);
static Process create(const CommandLine&, process::IO);
+ static Process runas(const CommandLine&);
+
void wait() const;
int get_exit_code() const;
diff --git a/src/process.cpp b/src/process.cpp
index 9fe19e5..a9f24cc 100644
--- a/src/process.cpp
+++ b/src/process.cpp
@@ -12,7 +12,10 @@
#include <boost/config.hpp>
+// clang-format off
#include <windows.h>
+#include <shellapi.h>
+// clang-format on
#include <cstddef>
#include <cstring>
@@ -69,6 +72,30 @@ Handle create_process(const CommandLine& cmd_line, process::IO& io) {
return create_process(escape_command_line(cmd_line), io);
}
+Handle shell_execute(const CommandLine& cmd_line) {
+ BOOST_STATIC_CONSTEXPR unsigned long flags =
+ SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI | SEE_MASK_NO_CONSOLE;
+
+ const auto exe_path = widen(cmd_line.get_argv0());
+ const auto args = widen(cmd_line.args_to_string());
+
+ SHELLEXECUTEINFOW info;
+ std::memset(&info, 0, sizeof(info));
+ info.cbSize = sizeof(info);
+ info.fMask = flags;
+ info.lpVerb = L"runas";
+ info.lpFile = exe_path.c_str();
+ if (!args.empty())
+ info.lpParameters = args.c_str();
+ info.nShow = SW_SHOWDEFAULT;
+
+ if (!::ShellExecuteExW(&info)) {
+ throw error::windows(GetLastError(), "ShellExecuteExW");
+ }
+
+ return Handle{info.hProcess};
+}
+
} // namespace
Process Process::create(const CommandLine& cmd_line) {
@@ -79,6 +106,10 @@ Process Process::create(const CommandLine& cmd_line, process::IO io) {
return Process{create_process(cmd_line, io)};
}
+Process Process::runas(const CommandLine& cmd_line) {
+ return Process{shell_execute(cmd_line)};
+}
+
void Process::wait() const {
const auto ret = ::WaitForSingleObject(static_cast<HANDLE>(m_handle), INFINITE);
diff --git a/test/unit_tests/process.cpp b/test/unit_tests/process.cpp
index a126f86..715364f 100644
--- a/test/unit_tests/process.cpp
+++ b/test/unit_tests/process.cpp
@@ -82,4 +82,11 @@ BOOST_FIXTURE_TEST_CASE(echo_stdin_from_file, WithEchoExe) {
BOOST_TEST(stdout8 == stdin8);
}
+BOOST_FIXTURE_TEST_CASE(echo_runas, WithEchoExe) {
+ const CommandLine cmd_line{get_echo_exe(), {"foo", "bar"}};
+ const auto process = Process::runas(cmd_line);
+ process.wait();
+ BOOST_TEST(process.get_exit_code() == 0);
+}
+
BOOST_AUTO_TEST_SUITE_END()