File indexing completed on 2024-04-14 14:20:16
0001 /* 0002 This file is part of the KDE libraries 0003 Copyright (C) 2004-2008 Jarosław Staniek <staniek@kde.org> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License version 2 as published by the Free Software Foundation. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include <QApplication> 0021 #include <klocale.h> 0022 #include <kwindowsystem.h> 0023 0024 #include <QTranslator> 0025 #include <QLocale> 0026 #include <QLibraryInfo> 0027 #include <QLibrary> 0028 0029 #include <stdio.h> 0030 0031 /** 0032 * MS Windows-related actions for KApplication startup. 0033 * 0034 * - Use Qt translation which will be usable for QFileDialog 0035 * and other Qt-only GUIs. The "qt_<language>.qm" file should be stored 0036 * in the same place as .po files for a given language. 0037 * 0038 * - Increase the default open file limit with the stdio API from 512 to 2048 0039 * (2048 is the hard limit on Windows) 0040 * @internal 0041 */ 0042 void KApplication_init_windows() 0043 { 0044 //QString qt_transl_file = ::locate( "locale", KLocale::global()->language() 0045 // + "/LC_MESSAGES/qt_" + KLocale::global()->language() + ".qm" ); 0046 0047 QString qt_transl_file = QString("qt_") + QLocale::system().name(); 0048 qt_transl_file.truncate(5); 0049 QTranslator *qt_transl = new QTranslator(); 0050 if (qt_transl->load(qt_transl_file, 0051 QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { 0052 qApp->installTranslator(qt_transl); 0053 } else { 0054 delete qt_transl; 0055 } 0056 0057 // For apps like KMail which have lots of open files, the default is too low 0058 // so increase it to the maximum. 0059 #ifndef _WIN32_WCE 0060 _setmaxstdio(2048); 0061 #endif 0062 0063 } 0064 0065 // <copy of kdepim/libkdepim/utils.cpp, TODO: move to a shared helper library> 0066 0067 #include <windows.h> 0068 #include <winperf.h> 0069 #include <psapi.h> 0070 #include <signal.h> 0071 #include <unistd.h> 0072 0073 #include <QList> 0074 #include <QtDebug> 0075 0076 static PPERF_OBJECT_TYPE FirstObject(PPERF_DATA_BLOCK PerfData) 0077 { 0078 return (PPERF_OBJECT_TYPE)((PBYTE)PerfData + PerfData->HeaderLength); 0079 } 0080 0081 static PPERF_INSTANCE_DEFINITION FirstInstance(PPERF_OBJECT_TYPE PerfObj) 0082 { 0083 return (PPERF_INSTANCE_DEFINITION)((PBYTE)PerfObj + PerfObj->DefinitionLength); 0084 } 0085 0086 static PPERF_OBJECT_TYPE NextObject(PPERF_OBJECT_TYPE PerfObj) 0087 { 0088 return (PPERF_OBJECT_TYPE)((PBYTE)PerfObj + PerfObj->TotalByteLength); 0089 } 0090 0091 static PPERF_COUNTER_DEFINITION FirstCounter(PPERF_OBJECT_TYPE PerfObj) 0092 { 0093 return (PPERF_COUNTER_DEFINITION)((PBYTE)PerfObj + PerfObj->HeaderLength); 0094 } 0095 0096 static PPERF_INSTANCE_DEFINITION NextInstance(PPERF_INSTANCE_DEFINITION PerfInst) 0097 { 0098 PPERF_COUNTER_BLOCK PerfCntrBlk 0099 = (PPERF_COUNTER_BLOCK)((PBYTE)PerfInst + PerfInst->ByteLength); 0100 return (PPERF_INSTANCE_DEFINITION)((PBYTE)PerfCntrBlk + PerfCntrBlk->ByteLength); 0101 } 0102 0103 static PPERF_COUNTER_DEFINITION NextCounter(PPERF_COUNTER_DEFINITION PerfCntr) 0104 { 0105 return (PPERF_COUNTER_DEFINITION)((PBYTE)PerfCntr + PerfCntr->ByteLength); 0106 } 0107 0108 static PPERF_COUNTER_BLOCK CounterBlock(PPERF_INSTANCE_DEFINITION PerfInst) 0109 { 0110 return (PPERF_COUNTER_BLOCK)((LPBYTE) PerfInst + PerfInst->ByteLength); 0111 } 0112 0113 #define GETPID_TOTAL 64 * 1024 0114 #define GETPID_BYTEINCREMENT 1024 0115 #define GETPID_PROCESS_OBJECT_INDEX 230 0116 #define GETPID_PROC_ID_COUNTER 784 0117 0118 QString fromWChar(const wchar_t *string, int size = -1) 0119 { 0120 return (sizeof(wchar_t) == sizeof(QChar)) ? QString::fromUtf16((ushort *)string, size) 0121 : QString::fromUcs4((uint *)string, size); 0122 } 0123 0124 #ifndef _WIN32_WCE 0125 void KApplication_getProcessesIdForName(const QString &processName, QList<int> &pids) 0126 { 0127 qDebug() << "KApplication_getProcessesIdForName" << processName; 0128 PPERF_OBJECT_TYPE perfObject; 0129 PPERF_INSTANCE_DEFINITION perfInstance; 0130 PPERF_COUNTER_DEFINITION perfCounter, curCounter; 0131 PPERF_COUNTER_BLOCK counterPtr; 0132 DWORD bufSize = GETPID_TOTAL; 0133 PPERF_DATA_BLOCK perfData = (PPERF_DATA_BLOCK) malloc(bufSize); 0134 0135 char key[64]; 0136 sprintf(key, "%d %d", GETPID_PROCESS_OBJECT_INDEX, GETPID_PROC_ID_COUNTER); 0137 LONG lRes; 0138 while ((lRes = RegQueryValueExA(HKEY_PERFORMANCE_DATA, 0139 key, 0140 NULL, 0141 NULL, 0142 (LPBYTE) perfData, 0143 &bufSize)) == ERROR_MORE_DATA) { 0144 // get a buffer that is big enough 0145 bufSize += GETPID_BYTEINCREMENT; 0146 perfData = (PPERF_DATA_BLOCK) realloc(perfData, bufSize); 0147 } 0148 0149 // Get the first object type. 0150 perfObject = FirstObject(perfData); 0151 0152 // Process all objects. 0153 for (uint i = 0; i < perfData->NumObjectTypes; i++) { 0154 if (perfObject->ObjectNameTitleIndex != GETPID_PROCESS_OBJECT_INDEX) { 0155 perfObject = NextObject(perfObject); 0156 continue; 0157 } 0158 pids.clear(); 0159 perfCounter = FirstCounter(perfObject); 0160 perfInstance = FirstInstance(perfObject); 0161 // retrieve the instances 0162 qDebug() << "INSTANCES: " << perfObject->NumInstances; 0163 for (int instance = 0; instance < perfObject->NumInstances; instance++) { 0164 curCounter = perfCounter; 0165 const QString foundProcessName( 0166 fromWChar((wchar_t *)((PBYTE)perfInstance + perfInstance->NameOffset))); 0167 qDebug() << "foundProcessName: " << foundProcessName; 0168 if (foundProcessName == processName) { 0169 // retrieve the counters 0170 for (uint counter = 0; counter < perfObject->NumCounters; counter++) { 0171 if (curCounter->CounterNameTitleIndex == GETPID_PROC_ID_COUNTER) { 0172 counterPtr = CounterBlock(perfInstance); 0173 DWORD *value = (DWORD *)((LPBYTE) counterPtr + curCounter->CounterOffset); 0174 pids.append(int(*value)); 0175 qDebug() << "found PID: " << int(*value); 0176 break; 0177 } 0178 curCounter = NextCounter(curCounter); 0179 } 0180 } 0181 perfInstance = NextInstance(perfInstance); 0182 } 0183 } 0184 free(perfData); 0185 RegCloseKey(HKEY_PERFORMANCE_DATA); 0186 } 0187 0188 bool KApplication_otherProcessesExist(const QString &processName) 0189 { 0190 QList<int> pids; 0191 KApplication_getProcessesIdForName(processName, pids); 0192 int myPid = getpid(); 0193 foreach (int pid, pids) { 0194 if (myPid != pid) { 0195 // kDebug() << "Process ID is " << pid; 0196 return true; 0197 } 0198 } 0199 return false; 0200 } 0201 0202 bool KApplication_killProcesses(const QString &processName) 0203 { 0204 QList<int> pids; 0205 KApplication_getProcessesIdForName(processName, pids); 0206 if (pids.empty()) { 0207 return true; 0208 } 0209 qWarning() << "Killing process \"" << processName << " (pid=" << pids[0] << ").."; 0210 int overallResult = 0; 0211 foreach (int pid, pids) { 0212 int result = kill(pid, SIGTERM); 0213 if (result == 0) { 0214 continue; 0215 } 0216 result = kill(pid, SIGKILL); 0217 if (result != 0) { 0218 overallResult = result; 0219 } 0220 } 0221 return overallResult == 0; 0222 } 0223 0224 struct EnumWindowsStruct { 0225 EnumWindowsStruct() : windowId(0) {} 0226 int pid; 0227 HWND windowId; 0228 }; 0229 0230 BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) 0231 { 0232 if (GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE) { 0233 DWORD pidwin; 0234 GetWindowThreadProcessId(hwnd, &pidwin); 0235 if (pidwin == ((EnumWindowsStruct *)lParam)->pid) { 0236 ((EnumWindowsStruct *)lParam)->windowId = hwnd; 0237 return false; 0238 } 0239 } 0240 return true; 0241 } 0242 0243 void KApplication_activateWindowForProcess(const QString &executableName) 0244 { 0245 QList<int> pids; 0246 KApplication_getProcessesIdForName(executableName, pids); 0247 int myPid = getpid(); 0248 int foundPid = 0; 0249 foreach (int pid, pids) { 0250 if (myPid != pid) { 0251 qDebug() << "activateWindowForProcess(): PID to activate:" << pid; 0252 foundPid = pid; 0253 break; 0254 } 0255 } 0256 if (foundPid == 0) { 0257 return; 0258 } 0259 EnumWindowsStruct winStruct; 0260 winStruct.pid = foundPid; 0261 EnumWindows(EnumWindowsProc, (LPARAM)&winStruct); 0262 if (winStruct.windowId == NULL) { 0263 return; 0264 } 0265 KWindowSystem::forceActiveWindow((WId)winStruct.windowId, 0); 0266 } 0267 #endif 0268 0269 // </copy>