Browse Source

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.
Iain Patterson 7 years ago
parent
commit
f124b07b52
2 changed files with 19 additions and 7 deletions
  1. 4 5
      hook.cpp
  2. 15 2
      service.cpp

+ 4 - 5
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);
 

+ 15 - 2
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();