// Copyright (c) 2022 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_V2_DETAIL_IMPL_PROCESS_HANDLE_WINDOWS_IPP #define BOOST_PROCESS_V2_DETAIL_IMPL_PROCESS_HANDLE_WINDOWS_IPP #include #include #include #include #include #include #if !defined(BOOST_PROCESS_V2_DISABLE_UNDOCUMENTED_API) extern "C" { LONG WINAPI NtResumeProcess(HANDLE ProcessHandle); LONG WINAPI NtSuspendProcess(HANDLE ProcessHandle); } #endif BOOST_PROCESS_V2_BEGIN_NAMESPACE namespace detail { void get_exit_code_( HANDLE handle, native_exit_code_type & exit_code, error_code & ec) { if (!::GetExitCodeProcess(handle, &exit_code)) BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } HANDLE open_process_(DWORD pid) { auto proc = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, FALSE, pid); if (proc == nullptr) { error_code ec; BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) throw system_error(ec, "open_process()"); } return proc; } void terminate_if_running_(HANDLE handle) { DWORD exit_code = 0u; if (handle == INVALID_HANDLE_VALUE) return ; if (::GetExitCodeProcess(handle, &exit_code)) if (exit_code == STILL_ACTIVE) ::TerminateProcess(handle, 260); } bool check_handle_(HANDLE handle, error_code & ec) { if (handle == INVALID_HANDLE_VALUE) { BOOST_PROCESS_V2_ASSIGN_EC(ec, ERROR_INVALID_HANDLE_STATE, system_category()) return false; } return true; } bool check_pid_(pid_type pid_, error_code & ec) { if (pid_ == 0) { BOOST_PROCESS_V2_ASSIGN_EC(ec, ERROR_INVALID_HANDLE_STATE, system_category()) return false; } return true; } struct enum_windows_data_t { error_code &ec; pid_type pid; }; static BOOL CALLBACK enum_window(HWND hwnd, LPARAM param) { auto data = reinterpret_cast(param); DWORD pid{0u}; GetWindowThreadProcessId(hwnd, &pid); if (pid != data->pid) return TRUE; LRESULT res = ::SendMessageW(hwnd, WM_CLOSE, 0, 0); if (res) BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(data->ec) return res == 0; } void request_exit_(pid_type pid_, error_code & ec) { enum_windows_data_t data{ec, pid_}; if (!::EnumWindows(enum_window, reinterpret_cast(&data))) BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } void interrupt_(pid_type pid_, error_code & ec) { if (!::GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid_)) BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } void terminate_(HANDLE handle, error_code & ec, DWORD & exit_status) { if (!::TerminateProcess(handle, 260)) BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } void check_running_(HANDLE handle, error_code & ec, DWORD & exit_status) { if (!::GetExitCodeProcess(handle, &exit_status)) BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } #if !defined(BOOST_PROCESS_V2_DISABLE_UNDOCUMENTED_API) void suspend_(HANDLE handle, error_code & ec) { auto nt_err = NtSuspendProcess(handle); ULONG dos_err = RtlNtStatusToDosError(nt_err); if (dos_err) BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } void resume_(HANDLE handle, error_code & ec) { auto nt_err = NtResumeProcess(handle); ULONG dos_err = RtlNtStatusToDosError(nt_err); if (dos_err) BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec) } #else void suspend_(HANDLE, error_code & ec) { BOOST_PROCESS_V2_ASSIGN_EC(ec, ERROR_CALL_NOT_IMPLEMENTED, system_category()) } void resume_(HANDLE handle, error_code & ec) { BOOST_PROCESS_V2_ASSIGN_EC(ec, ERROR_CALL_NOT_IMPLEMENTED, system_category()) } #endif #if !defined(BOOST_PROCESS_V2_HEADER_ONLY) template struct basic_process_handle_win<>; #endif } BOOST_PROCESS_V2_END_NAMESPACE #endif //BOOST_PROCESS_V2_DETAIL_IMPL_PROCESS_HANDLE_WINDOWS_IPP