mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-24 02:42:51 +00:00
223 lines
5.6 KiB
C++
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
|