Log messages properly.
authorIain Patterson <me@iain.cx>
Tue, 20 Apr 2010 21:56:55 +0000 (22:56 +0100)
committerIain Patterson <me@iain.cx>
Tue, 20 Apr 2010 21:56:55 +0000 (22:56 +0100)
Format messages from resource.  Use NSSM binary as the message source.
Note that replacing the binary is prevented if the event viewer is open.

event.cpp
event.h
messages.mc [new file with mode: 0644]
nssm.cpp
nssm.vcproj [changed mode: 0644->0755]
registry.cpp
service.cpp

index 2a9bbf2..661761d 100644 (file)
--- a/event.cpp
+++ b/event.cpp
@@ -1,40 +1,22 @@
 #include "nssm.h"\r
 \r
-/* Convert error code to error string - must call LocalFree() on return value */\r
-char *error_string(unsigned long error) {\r
-  static char message[65535];\r
-  if (! FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, 0, NSSM_MESSAGE_DEFAULT, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), message, sizeof(message), 0)) return 0;\r
-  return message;\r
-}\r
-\r
 /* Log a message to the Event Log */\r
-void eventprintf(unsigned short type, unsigned long id, char *format, ...) {\r
-  char message[4096];\r
-  char *strings[2];\r
-  int n, size;\r
+void log_event(unsigned short type, unsigned long id, ...) {\r
   va_list arg;\r
+  int count;\r
+  char *s;\r
+  char *strings[6];\r
 \r
-  /* Construct the message */\r
-  size = sizeof(message);\r
-  va_start(arg, format);\r
-  n = _vsnprintf(message, size, format, arg);\r
-  va_end(arg);\r
-\r
-  /* Check success */\r
-  if (n < 0 || n >= size) return;\r
-\r
-  /* Construct strings array */\r
-  strings[0] = message;\r
-  strings[1] = 0;\r
-    \r
   /* Open event log */\r
   HANDLE handle = RegisterEventSource(0, TEXT(NSSM));\r
   if (! handle) return;\r
 \r
   /* Log it */\r
-  if (! ReportEvent(handle, type, 0, id, 0, 1, 0, (const char **) strings, 0)) {\r
-    printf("ReportEvent(): %s\n", error_string(GetLastError()));\r
-  }\r
+  count = 0;\r
+  va_start(arg, id);\r
+  while ((s = va_arg(arg, char *))) strings[count++] = s;\r
+  va_end(arg);\r
+  ReportEvent(handle, type, 0, id, 0, count, 0, (const char **) strings, 0);\r
 \r
   /* Close event log */\r
   DeregisterEventSource(handle);\r
diff --git a/event.h b/event.h
index d6fb7ed..3c977a3 100644 (file)
--- a/event.h
+++ b/event.h
@@ -1,7 +1,6 @@
 #ifndef EVENT_H\r
 #define EVENT_H\r
 \r
-char *error_string(unsigned long);\r
-void eventprintf(unsigned short, unsigned long, char *, ...);\r
+void log_event(unsigned short, unsigned long, ...);\r
 \r
 #endif\r
diff --git a/messages.mc b/messages.mc
new file mode 100644 (file)
index 0000000..84dc287
--- /dev/null
@@ -0,0 +1,149 @@
+LanguageNames=(English=0x0409:MSG00409)
+
+MessageId = 1001
+SymbolicName = NSSM_EVENT_DISPATCHER_FAILED
+Severity = Error
+Language = English
+StartServiceCtrlDispatcher() failed:
+%1
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_OPENSCMANAGER_FAILED
+Severity = Error
+Language = English
+Unable to connect to service manager!
+Perhaps you need to be an administrator...
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_OUT_OF_MEMORY
+Severity = Error
+Language = English
+Out of memory for %1 in %2!
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_GET_PARAMETERS_FAILED
+Severity = Error
+Language = English
+Failed to get startup parameters for service %1.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_REGISTERSERVICECTRLHANDER_FAILED
+Severity = Error
+Language = English
+RegisterServiceCtrlHandlerEx() failed:
+%1
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_START_SERVICE_FAILED
+Severity = Error
+Language = English
+Can't start %1 for service %2.
+Error code: %3.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_RESTART_SERVICE_FAILED
+Severity = Warning
+Language = English
+Failed to restart %1 for service %2.
+Sleeping...
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_STARTED_SERVICE
+Severity = Informational
+Language = English
+Started %1 %2 for service %3 in %4.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_REGISTERWAITFORSINGLEOBJECT_FAILED
+Severity = Warning
+Language = English
+Service %1 may claim to be still running when %2 exits.
+RegisterWaitForSingleObject() failed:
+%3
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_CREATEPROCESS_FAILED
+Severity = Error
+Language = English
+Failed to start service %1.  Program %2 couldn't be launched.
+CreateProcess() failed:
+%3
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_TERMINATEPROCESS
+Severity = Informational
+Language = English
+Requested stop of service %1.  Killing program %2.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_PROCESS_ALREADY_STOPPED
+Severity = Informational
+Language = English
+Requested stop of service %1.  No action is required as program %2 is not running.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_ENDED_SERVICE
+Severity = Informational
+Language = English
+Program %1 for service %2 exited with return code %3.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_EXIT_RESTART
+Severity = Informational
+Language = English
+Service %1 action for exit code %2 is %3.
+Attempting to restart %4.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_EXIT_IGNORE
+Severity = Informational
+Language = English
+Service %1 action for exit code %2 is %3.
+No action will be taken to restart %4.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_EXIT_REALLY
+Severity = Informational
+Language = English
+Service %1 action for exit code %2 is %3.
+Exiting.
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_OPENKEY_FAILED
+Severity = Error
+Language = English
+Failed to open registry key HKLM\%1:
+%2
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_QUERYVALUE_FAILED
+Severity = Error
+Language = English
+Failed to read registry value %1:
+%2
+.
+
+MessageId = +1
+SymbolicName = NSSM_EVENT_SETVALUE_FAILED
+Severity = Error
+Language = English
+Failed to write registry value %1:
+%2
+.
index 85add5f..08b9432 100644 (file)
--- a/nssm.cpp
+++ b/nssm.cpp
@@ -45,9 +45,7 @@ int main(int argc, char **argv) {
   /* Start service magic */\r
   SERVICE_TABLE_ENTRY table[] = { { NSSM, service_main }, { 0, 0 } };\r
   if (! StartServiceCtrlDispatcher(table)) {\r
-    char *message = error_string(GetLastError());\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "StartServiceCtrlDispatcher() failed: %s", message);\r
-    if (message) LocalFree(message);\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_DISPATCHER_FAILED, GetLastError(), 0);\r
     return 100;\r
   }\r
 \r
old mode 100644 (file)
new mode 100755 (executable)
index f8300fb..93492e2
@@ -33,9 +33,9 @@
                        />\r
                        <Tool\r
                                Name="VCCustomBuildTool"\r
-                               Description="Compiling messages"\r
-                               CommandLine="mc -A &quot;$(InputDir)\$(InputName).mc&quot; -r &quot;$(InputDir)&quot; -h &quot;$(InputDir)&quot;"\r
-                               Outputs="$(InputDir)\$(InputName).rc;$(InputDir)\$(InputName).h"\r
+                               Description=""\r
+                               CommandLine=""\r
+                               Outputs=""\r
                        />\r
                        <Tool\r
                                Name="VCXMLDataGeneratorTool"\r
                        />\r
                        <Tool\r
                                Name="VCCustomBuildTool"\r
-                               Description="Compiling messages"\r
-                               CommandLine="mc -A &quot;$(InputDir)\$(InputName).mc&quot; -r &quot;$(InputDir)&quot; -h &quot;$(InputDir)&quot;"\r
-                               Outputs="$(InputDir)\$(InputName).rc;$(InputDir)\$(InputName).h"\r
+                               Description=""\r
+                               CommandLine=""\r
+                               Outputs=""\r
                        />\r
                        <Tool\r
                                Name="VCXMLDataGeneratorTool"\r
                                <Tool\r
                                        Name="VCCustomBuildTool"\r
                                        Description="Compiling messages"\r
-                                       CommandLine="mc -A $(InputPath) -r $(InputDir) -h $(InputDir)"\r
-                                       Outputs="$(InputFileName).rc;$(InputFileName).h"\r
+                                       CommandLine="mc -A $(InputDir)/$(InputName).mc -r $(InputDir) -h $(InputDir)&#x0D;&#x0A;"\r
+                                       Outputs="$(InputName).rc;$(InputName).h"\r
                                />\r
                        </FileConfiguration>\r
                        <FileConfiguration\r
                                <Tool\r
                                        Name="VCCustomBuildTool"\r
                                        Description="Compiling messages"\r
-                                       CommandLine="mc -A $(InputPath) -r $(InputDir) -h $(InputDir)"\r
-                                       Outputs="$(InputFileName).rc;$(InputFileName).h"\r
+                                       CommandLine="mc -A $(InputDir)\$(InputName).mc -r $(InputDir) -h $(InputDir)&#x0D;&#x0A;"\r
+                                       Outputs="$(InputName).rc;$(InputName).h"\r
                                />\r
                        </FileConfiguration>\r
                        <FileConfiguration\r
                                <Tool\r
                                        Name="VCCustomBuildTool"\r
                                        Description="Compiling messages"\r
-                                       CommandLine="mc -A $(InputPath) -r $(InputDir) -h $(InputDir)"\r
+                                       CommandLine="mc -A $(InputDir)/$(InputName).mc -r $(InputDir) -h $(InputDir)&#x0D;&#x0A;"\r
                                        AdditionalDependencies=""\r
-                                       Outputs="$(InputFileName).rc;$(InputFileName).h"\r
+                                       Outputs="$(InputName).rc;$(InputName).h"\r
                                />\r
                        </FileConfiguration>\r
                        <FileConfiguration\r
                                <Tool\r
                                        Name="VCCustomBuildTool"\r
                                        Description="Compiling messages"\r
-                                       CommandLine="mc -A $(InputPath) -r $(InputDir) -h $(InputDir)"\r
+                                       CommandLine="mc -A $(InputDir)/$(InputName).mc -r $(InputDir) -h $(InputDir)&#x0D;&#x0A;"\r
                                        AdditionalDependencies=""\r
-                                       Outputs="$(InputFileName).rc;$(InputFileName).h"\r
+                                       Outputs="$(InputName).rc;$(InputName).h"\r
                                />\r
                        </FileConfiguration>\r
                </File>\r
index eca8e78..4b92696 100644 (file)
@@ -5,12 +5,12 @@ int create_messages() {
 \r
   char registry[MAX_PATH];\r
   if (_snprintf(registry, sizeof(registry), "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s", NSSM) < 0) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Out of memory for eventlog registry()!");\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "eventlog registry", "create_messages()", 0);\r
     return 1;\r
   }\r
 \r
   if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, registry, 0, 0, REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &key, 0) != ERROR_SUCCESS) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't open eventlog registry!", NSSM_REGISTRY);\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, GetLastError(), 0);\r
     return 2;\r
   }\r
 \r
@@ -30,32 +30,32 @@ int create_parameters(char *service_name, char *exe, char *flags, char *dir) {
   /* Get registry */\r
   char registry[MAX_PATH];\r
   if (_snprintf(registry, sizeof(registry), NSSM_REGISTRY, service_name) < 0) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Out of memory for NSSM_REGISTRY in create_parameters()!");\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "NSSM_REGISTRY", "create_parameters()", 0);\r
     return 1;\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
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't open service registry settings!", NSSM_REGISTRY);\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, GetLastError(), 0);\r
     return 2;\r
   }\r
 \r
   /* Try to create the parameters */\r
   if (RegSetValueEx(key, NSSM_REG_EXE, 0, REG_SZ, (const unsigned char *) exe, strlen(exe) + 1) != ERROR_SUCCESS) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't add registry value %s: %s", NSSM_REG_EXE, error_string(GetLastError()));\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_EXE, 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_SZ, (const unsigned char *) flags, strlen(flags) + 1) != ERROR_SUCCESS) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't add registry value %s: %s", NSSM_REG_FLAGS, error_string(GetLastError()));\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_FLAGS, 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_SZ, (const unsigned char *) dir, strlen(dir) + 1) != ERROR_SUCCESS) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't add registry value %s: %s", NSSM_REG_DIR, error_string(GetLastError()));\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_DIR, GetLastError(), 0);\r
     RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY);\r
     RegCloseKey(key);\r
     return 5;\r
@@ -71,7 +71,7 @@ int create_exit_action(char *service_name, const char *action_string) {
   /* Get registry */\r
   char registry[MAX_PATH];\r
   if (_snprintf(registry, sizeof(registry), NSSM_REGISTRY "\\%s", service_name, NSSM_REG_EXIT) < 0) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Out of memory for NSSM_REG_EXIT in create_exit_action()!");\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "NSSM_REG_EXIT", "create_exit_action()", 0);\r
     return 1;\r
   }\r
 \r
@@ -79,7 +79,7 @@ int create_exit_action(char *service_name, const char *action_string) {
   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
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't open service exit action registry settings!");\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, GetLastError(), 0);\r
     return 2;\r
   }\r
 \r
@@ -91,7 +91,7 @@ int create_exit_action(char *service_name, const char *action_string) {
 \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
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't add default registry value %s: %s", NSSM_REG_EXIT, error_string(GetLastError()));\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_EXIT, GetLastError(), 0);\r
     RegCloseKey(key);\r
     return 3;\r
   }\r
@@ -106,14 +106,14 @@ int get_parameters(char *service_name, char *exe, int exelen, char *flags, int f
   /* Get registry */\r
   char registry[MAX_PATH];\r
   if (_snprintf(registry, sizeof(registry), NSSM_REGISTRY, service_name) < 0) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Out of memory for NSSM_REGISTRY in get_parameters()!");\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "NSSM_REGISTRY", "get_parameters()", 0);\r
     return 1;\r
   }\r
 \r
   /* Try to open the registry */\r
   HKEY key;\r
   if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, registry, 0, KEY_READ, &key) != ERROR_SUCCESS) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't open service registry settings!", NSSM_REGISTRY);\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, GetLastError(), 0);\r
     return 2;\r
   }\r
 \r
@@ -121,21 +121,21 @@ int get_parameters(char *service_name, char *exe, int exelen, char *flags, int f
 \r
   /* Try to get executable file - MUST succeed */\r
   if (RegQueryValueEx(key, NSSM_REG_EXE, 0, &type, (unsigned char *) exe, (unsigned long *) &exelen) != ERROR_SUCCESS) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't get application path (registry value %s): %s", NSSM_REG_EXE, error_string(GetLastError()));\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, NSSM_REG_EXE, GetLastError(), 0);\r
     RegCloseKey(key);\r
     return 3;\r
   }\r
 \r
   /* Try to get flags - may fail */\r
   if (RegQueryValueEx(key, NSSM_REG_FLAGS, 0, &type, (unsigned char *) flags, (unsigned long *) &flagslen) != ERROR_SUCCESS) {\r
-    eventprintf(EVENTLOG_WARNING_TYPE, NSSM_MESSAGE_DEFAULT, "Can't get application flags (registry value %s): %s", NSSM_REG_FLAGS, error_string(GetLastError()));\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, NSSM_REG_FLAGS, GetLastError(), 0);\r
     RegCloseKey(key);\r
     return 4;\r
   }\r
 \r
   /* Try to get startup directory - may fail */\r
   if (RegQueryValueEx(key, NSSM_REG_DIR, 0, &type, (unsigned char *) dir, (unsigned long *) &dirlen) != ERROR_SUCCESS) {\r
-    eventprintf(EVENTLOG_WARNING_TYPE, NSSM_MESSAGE_DEFAULT, "Can't get application startup directory (registry value %s): %s", NSSM_REG_DIR, error_string(GetLastError()));\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, NSSM_REG_DIR, GetLastError(), 0);\r
     RegCloseKey(key);\r
     return 5;\r
   }\r
@@ -150,7 +150,7 @@ int get_exit_action(char *service_name, unsigned long *ret, unsigned char *actio
   /* Get registry */\r
   char registry[MAX_PATH];\r
   if (_snprintf(registry, sizeof(registry), NSSM_REGISTRY "\\%s", service_name, NSSM_REG_EXIT) < 0) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Out of memory for NSSM_REG_EXIT in get_exit_action()!");\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "NSSM_REG_EXIT", "get_exit_action()", 0);\r
     return 1;\r
   }\r
 \r
@@ -158,7 +158,7 @@ int get_exit_action(char *service_name, unsigned long *ret, unsigned char *actio
   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
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't open registry %s!", registry);\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, GetLastError(), 0);\r
     return 2;\r
   }\r
 \r
index ad5f2c2..b8b9992 100644 (file)
@@ -16,7 +16,7 @@ static const char *exit_action_strings[] = { "Restart", "Ignore", "Exit", 0 };
 SC_HANDLE open_service_manager() {\r
   SC_HANDLE ret = OpenSCManager(0, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS);\r
   if (! ret) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Unable to connect to service manager!\nPerhaps you need to be an administrator...");\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENSCMANAGER_FAILED, 0);\r
     return 0;\r
   }\r
 \r
@@ -139,7 +139,7 @@ int remove_service(char *name) {
 /* Service initialisation */\r
 void WINAPI service_main(unsigned long argc, char **argv) {\r
   if (_snprintf(service_name, sizeof(service_name), "%s", argv[0]) < 0) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "service_main(): Out of memory for service_name!");\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "service_name", "service_main()", 0);\r
     return;\r
   }\r
 \r
@@ -159,14 +159,14 @@ void WINAPI service_main(unsigned long argc, char **argv) {
   /* Get startup parameters */\r
   int ret = get_parameters(argv[0], exe, sizeof(exe), flags, sizeof(flags), dir, sizeof(dir));\r
   if (ret) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "service_main(): Can't get startup parameters: error %d", ret);\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_PARAMETERS_FAILED, argv[0], 0);\r
     return;\r
   }\r
 \r
   /* Register control handler */\r
   service_handle = RegisterServiceCtrlHandlerEx(NSSM, service_control_handler, 0);\r
   if (! service_handle) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "service_main(): RegisterServiceCtrlHandlerEx() failed: %s", error_string(GetLastError()));\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_REGISTERSERVICECTRLHANDER_FAILED, GetLastError(), 0);\r
     return;\r
   }\r
 \r
@@ -180,14 +180,16 @@ int monitor_service() {
   /* Set service status to started */\r
   int ret = start_service();\r
   if (ret) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't start service %s: error code %d", service_name, ret);\r
+    char code[16];\r
+    snprintf(code, sizeof(code), "%d", ret);\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_START_SERVICE_FAILED, exe, service_name, ret, 0);\r
     return ret;\r
   }\r
-  eventprintf(EVENTLOG_INFORMATION_TYPE, NSSM_MESSAGE_DEFAULT, "Started process %s %s in %s for service %s", exe, flags, dir, service_name);\r
+  log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_STARTED_SERVICE, exe, flags, service_name, dir, 0);\r
 \r
   /* Monitor service service */\r
   if (! RegisterWaitForSingleObject(&wait_handle, pid, end_service, 0, INFINITE, WT_EXECUTEONLYONCE | WT_EXECUTELONGFUNCTION)) {\r
-    eventprintf(EVENTLOG_WARNING_TYPE, NSSM_MESSAGE_DEFAULT, "RegisterWaitForSingleObject() returned %s - service may claim to be still running when %s exits ", error_string(GetLastError()), exe);\r
+    log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_REGISTERWAITFORSINGLEOBJECT_FAILED, service_name, exe, GetLastError(), 0);\r
   }\r
 \r
   return 0;\r
@@ -222,11 +224,11 @@ int start_service() {
   /* Launch executable with arguments */\r
   char cmd[MAX_PATH];\r
   if (_snprintf(cmd, sizeof(cmd), "%s %s", exe, flags) < 0) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Error constructing command line");\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, "command line", "start_service", 0);\r
     return stop_service(2);\r
   }\r
   if (! CreateProcess(0, cmd, 0, 0, 0, 0, 0, dir, &si, &pi)) {\r
-    eventprintf(EVENTLOG_ERROR_TYPE, NSSM_MESSAGE_DEFAULT, "Can't launch %s.  CreateProcess() returned %s", exe, error_string(GetLastError()));\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEPROCESS_FAILED, service_name, exe, GetLastError(), 0);\r
     return stop_service(3);\r
   }\r
   pid = pi.hProcess;\r
@@ -247,9 +249,11 @@ int stop_service(unsigned long exitcode) {
   /* Nothing to do if server isn't running */\r
   if (pid) {\r
     /* Shut down server */\r
+    log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_TERMINATEPROCESS, service_name, exe, 0);\r
     TerminateProcess(pid, 0);\r
     pid = 0;\r
   }\r
+  else log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_PROCESS_ALREADY_STOPPED, service_name, exe, 0);\r
 \r
   /* Signal we stopped */\r
   service_status.dwCurrentState = SERVICE_STOPPED;\r
@@ -272,7 +276,9 @@ void CALLBACK end_service(void *arg, unsigned char why) {
   unsigned long ret = 0;\r
   GetExitCodeProcess(pid, &ret);\r
 \r
-  eventprintf(EVENTLOG_INFORMATION_TYPE, NSSM_MESSAGE_DEFAULT, "Process %s for service %s exited with return code %u", exe, service_name, ret);\r
+  char code[16];\r
+  _snprintf(code, sizeof(code), "%d", ret);\r
+  log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_ENDED_SERVICE, exe, service_name, code, 0);\r
 \r
   /* What action should we take? */\r
   int action = NSSM_EXIT_RESTART;\r
@@ -290,22 +296,22 @@ void CALLBACK end_service(void *arg, unsigned char why) {
   switch (action) {\r
     /* Try to restart the service or return failure code to service manager */\r
     case NSSM_EXIT_RESTART:\r
-      eventprintf(EVENTLOG_INFORMATION_TYPE, NSSM_MESSAGE_DEFAULT, "Action for exit code %lu is %s: Attempting to restart %s for service %s", ret, exit_action_strings[action], exe, service_name);\r
+      log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_EXIT_RESTART, service_name, code, exit_action_strings[action], exe, 0);\r
       while (monitor_service()) {\r
-        eventprintf(EVENTLOG_INFORMATION_TYPE, NSSM_MESSAGE_DEFAULT, "Failed to restart %s - sleeping ", exe, ret);\r
+        log_event(EVENTLOG_WARNING_TYPE, NSSM_EVENT_RESTART_SERVICE_FAILED, exe, service_name, 0);\r
         Sleep(30000);\r
       }\r
     break;\r
 \r
     /* Do nothing, just like srvany would */\r
     case NSSM_EXIT_IGNORE:\r
-      eventprintf(EVENTLOG_INFORMATION_TYPE, NSSM_MESSAGE_DEFAULT, "Action for exit code %lu is %s: Not attempting to restart %s for service %s", ret, exit_action_strings[action], exe, service_name);\r
+      log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_EXIT_IGNORE, service_name, code, exit_action_strings[action], exe, 0);\r
       Sleep(INFINITE);\r
     break;\r
 \r
     /* Tell the service manager we are finished */\r
     case NSSM_EXIT_REALLY:\r
-      eventprintf(EVENTLOG_INFORMATION_TYPE, NSSM_MESSAGE_DEFAULT, "Action for exit code %lu is %s: Stopping service %s", ret, exit_action_strings[action], service_name);\r
+      log_event(EVENTLOG_INFORMATION_TYPE, NSSM_EVENT_EXIT_REALLY, service_name, code, exit_action_strings[action], 0);\r
       stop_service(ret);\r
     break;\r
   }\r