File indexing completed on 2024-12-01 11:06:26
0001 /****************************************************************** 0002 * 0003 * kdbgwin - Helper application for DrKonqi 0004 * 0005 * This file is part of the KDE project 0006 * 0007 * SPDX-FileCopyrightText: 2010 Ilie Halip <lupuroshu@gmail.com> 0008 * 0009 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0010 *****************************************************************/ 0011 0012 #include "kdbgwin_process.h" 0013 0014 Process::Process() 0015 : m_bValid(FALSE) 0016 { 0017 } 0018 0019 // we need debug privileges to open the proces with PROCESS_ALL_ACCESS, and 0020 // to successfully use ReadProcessMemory() 0021 BOOL Process::EnableDebugPrivilege() 0022 { 0023 qCDebug(DRKONQI_LOG) << "Enabling debug privilege"; 0024 HANDLE hToken = NULL; 0025 0026 if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken)) { 0027 if (GetLastError() == ERROR_NO_TOKEN) { 0028 if (!ImpersonateSelf(SecurityImpersonation)) { 0029 qCCritical(DRKONQI_LOG) << "ImpersonateSelf() failed: " << GetLastError(); 0030 return FALSE; 0031 } 0032 if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &hToken)) { 0033 qCCritical(DRKONQI_LOG) << "OpenThreadToken() #2 failed: " << GetLastError(); 0034 return FALSE; 0035 } 0036 } else { 0037 qCCritical(DRKONQI_LOG) << "OpenThreadToken() #1 failed: " << GetLastError(); 0038 return FALSE; 0039 } 0040 } 0041 0042 LUID luid; 0043 if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) { 0044 assert(false); 0045 qCCritical(DRKONQI_LOG) << "Cannot lookup privilege: " << GetLastError(); 0046 SafeCloseHandle(hToken); 0047 return FALSE; 0048 } 0049 0050 TOKEN_PRIVILEGES tp; 0051 tp.PrivilegeCount = 1; 0052 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 0053 tp.Privileges[0].Luid = luid; 0054 0055 if (!AdjustTokenPrivileges(hToken, FALSE, &tp, NULL, (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) { 0056 assert(false); 0057 qCCritical(DRKONQI_LOG) << "Cannot adjust privilege: " << GetLastError(); 0058 SafeCloseHandle(hToken); 0059 return FALSE; 0060 } 0061 0062 SafeCloseHandle(hToken); 0063 return TRUE; 0064 } 0065 0066 BOOL Process::GetInfo(const char *pid, const char *threadId) 0067 { 0068 qCDebug(DRKONQI_LOG) << "Trying to get info about pid=" << pid; 0069 0070 DWORD dwPid = DWORD(atoi(pid)); 0071 DWORD dwThread = DWORD(atoi(threadId)); 0072 0073 // get handle to the process 0074 HANDLE hProcess = NULL; 0075 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); 0076 assert(hProcess); 0077 if (hProcess == NULL) { 0078 qCCritical(DRKONQI_LOG) << "Cannot open process " << dwPid << ": " << GetLastError(); 0079 return m_bValid; 0080 } 0081 m_dwPid = dwPid; 0082 m_hProcess = hProcess; 0083 m_dwThread = dwThread; 0084 0085 TCHAR procPath[MAX_PATH * 2 + 1] = {0}; 0086 GetModuleFileNameEx(hProcess, NULL, procPath, MAX_PATH * 2 + 1); 0087 m_path = QString::fromWCharArray(procPath); 0088 0089 // we can't get the threads for a single process, so get all system's 0090 // threads, and enumerate through them 0091 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, NULL); 0092 if (hSnapshot == INVALID_HANDLE_VALUE) { 0093 qCCritical(DRKONQI_LOG) << "CreateToolhelp32Snapshot() failed: " << GetLastError(); 0094 assert(false); 0095 return m_bValid; 0096 } 0097 0098 // get process threads 0099 THREADENTRY32 te; 0100 ZeroMemory(&te, sizeof(te)); 0101 te.dwSize = sizeof(te); 0102 if (Thread32First(hSnapshot, &te)) { 0103 do { 0104 if (te.th32OwnerProcessID == dwPid) { 0105 qCDebug(DRKONQI_LOG) << "Found thread " << te.th32ThreadID << ", adding to list"; 0106 0107 HANDLE hThread = NULL; 0108 hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te.th32ThreadID); 0109 assert(hThread); 0110 if (hThread == NULL) { 0111 qCCritical(DRKONQI_LOG) << "Cannot open thread " << te.th32ThreadID << ": " << GetLastError(); 0112 continue; 0113 } 0114 0115 m_threads[te.th32ThreadID] = hThread; 0116 // we have at least 1 thread, make this valid 0117 m_bValid = TRUE; 0118 } 0119 } while (Thread32Next(hSnapshot, &te)); 0120 } 0121 SafeCloseHandle(hSnapshot); 0122 0123 assert(m_threads.size() > 0); 0124 0125 // get process modules 0126 HMODULE hMods[1024]; 0127 DWORD cbNeeded = 0; 0128 if (!EnumProcessModules(hProcess, hMods, ArrayCount(hMods), &cbNeeded)) { 0129 qCCritical(DRKONQI_LOG) << "Cannot enumerate modules: " << GetLastError(); 0130 return m_bValid; 0131 } 0132 for (size_t i = 0; i < (cbNeeded / sizeof(hMods[0])); i++) { 0133 /* 0134 * In Windows, a wchar_t has 2 bytes; GCC defines wchar_t as int, 0135 * which is 4 bytes; so i can't use TCHAR here; better off using ushort 0136 * and casting when necessary 0137 */ 0138 ushort szModName[MAX_PATH]; 0139 if (GetModuleFileNameEx(hProcess, hMods[i], (LPTSTR)szModName, MAX_PATH)) { 0140 // QString str = QString::fromUtf16(szModName); 0141 // qCDebug(DRKONQI_LOG) << "Got module: " << str; 0142 // m_modules.push_back(QString::fromUtf16(szModName)); 0143 m_modules[QString::fromUtf16(szModName)] = hMods[i]; 0144 } 0145 } 0146 0147 return m_bValid; 0148 }