#include "nssm.h"\r
\r
+static char error_message[65535];\r
+\r
+/* Convert error code to error string - must call LocalFree() on return value */\r
+char *error_string(unsigned long error) {\r
+ if (! FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char *) &error_message, sizeof(error_message), 0)) {\r
+ if (_snprintf(error_message, sizeof(error_message), "system error %lu", error) < 0) return 0;\r
+ }\r
+ return error_message;\r
+}\r
+\r
/* Log a message to the Event Log */\r
void log_event(unsigned short type, unsigned long id, ...) {\r
va_list arg;\r
#ifndef EVENT_H\r
#define EVENT_H\r
\r
+char *error_string(unsigned long);\r
void log_event(unsigned short, unsigned long, ...);\r
\r
#endif\r
/* Start service magic */\r
SERVICE_TABLE_ENTRY table[] = { { NSSM, service_main }, { 0, 0 } };\r
if (! StartServiceCtrlDispatcher(table)) {\r
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DISPATCHER_FAILED, GetLastError(), 0);\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DISPATCHER_FAILED, error_string(GetLastError()), 0);\r
return 100;\r
}\r
\r
/* Get a snapshot of all threads in the system. */
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (! snapshot) {
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATETOOLHELP32SNAPSHOT_THREAD_FAILED, service_name, GetLastError(), 0);
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATETOOLHELP32SNAPSHOT_THREAD_FAILED, service_name, error_string(GetLastError()), 0);
return 0;
}
te.dwSize = sizeof(te);
if (! Thread32First(snapshot, &te)) {
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_THREAD_ENUMERATE_FAILED, service_name, GetLastError(), 0);
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_THREAD_ENUMERATE_FAILED, service_name, error_string(GetLastError()), 0);
return 0;
}
if (! Thread32Next(snapshot, &te)) {
unsigned long error = GetLastError();
if (error == ERROR_NO_MORE_FILES) break;
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_THREAD_ENUMERATE_FAILED, service_name, GetLastError(), 0);
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_THREAD_ENUMERATE_FAILED, service_name, error_string(GetLastError()), 0);
return ret;
}
}
void kill_process_tree(char *service_name, unsigned long pid, unsigned long exitcode, unsigned long ppid) {
- log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_KILLING, service_name, pid, exitcode, 0);
-
- /* Shouldn't happen. */
+ /* Shouldn't happen unless the service failed to start. */
if (! pid) return;
+ char pid_string[16], code[16];
+ _snprintf(pid_string, sizeof(pid_string), "%d", pid);
+ _snprintf(code, sizeof(code), "%d", exitcode);
+ log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_KILLING, service_name, pid_string, code, 0);
+
/* Get a snapshot of all processes in the system. */
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (! snapshot) {
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATETOOLHELP32SNAPSHOT_PROCESS_FAILED, service_name, GetLastError(), 0);
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATETOOLHELP32SNAPSHOT_PROCESS_FAILED, service_name, error_string(GetLastError()), 0);
return;
}
pe.dwSize = sizeof(pe);
if (! Process32First(snapshot, &pe)) {
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_PROCESS_ENUMERATE_FAILED, service_name, GetLastError(), 0);
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_PROCESS_ENUMERATE_FAILED, service_name, error_string(GetLastError()), 0);
return;
}
if (! Process32Next(snapshot, &pe)) {
unsigned long ret = GetLastError();
if (ret == ERROR_NO_MORE_FILES) break;
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_PROCESS_ENUMERATE_FAILED, service_name, GetLastError(), 0);
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_PROCESS_ENUMERATE_FAILED, service_name, error_string(GetLastError()), 0);
return;
}
/* 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);
if (! process_handle) {
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENPROCESS_FAILED, pid, service_name, GetLastError(), 0);
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENPROCESS_FAILED, pid_string, service_name, error_string(GetLastError()), 0);
return;
}
- log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_KILL_PROCESS_TREE, pid, ppid, service_name, 0);
+ char ppid_string[16];
+ _snprintf(ppid_string, sizeof(ppid_string), "%d", ppid);
+ log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_KILL_PROCESS_TREE, pid_string, ppid_string, service_name, 0);
if (! kill_process(service_name, process_handle, pid, exitcode)) {
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_TERMINATEPROCESS_FAILED, pid, service_name, GetLastError(), 0);
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_TERMINATEPROCESS_FAILED, pid_string, service_name, error_string(GetLastError()), 0);
return;
}
}
}\r
\r
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, registry, 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &key, 0) != ERROR_SUCCESS) {\r
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, GetLastError(), 0);\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, error_string(GetLastError()), 0);\r
return 2;\r
}\r
\r
/* Try to open the registry */\r
HKEY key;\r
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, registry, 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &key, 0) != ERROR_SUCCESS) {\r
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, GetLastError(), 0);\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, error_string(GetLastError()), 0);\r
return 2;\r
}\r
\r
/* Try to create the parameters */\r
if (RegSetValueEx(key, NSSM_REG_EXE, 0, REG_EXPAND_SZ, (const unsigned char *) exe, strlen(exe) + 1) != ERROR_SUCCESS) {\r
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_EXE, GetLastError(), 0);\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_EXE, error_string(GetLastError()), 0);\r
RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY);\r
RegCloseKey(key);\r
return 3;\r
}\r
if (RegSetValueEx(key, NSSM_REG_FLAGS, 0, REG_EXPAND_SZ, (const unsigned char *) flags, strlen(flags) + 1) != ERROR_SUCCESS) {\r
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_FLAGS, GetLastError(), 0);\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_FLAGS, error_string(GetLastError()), 0);\r
RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY);\r
RegCloseKey(key);\r
return 4;\r
}\r
if (RegSetValueEx(key, NSSM_REG_DIR, 0, REG_EXPAND_SZ, (const unsigned char *) dir, strlen(dir) + 1) != ERROR_SUCCESS) {\r
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_DIR, GetLastError(), 0);\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_DIR, error_string(GetLastError()), 0);\r
RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY);\r
RegCloseKey(key);\r
return 5;\r
HKEY key;\r
unsigned long disposition;\r
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, registry, 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &key, &disposition) != ERROR_SUCCESS) {\r
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, GetLastError(), 0);\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, error_string(GetLastError()), 0);\r
return 2;\r
}\r
\r
\r
/* Create the default value */\r
if (RegSetValueEx(key, 0, 0, REG_SZ, (const unsigned char *) action_string, strlen(action_string) + 1) != ERROR_SUCCESS) {\r
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_EXIT, GetLastError(), 0);\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_EXIT, error_string(GetLastError()), 0);\r
RegCloseKey(key);\r
return 3;\r
}\r
\r
unsigned long ret = RegQueryValueEx(key, value, 0, &type, buffer, &buflen);\r
if (ret != ERROR_SUCCESS) {\r
- if (ret != ERROR_FILE_NOT_FOUND) log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, GetLastError(), 0);\r
+ if (ret != ERROR_FILE_NOT_FOUND) log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, error_string(GetLastError()), 0);\r
HeapFree(GetProcessHeap(), 0, buffer);\r
return 2;\r
}\r
\r
ret = ExpandEnvironmentStrings((char *) buffer, data, datalen);\r
if (! ret || ret > datalen) {\r
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_EXPANDENVIRONMENTSTRINGS_FAILED, value, buffer, GetLastError(), 0);\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_EXPANDENVIRONMENTSTRINGS_FAILED, value, buffer, error_string(GetLastError()), 0);\r
HeapFree(GetProcessHeap(), 0, buffer);\r
return 3;\r
}\r
/* Try to open the registry */\r
HKEY key;\r
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, registry, 0, KEY_READ, &key) != ERROR_SUCCESS) {\r
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, GetLastError(), 0);\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, error_string(GetLastError()), 0);\r
return 2;\r
}\r
\r
HKEY key;\r
long error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, registry, 0, KEY_READ, &key);\r
if (error != ERROR_SUCCESS && error != ERROR_FILE_NOT_FOUND) {\r
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, GetLastError(), 0);\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, error_string(GetLastError()), 0);\r
return 2;\r
}\r
\r
/* Register control handler */\r
service_handle = RegisterServiceCtrlHandlerEx(NSSM, service_control_handler, 0);\r
if (! service_handle) {\r
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_REGISTERSERVICECTRLHANDER_FAILED, GetLastError(), 0);\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_REGISTERSERVICECTRLHANDER_FAILED, error_string(GetLastError()), 0);\r
return;\r
}\r
\r
\r
/* Monitor service service */\r
if (! RegisterWaitForSingleObject(&wait_handle, process_handle, end_service, (void *) pid, INFINITE, WT_EXECUTEONLYONCE | WT_EXECUTELONGFUNCTION)) {\r
- log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_REGISTERWAITFORSINGLEOBJECT_FAILED, service_name, exe, GetLastError(), 0);\r
+ log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_REGISTERWAITFORSINGLEOBJECT_FAILED, service_name, exe, error_string(GetLastError()), 0);\r
}\r
\r
return 0;\r
throttle_restart();\r
\r
if (! CreateProcess(0, cmd, 0, 0, false, 0, 0, dir, &si, &pi)) {\r
- log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEPROCESS_FAILED, service_name, exe, GetLastError(), 0);\r
+ log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEPROCESS_FAILED, service_name, exe, error_string(GetLastError()), 0);\r
return stop_service(3, true, true);\r
}\r
process_handle = pi.hProcess;\r