andre@603: /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik andre@603: * Software engineering by Intevation GmbH andre@603: * andre@603: * This file is Free Software under the GNU GPL (v>=2) andre@603: * and comes with ABSOLUTELY NO WARRANTY! andre@603: * See LICENSE.txt for details. */ andre@603: andre@603: #ifdef WIN32 andre@603: #include "processhelp.h" andre@603: #include "strhelp.h" andre@603: andre@603: #include andre@603: #include andre@603: #include andre@603: #include andre@603: andre@603: #include andre@603: andre@606: struct EnumWindowsStruct { andre@606: EnumWindowsStruct() : windowId(0) {} andre@606: DWORD pid; andre@606: HWND windowId; andre@603: }; andre@603: andre@603: PSID copySid(PSID from) andre@603: { andre@606: if (!from) { andre@603: return 0; andre@603: } andre@603: andre@606: int sidLength = GetLengthSid(from); andre@606: PSID to = (PSID) xmalloc(sidLength); andre@603: CopySid(sidLength, to, from); andre@603: return to; andre@603: } andre@603: andre@603: static PSID getProcessOwner(HANDLE hProcess) andre@603: { andre@603: HANDLE hToken = NULL; andre@603: PSID sid; andre@603: andre@603: OpenProcessToken(hProcess, TOKEN_READ, &hToken); andre@606: if (hToken) { andre@603: DWORD size; andre@603: PTOKEN_USER userStruct; andre@603: andre@603: // check how much space is needed andre@606: GetTokenInformation(hToken, TokenUser, NULL, 0, &size); andre@606: if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) { andre@606: userStruct = reinterpret_cast(new BYTE[size]); andre@606: GetTokenInformation(hToken, TokenUser, userStruct, size, &size); andre@603: andre@606: sid = copySid(userStruct->User.Sid); andre@606: CloseHandle(hToken); andre@603: delete [] userStruct; andre@603: return sid; andre@603: } andre@603: } andre@603: return 0; andre@603: } andre@603: andre@603: BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) andre@603: { andre@603: if (GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE) { andre@603: andre@603: DWORD pidwin; andre@603: andre@603: GetWindowThreadProcessId(hwnd, &pidwin); andre@603: if (pidwin == ((EnumWindowsStruct *)lParam)->pid) { andre@603: ((EnumWindowsStruct *)lParam)->windowId = hwnd; andre@603: return FALSE; andre@603: } andre@603: } andre@603: return TRUE; andre@603: } andre@603: andre@603: andre@603: static HANDLE getProcessHandle(int processID) andre@603: { andre@603: return OpenProcess(SYNCHRONIZE | andre@603: PROCESS_QUERY_INFORMATION | andre@603: PROCESS_VM_READ | andre@603: PROCESS_TERMINATE, andre@603: false, processID); andre@603: } andre@603: andre@603: const QList ProcessHelp::getProcessesIdForName(const QString &processName) andre@603: { andre@603: HANDLE h; andre@603: PROCESSENTRY32 pe32; andre@603: QList pids; andre@603: andre@603: h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); andre@603: if (h == INVALID_HANDLE_VALUE) { andre@603: return pids; andre@603: } andre@603: andre@603: pe32.dwSize = sizeof(PROCESSENTRY32); // Necessary according to MSDN andre@603: if (!Process32First(h, &pe32)) { andre@603: return pids; andre@603: } andre@603: andre@603: pids.clear(); andre@603: andre@608: const QString processNameLower = processName.toLower().replace(".exe", ""); andre@608: const QString processNameExe = processNameLower + ".exe"; andre@608: andre@603: do { andre@608: const QString exeFile = QString::fromWCharArray(pe32.szExeFile).toLower(); andre@608: if (exeFile == processNameLower || exeFile == processNameExe) { andre@603: PSID user_sid = getProcessOwner(GetCurrentProcess()); andre@606: if (user_sid) { andre@603: // Also check that we are the owner of that process andre@603: HANDLE hProcess = getProcessHandle(pe32.th32ProcessID); andre@606: if (!hProcess) { andre@603: continue; andre@603: } andre@603: andre@603: PSID sid = getProcessOwner(hProcess); andre@603: PSID userSid = getProcessOwner(GetCurrentProcess()); andre@606: if (!sid || (userSid && !EqualSid(userSid, sid))) { andre@606: free(sid); andre@603: continue; andre@603: } andre@603: } andre@603: pids.append((int)pe32.th32ProcessID); andre@603: qDebug() << "found PID: " << (int)pe32.th32ProcessID; andre@603: } andre@603: } while (Process32Next(h, &pe32)); andre@606: CloseHandle(h); andre@603: return pids; andre@603: } andre@603: andre@603: bool ProcessHelp::otherProcessesExist(const QString &processName) andre@603: { andre@603: const QList pids = getProcessesIdForName(processName); andre@603: int myPid = getpid(); andre@606: foreach(int pid, pids) { andre@603: if (myPid != pid) { andre@603: qDebug() << "Found another process with id: " << pid; andre@603: return true; andre@603: } andre@603: } andre@603: return false; andre@603: } andre@603: andre@606: void ProcessHelp::activateWindowForProcess(const QString &executableName) andre@606: { andre@603: const QList pids = getProcessesIdForName(executableName); andre@603: int myPid = getpid(); andre@603: int foundPid = 0; andre@606: foreach(int pid, pids) { andre@603: if (myPid != pid) { andre@603: qDebug() << "activateWindowForProcess(): PID to activate:" << pid; andre@603: foundPid = pid; andre@603: break; andre@603: } andre@603: } andre@606: if (foundPid == 0) { andre@603: return; andre@603: } andre@603: EnumWindowsStruct winStruct; andre@603: winStruct.pid = foundPid; andre@606: EnumWindows(EnumWindowsProc, (LPARAM)&winStruct); andre@606: if (winStruct.windowId == 0) { andre@603: return; andre@603: } andre@606: SetForegroundWindow(winStruct.windowId); andre@603: } andre@603: #endif // WIN32 andre@603: