ソースを参照

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 9 年 前
コミット
f124b07b52
2 ファイル変更19 行追加7 行削除
  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();