Run hooks in response to certain events.
[nssm.git] / registry.cpp
index 42c5425..00d6eaf 100644 (file)
@@ -457,7 +457,7 @@ void override_milliseconds(TCHAR *service_name, HKEY key, TCHAR *value, unsigned
   if (! ok) *buffer = default_value;\r
 }\r
 \r
-HKEY open_registry(const TCHAR *service_name, const TCHAR *sub, REGSAM sam) {\r
+HKEY open_registry(const TCHAR *service_name, const TCHAR *sub, REGSAM sam, bool must_exist) {\r
   /* Get registry */\r
   TCHAR registry[KEY_LENGTH];\r
   HKEY key;\r
@@ -470,14 +470,16 @@ HKEY open_registry(const TCHAR *service_name, const TCHAR *sub, REGSAM sam) {
     return 0;\r
   }\r
 \r
-  if (sam & KEY_WRITE) {\r
+  if (sam & KEY_SET_VALUE) {\r
     if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, registry, 0, 0, REG_OPTION_NON_VOLATILE, sam, 0, &key, 0) != ERROR_SUCCESS) {\r
       log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, error_string(GetLastError()), 0);\r
       return 0;\r
     }\r
   }\r
   else {\r
-    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, registry, 0, sam, &key) != ERROR_SUCCESS) {\r
+    long error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, registry, 0, sam, &key);\r
+    if (error != ERROR_SUCCESS) {\r
+      if (error == ERROR_FILE_NOT_FOUND && ! must_exist) return 0;\r
       log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OPENKEY_FAILED, registry, error_string(GetLastError()), 0);\r
       return 0;\r
     }\r
@@ -486,8 +488,12 @@ HKEY open_registry(const TCHAR *service_name, const TCHAR *sub, REGSAM sam) {
   return key;\r
 }\r
 \r
+HKEY open_registry(const TCHAR *service_name, const TCHAR *sub, REGSAM sam) {\r
+  return open_registry(service_name, sub, sam, true);\r
+}\r
+\r
 HKEY open_registry(const TCHAR *service_name, REGSAM sam) {\r
-  return open_registry(service_name, 0, sam);\r
+  return open_registry(service_name, 0, sam, true);\r
 }\r
 \r
 int get_io_parameters(nssm_service_t *service, HKEY key) {\r
@@ -729,3 +735,57 @@ int get_exit_action(const TCHAR *service_name, unsigned long *ret, TCHAR *action
 \r
   return 0;\r
 }\r
+\r
+int set_hook(const TCHAR *service_name, const TCHAR *hook_event, const TCHAR *hook_action, TCHAR *cmd) {\r
+  /* Try to open the registry */\r
+  TCHAR registry[KEY_LENGTH];\r
+  if (_sntprintf_s(registry, _countof(registry), _TRUNCATE, _T("%s\\%s"), NSSM_REG_HOOK, hook_event) < 0) {\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("hook registry"), _T("set_hook()"), 0);\r
+    return 1;\r
+  }\r
+\r
+  HKEY key;\r
+  long error;\r
+\r
+  /* Don't create keys needlessly. */\r
+  if (! _tcslen(cmd)) {\r
+    key = open_registry(service_name, registry, KEY_READ, false);\r
+    if (! key) return 0;\r
+    error = RegQueryValueEx(key, hook_action, 0, 0, 0, 0);\r
+    RegCloseKey(key);\r
+    if (error == ERROR_FILE_NOT_FOUND) return 0;\r
+  }\r
+\r
+  key = open_registry(service_name, registry, KEY_WRITE);\r
+  if (! key) return 1;\r
+\r
+  int ret = 1;\r
+  if (_tcslen(cmd)) ret = set_string(key, (TCHAR *) hook_action, cmd, true);\r
+  else {\r
+    error = RegDeleteValue(key, hook_action);\r
+    if (error == ERROR_SUCCESS || error == ERROR_FILE_NOT_FOUND) ret = 0;\r
+  }\r
+\r
+  /* Close registry */\r
+  RegCloseKey(key);\r
+\r
+  return ret;\r
+}\r
+\r
+int get_hook(const TCHAR *service_name, const TCHAR *hook_event, const TCHAR *hook_action, TCHAR *buffer, unsigned long buflen) {\r
+  /* Try to open the registry */\r
+  TCHAR registry[KEY_LENGTH];\r
+  if (_sntprintf_s(registry, _countof(registry), _TRUNCATE, _T("%s\\%s"), NSSM_REG_HOOK, hook_event) < 0) {\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("hook registry"), _T("get_hook()"), 0);\r
+    return 1;\r
+  }\r
+  HKEY key = open_registry(service_name, registry, KEY_READ, false);\r
+  if (! key) return 1;\r
+\r
+  int ret = expand_parameter(key, (TCHAR *) hook_action, buffer, buflen, true, false);\r
+\r
+  /* Close registry */\r
+  RegCloseKey(key);\r
+\r
+  return ret;\r
+}\r