X-Git-Url: http://git.iain.cx/?a=blobdiff_plain;f=process.cpp;h=e78283c1f05a0f7cf8b55fa9f8f116bf55a875c8;hb=ee9a86c8408feaf173733aea12a80211e5d74483;hp=22e5a121634ebd95722e4e0b9299635992807359;hpb=eed3860f97880967f2a6b92c18c0c6631d8a74b4;p=nssm.git diff --git a/process.cpp b/process.cpp index 22e5a12..e78283c 100644 --- a/process.cpp +++ b/process.cpp @@ -2,6 +2,47 @@ extern imports_t imports; +HANDLE get_debug_token() { + long error; + HANDLE token; + if (! OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, false, &token)) { + error = GetLastError(); + if (error == ERROR_NO_TOKEN) { + (void) ImpersonateSelf(SecurityImpersonation); + (void) OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, false, &token); + } + } + if (! token) return INVALID_HANDLE_VALUE; + + TOKEN_PRIVILEGES privileges, old; + unsigned long size = sizeof(TOKEN_PRIVILEGES); + LUID luid; + if (! LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) { + CloseHandle(token); + return INVALID_HANDLE_VALUE; + } + + privileges.PrivilegeCount = 1; + privileges.Privileges[0].Luid = luid; + privileges.Privileges[0].Attributes = 0; + + if (! AdjustTokenPrivileges(token, false, &privileges, size, &old, &size)) { + CloseHandle(token); + return INVALID_HANDLE_VALUE; + } + + old.PrivilegeCount = 1; + old.Privileges[0].Luid = luid; + old.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED; + + if (! AdjustTokenPrivileges(token, false, &old, size, NULL, NULL)) { + CloseHandle(token); + return INVALID_HANDLE_VALUE; + } + + return token; +} + void service_kill_t(nssm_service_t *service, kill_t *k) { if (! service) return; if (! k) return; @@ -275,16 +316,17 @@ int kill_console(kill_t *k) { return kill_console(NULL, k); } -void kill_process_tree(nssm_service_t * service, kill_t *k, unsigned long ppid) { +void walk_process_tree(nssm_service_t *service, walk_function_t fn, kill_t *k, unsigned long ppid) { if (! k) return; /* Shouldn't happen unless the service failed to start. */ if (! k->pid) return; /* XXX: needed? */ unsigned long pid = k->pid; + unsigned long depth = k->depth; TCHAR pid_string[16], code[16]; _sntprintf_s(pid_string, _countof(pid_string), _TRUNCATE, _T("%lu"), pid); _sntprintf_s(code, _countof(code), _TRUNCATE, _T("%lu"), k->exitcode); - log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_KILLING, k->name, pid_string, code, 0); + if (fn == kill_process) log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_KILLING, k->name, pid_string, code, 0); /* We will need a process handle in order to call TerminateProcess() later. */ HANDLE process_handle = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, false, pid); @@ -292,9 +334,9 @@ void kill_process_tree(nssm_service_t * service, kill_t *k, unsigned long ppid) /* Kill this process first, then its descendents. */ TCHAR ppid_string[16]; _sntprintf_s(ppid_string, _countof(ppid_string), _TRUNCATE, _T("%lu"), ppid); - log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_KILL_PROCESS_TREE, pid_string, ppid_string, k->name, 0); + if (fn == kill_process) log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_KILL_PROCESS_TREE, pid_string, ppid_string, k->name, 0); k->process_handle = process_handle; /* XXX: open directly? */ - if (! kill_process(k)) { + if (! fn(service, k)) { /* Maybe it already died. */ unsigned long ret; if (! GetExitCodeProcess(process_handle, &ret) || ret == STILL_ACTIVE) { @@ -325,9 +367,10 @@ void kill_process_tree(nssm_service_t * service, kill_t *k, unsigned long ppid) } /* This is a child of the doomed process so kill it. */ + k->depth++; if (! check_parent(k, &pe, pid)) { k->pid = pe.th32ProcessID; - kill_process_tree(k, ppid); + walk_process_tree(service, fn, k, ppid); } k->pid = pid; @@ -338,19 +381,55 @@ void kill_process_tree(nssm_service_t * service, kill_t *k, unsigned long ppid) if (ret == ERROR_NO_MORE_FILES) break; log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_PROCESS_ENUMERATE_FAILED, k->name, error_string(GetLastError()), 0); CloseHandle(snapshot); + k->depth = depth; return; } if (! check_parent(k, &pe, pid)) { k->pid = pe.th32ProcessID; - kill_process_tree(k, ppid); + walk_process_tree(service, fn, k, ppid); } k->pid = pid; } + k->depth = depth; CloseHandle(snapshot); } void kill_process_tree(kill_t *k, unsigned long ppid) { - return kill_process_tree(NULL, k, ppid); + return walk_process_tree(NULL, kill_process, k, ppid); +} + +int print_process(nssm_service_t *service, kill_t *k) { + TCHAR exe[EXE_LENGTH]; + TCHAR *buffer = 0; + if (k->depth) { + buffer = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, (k->depth + 1) * sizeof(TCHAR)); + if (buffer) { + unsigned long i; + for (i = 0; i < k->depth; i++) buffer[i] = _T(' '); + buffer[i] = _T('\0'); + } + } + + unsigned long size = _countof(exe); + if (! imports.QueryFullProcessImageName || ! imports.QueryFullProcessImageName(k->process_handle, 0, exe, &size)) { + /* + Fall back to GetModuleFileNameEx(), which won't work for WOW64 processes. + */ + if (! GetModuleFileNameEx(k->process_handle, NULL, exe, _countof(exe))) { + long error = GetLastError(); + if (error == ERROR_PARTIAL_COPY) _sntprintf_s(exe, _countof(exe), _TRUNCATE, _T("[WOW64]")); + else _sntprintf_s(exe, _countof(exe), _TRUNCATE, _T("???")); + } + } + + _tprintf(_T("% 8lu %s%s\n"), k->pid, buffer ? buffer : _T(""), exe); + + if (buffer) HeapFree(GetProcessHeap(), 0, buffer); + return 1; +} + +int print_process(kill_t *k) { + return print_process(NULL, k); }