as_user_launcher.hpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. //
  2. // boost/process/v2/windows/default_launcher.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_PROCESS_V2_WINDOWS_AS_USER_LAUNCHER_HPP
  11. #define BOOST_PROCESS_V2_WINDOWS_AS_USER_LAUNCHER_HPP
  12. #include <boost/process/v2/detail/config.hpp>
  13. #include <boost/process/v2/windows/default_launcher.hpp>
  14. BOOST_PROCESS_V2_BEGIN_NAMESPACE
  15. namespace windows
  16. {
  17. /// A windows launcher using CreateProcessAsUser instead of CreateProcess
  18. struct as_user_launcher : default_launcher
  19. {
  20. /// The token to be used in CreateProcessAsUser.
  21. HANDLE token;
  22. as_user_launcher(HANDLE token = INVALID_HANDLE_VALUE) : token(token) {}
  23. template<typename ExecutionContext, typename Args, typename ... Inits>
  24. auto operator()(ExecutionContext & context,
  25. const typename std::enable_if<std::is_convertible<
  26. ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
  27. filesystem::path >::type & executable,
  28. Args && args,
  29. Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
  30. {
  31. error_code ec;
  32. auto proc = (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
  33. if (ec)
  34. v2::detail::throw_error(ec, "as_user_launcher");
  35. return proc;
  36. }
  37. template<typename ExecutionContext, typename Args, typename ... Inits>
  38. auto operator()(ExecutionContext & context,
  39. error_code & ec,
  40. const typename std::enable_if<std::is_convertible<
  41. ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
  42. filesystem::path >::type & executable,
  43. Args && args,
  44. Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
  45. {
  46. return (*this)(context.get_executor(), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
  47. }
  48. template<typename Executor, typename Args, typename ... Inits>
  49. auto operator()(Executor exec,
  50. const typename std::enable_if<
  51. BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
  52. BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
  53. filesystem::path >::type & executable,
  54. Args && args,
  55. Inits && ... inits ) -> basic_process<Executor>
  56. {
  57. error_code ec;
  58. auto proc = (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
  59. if (ec)
  60. detail::throw_error(ec, "as_user_launcher");
  61. return proc;
  62. }
  63. template<typename Executor, typename Args, typename ... Inits>
  64. auto operator()(Executor exec,
  65. error_code & ec,
  66. const typename std::enable_if<
  67. BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
  68. BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
  69. filesystem::path >::type & executable,
  70. Args && args,
  71. Inits && ... inits ) -> basic_process<Executor>
  72. {
  73. auto command_line = this->build_command_line(executable, args);
  74. ec = detail::on_setup(*this, executable, command_line, inits...);
  75. if (ec)
  76. {
  77. detail::on_error(*this, executable, command_line, ec, inits...);
  78. return basic_process<Executor>(exec);
  79. }
  80. auto ok = ::CreateProcessAsUserW(
  81. token,
  82. executable.empty() ? nullptr : executable.c_str(),
  83. command_line.empty() ? nullptr : &command_line.front(),
  84. process_attributes,
  85. thread_attributes,
  86. inherit_handles ? TRUE : FALSE,
  87. creation_flags,
  88. environment,
  89. current_directory.empty() ? nullptr : current_directory.c_str(),
  90. &startup_info.StartupInfo,
  91. &process_information);
  92. if (ok == 0)
  93. {
  94. BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
  95. detail::on_error(*this, executable, command_line, ec, inits...);
  96. if (process_information.hProcess != INVALID_HANDLE_VALUE)
  97. ::CloseHandle(process_information.hProcess);
  98. if (process_information.hThread != INVALID_HANDLE_VALUE)
  99. ::CloseHandle(process_information.hThread);
  100. return basic_process<Executor>(exec);
  101. } else
  102. {
  103. detail::on_success(*this, executable, command_line, inits...);
  104. if (process_information.hThread != INVALID_HANDLE_VALUE)
  105. ::CloseHandle(process_information.hThread);
  106. return basic_process<Executor>(exec,
  107. this->process_information.dwProcessId,
  108. this->process_information.hProcess);
  109. }
  110. }
  111. };
  112. }
  113. BOOST_PROCESS_V2_END_NAMESPACE
  114. #endif // BOOST_PROCESS_V2_WINDOWS_AS_USER_LAUNCHER_HPP