# HG changeset patch # User Andre Heinecke # Date 1403018770 -7200 # Node ID cfef809b890dee1017e360fd466fa34319628139 # Parent 854248d81ba41dc0031818c321786fb3befcb87b Add Process Management functions and ther implementation for windows. diff -r 854248d81ba4 -r cfef809b890d ui/CMakeLists.txt --- a/ui/CMakeLists.txt Tue Jun 17 17:25:12 2014 +0200 +++ b/ui/CMakeLists.txt Tue Jun 17 17:26:10 2014 +0200 @@ -20,6 +20,8 @@ ${CMAKE_CURRENT_SOURCE_DIR}/downloader.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sslconnection.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sslhelp.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/processhelp_win.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/processhelp_linux.cpp ) # Cmake does not correctly identify gcc windres when cross compiling diff -r 854248d81ba4 -r cfef809b890d ui/processhelp.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/processhelp.h Tue Jun 17 17:26:10 2014 +0200 @@ -0,0 +1,48 @@ +/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + * + * Parts of this code (especially windows) are based on kpimutils processes.cpp + * available under LGPL 2.1 or later. + */ +#ifndef PROCESSHELP_H +#define PROCESSHELP_H + +#include +#include + +/** + * @file Static helper functions for process handling + * @brief process handling functions + */ + +namespace ProcessHelp { + /** + * @brief look up process id's for a processName + * + * Looks up processes run by the current user. + * + * @param[in] processName the name of the process to look for + * @returns a list of pids that match this process. May be empty + */ + const QList getProcessesIdForName(const QString &processName); + + /** + * @brief check if another process with the same name exists + * + * @param[in] processName name of the process to look for. + * + * @returns true if one or more processes (other than the current process) exist + */ + bool otherProcessesExist(const QString &processName); + + /** + * @brief Activates the window for first found process + * @param [in] executableName executableName (without path and .exe extension) + */ + void activateWindowForProcess(const QString &executableName); +} +#endif // PROCESSHELP_H diff -r 854248d81ba4 -r cfef809b890d ui/processhelp_linux.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/processhelp_linux.cpp Tue Jun 17 17:26:10 2014 +0200 @@ -0,0 +1,30 @@ +/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ +#ifndef WIN32 + +#include "processhelp.h" + +const QList ProcessHelp::getProcessesIdForName(const QString &processName) { + // TODO + Q_UNUSED(processName); + return QList(); +} + +bool ProcessHelp::otherProcessesExist(const QString &processName) { + // TODO + Q_UNUSED(processName); + return false; +} + +void ProcessHelp::activateWindowForProcess(const QString &executableName) { + // TODO + Q_UNUSED(executableName); + return; +} + +#endif /* Not WIN32 */ diff -r 854248d81ba4 -r cfef809b890d ui/processhelp_win.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/processhelp_win.cpp Tue Jun 17 17:26:10 2014 +0200 @@ -0,0 +1,167 @@ +/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. */ + +#ifdef WIN32 +#include "processhelp.h" +#include "strhelp.h" + +#include +#include +#include +#include + +#include + +struct EnumWindowsStruct +{ + EnumWindowsStruct() : windowId( 0 ) {} + DWORD pid; + HWND windowId; +}; + +PSID copySid(PSID from) +{ + if ( !from ) { + return 0; + } + + int sidLength = GetLengthSid( from ); + PSID to = (PSID) xmalloc( sidLength ); + CopySid(sidLength, to, from); + return to; +} + +static PSID getProcessOwner(HANDLE hProcess) +{ + HANDLE hToken = NULL; + PSID sid; + + OpenProcessToken(hProcess, TOKEN_READ, &hToken); + if ( hToken ) { + DWORD size; + PTOKEN_USER userStruct; + + // check how much space is needed + GetTokenInformation( hToken, TokenUser, NULL, 0, &size ); + if ( ERROR_INSUFFICIENT_BUFFER == GetLastError() ) { + userStruct = reinterpret_cast( new BYTE[size] ); + GetTokenInformation( hToken, TokenUser, userStruct, size, &size ); + + sid = copySid( userStruct->User.Sid ); + CloseHandle( hToken ); + delete [] userStruct; + return sid; + } + } + return 0; +} + +BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) +{ + if (GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE) { + + DWORD pidwin; + + GetWindowThreadProcessId(hwnd, &pidwin); + if (pidwin == ((EnumWindowsStruct *)lParam)->pid) { + ((EnumWindowsStruct *)lParam)->windowId = hwnd; + return FALSE; + } + } + return TRUE; +} + + +static HANDLE getProcessHandle(int processID) +{ + return OpenProcess(SYNCHRONIZE | + PROCESS_QUERY_INFORMATION | + PROCESS_VM_READ | + PROCESS_TERMINATE, + false, processID); +} + +const QList ProcessHelp::getProcessesIdForName(const QString &processName) +{ + HANDLE h; + PROCESSENTRY32 pe32; + QList pids; + + h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (h == INVALID_HANDLE_VALUE) { + return pids; + } + + pe32.dwSize = sizeof(PROCESSENTRY32); // Necessary according to MSDN + if (!Process32First(h, &pe32)) { + return pids; + } + + pids.clear(); + + do { + if ( QString::fromWCharArray(pe32.szExeFile) == processName ) { + PSID user_sid = getProcessOwner(GetCurrentProcess()); + if ( user_sid ) { + // Also check that we are the owner of that process + HANDLE hProcess = getProcessHandle(pe32.th32ProcessID); + if ( !hProcess ) { + continue; + } + + PSID sid = getProcessOwner(hProcess); + PSID userSid = getProcessOwner(GetCurrentProcess()); + if ( !sid || (userSid && !EqualSid(userSid, sid))) { + free (sid); + continue; + } + } + pids.append((int)pe32.th32ProcessID); + qDebug() << "found PID: " << (int)pe32.th32ProcessID; + } + } while (Process32Next(h, &pe32)); + CloseHandle( h ); + return pids; +} + +bool ProcessHelp::otherProcessesExist(const QString &processName) +{ + const QList pids = getProcessesIdForName(processName); + int myPid = getpid(); + foreach (int pid, pids) { + if (myPid != pid) { + qDebug() << "Found another process with id: " << pid; + return true; + } + } + return false; +} + +void ProcessHelp::activateWindowForProcess(const QString &executableName) { + const QList pids = getProcessesIdForName(executableName); + int myPid = getpid(); + int foundPid = 0; + foreach (int pid, pids) { + if (myPid != pid) { + qDebug() << "activateWindowForProcess(): PID to activate:" << pid; + foundPid = pid; + break; + } + } + if ( foundPid == 0 ) { + return; + } + EnumWindowsStruct winStruct; + winStruct.pid = foundPid; + EnumWindows( EnumWindowsProc, (LPARAM)&winStruct ); + if ( winStruct.windowId == 0 ) { + return; + } + SetForegroundWindow( winStruct.windowId ); +} +#endif // WIN32 +