浏览代码

Expand environment strings in parameters.

Allow use of REG_EXPAND_SZ values in the registry.
Iain Patterson 15 年之前
父节点
当前提交
0f7613aa2f
共有 4 个文件被更改,包括 52 次插入12 次删除
  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
 NSSM will look in the registry under
 HKLM\SYSTEM\CurrentControlSet\Services\<service>\Parameters\AppExit for
 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
 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
 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
 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.
 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 */
   /* 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);
     log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_EXE, GetLastError(), 0);
     RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY);
     RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY);
     RegCloseKey(key);
     RegCloseKey(key);
     return 3;
     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);
     log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_FLAGS, GetLastError(), 0);
     RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY);
     RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY);
     RegCloseKey(key);
     RegCloseKey(key);
     return 4;
     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);
     log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_SETVALUE_FAILED, NSSM_REG_DIR, GetLastError(), 0);
     RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY);
     RegDeleteKey(HKEY_LOCAL_MACHINE, NSSM_REGISTRY);
     RegCloseKey(key);
     RegCloseKey(key);
@@ -102,6 +102,42 @@ int create_exit_action(char *service_name, const char *action_string) {
   return 0;
   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) {
 int get_parameters(char *service_name, char *exe, int exelen, char *flags, int flagslen, char *dir, int dirlen) {
   /* Get registry */
   /* Get registry */
   char registry[KEY_LENGTH];
   char registry[KEY_LENGTH];
@@ -117,25 +153,20 @@ int get_parameters(char *service_name, char *exe, int exelen, char *flags, int f
     return 2;
     return 2;
   }
   }
 
 
-  unsigned long type = REG_SZ;
-
   /* Try to get executable file - MUST succeed */
   /* 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);
     RegCloseKey(key);
     return 3;
     return 3;
   }
   }
 
 
   /* Try to get flags - may fail */
   /* 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);
     RegCloseKey(key);
     return 4;
     return 4;
   }
   }
 
 
   /* Try to get startup directory - may fail */
   /* 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);
     RegCloseKey(key);
     return 5;
     return 5;
   }
   }

+ 1 - 0
registry.h

@@ -10,6 +10,7 @@
 int create_messages();
 int create_messages();
 int create_parameters(char *, char *, char *, char *);
 int create_parameters(char *, char *, char *, char *);
 int create_exit_action(char *, const 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_parameters(char *, char *, int, char *, int, char *, int);
 int get_exit_action(char *, unsigned long *, unsigned char *, bool *);
 int get_exit_action(char *, unsigned long *, unsigned char *, bool *);