ProcessWindows.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * Copyright (c) 2021, Andreas Kling <andreas@ladybird.org>
  3. * Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
  4. * Copyright (c) 2023-2024, Sam Atkins <atkinssj@serenityos.org>
  5. * Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org>
  6. * Copyright (c) 2024, stasoid <stasoid@yahoo.com>
  7. *
  8. * SPDX-License-Identifier: BSD-2-Clause
  9. */
  10. #include <AK/String.h>
  11. #include <AK/Utf16View.h>
  12. #include <LibCore/Process.h>
  13. #include <windows.h>
  14. namespace Core {
  15. Process::Process(Process&& other)
  16. : m_handle(exchange(other.m_handle, nullptr))
  17. {
  18. }
  19. Process& Process::operator=(Process&& other)
  20. {
  21. m_handle = exchange(other.m_handle, nullptr);
  22. return *this;
  23. }
  24. Process::~Process()
  25. {
  26. if (m_handle)
  27. CloseHandle(m_handle);
  28. }
  29. Process Process::current()
  30. {
  31. return GetCurrentProcess();
  32. }
  33. ErrorOr<Process> Process::spawn(ProcessSpawnOptions const& options)
  34. {
  35. // file actions are not supported
  36. VERIFY(options.file_actions.is_empty());
  37. char const* program_path = 0;
  38. StringBuilder builder;
  39. if (options.search_for_executable_in_path)
  40. builder.appendff("\"{}\" ", options.executable);
  41. else
  42. program_path = options.executable.characters();
  43. builder.join(' ', options.arguments);
  44. builder.append('\0');
  45. ByteBuffer command_line = TRY(builder.to_byte_buffer());
  46. auto curdir = options.working_directory.has_value() ? options.working_directory->characters() : 0;
  47. STARTUPINFO startup_info = {};
  48. PROCESS_INFORMATION process_info = {};
  49. BOOL result = CreateProcess(
  50. program_path,
  51. (char*)command_line.data(),
  52. NULL, // process security attributes
  53. NULL, // primary thread security attributes
  54. TRUE, // handles are inherited
  55. 0, // creation flags
  56. NULL, // use parent's environment
  57. curdir,
  58. &startup_info,
  59. &process_info);
  60. if (!result)
  61. return Error::from_windows_error();
  62. CloseHandle(process_info.hThread);
  63. return Process(process_info.hProcess);
  64. }
  65. ErrorOr<Process> Process::spawn(StringView path, ReadonlySpan<ByteString> arguments, ByteString working_directory, KeepAsChild)
  66. {
  67. return spawn({
  68. .executable = path,
  69. .arguments = Vector<ByteString> { arguments },
  70. .working_directory = working_directory.is_empty() ? Optional<ByteString> {} : working_directory,
  71. });
  72. }
  73. ErrorOr<Process> Process::spawn(StringView path, ReadonlySpan<StringView> arguments, ByteString working_directory, KeepAsChild)
  74. {
  75. Vector<ByteString> backing_strings;
  76. backing_strings.ensure_capacity(arguments.size());
  77. for (auto argument : arguments)
  78. backing_strings.append(argument);
  79. return spawn({
  80. .executable = path,
  81. .arguments = backing_strings,
  82. .working_directory = working_directory.is_empty() ? Optional<ByteString> {} : working_directory,
  83. });
  84. }
  85. // Get the full path of the executable file of the current process
  86. ErrorOr<String> Process::get_name()
  87. {
  88. wchar_t path[MAX_PATH] = {};
  89. DWORD length = GetModuleFileNameW(NULL, path, MAX_PATH);
  90. if (!length)
  91. return Error::from_windows_error();
  92. return String::from_utf16(Utf16View { { (u16*)path, length } });
  93. }
  94. ErrorOr<void> Process::set_name(StringView, SetThreadName)
  95. {
  96. // Process::set_name() probably cannot be implemented on Windows.
  97. return {};
  98. }
  99. ErrorOr<bool> Process::is_being_debugged()
  100. {
  101. return IsDebuggerPresent();
  102. }
  103. // Forces the process to sleep until a debugger is attached, then breaks.
  104. void Process::wait_for_debugger_and_break()
  105. {
  106. bool print_message = true;
  107. for (;;) {
  108. if (IsDebuggerPresent()) {
  109. DebugBreak();
  110. return;
  111. }
  112. if (print_message) {
  113. dbgln("Process {} with pid {} is sleeping, waiting for debugger.", Process::get_name(), GetCurrentProcessId());
  114. print_message = false;
  115. }
  116. Sleep(100);
  117. }
  118. }
  119. pid_t Process::pid() const
  120. {
  121. return GetProcessId(m_handle);
  122. }
  123. ErrorOr<int> Process::wait_for_termination()
  124. {
  125. auto result = WaitForSingleObject(m_handle, INFINITE);
  126. if (result == WAIT_FAILED)
  127. return Error::from_windows_error();
  128. DWORD exit_code = 0;
  129. if (!GetExitCodeProcess(m_handle, &exit_code))
  130. return Error::from_windows_error();
  131. return exit_code;
  132. }
  133. }