view ui/processhelp_win.cpp @ 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
children 91dd38a71783
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();

    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/