Save the environment.
authorIain Patterson <me@iain.cx>
Tue, 24 Feb 2015 13:37:17 +0000 (13:37 +0000)
committerIain Patterson <me@iain.cx>
Tue, 24 Feb 2015 13:37:17 +0000 (13:37 +0000)
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
service.cpp

index 17204ae..09b98d9 100644 (file)
--- 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);
 
index f575a37..617cad1 100644 (file)
@@ -275,8 +275,18 @@ static inline unsigned long throttle_milliseconds(unsigned long throttle) {
 \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
+    We have to duplicate the block because this function will be called\r
+    multiple times between registry reads.\r
+  */\r
+  if (service->env) duplicate_environment_strings(service->env);\r
+  if (! service->env_extra) return;\r
+  TCHAR *env_extra = copy_environment_block(service->env_extra);\r
+  if (! env_extra) return;\r
+\r
+  set_environment_block(env_extra);\r
+  HeapFree(GetProcessHeap(), 0, env_extra);\r
 }\r
 \r
 void unset_service_environment(nssm_service_t *service) {\r
@@ -1734,6 +1744,9 @@ int start_service(nssm_service_t *service) {
       return stop_service(service, 4, true, true);\r
     }\r
 \r
+    /* The pre-start hook will have cleaned the environment. */\r
+    set_service_environment(service);\r
+\r
     bool inherit_handles = false;\r
     if (si.dwFlags & STARTF_USESTDHANDLES) inherit_handles = true;\r
     unsigned long flags = service->priority & priority_mask();\r