view ui/processhelp_win.cpp @ 608:81a44b93229e

Be more permissive with process names. Case insenstive and with suffix or not.
author Andre Heinecke <andre.heinecke@intevation.de>
date Wed, 18 Jun 2014 11:22:15 +0200
parents 91dd38a71783
children 175370634226
line wrap: on
line source
/* 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();

    const QString processNameLower = processName.toLower().replace(".exe", "");
    const QString processNameExe = processNameLower + ".exe";

    do {
        const QString exeFile = QString::fromWCharArray(pe32.szExeFile).toLower();
        if (exeFile == processNameLower || exeFile == processNameExe) {
            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/