Browse Source

Set log on details in the GUI.

The GUI can now set service logon and desktop interactive details.
Iain Patterson 9 years ago
parent
commit
6a12d5bf24
8 changed files with 252 additions and 14 deletions
  1. 2 2
      ChangeLog.txt
  2. 2 2
      README.txt
  3. 134 2
      gui.cpp
  4. 65 0
      messages.mc
  5. 16 0
      nssm.rc
  6. 14 7
      resource.h
  7. 14 1
      service.cpp
  8. 5 0
      service.h

+ 2 - 2
ChangeLog.txt

@@ -6,8 +6,8 @@ Changes since 2.21
   * Unqualified path names are now relative to the
     application startup directory when redirecting I/O.
 
-  * NSSM can now set the service display name, description
-    and startup type.
+  * NSSM can now set the service display name, description,
+    startup type and log on details.
 
 Changes since 2.20
 ------------------

+ 2 - 2
README.txt

@@ -55,8 +55,8 @@ AppEnvironment.
 
 Since version 2.22, NSSM can rotate existing output files when redirecting I/O.
 
-Since version 2.22, NSSM can set service display name, description and startup
-type.
+Since version 2.22, NSSM can set service display name, description, startup
+type and log on details.
 
 
 Usage

+ 134 - 2
gui.cpp

@@ -1,6 +1,6 @@
 #include "nssm.h"
 
-static enum { NSSM_TAB_APPLICATION, NSSM_TAB_DETAILS, NSSM_TAB_SHUTDOWN, NSSM_TAB_EXIT, NSSM_TAB_IO, NSSM_TAB_ROTATION, NSSM_TAB_ENVIRONMENT, NSSM_NUM_TABS };
+static enum { NSSM_TAB_APPLICATION, NSSM_TAB_DETAILS, NSSM_TAB_LOGON, NSSM_TAB_SHUTDOWN, NSSM_TAB_EXIT, NSSM_TAB_IO, NSSM_TAB_ROTATION, NSSM_TAB_ENVIRONMENT, NSSM_NUM_TABS };
 static HWND tablist[NSSM_NUM_TABS];
 static int selected_tab;
 
@@ -49,7 +49,7 @@ void centre_window(HWND window) {
 
   /* Find window size */
   if (! GetWindowRect(window, &size)) return;
-  
+
   /* Find desktop window */
   desktop = GetDesktopWindow();
   if (! desktop) return;
@@ -80,6 +80,12 @@ static inline void set_timeout_enabled(unsigned long control, unsigned long depe
   EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], dependent), enabled);
 }
 
+static inline void set_logon_enabled(unsigned char enabled) {
+  EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_USERNAME), enabled);
+  EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1), enabled);
+  EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2), enabled);
+}
+
 static inline void set_rotation_enabled(unsigned char enabled) {
   EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS), enabled);
   EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW), enabled);
@@ -146,6 +152,112 @@ int install(HWND window) {
     service->startup = (unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0);
     if (service->startup == CB_ERR) service->startup = 0;
 
+    /* Get logon stuff. */
+    if (SendDlgItemMessage(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, BM_GETCHECK, 0, 0) & BST_CHECKED) {
+      if (SendDlgItemMessage(tablist[NSSM_TAB_LOGON], IDC_INTERACT, BM_GETCHECK, 0, 0) & BST_CHECKED) {
+        service->type |= SERVICE_INTERACTIVE_PROCESS;
+      }
+    }
+    else {
+      /* Username. */
+      service->usernamelen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_USERNAME), WM_GETTEXTLENGTH, 0, 0);
+      if (! service->usernamelen) {
+        popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_USERNAME);
+        return 6;
+      }
+      service->usernamelen++;
+
+      service->username = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->usernamelen * sizeof(TCHAR));
+      if (! service->username) {
+        popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("account name"), _T("install()"));
+        return 6;
+      }
+      if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_USERNAME, service->username, (int) service->usernamelen)) {
+        HeapFree(GetProcessHeap(), 0, service->username);
+        service->username = 0;
+        service->usernamelen = 0;
+        popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_USERNAME);
+        return 6;
+      }
+
+      /* Password. */
+      service->passwordlen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1), WM_GETTEXTLENGTH, 0, 0);
+      if (! service->passwordlen) {
+        popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
+        return 6;
+      }
+      if (SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2), WM_GETTEXTLENGTH, 0, 0) != service->passwordlen) {
+        popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
+        return 6;
+      }
+      service->passwordlen++;
+
+      /* Temporary buffer for password validation. */
+      TCHAR *password = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->passwordlen * sizeof(TCHAR));
+      if (! password) {
+        HeapFree(GetProcessHeap(), 0, service->username);
+        service->username = 0;
+        service->usernamelen = 0;
+        popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("password confirmation"), _T("install()"));
+        return 6;
+      }
+
+      /* Actual password buffer. */
+      service->password = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->passwordlen * sizeof(TCHAR));
+      if (! service->password) {
+        HeapFree(GetProcessHeap(), 0, password);
+        HeapFree(GetProcessHeap(), 0, service->username);
+        service->username = 0;
+        service->usernamelen = 0;
+        popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("password"), _T("install()"));
+        return 6;
+      }
+
+      /* Get first password. */
+      if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1, service->password, (int) service->passwordlen)) {
+        HeapFree(GetProcessHeap(), 0, password);
+        SecureZeroMemory(service->password, service->passwordlen);
+        HeapFree(GetProcessHeap(), 0, service->password);
+        service->password = 0;
+        service->passwordlen = 0;
+        HeapFree(GetProcessHeap(), 0, service->username);
+        service->username = 0;
+        service->usernamelen = 0;
+        popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_PASSWORD);
+        return 6;
+      }
+
+      /* Get confirmation. */
+      if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2, password, (int) service->passwordlen)) {
+        SecureZeroMemory(password, service->passwordlen);
+        HeapFree(GetProcessHeap(), 0, password);
+        SecureZeroMemory(service->password, service->passwordlen);
+        HeapFree(GetProcessHeap(), 0, service->password);
+        service->password = 0;
+        service->passwordlen = 0;
+        HeapFree(GetProcessHeap(), 0, service->username);
+        service->username = 0;
+        service->usernamelen = 0;
+        popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_PASSWORD);
+        return 6;
+      }
+
+      /* Compare. */
+      if (_tcsncmp(password, service->password, service->passwordlen)) {
+        popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
+        SecureZeroMemory(password, service->passwordlen);
+        HeapFree(GetProcessHeap(), 0, password);
+        SecureZeroMemory(service->password, service->passwordlen);
+        HeapFree(GetProcessHeap(), 0, service->password);
+        service->password = 0;
+        service->passwordlen = 0;
+        HeapFree(GetProcessHeap(), 0, service->username);
+        service->username = 0;
+        service->usernamelen = 0;
+        return 6;
+      }
+    }
+
     /* Get stop method stuff. */
     check_stop_method(service, NSSM_STOP_METHOD_CONSOLE, IDC_METHOD_CONSOLE);
     check_stop_method(service, NSSM_STOP_METHOD_WINDOW, IDC_METHOD_WINDOW);
@@ -429,6 +541,15 @@ INT_PTR CALLBACK tab_dlg(HWND tab, UINT message, WPARAM w, LPARAM l) {
           browse(dlg, buffer, OFN_NOVALIDATE, NSSM_GUI_BROWSE_FILTER_DIRECTORIES, 0);
           break;
 
+        /* Log on. */
+        case IDC_LOCALSYSTEM:
+          set_logon_enabled(0);
+          break;
+
+        case IDC_ACCOUNT:
+          set_logon_enabled(1);
+          break;
+
         /* Shutdown methods. */
         case IDC_METHOD_CONSOLE:
           set_timeout_enabled(LOWORD(w), IDC_KILL_CONSOLE);
@@ -521,6 +642,17 @@ INT_PTR CALLBACK install_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {
       SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DISABLED, (LPARAM) message_string(NSSM_GUI_STARTUP_DISABLED));
       SendMessage(combo, CB_SETCURSEL, NSSM_STARTUP_AUTOMATIC, 0);
 
+      /* Logon tab. */
+      tab.pszText = message_string(NSSM_GUI_TAB_LOGON);
+      tab.cchTextMax = (int) _tcslen(tab.pszText);
+      SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_LOGON, (LPARAM) &tab);
+      tablist[NSSM_TAB_LOGON] = CreateDialog(0, MAKEINTRESOURCE(IDD_LOGON), window, tab_dlg);
+      ShowWindow(tablist[NSSM_TAB_LOGON], SW_HIDE);
+
+      /* Set defaults. */
+      CheckRadioButton(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, IDC_ACCOUNT, IDC_LOCALSYSTEM);
+      set_logon_enabled(0);
+
       /* Shutdown tab. */
       tab.pszText = message_string(NSSM_GUI_TAB_SHUTDOWN);
       tab.cchTextMax = (int) _tcslen(tab.pszText);

+ 65 - 0
messages.mc

@@ -296,6 +296,58 @@ Language = Italian
 Nessuna opzione valida specificata!
 .
 
+MessageId = +1
+SymbolicName = NSSM_GUI_MISSING_USERNAME
+Severity = Informational
+Language = English
+Missing account name!
+.
+Language = French
+Missing account name!
+.
+Language = Italian
+Missing account name!
+.
+
+MessageId = +1
+SymbolicName = NSSM_GUI_INVALID_USERNAME
+Severity = Informational
+Language = English
+Invalid account name!
+.
+Language = French
+Invalid account name!
+.
+Language = Italian
+Invalid account name!
+.
+
+MessageId = +1
+SymbolicName = NSSM_GUI_MISSING_PASSWORD
+Severity = Informational
+Language = English
+Missing or mismatched password(s)!
+.
+Language = French
+Missing or mismatched password(s)!
+.
+Language = Italian
+Missing or mismatched password(s)!
+.
+
+MessageId = +1
+SymbolicName = NSSM_GUI_INVALID_PASSWORD
+Severity = Informational
+Language = English
+Invalid password!
+.
+Language = French
+Invalid password!
+.
+Language = Italian
+Invalid password!
+.
+
 MessageId = +1
 SymbolicName = NSSM_GUI_INVALID_DISPLAYNAME
 Severity = Informational
@@ -510,6 +562,19 @@ Language = Italian
 Details%0
 .
 
+MessageId = +1
+SymbolicName = NSSM_GUI_TAB_LOGON
+Severity = Informational
+Language = English
+Log on%0
+.
+Language = French
+Log on%0
+.
+Language = Italian
+Log on%0
+.
+
 MessageId = +1
 SymbolicName = NSSM_GUI_TAB_SHUTDOWN
 Severity = Informational

+ 16 - 0
nssm.rc

@@ -118,6 +118,22 @@ FONT 8, "MS Sans Serif"
     COMBOBOX        IDC_STARTUP, 70, 58, 100, 120, CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_TABSTOP
 }
 
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDD_LOGON DIALOG 9, 20, 261, 75
+STYLE DS_SHELLFONT | WS_VISIBLE | WS_CHILD | DS_CONTROL
+FONT 8, "MS Sans Serif"
+{
+    GROUPBOX        "Log on as", IDC_STATIC, 7, 7, 251, 68
+    AUTORADIOBUTTON "Local System account", IDC_LOCALSYSTEM, 13, 18, 86, 8
+    AUTOCHECKBOX    "Allow service to interact with desktop", IDC_INTERACT, 101, 18, 133, 8
+    AUTORADIOBUTTON "This account:", IDC_ACCOUNT, 13, 32, 59, 8
+    EDITTEXT        IDC_USERNAME, 75, 30, 178, 12, ES_AUTOHSCROLL
+    LTEXT           "Password:", IDC_STATIC, 25, 46, 32, 8, SS_LEFT
+    EDITTEXT        IDC_PASSWORD1, 75, 44, 178, 12, ES_AUTOHSCROLL | ES_PASSWORD
+    LTEXT           "Confirm:", IDC_STATIC, 25, 60, 26, 8, SS_LEFT
+    EDITTEXT        IDC_PASSWORD2, 75, 58, 178, 12, ES_AUTOHSCROLL | ES_PASSWORD
+}
+
 LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
 IDD_SHUTDOWN DIALOG 9, 20, 261, 75
 STYLE DS_SHELLFONT | WS_VISIBLE | WS_CHILD | DS_CONTROL

+ 14 - 7
resource.h

@@ -8,11 +8,12 @@
 #define IDD_REMOVE                      103
 #define IDD_APPLICATION                 104
 #define IDD_DETAILS                     105
-#define IDD_IO                          106
-#define IDD_ROTATION                    107
-#define IDD_APPEXIT                     108
-#define IDD_SHUTDOWN                    109
-#define IDD_ENVIRONMENT                 110
+#define IDD_LOGON                       106
+#define IDD_IO                          107
+#define IDD_ROTATION                    108
+#define IDD_APPEXIT                     109
+#define IDD_SHUTDOWN                    110
+#define IDD_ENVIRONMENT                 111
 #define IDC_PATH                        1000
 #define IDC_TAB1                        1001
 #define IDC_CANCEL                      1002
@@ -46,14 +47,20 @@
 #define IDC_DISPLAYNAME                 1031
 #define IDC_DESCRIPTION                 1032
 #define IDC_STARTUP                     1033
+#define IDC_LOCALSYSTEM                 1034
+#define IDC_INTERACT                    1035
+#define IDC_ACCOUNT                     1036
+#define IDC_USERNAME                    1037
+#define IDC_PASSWORD1                   1038
+#define IDC_PASSWORD2                   1039
 
 // Next default values for new objects
 // 
 #ifdef APSTUDIO_INVOKED
 #ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        111
+#define _APS_NEXT_RESOURCE_VALUE        112
 #define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1034
+#define _APS_NEXT_CONTROL_VALUE         1040
 #define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif

+ 14 - 1
service.cpp

@@ -36,6 +36,7 @@ SC_HANDLE open_service_manager() {
 void set_nssm_service_defaults(nssm_service_t *service) {
   if (! service) return;
 
+  service->type = SERVICE_WIN32_OWN_PROCESS;
   service->stdin_sharing = NSSM_STDIN_SHARING;
   service->stdin_disposition = NSSM_STDIN_DISPOSITION;
   service->stdin_flags = NSSM_STDIN_FLAGS;
@@ -62,6 +63,11 @@ nssm_service_t *alloc_nssm_service() {
 /* Free memory for a service. */
 void cleanup_nssm_service(nssm_service_t *service) {
   if (! service) return;
+  if (service->username) HeapFree(GetProcessHeap(), 0, service->username);
+  if (service->password) {
+    SecureZeroMemory(service->password, service->passwordlen);
+    HeapFree(GetProcessHeap(), 0, service->password);
+  }
   if (service->env) HeapFree(GetProcessHeap(), 0, service->env);
   if (service->env_extra) HeapFree(GetProcessHeap(), 0, service->env_extra);
   if (service->handle) CloseServiceHandle(service->handle);
@@ -145,6 +151,13 @@ int install_service(nssm_service_t *service) {
   TCHAR command[MAX_PATH];
   GetModuleFileName(0, command, _countof(command));
 
+  /*
+    The only two valid flags for service type are SERVICE_WIN32_OWN_PROCESS
+    and SERVICE_INTERACTIVE_PROCESS.
+  */
+  service->type &= SERVICE_INTERACTIVE_PROCESS;
+  service->type |= SERVICE_WIN32_OWN_PROCESS;
+
   /* Startup type. */
   unsigned long startup;
   switch (service->startup) {
@@ -157,7 +170,7 @@ int install_service(nssm_service_t *service) {
   if (! service->displayname[0]) _sntprintf_s(service->displayname, _countof(service->displayname), _TRUNCATE, _T("%s"), service->name);
 
   /* Create the service */
-  service->handle = CreateService(services, service->name, service->displayname, SC_MANAGER_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, startup, SERVICE_ERROR_NORMAL, command, 0, 0, 0, 0, 0);
+  service->handle = CreateService(services, service->name, service->displayname, SC_MANAGER_ALL_ACCESS, service->type, startup, SERVICE_ERROR_NORMAL, command, 0, 0, 0, service->username, service->password);
   if (! service->handle) {
     print_message(stderr, NSSM_MESSAGE_CREATESERVICE_FAILED);
     CloseServiceHandle(services);

+ 5 - 0
service.h

@@ -22,6 +22,11 @@ typedef struct {
   TCHAR displayname[SERVICE_DISPLAYNAME_LENGTH];
   TCHAR description[VALUE_LENGTH];
   unsigned long startup;
+  TCHAR *username;
+  size_t usernamelen;
+  TCHAR *password;
+  size_t passwordlen;
+  unsigned long type;
   TCHAR exe[EXE_LENGTH];
   TCHAR flags[VALUE_LENGTH];
   TCHAR dir[MAX_PATH];