summaryrefslogtreecommitdiff
path: root/kpimutils/processes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kpimutils/processes.cpp')
-rw-r--r--kpimutils/processes.cpp231
1 files changed, 231 insertions, 0 deletions
diff --git a/kpimutils/processes.cpp b/kpimutils/processes.cpp
new file mode 100644
index 0000000..ac87a92
--- /dev/null
+++ b/kpimutils/processes.cpp
@@ -0,0 +1,231 @@
+/**
+ * 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.
+
+ @author Jarosław Staniek \<staniek@kde.org\>
+*/
+
+#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>
+
+#ifdef Q_OS_WINCE
+#include <Tlhelp32.h>
+#endif
+
+#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)
+{
+#ifndef _WIN32_WCE
+ 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;
+ }
+ }
+#endif
+ 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 ) );
+#ifndef _WIN32_WCE
+ CloseHandle(h);
+#else
+ CloseToolhelp32Snapshot(h);
+#endif
+}
+
+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;
+#ifndef _WIN32_WCE
+ result = kill( pid, SIGTERM );
+ if ( result == 0 ) {
+ continue;
+ }
+#endif
+ 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; //krazy:exclude=captruefalse
+ }
+ }
+ return TRUE; //krazy:exclude=captruefalse
+}
+
+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