From: Iain Patterson Date: Sun, 22 Dec 2013 12:05:48 +0000 (+0000) Subject: Set log on details in the GUI. X-Git-Tag: v2.22~121 X-Git-Url: http://git.iain.cx/?p=nssm.git;a=commitdiff_plain;h=6a12d5bf24211cfee30c47354b32befc3abae5b8 Set log on details in the GUI. The GUI can now set service logon and desktop interactive details. --- diff --git a/ChangeLog.txt b/ChangeLog.txt index 8bd2dd0..911aa4d 100644 --- a/ChangeLog.txt +++ b/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 ------------------ diff --git a/README.txt b/README.txt index 8be1383..d650970 100644 --- a/README.txt +++ b/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 diff --git a/gui.cpp b/gui.cpp index ef4b450..80d74ef 100644 --- a/gui.cpp +++ b/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); diff --git a/messages.mc b/messages.mc index 427905e..4304d98 100644 --- a/messages.mc +++ b/messages.mc @@ -297,6 +297,58 @@ 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 Language = English @@ -511,6 +563,19 @@ 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 Language = English diff --git a/nssm.rc b/nssm.rc index 62b6508..5c21be3 100644 --- a/nssm.rc +++ b/nssm.rc @@ -119,6 +119,22 @@ FONT 8, "MS Sans Serif" } 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 FONT 8, "MS Sans Serif" diff --git a/resource.h b/resource.h index accc4b7..6964003 100644 --- a/resource.h +++ b/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 diff --git a/service.cpp b/service.cpp index 5b75a41..57dc7a2 100644 --- a/service.cpp +++ b/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); diff --git a/service.h b/service.h index 474f365..dc1715b 100644 --- a/service.h +++ b/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];