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@603: struct EnumWindowsStruct andre@603: { andre@603: EnumWindowsStruct() : windowId( 0 ) {} andre@603: DWORD pid; andre@603: HWND windowId; andre@603: }; andre@603: andre@603: PSID copySid(PSID from) andre@603: { andre@603: if ( !from ) { andre@603: return 0; andre@603: } andre@603: andre@603: int sidLength = GetLengthSid( from ); andre@603: 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@603: if ( hToken ) { andre@603: DWORD size; andre@603: PTOKEN_USER userStruct; andre@603: andre@603: // check how much space is needed andre@603: GetTokenInformation( hToken, TokenUser, NULL, 0, &size ); andre@603: if ( ERROR_INSUFFICIENT_BUFFER == GetLastError() ) { andre@603: userStruct = reinterpret_cast( new BYTE[size] ); andre@603: GetTokenInformation( hToken, TokenUser, userStruct, size, &size ); andre@603: andre@603: sid = copySid( userStruct->User.Sid ); andre@603: 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@603: do { andre@603: if ( QString::fromWCharArray(pe32.szExeFile) == processName ) { andre@603: PSID user_sid = getProcessOwner(GetCurrentProcess()); andre@603: if ( user_sid ) { andre@603: // Also check that we are the owner of that process andre@603: HANDLE hProcess = getProcessHandle(pe32.th32ProcessID); andre@603: if ( !hProcess ) { andre@603: continue; andre@603: } andre@603: andre@603: PSID sid = getProcessOwner(hProcess); andre@603: PSID userSid = getProcessOwner(GetCurrentProcess()); andre@603: if ( !sid || (userSid && !EqualSid(userSid, sid))) { andre@603: 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@603: 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@603: 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@603: void ProcessHelp::activateWindowForProcess(const QString &executableName) { andre@603: const QList pids = getProcessesIdForName(executableName); andre@603: int myPid = getpid(); andre@603: int foundPid = 0; andre@603: 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@603: if ( foundPid == 0 ) { andre@603: return; andre@603: } andre@603: EnumWindowsStruct winStruct; andre@603: winStruct.pid = foundPid; andre@603: EnumWindows( EnumWindowsProc, (LPARAM)&winStruct ); andre@603: if ( winStruct.windowId == 0 ) { andre@603: return; andre@603: } andre@603: SetForegroundWindow( winStruct.windowId ); andre@603: } andre@603: #endif // WIN32 andre@603: