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