changeset 603:cfef809b890d

Add Process Management functions and ther implementation for windows.
author Andre Heinecke <andre.heinecke@intevation.de>
date Tue, 17 Jun 2014 17:26:10 +0200
parents 854248d81ba4
children 3d45f5bca0aa
files ui/CMakeLists.txt ui/processhelp.h ui/processhelp_linux.cpp ui/processhelp_win.cpp
diffstat 4 files changed, 247 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- 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
--- /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 <QList>
+#include <QString>
+
+/**
+ * @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<int> 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
--- /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<int> ProcessHelp::getProcessesIdForName(const QString &processName) {
+    // TODO
+    Q_UNUSED(processName);
+    return QList<int>();
+}
+
+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 */
--- /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 <windows.h>
+#include <tlhelp32.h>
+#include <psapi.h>
+#include <unistd.h>
+
+#include <QDebug>
+
+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<PTOKEN_USER>( 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<int> ProcessHelp::getProcessesIdForName(const QString &processName)
+{
+    HANDLE h;
+    PROCESSENTRY32 pe32;
+    QList <int> 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<int> 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<int> 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
+

http://wald.intevation.org/projects/trustbridge/