Cache the document element: now that we have comments in dom,
[kdelibs.git] / kinit / kinit_win.cpp
blob87090e3da415161904231ffee0948f247233d4f9
1 /*
2 * This file is part of the KDE libraries
3 * Copyright (c) 1999-2000 Waldo Bastian <bastian@kde.org>
4 * (c) 1999 Mario Weilguni <mweilguni@sime.com>
5 * (c) 2001 Lubos Lunak <l.lunak@kde.org>
6 * (c) 2006 Ralf Habacker <ralf.habacker@freenet.de>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License version 2 as published by the Free Software Foundation.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
23 #include <config.h>
26 #include <errno.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
31 #include <windows.h>
32 #include <psapi.h>
35 #include <QtCore/QProcess>
36 #include <QtCore/QFileInfo>
37 #include <QtDBus/QtDBus>
39 #include <kcomponentdata.h>
40 #include <kstandarddirs.h>
41 #include <kapplication.h>
42 #include <kdeversion.h>
45 #define KDED_EXENAME "kded4"
46 #define KNOTIFY_EXENAME "knotify4"
48 static KComponentData *s_instance = 0;
50 // print verbose messages
51 int verbose=0;
53 /// holds process list for suicide mode
54 QList<QProcess*> startedProcesses;
56 // internal launch function
57 int launch(const QString &cmd)
59 QProcess *proc = new QProcess();
60 proc->start(cmd);
61 proc->waitForStarted();
62 startedProcesses << proc;
63 _PROCESS_INFORMATION* _pid = proc->pid();
64 int pid = _pid ? _pid->dwProcessId : 0;
65 if (verbose) {
66 fprintf(stderr,"%s",proc->readAllStandardError().constData());
67 fprintf(stderr,"%s",proc->readAllStandardOutput().constData());
69 if (pid) {
70 if (verbose)
71 fprintf(stderr, "kdeinit4: Launched %s, pid = %ld\n", qPrintable(cmd),(long) pid);
73 else {
74 if (verbose)
75 fprintf(stderr, "kdeinit4: could not launch %s, exiting",qPrintable(cmd));
77 return pid;
80 /// check dbus registration
81 bool checkIfRegisteredInDBus(const QString &name, int _timeout=10)
83 int timeout = _timeout * 5;
84 while(timeout) {
85 if ( QDBusConnection::sessionBus().interface()->isServiceRegistered( name ) )
86 break;
87 Sleep(200);
88 timeout--;
90 if (!timeout) {
91 if (verbose)
92 fprintf(stderr,"not registered %s in dbus after %d secs\n",qPrintable(name),_timeout);
93 return false;
95 if (verbose)
96 fprintf(stderr,"%s is registered in dbus\n",qPrintable(name));
97 return true;
100 class ProcessListEntry {
101 public:
102 ProcessListEntry(HANDLE _handle,char *_path, int _pid )
104 QFileInfo p(_path);
105 path = p.absolutePath();
106 name = p.baseName();
107 handle = _handle;
108 pid = _pid;
110 QString name;
111 QString path;
112 int pid;
113 HANDLE handle;
117 holds system process list
119 class ProcessList {
120 public:
121 ProcessList() {initProcessList(); }
122 ~ProcessList();
123 ProcessListEntry *hasProcessInList(const QString &name);
124 bool terminateProcess(const QString &name);
125 void dumpList();
126 private:
127 void initProcessList();
128 void getProcessNameAndID( DWORD processID );
129 QList<ProcessListEntry *> processList;
133 void ProcessList::getProcessNameAndID( DWORD processID )
135 char szProcessName[MAX_PATH];
137 // Get a handle to the process.
139 HANDLE hProcess = OpenProcess( SYNCHRONIZE|PROCESS_QUERY_INFORMATION |
140 PROCESS_VM_READ | PROCESS_TERMINATE,
141 false, processID );
143 // Get the process name.
145 if (NULL != hProcess )
147 HMODULE hMod;
148 DWORD cbNeeded;
150 if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod),
151 &cbNeeded) )
153 GetModuleFileNameExA( hProcess, hMod, szProcessName,
154 sizeof(szProcessName)/sizeof(TCHAR) );
158 processList << new ProcessListEntry(hProcess,szProcessName,processID );
160 if (verbose)
161 fprintf(stderr,"%s (PID: %u)\n", szProcessName, processID );
166 read process list from system and fill in global var aProcessList
168 void ProcessList::initProcessList()
170 // Get the list of process identifiers.
172 DWORD aProcesses[1024], cbNeeded, cProcesses;
173 unsigned int i;
175 if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
176 return;
178 // Calculate how many process identifiers were returned.
180 cProcesses = cbNeeded / sizeof(DWORD);
182 // Print the name and process identifier for each process.
184 for ( i = 0; i < cProcesses; i++ )
185 if( aProcesses[i] != 0 )
186 getProcessNameAndID( aProcesses[i] );
190 ProcessList::~ProcessList()
192 ProcessListEntry *ple;
193 foreach(ple,processList) {
194 CloseHandle(ple->handle);
195 delete ple;
200 void ProcessList::dumpList()
202 ProcessListEntry *ple;
203 foreach(ple,processList) {
204 fprintf(stdout,"%s (PID: %u)\n", ple->name.toLatin1().data(), ple->pid);
209 return process list entry of given name
211 ProcessListEntry *ProcessList::hasProcessInList(const QString &name)
213 ProcessListEntry *ple;
214 foreach(ple,processList) {
215 if (ple->name == name || ple->name == name + ".exe") {
216 if (verbose)
217 fprintf(stderr,"found %s with pid=%d\n",qPrintable(ple->name),ple->pid);
218 return ple;
221 return NULL;
224 bool ProcessList::terminateProcess(const QString &name)
226 ProcessListEntry *p = hasProcessInList(name);
227 if (p) {
228 int ret = TerminateProcess(p->handle,0) ? true : false;
229 if (verbose)
230 fprintf(stderr,"process %s terminated %d %d\n",qPrintable(name),ret,GetLastError());
231 return ret;
233 else {
234 if (verbose)
235 fprintf(stderr,"process %s not found\n",qPrintable(name));
236 return false;
241 int main(int argc, char **argv, char **envp)
243 pid_t pid;
244 bool launch_dbus = true;
245 bool launch_klauncher = true;
246 bool launch_kded = true;
247 bool suicide = false;
248 // bool terminate_kde = false; // unused atm
250 ProcessList processList;
252 /** Save arguments first... **/
253 char **safe_argv = (char **) malloc( sizeof(char *) * argc);
254 for(int i = 0; i < argc; i++)
256 safe_argv[i] = strcpy((char*)malloc(strlen(argv[i])+1), argv[i]);
257 if (strcmp(safe_argv[i], "--no-dbus") == 0)
258 launch_dbus = false;
259 if (strcmp(safe_argv[i], "--no-klauncher") == 0)
260 launch_klauncher = false;
261 if (strcmp(safe_argv[i], "--no-kded") == 0)
262 launch_kded = false;
263 if (strcmp(safe_argv[i], "--suicide") == 0)
264 suicide = true;
265 // if (strcmp(safe_argv[i], "--exit") == 0)
266 // keep_running = 0;
267 if (strcmp(safe_argv[i], "--verbose") == 0)
268 verbose = 1;
269 if (strcmp(safe_argv[i], "--help") == 0)
271 printf("Usage: kdeinit4 [options]\n");
272 printf(" --no-dbus Do not start dcopserver\n");
273 printf(" --no-klauncher Do not start klauncher\n");
274 printf(" --no-kded Do not start kded\n");
275 printf(" --suicide Terminate when no KDE applications are left running\n");
276 printf(" --terminate Terminate all running kde processes\n");
277 printf(" --verbose print verbose messages\n");
278 printf(" --list list system process for which the user has the right to terminate\n");
279 // printf(" --exit Terminate when kded has run\n");
280 exit(0);
282 if (strcmp(safe_argv[i], "--list") == 0) {
283 processList.dumpList();
284 exit(0);
286 if (strcmp(safe_argv[i], "--terminate") == 0) {
287 QStringList appList;
288 appList << KDED_EXENAME << KNOTIFY_EXENAME << "nepomukdaemon"
289 << "kuiserver" << "kioslave" << "klauncher" << "dbus-daemon";
291 foreach(QString app, appList)
292 processList.terminateProcess(app);
293 exit(0);
297 /** Make process group leader (for shutting down children later) **/
299 /** Create our instance **/
300 s_instance = new KComponentData("kdeinit4", QByteArray(), KComponentData::SkipMainComponentRegistration);
302 if (launch_dbus && !processList.hasProcessInList("dbus-daemon"))
304 pid = launch("dbus-launch.exe");
305 if (!pid)
306 pid = launch("dbus-launch.bat");
307 if (!pid)
308 exit(1);
311 if (launch_klauncher && !processList.hasProcessInList("klauncher"))
313 pid = launch("klauncher");
314 if (!pid || !checkIfRegisteredInDBus("org.kde.klauncher",10))
315 exit(1);
319 if (launch_kded && !processList.hasProcessInList(KDED_EXENAME))
321 pid = launch(KDED_EXENAME);
322 if (!pid || !checkIfRegisteredInDBus("org.kde.kded",10))
323 exit(1);
326 for(int i = 1; i < argc; i++)
328 if (safe_argv[i][0] == '+')
330 pid = launch(safe_argv[i]+1);
332 else if (safe_argv[i][0] == '-')
334 // Ignore
336 else
338 pid = launch( safe_argv[i]);
342 /** Free arguments **/
343 for(int i = 0; i < argc; i++)
345 free(safe_argv[i]);
347 free (safe_argv);
349 /** wait for termination of all (core) processes */
350 if (suicide) {
351 QProcess *proc;
352 int can_exit=1;
353 do {
354 foreach(proc,startedProcesses) {
355 if (proc->state() != QProcess::NotRunning)
356 can_exit = 0;
358 if (!can_exit)
359 Sleep(2000);
360 } while(!can_exit);
361 return 0;
363 return 0;