Set the environment before querying the registry.
authorIain Patterson <me@iain.cx>
Mon, 23 Feb 2015 21:22:22 +0000 (21:22 +0000)
committerIain Patterson <me@iain.cx>
Mon, 23 Feb 2015 21:37:36 +0000 (21:37 +0000)
Handle AppEnvironment and AppEnvironmentExtra before querying registry
parameters.  Doing so allows paths and arguments passed to the service
to reference such environment variables.

Thanks Yuriy Lesiuk.

ChangeLog.txt
README.txt
registry.cpp
service.cpp
service.h

index 62fd6b8..aa86f2e 100644 (file)
@@ -9,6 +9,11 @@ Changes since 2.24
     followed by SetEndOfFile(), allowing it to rotate files\r
     which other processes hold open.\r
 \r
+  * NSSM now sets the service environment before querying\r
+    parameters from the registry, so paths and arguments\r
+    can reference environment configured in AppEnvironment\r
+    or AppEnvironmentExtra.\r
+\r
 Changes since 2.23\r
 ------------------\r
   * NSSM once again calls TerminateProcess() correctly.\r
index 9bb5076..ecca5e9 100644 (file)
@@ -820,6 +820,8 @@ Thanks to Sam Townsend for noticing a regression with TerminateProcess().
 Thanks to Barrett Lewis for suggesting the option to skip terminating the\r
 application's child processes.\r
 Thanks to Miguel Angel TerrĂ³n for suggesting copy/truncate rotation.\r
+Thanks to Yuriy Lesiuk for suggesting setting the environment before querying\r
+the registry for parameters.\r
 \r
 Licence\r
 -------\r
index 00d6eaf..de3127f 100644 (file)
@@ -531,6 +531,14 @@ int get_parameters(nssm_service_t *service, STARTUPINFO *si) {
   /* Don't expand parameters when retrieving for the GUI. */\r
   bool expand = si ? true : false;\r
 \r
+  /* Try to get environment variables - may fail */\r
+  get_environment(service->name, key, NSSM_REG_ENV, &service->env, &service->envlen);\r
+  /* Environment variables to add to existing rather than replace - may fail. */\r
+  get_environment(service->name, key, NSSM_REG_ENV_EXTRA, &service->env_extra, &service->env_extralen);\r
+\r
+  /* Set environment if we are starting the service. */\r
+  if (si) set_service_environment(service);\r
+\r
   /* Try to get executable file - MUST succeed */\r
   if (get_string(key, NSSM_REG_EXE, service->exe, sizeof(service->exe), expand, false, true)) {\r
     RegCloseKey(key);\r
@@ -585,11 +593,6 @@ int get_parameters(nssm_service_t *service, STARTUPINFO *si) {
     }\r
   }\r
 \r
-  /* Try to get environment variables - may fail */\r
-  get_environment(service->name, key, NSSM_REG_ENV, &service->env, &service->envlen);\r
-  /* Environment variables to add to existing rather than replace - may fail. */\r
-  get_environment(service->name, key, NSSM_REG_ENV_EXTRA, &service->env_extra, &service->env_extralen);\r
-\r
   /* Try to get priority - may fail. */\r
   unsigned long priority;\r
   if (get_number(key, NSSM_REG_PRIORITY, &priority, false) == 1) {\r
index 6cdad35..f575a37 100644 (file)
@@ -273,6 +273,17 @@ static inline unsigned long throttle_milliseconds(unsigned long throttle) {
   return ret * 1000;\r
 }\r
 \r
+void set_service_environment(nssm_service_t *service) {\r
+  if (! service) return;\r
+  if (service->env) duplicate_environment(service->env);\r
+  if (service->env_extra) set_environment_block(service->env_extra);\r
+}\r
+\r
+void unset_service_environment(nssm_service_t *service) {\r
+  if (! service) return;\r
+  duplicate_environment_strings(service->initial_env);\r
+}\r
+\r
 /*\r
   Wrapper to be called in a new thread so that we can acknowledge a STOP\r
   control immediately.\r
@@ -1684,6 +1695,7 @@ int start_service(nssm_service_t *service) {
   int ret = get_parameters(service, &si);\r
   if (ret) {\r
     log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_PARAMETERS_FAILED, service->name, 0);\r
+    unset_service_environment(service);\r
     return stop_service(service, 2, true, true);\r
   }\r
 \r
@@ -1691,15 +1703,12 @@ int start_service(nssm_service_t *service) {
   TCHAR cmd[CMD_LENGTH];\r
   if (_sntprintf_s(cmd, _countof(cmd), _TRUNCATE, _T("\"%s\" %s"), service->exe, service->flags) < 0) {\r
     log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("command line"), _T("start_service"), 0);\r
+    unset_service_environment(service);\r
     return stop_service(service, 2, true, true);\r
   }\r
 \r
   throttle_restart(service);\r
 \r
-  /* Set the environment. */\r
-  if (service->env) duplicate_environment(service->env);\r
-  if (service->env_extra) set_environment_block(service->env_extra);\r
-\r
   service->status.dwCurrentState = SERVICE_START_PENDING;\r
   service->status.dwControlsAccepted = SERVICE_ACCEPT_POWEREVENT | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP;\r
   SetServiceStatus(service->status_handle, &service->status);\r
@@ -1710,7 +1719,7 @@ int start_service(nssm_service_t *service) {
     TCHAR code[16];\r
     _sntprintf_s(code, _countof(code), _TRUNCATE, _T("%lu"), NSSM_HOOK_STATUS_ABORT);\r
     log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_PRESTART_HOOK_ABORT, NSSM_HOOK_EVENT_START, NSSM_HOOK_ACTION_PRE, service->name, code, 0);\r
-    duplicate_environment_strings(service->initial_env);\r
+    unset_service_environment(service);\r
     return stop_service(service, 5, true, true);\r
   }\r
 \r
@@ -1721,7 +1730,7 @@ int start_service(nssm_service_t *service) {
       log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_OUTPUT_HANDLES_FAILED, service->name, 0);\r
       if (! service->no_console) FreeConsole();\r
       close_output_handles(&si);\r
-      duplicate_environment_strings(service->initial_env);\r
+      unset_service_environment(service);\r
       return stop_service(service, 4, true, true);\r
     }\r
 \r
@@ -1734,7 +1743,7 @@ int start_service(nssm_service_t *service) {
       unsigned long error = GetLastError();\r
       log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATEPROCESS_FAILED, service->name, service->exe, error_string(error), 0);\r
       close_output_handles(&si);\r
-      duplicate_environment_strings(service->initial_env);\r
+      unset_service_environment(service);\r
       return stop_service(service, exitcode, true, true);\r
     }\r
     service->start_count++;\r
@@ -1778,7 +1787,7 @@ int start_service(nssm_service_t *service) {
   }\r
 \r
   /* Restore our environment. */\r
-  duplicate_environment_strings(service->initial_env);\r
+  unset_service_environment(service);\r
 \r
   /*\r
     Wait for a clean startup before changing the service status to RUNNING\r
index 6a30af6..187b57d 100644 (file)
--- a/service.h
+++ b/service.h
@@ -140,6 +140,8 @@ int set_service_description(const TCHAR *, SC_HANDLE, TCHAR *);
 int get_service_description(const TCHAR *, SC_HANDLE, unsigned long, TCHAR *);\r
 int get_service_startup(const TCHAR *, SC_HANDLE, const QUERY_SERVICE_CONFIG *, unsigned long *);\r
 int get_service_username(const TCHAR *, const QUERY_SERVICE_CONFIG *, TCHAR **, size_t *);\r
+int set_service_environment(nssm_service_t *);\r
+int unset_service_environment(nssm_service_t *);\r
 int pre_install_service(int, TCHAR **);\r
 int pre_remove_service(int, TCHAR **);\r
 int pre_edit_service(int, TCHAR **);\r