15fc83dce1b7f2e8ec19846cfc649be5f48e8b80
[nssm.git] / process.cpp
1 #include "nssm.h"
2
3 void kill_process_tree(char *service_name, unsigned long pid, unsigned long exitcode, unsigned long ppid) {
4   log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_KILLING, service_name, pid, exitcode, 0);
5
6   /* Shouldn't happen. */
7   if (! pid) return;
8
9   HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
10   if (! snapshot) {
11     log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATETOOLHELP32SNAPSHOT_FAILED, service_name, GetLastError(), 0);
12     return;
13   }
14
15   PROCESSENTRY32 pe;
16   ZeroMemory(&pe, sizeof(pe));
17   pe.dwSize = sizeof(pe);
18
19   if (! Process32First(snapshot, &pe)) {
20     log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_PROCESS_ENUMERATE_FAILED, service_name, GetLastError(), 0);
21     return;
22   }
23
24   if (pe.th32ParentProcessID == pid) kill_process_tree(service_name, pe.th32ProcessID, exitcode, ppid);
25
26   while (true) {
27     /* Try to get the next process. */
28     if (! Process32Next(snapshot, &pe)) {
29       unsigned long ret = GetLastError();
30       if (ret == ERROR_NO_MORE_FILES) break;
31       log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_PROCESS_ENUMERATE_FAILED, service_name, GetLastError(), 0);
32       return;
33     }
34
35     if (pe.th32ParentProcessID == pid) kill_process_tree(service_name, pe.th32ProcessID, exitcode, ppid);
36   }
37
38   HANDLE process_handle = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, false, pid);
39   if (! process_handle) {
40     log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENPROCESS_FAILED, pid, service_name, GetLastError(), 0);
41     return;
42   }
43
44   log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_KILL_PROCESS_TREE, pid, ppid, service_name, 0);
45   if (! TerminateProcess(process_handle, exitcode)) {
46     log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_TERMINATEPROCESS_FAILED, pid, service_name, GetLastError(), 0);
47     return;
48   }
49 }