From f124b07b52a569dd9e332d0940af592d0e8e201d Mon Sep 17 00:00:00 2001 From: Iain Patterson Date: Tue, 24 Feb 2015 13:37:17 +0000 Subject: [PATCH 1/1] Save the environment. Before the previous two commits we used to read the environment from the registry and set it using an optimisation which modified the retrieved block in-place. Now we need to set the environment twice after querying the registry - once in get_parameters() and once just before CreateProcess(), which means we can't use the in-place optimisation and must copy the block before operating on it. Additionally, nssm_hook() cleans the environment so we have to reinstate it immediately prior to launching the application. --- hook.cpp | 9 ++++----- service.cpp | 17 +++++++++++++++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/hook.cpp b/hook.cpp index 17204ae..09b98d9 100644 --- a/hook.cpp +++ b/hook.cpp @@ -234,8 +234,7 @@ int nssm_hook(hook_thread_t *hook_threads, nssm_service_t *service, TCHAR *hook_ EnterCriticalSection(&service->hook_section); /* Set the environment. */ - if (service->env) duplicate_environment(service->env); - if (service->env_extra) set_environment_block(service->env_extra); + set_service_environment(service); /* ABI version. */ TCHAR number[16]; @@ -327,7 +326,7 @@ int nssm_hook(hook_thread_t *hook_threads, nssm_service_t *service, TCHAR *hook_ TCHAR cmd[CMD_LENGTH]; if (get_hook(service->name, hook_event, hook_action, cmd, sizeof(cmd))) { log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_HOOK_FAILED, hook_event, hook_action, service->name, 0); - duplicate_environment_strings(service->initial_env); + unset_service_environment(service); LeaveCriticalSection(&service->hook_section); HeapFree(GetProcessHeap(), 0, hook); return NSSM_HOOK_STATUS_ERROR; @@ -335,7 +334,7 @@ int nssm_hook(hook_thread_t *hook_threads, nssm_service_t *service, TCHAR *hook_ /* No hook. */ if (! _tcslen(cmd)) { - duplicate_environment_strings(service->initial_env); + unset_service_environment(service); LeaveCriticalSection(&service->hook_section); HeapFree(GetProcessHeap(), 0, hook); return NSSM_HOOK_STATUS_NOTFOUND; @@ -389,7 +388,7 @@ int nssm_hook(hook_thread_t *hook_threads, nssm_service_t *service, TCHAR *hook_ } /* Restore our environment. */ - duplicate_environment_strings(service->initial_env); + unset_service_environment(service); LeaveCriticalSection(&service->hook_section); diff --git a/service.cpp b/service.cpp index f575a37..617cad1 100644 --- a/service.cpp +++ b/service.cpp @@ -275,8 +275,18 @@ static inline unsigned long throttle_milliseconds(unsigned long throttle) { 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); + + /* + We have to duplicate the block because this function will be called + multiple times between registry reads. + */ + if (service->env) duplicate_environment_strings(service->env); + if (! service->env_extra) return; + TCHAR *env_extra = copy_environment_block(service->env_extra); + if (! env_extra) return; + + set_environment_block(env_extra); + HeapFree(GetProcessHeap(), 0, env_extra); } void unset_service_environment(nssm_service_t *service) { @@ -1734,6 +1744,9 @@ int start_service(nssm_service_t *service) { return stop_service(service, 4, true, true); } + /* The pre-start hook will have cleaned the environment. */ + set_service_environment(service); + bool inherit_handles = false; if (si.dwFlags & STARTF_USESTDHANDLES) inherit_handles = true; unsigned long flags = service->priority & priority_mask(); -- 2.7.4