You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
5.8 KiB
181 lines
5.8 KiB
/****************************************************************** |
|
* |
|
* kdbgwin - Helper application for DrKonqi |
|
* |
|
* This file is part of the KDE project |
|
* |
|
* Copyright (C) 2010 Ilie Halip <lupuroshu@gmail.com> |
|
* |
|
* This library is free software; you can redistribute it and/or |
|
* modify it under the terms of the GNU Lesser General Public |
|
* License as published by the Free Software Foundation; either |
|
* version 2.1 of the License, or (at your option) version 3, or any |
|
* later version accepted by the membership of KDE e.V. (or its |
|
* successor approved by the membership of KDE e.V.), which shall |
|
* act as a proxy defined in Section 6 of version 3 of the license. |
|
* |
|
* This library is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
* Lesser General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU Lesser General Public |
|
* License along with this library. If not, see <http://www.gnu.org/licenses/> |
|
*****************************************************************/ |
|
|
|
#include "common.h" |
|
#include "process.h" |
|
|
|
Process::Process() |
|
: m_bValid(FALSE) |
|
{ |
|
} |
|
|
|
// we need debug privileges to open the proces with PROCESS_ALL_ACCESS, and |
|
// to successfully use ReadProcessMemory() |
|
BOOL Process::EnableDebugPrivilege() |
|
{ |
|
kDebug() << "Enabling debug privilege"; |
|
HANDLE hToken = NULL; |
|
|
|
if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken)) |
|
{ |
|
if (GetLastError() == ERROR_NO_TOKEN) |
|
{ |
|
if (!ImpersonateSelf(SecurityImpersonation)) |
|
{ |
|
kError() << "ImpersonateSelf() failed: " << GetLastError(); |
|
return FALSE; |
|
} |
|
if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken)) |
|
{ |
|
kError() << "OpenThreadToken() #2 failed: " << GetLastError(); |
|
return FALSE; |
|
} |
|
} |
|
else |
|
{ |
|
kError() << "OpenThreadToken() #1 failed: " << GetLastError(); |
|
return FALSE; |
|
} |
|
} |
|
|
|
LUID luid; |
|
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) |
|
{ |
|
assert(false); |
|
kError() << "Cannot lookup privilege: " << GetLastError(); |
|
SafeCloseHandle(hToken); |
|
return FALSE; |
|
} |
|
|
|
TOKEN_PRIVILEGES tp; |
|
tp.PrivilegeCount = 1; |
|
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; |
|
tp.Privileges[0].Luid = luid; |
|
|
|
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, NULL, (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL)) |
|
{ |
|
assert(false); |
|
kError() << "Cannot adjust privilege: " << GetLastError(); |
|
SafeCloseHandle(hToken); |
|
return FALSE; |
|
} |
|
|
|
SafeCloseHandle(hToken); |
|
return TRUE; |
|
} |
|
|
|
BOOL Process::GetInfo(const char* pid, const char* threadId) |
|
{ |
|
kDebug() << "Trying to get info about pid=" << pid; |
|
|
|
DWORD dwPid = DWORD(atoi(pid)); |
|
DWORD dwThread = DWORD(atoi(threadId)); |
|
|
|
// get handle to the process |
|
HANDLE hProcess = NULL; |
|
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); |
|
assert(hProcess); |
|
if (hProcess == NULL) |
|
{ |
|
kError() << "Cannot open process " << dwPid << ": " << GetLastError(); |
|
return m_bValid; |
|
} |
|
m_dwPid = dwPid; |
|
m_hProcess = hProcess; |
|
m_dwThread = dwThread; |
|
|
|
TCHAR procPath[MAX_PATH * 2 + 1] = {0}; |
|
GetModuleFileNameEx(hProcess, NULL, procPath, MAX_PATH*2 + 1); |
|
m_path = QString::fromWCharArray(procPath); |
|
|
|
// we can't get the threads for a single process, so get all system's |
|
// threads, and enumerate through them |
|
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, NULL); |
|
if (hSnapshot == INVALID_HANDLE_VALUE) |
|
{ |
|
kError() << "CreateToolhelp32Snapshot() failed: " << GetLastError(); |
|
assert(false); |
|
return m_bValid; |
|
} |
|
|
|
// get process threads |
|
THREADENTRY32 te; |
|
ZeroMemory(&te, sizeof(te)); |
|
te.dwSize = sizeof(te); |
|
if (Thread32First(hSnapshot, &te)) |
|
{ |
|
do |
|
{ |
|
if (te.th32OwnerProcessID == dwPid) |
|
{ |
|
kDebug() << "Found thread " << te.th32ThreadID << ", adding to list"; |
|
|
|
HANDLE hThread = NULL; |
|
hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te.th32ThreadID); |
|
assert(hThread); |
|
if (hThread == NULL) |
|
{ |
|
kError() << "Cannot open thread " << te.th32ThreadID << ": " << GetLastError(); |
|
continue; |
|
} |
|
|
|
m_threads[te.th32ThreadID] = hThread; |
|
// we have at least 1 thread, make this valid |
|
m_bValid = TRUE; |
|
} |
|
} |
|
while (Thread32Next(hSnapshot, &te)); |
|
} |
|
SafeCloseHandle(hSnapshot); |
|
|
|
assert(m_threads.size() > 0); |
|
|
|
// get process modules |
|
HMODULE hMods[1024]; |
|
DWORD cbNeeded = 0; |
|
if (!EnumProcessModules(hProcess, hMods, ArrayCount(hMods), &cbNeeded)) |
|
{ |
|
kError() << "Cannot enumerate modules: " << GetLastError(); |
|
return m_bValid; |
|
} |
|
for (size_t i = 0; i < (cbNeeded / sizeof(hMods[0])); i++) |
|
{ |
|
/* |
|
* In Windows, a wchar_t has 2 bytes; GCC defines wchar_t as int, |
|
* which is 4 bytes; so i can't use TCHAR here; better off using ushort |
|
* and casting when necessary |
|
*/ |
|
ushort szModName[MAX_PATH]; |
|
if (GetModuleFileNameEx(hProcess, hMods[i], (LPTSTR) szModName, MAX_PATH)) |
|
{ |
|
//QString str = QString::fromUtf16(szModName); |
|
//kDebug() << "Got module: " << str; |
|
//m_modules.push_back(QString::fromUtf16(szModName)); |
|
m_modules[QString::fromUtf16(szModName)] = hMods[i]; |
|
} |
|
} |
|
|
|
return m_bValid; |
|
}
|
|
|