X-Git-Url: http://git.iain.cx/?a=blobdiff_plain;f=process.cpp;h=220411b308754738a8f76126a3cd0ef5c91eab5c;hb=b6d5dc93f294a2c781a7613c72169d0389137a3d;hp=d1a9a4982395117e1caf6f1875b52dfa4a9d7733;hpb=b6f7fe3b11fd130f46eb6b5009391cc3bb0cad49;p=nssm.git diff --git a/process.cpp b/process.cpp index d1a9a49..220411b 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; @@ -115,7 +156,7 @@ int kill_threads(nssm_service_t *service, kill_t *k) { /* Get a snapshot of all threads in the system. */ HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - if (! snapshot) { + if (snapshot == INVALID_HANDLE_VALUE) { log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATETOOLHELP32SNAPSHOT_THREAD_FAILED, k->name, error_string(GetLastError()), 0); return 0; } @@ -241,7 +282,8 @@ int kill_console(nssm_service_t *service, kill_t *k) { /* Ignore the event ourselves. */ ret = 0; - if (! SetConsoleCtrlHandler(0, TRUE)) { + BOOL ignored = SetConsoleCtrlHandler(0, TRUE); + if (! ignored) { log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETCONSOLECTRLHANDLER_FAILED, k->name, error_string(GetLastError()), 0); ret = 4; } @@ -262,6 +304,11 @@ int kill_console(nssm_service_t *service, kill_t *k) { /* Wait for process to exit. */ if (await_single_handle(k->status_handle, k->status, k->process_handle, k->name, _T(__FUNCTION__), k->kill_console_delay)) ret = 6; + /* Remove our handler. */ + if (ignored && ! SetConsoleCtrlHandler(0, FALSE)) { + log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETCONSOLECTRLHANDLER_FAILED, k->name, error_string(GetLastError()), 0); + } + return ret; } @@ -269,7 +316,7 @@ 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? */ @@ -288,7 +335,7 @@ void kill_process_tree(nssm_service_t * service, kill_t *k, unsigned long ppid) _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); 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) { @@ -303,7 +350,7 @@ void kill_process_tree(nssm_service_t * service, kill_t *k, unsigned long ppid) /* Get a snapshot of all processes in the system. */ HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (! snapshot) { + if (snapshot == INVALID_HANDLE_VALUE) { log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATETOOLHELP32SNAPSHOT_PROCESS_FAILED, k->name, error_string(GetLastError()), 0); return; } @@ -321,7 +368,7 @@ 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. */ 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; @@ -337,7 +384,7 @@ void kill_process_tree(nssm_service_t * service, kill_t *k, unsigned long ppid) 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; } @@ -346,5 +393,5 @@ void kill_process_tree(nssm_service_t * service, kill_t *k, unsigned long ppid) } 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); }