source: dev/branches/egtra/ab5.0/abdev/ab_common/src/ProcessAndModule.cpp@ 801

Last change on this file since 801 was 798, checked in by イグトランス (egtra), 14 years ago

PSAPIを使用している箇所について、Toolhelp32と選択するよう修正

File size: 4.7 KB
Line 
1#include "stdafx.h"
2#include "ProcessAndModule.h"
3#include "OSVersion.h"
4
5#include <memory>
6#include <psapi.h>
7#include <tlhelp32.h>
8
9#pragma comment(lib, "psapi.lib")
10
11namespace ActiveBasic { namespace Common {
12
13struct HandleDeleter
14{
15 typedef HANDLE pointer;
16
17 void operator ()(pointer h) const
18 {
19 ::CloseHandle(h);
20 }
21};
22
23typedef std::unique_ptr<HANDLE, HandleDeleter> UniqueHandle;
24
25boost::filesystem::path GetModuleFilePath(HANDLE hProcess, HMODULE hmod)
26{
27 if (GetOSVersion().dwPlatformId == VER_PLATFORM_WIN32_NT)
28 {
29 WCHAR temp[MAX_PATH] = {};
30 if (::GetModuleFileNameExW(hProcess, hmod, temp, MAX_PATH) != 0)
31 {
32 return temp;
33 }
34 }
35 else
36 {
37 CHAR temp[MAX_PATH] = {};
38 if (::GetModuleFileNameA(hmod, temp, MAX_PATH) != 0)
39 {
40 return boost::filesystem::path(Jenga::Common::ToWString(temp));
41 }
42 }
43 throw std::runtime_error("GetModuleFileName or GetModuleFileNameEx failed");
44}
45
46namespace {
47
48struct Toolhelp32Function
49{
50 decltype(::CreateToolhelp32Snapshot)* pCreateToolhelp32Snapshot;
51 decltype(::Process32First)* pProcess32First;
52 decltype(::Process32Next)* pProcess32Next;
53 decltype(::Module32First)* pModule32First;
54 decltype(::Module32Next)* pModule32Next;
55};
56
57Toolhelp32Function const& GetToolhelp32Function(HMODULE hmodKernel)
58{
59 static Toolhelp32Function const tf =
60 {
61 reinterpret_cast<decltype(::CreateToolhelp32Snapshot)*>(::GetProcAddress(hmodKernel, "CreateToolhelp32Snapshot")),
62 reinterpret_cast<decltype(::Process32First)*>(::GetProcAddress(hmodKernel, "Process32First")),
63 reinterpret_cast<decltype(::Process32Next)*>(::GetProcAddress(hmodKernel, "Process32Next")),
64 reinterpret_cast<decltype(::Module32First)*>(::GetProcAddress(hmodKernel, "Module32First")),
65 reinterpret_cast<decltype(::Module32Next)*>(::GetProcAddress(hmodKernel, "Module32Next")),
66 };
67 return tf;
68}
69
70UniqueHandle CreateToolhelp32SnapshotHelper(Toolhelp32Function const& tf, DWORD flags, DWORD processId = 0)
71{
72 UniqueHandle h(tf.pCreateToolhelp32Snapshot(flags, processId));
73 if (h.get() == INVALID_HANDLE_VALUE)
74 {
75 h.release();
76 return UniqueHandle();
77 }
78 return h;
79}
80
81} // unnamed namespace
82
83std::vector<DWORD> GetProcesses()
84{
85 auto const& tf = GetToolhelp32Function(::GetModuleHandle(TEXT("kernel32")));
86 if (tf.pCreateToolhelp32Snapshot)
87 {
88 UniqueHandle h = CreateToolhelp32SnapshotHelper(tf, TH32CS_SNAPPROCESS);
89 if (h == nullptr)
90 {
91 return std::vector<DWORD>();
92 }
93 std::vector<DWORD> processes;
94 PROCESSENTRY32 pe = {sizeof pe};
95 if (tf.pProcess32First(h.get(), &pe))
96 {
97 do
98 {
99 processes.push_back(pe.th32ProcessID);
100 } while (tf.pProcess32Next(h.get(), &pe));
101 }
102 return processes;
103 }
104 else
105 {
106 std::vector<DWORD> processes(8192);
107 DWORD cbNeeded = 0;
108 if (EnumProcesses(processes.data(), processes.size() * sizeof (DWORD), &cbNeeded))
109 {
110 processes.resize(cbNeeded / sizeof (DWORD));
111 return processes;
112 }
113 return std::vector<DWORD>();
114 }
115}
116
117boost::filesystem::path GetExecutableModulePath(DWORD processId)
118{
119 if (ActiveBasic::Common::Is9x())
120 {
121 auto const& tf = GetToolhelp32Function(::GetModuleHandle(TEXT("kernel32")));
122 UniqueHandle h = CreateToolhelp32SnapshotHelper(tf, TH32CS_SNAPMODULE, processId);
123 if (h == nullptr)
124 {
125 return boost::filesystem::path();
126 }
127 MODULEENTRY32 me = {sizeof me};
128 if (tf.pModule32First(h.get(), &me))
129 {
130 return boost::filesystem::path(me.szExePath);
131 }
132 else
133 {
134 return boost::filesystem::path();
135 }
136 }
137 else
138 {
139 UniqueHandle hProcess(::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId));
140 // PSAPIが使える環境はそちらを優先。
141 WCHAR filename[MAX_PATH] = {};
142 ::GetModuleFileNameExW(hProcess.get(), nullptr, filename, MAX_PATH);
143 return boost::filesystem::path(filename);
144 }
145}
146
147std::vector<HMODULE> GetModules(DWORD processId)
148{
149 auto const& tf = GetToolhelp32Function(::GetModuleHandle(TEXT("kernel32")));
150 if (tf.pCreateToolhelp32Snapshot)
151 {
152 UniqueHandle h = CreateToolhelp32SnapshotHelper(tf, TH32CS_SNAPMODULE, processId);
153 if (h == nullptr)
154 {
155 return std::vector<HMODULE>();
156 }
157 std::vector<HMODULE> modules;
158 MODULEENTRY32 me = {sizeof me};
159 if (tf.pModule32First(h.get(), &me))
160 {
161 do
162 {
163 modules.push_back(me.hModule);
164 } while (tf.pModule32Next(h.get(), &me));
165 }
166 return modules;
167 }
168 else
169 {
170 UniqueHandle hProcess(::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId));
171 const DWORD MAX_MODULE = 1024;
172 std::vector<HMODULE> module(MAX_MODULE);
173 DWORD cbReturned = 0;
174 EnumProcessModules(hProcess.get(), module.data(), sizeof (HMODULE) * MAX_MODULE, &cbReturned);
175 module.resize(cbReturned / sizeof (HMODULE));
176 return module;
177 }
178}
179
180}}
181
Note: See TracBrowser for help on using the repository browser.