فهرست منبع

Set log on details in the GUI.

The GUI can now set service logon and desktop interactive details.
Iain Patterson 10 سال پیش
والد
کامیت
6a12d5bf24
8فایلهای تغییر یافته به همراه252 افزوده شده و 14 حذف شده
  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];