kde-playground/kdepimlibs/kpimutils/processes.cpp
2015-04-14 21:49:29 +00:00

223 lines
5.6 KiB
C++

/**
* This file is part of the kpimutils library.
*
* Copyright (C) 2008 Jarosław Staniek <staniek@kde.org>
* Copyright (C) 2012 Andre Heinecke <aheinecke@intevation.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
/**
@file
This file is part of the KDEPIM Utilities library and provides
static methods for process handling (Windows only at this time).
@author Jarosław Staniek \<staniek@kde.org\>
*/
//krazy:excludeall=captruefalse,null
#include "processes.h"
using namespace KPIMUtils;
#ifdef Q_WS_WIN
#include <windows.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <signal.h>
#include <unistd.h>
#include <QtCore/QList>
#include <QtCore/QtDebug>
#include <KDebug>
// Copy from kdelibs/kinit/kinit_win.cpp
PSID copySid( PSID from )
{
if ( !from ) {
return 0;
}
int sidLength = GetLengthSid( from );
PSID to = (PSID) malloc( sidLength );
CopySid( sidLength, to, from );
return to;
}
// Copy from kdelibs/kinit/kinit_win.cpp
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;
}
// Copy from kdelibs/kinit/kinit_win.cpp
static HANDLE getProcessHandle( int processID )
{
return OpenProcess( SYNCHRONIZE |
PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ |
PROCESS_TERMINATE,
false, processID );
}
void KPIMUtils::getProcessesIdForName( const QString &processName, QList<int> &pids )
{
HANDLE h;
PROCESSENTRY32 pe32;
h = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if ( h == INVALID_HANDLE_VALUE ) {
return;
}
pe32.dwSize = sizeof( PROCESSENTRY32 ); // Necessary according to MSDN
if ( !Process32First( h, &pe32 ) ) {
return;
}
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 );
kDebug() << "found PID: " << (int)pe32.th32ProcessID;
}
} while ( Process32Next( h, &pe32 ) );
CloseHandle( h );
}
bool KPIMUtils::otherProcessesExist( const QString &processName )
{
QList<int> pids;
getProcessesIdForName( processName, pids );
int myPid = getpid();
foreach ( int pid, pids ) {
if ( myPid != pid ) {
// kDebug() << "Process ID is " << pid;
return true;
}
}
return false;
}
bool KPIMUtils::killProcesses( const QString &processName )
{
QList<int> pids;
getProcessesIdForName( processName, pids );
if ( pids.empty() ) {
return true;
}
qWarning() << "Killing process \"" << processName << " (pid=" << pids[0] << ")..";
int overallResult = 0;
foreach ( int pid, pids ) {
int result;
result = kill( pid, SIGTERM );
if ( result == 0 ) {
continue;
}
result = kill( pid, SIGKILL );
if ( result != 0 ) {
overallResult = result;
}
}
return overallResult == 0;
}
struct EnumWindowsStruct
{
EnumWindowsStruct() : windowId( 0 ) {}
int pid;
HWND windowId;
};
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;
}
void KPIMUtils::activateWindowForProcess( const QString &executableName )
{
QList<int> pids;
KPIMUtils::getProcessesIdForName( executableName, pids );
int myPid = getpid();
int foundPid = 0;
foreach ( int pid, pids ) {
if ( myPid != pid ) {
kDebug() << "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 // Q_WS_WIN