Expand environment strings in parameters.
authorIain Patterson <me@iain.cx>
Sat, 25 Sep 2010 14:52:07 +0000 (15:52 +0100)
committerIain Patterson <me@iain.cx>
Sat, 25 Sep 2010 15:00:31 +0000 (16:00 +0100)
Allow use of REG_EXPAND_SZ values in the registry.

README.txt
messages.mc
registry.cpp
registry.h

index d9e6ee0..8a41431 100644 (file)
@@ -71,7 +71,7 @@ successfully started or you send it a stop signal.
 \r
 NSSM will look in the registry under\r
 HKLM\SYSTEM\CurrentControlSet\Services\<service>\Parameters\AppExit for\r
-string (REG_SZ) values corresponding to the exit code of the application.\r
+string (REG_EXPAND_SZ) values corresponding to the exit code of the application.\r
 If the application exited with code 1, for instance, NSSM will look for a\r
 string value under AppExit called "1" or, if it does not find it, will\r
 fall back to the AppExit (Default) value.  You can find out the exit code\r
index 6048077..3b2df77 100644 (file)
@@ -165,3 +165,11 @@ Honouring the %4 action would result in the service being flagged as failed and
 The service will instead be stopped gracefully.  To suppress this message, explicitly configure the exit action for exit code 0 to either %5 or %6.
 .
 
+MessageId = +1
+SymbolicName = NSSM_EVENT_EXPANDENVIRONMENTSTRINGS_FAILED
+Severity = Error
+Language = English
+Failed to expand registry value %1:
+%2
+.
+
index ed01303..55bd36b 100644 (file)
@@ -42,19 +42,19 @@ int create_parameters(char *service_name, char *exe, char *flags, char *dir) {
   }\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
+  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
     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
+  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
     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
+  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
     RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY);\r
     RegCloseKey(key);\r
@@ -102,6 +102,42 @@ int create_exit_action(char *service_name, const char *action_string) {
   return 0;\r
 }\r
 \r
+int expand_parameter(HKEY key, char *value, char *data, unsigned long datalen) {\r
+  unsigned char *buffer = (unsigned char *) HeapAlloc(GetProcessHeap(), 0, datalen);\r
+  if (! buffer) {\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, value, "expand_parameter()", 0);\r
+    return 1;\r
+  }\r
+\r
+  unsigned long type = REG_EXPAND_SZ;\r
+  unsigned long buflen = datalen;\r
+\r
+  if (RegQueryValueEx(key, value, 0, &type, buffer, &buflen) != ERROR_SUCCESS) {\r
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, GetLastError(), 0);\r
+    HeapFree(GetProcessHeap(), 0, buffer);\r
+    return 2;\r
+  }\r
+\r
+  ZeroMemory(data, datalen);\r
+\r
+  /* Technically we shouldn't expand environment strings from REG_SZ values */\r
+  if (type != REG_EXPAND_SZ) {\r
+    memmove(data, buffer, buflen);\r
+    return 0;\r
+  }\r
+\r
+  unsigned long 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
+    HeapFree(GetProcessHeap(), 0, buffer);\r
+    return 3;\r
+  }\r
+  log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_EXPANDENVIRONMENTSTRINGS_FAILED, buffer, data, GetLastError(), 0);\r
+\r
+  HeapFree(GetProcessHeap(), 0, buffer);\r
+  return 0;\r
+}\r
+\r
 int get_parameters(char *service_name, char *exe, int exelen, char *flags, int flagslen, char *dir, int dirlen) {\r
   /* Get registry */\r
   char registry[KEY_LENGTH];\r
@@ -117,25 +153,20 @@ int get_parameters(char *service_name, char *exe, int exelen, char *flags, int f
     return 2;\r
   }\r
 \r
-  unsigned long type = REG_SZ;\r
-\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
-    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, NSSM_REG_EXE, GetLastError(), 0);\r
+  if (expand_parameter(key, NSSM_REG_EXE, exe, exelen)) {\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
-    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, NSSM_REG_FLAGS, GetLastError(), 0);\r
+  if (expand_parameter(key, NSSM_REG_FLAGS, flags, flagslen)) {\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
-    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, NSSM_REG_DIR, GetLastError(), 0);\r
+  if (expand_parameter(key, NSSM_REG_DIR, dir, dirlen)) {\r
     RegCloseKey(key);\r
     return 5;\r
   }\r
index 901a6ba..f814e42 100644 (file)
@@ -10,6 +10,7 @@
 int create_messages();\r
 int create_parameters(char *, char *, char *, char *);\r
 int create_exit_action(char *, const char *);\r
+int expand_parameter(HKEY, char *, char *, unsigned long);\r
 int get_parameters(char *, char *, int, char *, int, char *, int);\r
 int get_exit_action(char *, unsigned long *, unsigned char *, bool *);\r
 \r