Browse Source

Expand environment strings in parameters.

Allow use of REG_EXPAND_SZ values in the registry.
Iain Patterson 12 years ago
parent
commit
0f7613aa2f
4 changed files with 52 additions and 12 deletions
  1. 1 1
      README.txt
  2. 8 0
      messages.mc
  3. 42 11
      registry.cpp
  4. 1 0
      registry.h

+ 1 - 1
README.txt

@@ -71,7 +71,7 @@ successfully started or you send it a stop signal.
 
 NSSM will look in the registry under
 HKLM\SYSTEM\CurrentControlSet\Services\<service>\Parameters\AppExit for
-string (REG_SZ) values corresponding to the exit code of the application.
+string (REG_EXPAND_SZ) values corresponding to the exit code of the application.
 If the application exited with code 1, for instance, NSSM will look for a
 string value under AppExit called "1" or, if it does not find it, will
 fall back to the AppExit (Default) value.  You can find out the exit code

+ 8 - 0
messages.mc

@@ -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
+.
+

+ 42 - 11
registry.cpp

@@ -42,19 +42,19 @@ int create_parameters(char *service_name, char *exe, char *flags, char *dir) {
   }
 
   /* Try to create the parameters */
-  if (RegSetValueEx(key, NSSM_REG_EXE, 0, REG_SZ, (const unsigned char *) exe, strlen(exe) + 1) != ERROR_SUCCESS) {
+  if (RegSetValueEx(key, NSSM_REG_EXE, 0, REG_EXPAND_SZ, (const unsigned char *) exe, strlen(exe) + 1) != ERROR_SUCCESS) {
     log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_EXE, GetLastError(), 0);
     RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY);
     RegCloseKey(key);
     return 3;
   }
-  if (RegSetValueEx(key, NSSM_REG_FLAGS, 0, REG_SZ, (const unsigned char *) flags, strlen(flags) + 1) != ERROR_SUCCESS) {
+  if (RegSetValueEx(key, NSSM_REG_FLAGS, 0, REG_EXPAND_SZ, (const unsigned char *) flags, strlen(flags) + 1) != ERROR_SUCCESS) {
     log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_FLAGS, GetLastError(), 0);
     RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY);
     RegCloseKey(key);
     return 4;
   }
-  if (RegSetValueEx(key, NSSM_REG_DIR, 0, REG_SZ, (const unsigned char *) dir, strlen(dir) + 1) != ERROR_SUCCESS) {
+  if (RegSetValueEx(key, NSSM_REG_DIR, 0, REG_EXPAND_SZ, (const unsigned char *) dir, strlen(dir) + 1) != ERROR_SUCCESS) {
     log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_DIR, GetLastError(), 0);
     RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY);
     RegCloseKey(key);
@@ -102,6 +102,42 @@ int create_exit_action(char *service_name, const char *action_string) {
   return 0;
 }
 
+int expand_parameter(HKEY key, char *value, char *data, unsigned long datalen) {
+  unsigned char *buffer = (unsigned char *) HeapAlloc(GetProcessHeap(), 0, datalen);
+  if (! buffer) {
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, value, "expand_parameter()", 0);
+    return 1;
+  }
+
+  unsigned long type = REG_EXPAND_SZ;
+  unsigned long buflen = datalen;
+
+  if (RegQueryValueEx(key, value, 0, &type, buffer, &buflen) != ERROR_SUCCESS) {
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, value, GetLastError(), 0);
+    HeapFree(GetProcessHeap(), 0, buffer);
+    return 2;
+  }
+
+  ZeroMemory(data, datalen);
+
+  /* Technically we shouldn't expand environment strings from REG_SZ values */
+  if (type != REG_EXPAND_SZ) {
+    memmove(data, buffer, buflen);
+    return 0;
+  }
+
+  unsigned long ret = ExpandEnvironmentStrings((char *) buffer, data, datalen);
+  if (! ret || ret > datalen) {
+    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_EXPANDENVIRONMENTSTRINGS_FAILED, value, buffer, GetLastError(), 0);
+    HeapFree(GetProcessHeap(), 0, buffer);
+    return 3;
+  }
+  log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_EXPANDENVIRONMENTSTRINGS_FAILED, buffer, data, GetLastError(), 0);
+
+  HeapFree(GetProcessHeap(), 0, buffer);
+  return 0;
+}
+
 int get_parameters(char *service_name, char *exe, int exelen, char *flags, int flagslen, char *dir, int dirlen) {
   /* Get registry */
   char registry[KEY_LENGTH];
@@ -117,25 +153,20 @@ int get_parameters(char *service_name, char *exe, int exelen, char *flags, int f
     return 2;
   }
 
-  unsigned long type = REG_SZ;
-
   /* Try to get executable file - MUST succeed */
-  if (RegQueryValueEx(key, NSSM_REG_EXE, 0, &type, (unsigned char *) exe, (unsigned long *) &exelen) != ERROR_SUCCESS) {
-    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, NSSM_REG_EXE, GetLastError(), 0);
+  if (expand_parameter(key, NSSM_REG_EXE, exe, exelen)) {
     RegCloseKey(key);
     return 3;
   }
 
   /* Try to get flags - may fail */
-  if (RegQueryValueEx(key, NSSM_REG_FLAGS, 0, &type, (unsigned char *) flags, (unsigned long *) &flagslen) != ERROR_SUCCESS) {
-    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, NSSM_REG_FLAGS, GetLastError(), 0);
+  if (expand_parameter(key, NSSM_REG_FLAGS, flags, flagslen)) {
     RegCloseKey(key);
     return 4;
   }
 
   /* Try to get startup directory - may fail */
-  if (RegQueryValueEx(key, NSSM_REG_DIR, 0, &type, (unsigned char *) dir, (unsigned long *) &dirlen) != ERROR_SUCCESS) {
-    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_QUERYVALUE_FAILED, NSSM_REG_DIR, GetLastError(), 0);
+  if (expand_parameter(key, NSSM_REG_DIR, dir, dirlen)) {
     RegCloseKey(key);
     return 5;
   }

+ 1 - 0
registry.h

@@ -10,6 +10,7 @@
 int create_messages();
 int create_parameters(char *, char *, char *, char *);
 int create_exit_action(char *, const char *);
+int expand_parameter(HKEY, char *, char *, unsigned long);
 int get_parameters(char *, char *, int, char *, int, char *, int);
 int get_exit_action(char *, unsigned long *, unsigned char *, bool *);