Set environment from the GUI at install time.
[nssm.git] / gui.cpp
diff --git a/gui.cpp b/gui.cpp
index 013f2f0..4bcb144 100644 (file)
--- a/gui.cpp
+++ b/gui.cpp
@@ -1,6 +1,6 @@
 #include "nssm.h"\r
 \r
-static enum { NSSM_TAB_APPLICATION, NSSM_TAB_SHUTDOWN, NSSM_TAB_EXIT, NSSM_TAB_IO, NSSM_NUM_TABS };\r
+static enum { NSSM_TAB_APPLICATION, NSSM_TAB_SHUTDOWN, NSSM_TAB_EXIT, NSSM_TAB_IO, NSSM_TAB_ENVIRONMENT, NSSM_NUM_TABS };\r
 static HWND tablist[NSSM_NUM_TABS];\r
 static int selected_tab;\r
 \r
@@ -120,7 +120,7 @@ int install(HWND window) {
       if (! GetDlgItemText(window, IDC_FLAGS, service->flags, sizeof(service->flags))) {\r
         popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_OPTIONS);\r
         return 4;\r
-      }
+      }\r
     }\r
 \r
     /* Get stop method stuff. */\r
@@ -143,6 +143,80 @@ int install(HWND window) {
     check_io("stdin", service->stdin_path, sizeof(service->stdin_path), IDC_STDIN);\r
     check_io("stdout", service->stdout_path, sizeof(service->stdout_path), IDC_STDOUT);\r
     check_io("stderr", service->stderr_path, sizeof(service->stderr_path), IDC_STDERR);\r
+\r
+    /* Get environment. */\r
+    unsigned long envlen = (unsigned long) SendMessage(GetDlgItem(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT), WM_GETTEXTLENGTH, 0, 0);\r
+    if (envlen) {\r
+      char *env = (char *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, envlen + 2);\r
+      if (! env) {\r
+        popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, "environment", "install()");\r
+        cleanup_nssm_service(service);\r
+        return 5;\r
+      }\r
+\r
+      if (! GetDlgItemText(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT, env, envlen + 1)) {\r
+        popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT);\r
+        HeapFree(GetProcessHeap(), 0, env);\r
+        cleanup_nssm_service(service);\r
+        return 5;\r
+      }\r
+\r
+      /* Strip CR and replace LF with NULL. */\r
+      unsigned long newlen = 0;\r
+      unsigned long i, j;\r
+      for (i = 0; i < envlen; i++) if (env[i] != '\r') newlen++;\r
+      /* Must end with two NULLs. */\r
+      newlen++;\r
+\r
+      char *newenv = (char *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, newlen);\r
+      if (! newenv) {\r
+        HeapFree(GetProcessHeap(), 0, env);\r
+        popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, "environment", "install()");\r
+        cleanup_nssm_service(service);\r
+        return 5;\r
+      }\r
+\r
+      for (i = 0, j = 0; i < envlen; i++) {\r
+        if (env[i] == '\r') continue;\r
+        if (env[i] == '\n') newenv[j] = '\0';\r
+        else newenv[j] = env[i];\r
+        j++;\r
+      }\r
+\r
+      HeapFree(GetProcessHeap(), 0, env);\r
+      env = newenv;\r
+      envlen = newlen;\r
+\r
+      /* Test the environment is valid. */\r
+      char path[MAX_PATH];\r
+      GetModuleFileName(0, path, sizeof(path));\r
+      STARTUPINFO si;\r
+      ZeroMemory(&si, sizeof(si));\r
+      si.cb = sizeof(si);\r
+      PROCESS_INFORMATION pi;\r
+      ZeroMemory(&pi, sizeof(pi));\r
+\r
+      if (! CreateProcess(0, path, 0, 0, 0, CREATE_SUSPENDED, env, 0, &si, &pi)) {\r
+        unsigned long error = GetLastError();\r
+        if (error == ERROR_INVALID_PARAMETER) {\r
+          popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT);\r
+          HeapFree(GetProcessHeap(), 0, env);\r
+          envlen = 0;\r
+        }\r
+        cleanup_nssm_service(service);\r
+        return 5;\r
+      }\r
+      TerminateProcess(pi.hProcess, 0);\r
+\r
+      if (SendDlgItemMessage(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT_REPLACE, BM_GETCHECK, 0, 0) & BST_CHECKED) {\r
+        service->env = env;\r
+        service->envlen = envlen;\r
+      }\r
+      else {\r
+        service->env_extra = env;\r
+        service->env_extralen = envlen;\r
+      }\r
+    }\r
   }\r
 \r
   /* See if it works. */\r
@@ -426,6 +500,13 @@ INT_PTR CALLBACK install_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {
       tablist[NSSM_TAB_IO] = CreateDialog(0, MAKEINTRESOURCE(IDD_IO), window, tab_dlg);\r
       ShowWindow(tablist[NSSM_TAB_IO], SW_HIDE);\r
 \r
+      /* Environment tab. */\r
+      tab.pszText = message_string(NSSM_GUI_TAB_ENVIRONMENT);\r
+      tab.cchTextMax = (int) strlen(tab.pszText) + 1;\r
+      SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_ENVIRONMENT, (LPARAM) &tab);\r
+      tablist[NSSM_TAB_ENVIRONMENT] = CreateDialog(0, MAKEINTRESOURCE(IDD_ENVIRONMENT), window, tab_dlg);\r
+      ShowWindow(tablist[NSSM_TAB_ENVIRONMENT], SW_HIDE);\r
+\r
       selected_tab = 0;\r
 \r
       return 1;\r