proc_info.ipp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // Copyright (c) 2022 Klemens D. Morgenstern
  2. // Copyright (c) 2022 Samuel Venable
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_PROCESS_V2_IMPL_DETAIL_PROC_INFO_IPP
  7. #define BOOST_PROCESS_V2_IMPL_DETAIL_PROC_INFO_IPP
  8. #include <boost/process/v2/detail/config.hpp>
  9. #include <boost/process/v2/detail/last_error.hpp>
  10. #include <boost/process/v2/detail/throw_error.hpp>
  11. #include <boost/process/v2/ext/detail/proc_info.hpp>
  12. #include <string>
  13. #if (defined(__APPLE__) && defined(__MACH__))
  14. #include <cstdlib>
  15. #include <sys/types.h>
  16. #include <sys/sysctl.h>
  17. #include <sys/proc_info.h>
  18. #include <libproc.h>
  19. #endif
  20. BOOST_PROCESS_V2_BEGIN_NAMESPACE
  21. namespace detail
  22. {
  23. namespace ext
  24. {
  25. #if defined(BOOST_PROCESS_V2_WINDOWS)
  26. // type of process memory to read?
  27. enum MEMTYP {MEMCMD, MEMCWD};
  28. std::wstring cwd_cmd_from_proc(HANDLE proc, int type, boost::system::error_code & ec)
  29. {
  30. std::wstring buffer;
  31. PEB peb;
  32. SIZE_T nRead = 0;
  33. ULONG len = 0;
  34. PROCESS_BASIC_INFORMATION pbi;
  35. RTL_USER_PROCESS_PARAMETERS_EXTENDED upp;
  36. NTSTATUS status = 0;
  37. PVOID buf = nullptr;
  38. status = NtQueryInformationProcess(proc, ProcessBasicInformation, &pbi, sizeof(pbi), &len);
  39. ULONG error = RtlNtStatusToDosError(status);
  40. if (error)
  41. {
  42. BOOST_PROCESS_V2_ASSIGN_EC(ec, error, boost::system::system_category())
  43. return {};
  44. }
  45. if (!ReadProcessMemory(proc, pbi.PebBaseAddress, &peb, sizeof(peb), &nRead))
  46. {
  47. BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
  48. return {};
  49. }
  50. if (!ReadProcessMemory(proc, peb.ProcessParameters, &upp, sizeof(upp), &nRead))
  51. {
  52. BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
  53. return {};
  54. }
  55. if (type == MEMCWD)
  56. {
  57. buf = upp.CurrentDirectory.DosPath.Buffer;
  58. len = upp.CurrentDirectory.DosPath.Length;
  59. }
  60. else if (type == MEMCMD)
  61. {
  62. buf = upp.CommandLine.Buffer;
  63. len = upp.CommandLine.Length;
  64. }
  65. buffer.resize(len / 2 + 1);
  66. if (!ReadProcessMemory(proc, buf, &buffer[0], len, &nRead))
  67. {
  68. BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
  69. return {};
  70. }
  71. buffer.pop_back();
  72. return buffer;
  73. }
  74. // with debug_privilege enabled allows reading info from more processes
  75. // this includes stuff such as exe path, cwd path, cmdline, and environ
  76. HANDLE open_process_with_debug_privilege(boost::process::v2::pid_type pid, boost::system::error_code & ec)
  77. {
  78. HANDLE proc = nullptr;
  79. HANDLE hToken = nullptr;
  80. LUID luid;
  81. TOKEN_PRIVILEGES tkp;
  82. if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
  83. {
  84. if (LookupPrivilegeValue(nullptr, SE_DEBUG_NAME, &luid))
  85. {
  86. tkp.PrivilegeCount = 1;
  87. tkp.Privileges[0].Luid = luid;
  88. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  89. if (AdjustTokenPrivileges(hToken, false, &tkp, sizeof(tkp), nullptr, nullptr))
  90. {
  91. proc = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
  92. }
  93. }
  94. CloseHandle(hToken);
  95. }
  96. if (!proc)
  97. proc = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
  98. if (!proc)
  99. BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec)
  100. return proc;
  101. }
  102. #endif
  103. } // namespace ext
  104. } // namespace detail
  105. BOOST_PROCESS_V2_END_NAMESPACE
  106. #endif // BOOST_PROCESS_V2_IMPL_DETAIL_PROC_INFO_IPP