This source file includes following definitions.
- GetQIP
- GetCommandLineForProcess
- Includes
- KillAllNamedProcessesWithArgument
#include "base/test/test_process_killer_win.h"
#include <windows.h>
#include <winternl.h>
#include <algorithm>
#include "base/logging.h"
#include "base/process/kill.h"
#include "base/process/process_iterator.h"
#include "base/strings/string_util.h"
#include "base/win/scoped_handle.h"
namespace {
typedef LONG WINAPI
NtQueryInformationProcess(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
static bool GetQIP(NtQueryInformationProcess** qip_func_ptr) {
static NtQueryInformationProcess* qip_func =
reinterpret_cast<NtQueryInformationProcess*>(
GetProcAddress(GetModuleHandle(L"ntdll.dll"),
"NtQueryInformationProcess"));
DCHECK(qip_func) << "Could not get pointer to NtQueryInformationProcess.";
*qip_func_ptr = qip_func;
return qip_func != NULL;
}
bool GetCommandLineForProcess(uint32 process_id, base::string16* cmd_line) {
DCHECK(process_id != 0);
DCHECK(cmd_line);
base::win::ScopedHandle process_handle(::OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
false,
process_id));
if (!process_handle) {
DLOG(ERROR) << "Failed to open process " << process_id << ", last error = "
<< GetLastError();
}
NtQueryInformationProcess* qip_func = NULL;
if (process_handle) {
GetQIP(&qip_func);
}
DWORD process_params_address = 0;
if (qip_func) {
PROCESS_BASIC_INFORMATION info = { 0 };
if ((qip_func(process_handle.Get(),
ProcessBasicInformation,
&info,
sizeof(info),
NULL)) < 0) {
DLOG(ERROR) << "Failed to invoke NtQueryProcessInformation, last error = "
<< GetLastError();
} else {
BYTE* peb = reinterpret_cast<BYTE*>(info.PebBaseAddress);
SIZE_T bytes_read = 0;
if (!::ReadProcessMemory(process_handle.Get(),
peb + 0x10,
&process_params_address,
sizeof(process_params_address),
&bytes_read)) {
DLOG(ERROR) << "Failed to read process params address, last error = "
<< GetLastError();
}
}
}
bool success = false;
base::string16 buffer;
if (process_params_address) {
SIZE_T bytes_read;
RTL_USER_PROCESS_PARAMETERS params = { 0 };
if (!::ReadProcessMemory(process_handle.Get(),
reinterpret_cast<void*>(process_params_address),
¶ms,
sizeof(params),
&bytes_read)) {
DLOG(ERROR) << "Failed to read RTL_USER_PROCESS_PARAMETERS, "
<< "last error = " << GetLastError();
} else {
const int max_cmd_line_len = std::min(
static_cast<int>(params.CommandLine.MaximumLength),
4096);
buffer.resize(max_cmd_line_len + 1);
if (!::ReadProcessMemory(process_handle.Get(),
params.CommandLine.Buffer,
&buffer[0],
max_cmd_line_len,
&bytes_read)) {
DLOG(ERROR) << "Failed to copy process command line, "
<< "last error = " << GetLastError();
} else {
*cmd_line = buffer;
success = true;
}
}
}
return success;
}
class ArgumentFilter : public base::ProcessFilter {
public:
explicit ArgumentFilter(const base::string16& argument)
: argument_to_find_(argument) {}
virtual bool Includes(const base::ProcessEntry& entry) const {
bool found = false;
base::string16 command_line;
if (GetCommandLineForProcess(entry.pid(), &command_line)) {
base::string16::const_iterator it =
std::search(command_line.begin(),
command_line.end(),
argument_to_find_.begin(),
argument_to_find_.end(),
base::CaseInsensitiveCompareASCII<wchar_t>());
found = (it != command_line.end());
}
return found;
}
protected:
base::string16 argument_to_find_;
};
}
namespace base {
bool KillAllNamedProcessesWithArgument(const string16& process_name,
const string16& argument) {
ArgumentFilter argument_filter(argument);
return base::KillProcesses(process_name, 0, &argument_filter);
}
}