3 static enum { NSSM_TAB_APPLICATION, NSSM_TAB_DETAILS, NSSM_TAB_LOGON, NSSM_TAB_PROCESS, NSSM_TAB_SHUTDOWN, NSSM_TAB_EXIT, NSSM_TAB_IO, NSSM_TAB_ROTATION, NSSM_TAB_ENVIRONMENT, NSSM_NUM_TABS };
\r
4 static HWND tablist[NSSM_NUM_TABS];
\r
5 static int selected_tab;
\r
7 static HWND dialog(const TCHAR *templ, HWND parent, DLGPROC function, LPARAM l) {
\r
8 /* The caller will deal with GetLastError()... */
\r
9 HRSRC resource = FindResourceEx(0, RT_DIALOG, templ, GetUserDefaultLangID());
\r
11 if (GetLastError() != ERROR_RESOURCE_LANG_NOT_FOUND) return 0;
\r
12 resource = FindResourceEx(0, RT_DIALOG, templ, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
\r
13 if (! resource) return 0;
\r
16 HGLOBAL ret = LoadResource(0, resource);
\r
17 if (! ret) return 0;
\r
19 return CreateDialogIndirectParam(0, (DLGTEMPLATE *) ret, parent, function, l);
\r
22 static HWND dialog(const TCHAR *templ, HWND parent, DLGPROC function) {
\r
23 return dialog(templ, parent, function, 0);
\r
26 int nssm_gui(int resource, nssm_service_t *service) {
\r
28 HWND dlg = dialog(MAKEINTRESOURCE(resource), 0, nssm_dlg, (LPARAM) service);
\r
30 popup_message(0, MB_OK, NSSM_GUI_CREATEDIALOG_FAILED, error_string(GetLastError()));
\r
34 /* Load the icon. */
\r
35 HANDLE icon = LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDI_NSSM), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);
\r
36 if (icon) SendMessage(dlg, WM_SETICON, ICON_SMALL, (LPARAM) icon);
\r
37 icon = LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDI_NSSM), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0);
\r
38 if (icon) SendMessage(dlg, WM_SETICON, ICON_BIG, (LPARAM) icon);
\r
40 /* Remember what the window is for. */
\r
41 SetWindowLongPtr(dlg, GWLP_USERDATA, (LONG_PTR) resource);
\r
43 /* Display the window */
\r
45 ShowWindow(dlg, SW_SHOW);
\r
47 /* Set service name if given */
\r
48 if (service->name[0]) {
\r
49 SetDlgItemText(dlg, IDC_NAME, service->name);
\r
50 /* No point making user click remove if the name is already entered */
\r
51 if (resource == IDD_REMOVE) {
\r
52 HWND button = GetDlgItem(dlg, IDC_REMOVE);
\r
54 SendMessage(button, WM_LBUTTONDOWN, 0, 0);
\r
55 SendMessage(button, WM_LBUTTONUP, 0, 0);
\r
60 if (resource == IDD_EDIT) {
\r
61 /* We'll need the service handle later. */
\r
62 SetWindowLongPtr(dlg, DWLP_USER, (LONG_PTR) service);
\r
64 /* Service name can't be edited. */
\r
65 EnableWindow(GetDlgItem(dlg, IDC_NAME), 0);
\r
66 SetFocus(GetDlgItem(dlg, IDOK));
\r
68 /* Set existing details. */
\r
72 /* Application tab. */
\r
73 if (service->native) SetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_PATH, service->image);
\r
74 else SetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_PATH, service->exe);
\r
75 SetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_DIR, service->dir);
\r
76 SetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_FLAGS, service->flags);
\r
79 SetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DISPLAYNAME, service->displayname);
\r
80 SetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DESCRIPTION, service->description);
\r
81 combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP);
\r
82 SendMessage(combo, CB_SETCURSEL, service->startup, 0);
\r
85 if (service->username) {
\r
86 CheckRadioButton(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, IDC_ACCOUNT, IDC_ACCOUNT);
\r
87 SetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_USERNAME, service->username);
\r
88 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_INTERACT), 0);
\r
89 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_USERNAME), 1);
\r
90 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1), 1);
\r
91 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2), 1);
\r
94 CheckRadioButton(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, IDC_ACCOUNT, IDC_LOCALSYSTEM);
\r
95 if (service->type & SERVICE_INTERACTIVE_PROCESS) SendDlgItemMessage(tablist[NSSM_TAB_LOGON], IDC_INTERACT, BM_SETCHECK, BST_CHECKED, 0);
\r
99 if (service->priority) {
\r
100 int priority = priority_constant_to_index(service->priority);
\r
101 combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY);
\r
102 SendMessage(combo, CB_SETCURSEL, priority, 0);
\r
105 if (service->affinity) {
\r
106 list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY);
\r
107 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_SETCHECK, BST_UNCHECKED, 0);
\r
108 EnableWindow(GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY), 1);
\r
110 DWORD_PTR affinity, system_affinity;
\r
111 if (GetProcessAffinityMask(GetCurrentProcess(), &affinity, &system_affinity)) {
\r
112 if ((service->affinity & (__int64) system_affinity) != service->affinity) popup_message(dlg, MB_OK | MB_ICONWARNING, NSSM_GUI_WARN_AFFINITY);
\r
115 for (int i = 0; i < num_cpus(); i++) {
\r
116 if (! (service->affinity & (1LL << (__int64) i))) SendMessage(list, LB_SETSEL, 0, i);
\r
120 if (service->no_console) {
121 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_SETCHECK, BST_UNCHECKED, 0);
\r
124 /* Shutdown tab. */
\r
125 if (! (service->stop_method & NSSM_STOP_METHOD_CONSOLE)) {
\r
126 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_CONSOLE, BM_SETCHECK, BST_UNCHECKED, 0);
\r
127 EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE), 0);
\r
129 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, service->kill_console_delay, 0);
\r
130 if (! (service->stop_method & NSSM_STOP_METHOD_WINDOW)) {
\r
131 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_WINDOW, BM_SETCHECK, BST_UNCHECKED, 0);
\r
132 EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW), 0);
\r
134 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, service->kill_window_delay, 0);
\r
135 if (! (service->stop_method & NSSM_STOP_METHOD_THREADS)) {
\r
136 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_THREADS, BM_SETCHECK, BST_UNCHECKED, 0);
\r
137 EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS), 0);
\r
139 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, service->kill_threads_delay, 0);
\r
140 if (! (service->stop_method & NSSM_STOP_METHOD_TERMINATE)) {
\r
141 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_TERMINATE, BM_SETCHECK, BST_UNCHECKED, 0);
\r
145 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, service->throttle_delay, 0);
\r
146 combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
\r
147 SendMessage(combo, CB_SETCURSEL, service->default_exit_action, 0);
\r
148 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, service->restart_delay, 0);
\r
151 SetDlgItemText(tablist[NSSM_TAB_IO], IDC_STDIN, service->stdin_path);
\r
152 SetDlgItemText(tablist[NSSM_TAB_IO], IDC_STDOUT, service->stdout_path);
\r
153 SetDlgItemText(tablist[NSSM_TAB_IO], IDC_STDERR, service->stderr_path);
\r
155 /* Rotation tab. */
\r
156 if (service->stdout_disposition == CREATE_ALWAYS) SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_TRUNCATE, BM_SETCHECK, BST_CHECKED, 0);
\r
157 if (service->rotate_files) {
\r
158 SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE, BM_SETCHECK, BST_CHECKED, 0);
\r
159 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE), 1);
\r
160 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS), 1);
\r
161 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW), 1);
\r
163 if (service->rotate_stdout_online || service->rotate_stderr_online) SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_SETCHECK, BST_CHECKED, 0);
\r
164 SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, service->rotate_seconds, 0);
\r
165 if (! service->rotate_bytes_high) SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, service->rotate_bytes_low, 0);
\r
167 /* Check if advanced settings are in use. */
\r
168 if (service->stdout_disposition != service->stderr_disposition || (service->stdout_disposition && service->stdout_disposition != NSSM_STDOUT_DISPOSITION && service->stdout_disposition != CREATE_ALWAYS) || (service->stderr_disposition && service->stderr_disposition != NSSM_STDERR_DISPOSITION && service->stderr_disposition != CREATE_ALWAYS)) popup_message(dlg, MB_OK | MB_ICONWARNING, NSSM_GUI_WARN_STDIO);
\r
169 if (service->rotate_bytes_high) popup_message(dlg, MB_OK | MB_ICONWARNING, NSSM_GUI_WARN_ROTATE_BYTES);
\r
171 /* Environment tab. */
\r
173 unsigned long envlen;
\r
174 if (service->env_extralen) {
\r
175 env = service->env_extra;
\r
176 envlen = service->env_extralen;
\r
179 env = service->env;
\r
180 envlen = service->envlen;
\r
181 if (envlen) SendDlgItemMessage(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT_REPLACE, BM_SETCHECK, BST_CHECKED, 0);
\r
186 unsigned long newlen;
\r
187 if (format_environment(env, envlen, &formatted, &newlen)) {
\r
188 popup_message(dlg, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("nssm_dlg()"));
\r
191 SetDlgItemText(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT, formatted);
\r
192 HeapFree(GetProcessHeap(), 0, formatted);
\r
195 if (service->envlen && service->env_extralen) popup_message(dlg, MB_OK | MB_ICONWARNING, NSSM_GUI_WARN_ENVIRONMENT);
\r
200 while (GetMessage(&message, 0, 0, 0)) {
\r
201 if (IsDialogMessage(dlg, &message)) continue;
\r
202 TranslateMessage(&message);
\r
203 DispatchMessage(&message);
\r
206 return (int) message.wParam;
\r
209 void centre_window(HWND window) {
\r
211 RECT size, desktop_size;
\r
212 unsigned long x, y;
\r
214 if (! window) return;
\r
216 /* Find window size */
\r
217 if (! GetWindowRect(window, &size)) return;
\r
219 /* Find desktop window */
\r
220 desktop = GetDesktopWindow();
\r
221 if (! desktop) return;
\r
223 /* Find desktop window size */
\r
224 if (! GetWindowRect(desktop, &desktop_size)) return;
\r
226 /* Centre window */
\r
227 x = (desktop_size.right - size.right) / 2;
\r
228 y = (desktop_size.bottom - size.bottom) / 2;
\r
229 MoveWindow(window, x, y, size.right - size.left, size.bottom - size.top, 0);
\r
232 static inline void check_stop_method(nssm_service_t *service, unsigned long method, unsigned long control) {
\r
233 if (SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], control, BM_GETCHECK, 0, 0) & BST_CHECKED) return;
\r
234 service->stop_method &= ~method;
\r
237 static inline void check_number(HWND tab, unsigned long control, unsigned long *timeout) {
\r
239 unsigned long configured = GetDlgItemInt(tab, control, &translated, 0);
\r
240 if (translated) *timeout = configured;
\r
243 static inline void set_timeout_enabled(unsigned long control, unsigned long dependent) {
\r
244 unsigned char enabled = 0;
\r
245 if (SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], control, BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 1;
\r
246 EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], dependent), enabled);
\r
249 static inline void set_logon_enabled(unsigned char enabled) {
\r
250 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_INTERACT), ! enabled);
\r
251 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_USERNAME), enabled);
\r
252 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1), enabled);
\r
253 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2), enabled);
\r
256 static inline void set_affinity_enabled(unsigned char enabled) {
\r
257 EnableWindow(GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY), enabled);
\r
260 static inline void set_rotation_enabled(unsigned char enabled) {
\r
261 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE), enabled);
\r
262 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS), enabled);
\r
263 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW), enabled);
\r
266 static inline void check_io(HWND owner, TCHAR *name, TCHAR *buffer, unsigned long len, unsigned long control) {
\r
267 if (! SendMessage(GetDlgItem(tablist[NSSM_TAB_IO], control), WM_GETTEXTLENGTH, 0, 0)) return;
\r
268 if (GetDlgItemText(tablist[NSSM_TAB_IO], control, buffer, (int) len)) return;
\r
269 popup_message(owner, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, name);
\r
270 ZeroMemory(buffer, len * sizeof(TCHAR));
\r
273 /* Set service parameters. */
\r
274 int configure(HWND window, nssm_service_t *service, nssm_service_t *orig_service) {
\r
275 if (! service) return 1;
\r
277 set_nssm_service_defaults(service);
\r
279 if (orig_service) {
\r
280 service->native = orig_service->native;
\r
281 service->handle = orig_service->handle;
\r
284 /* Get service name. */
\r
285 if (! GetDlgItemText(window, IDC_NAME, service->name, _countof(service->name))) {
\r
286 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_SERVICE_NAME);
\r
287 cleanup_nssm_service(service);
\r
291 /* Get executable name */
\r
292 if (! service->native) {
\r
293 if (! GetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_PATH, service->exe, _countof(service->exe))) {
\r
294 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PATH);
\r
298 /* Get startup directory. */
\r
299 if (! GetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_DIR, service->dir, _countof(service->dir))) {
\r
300 _sntprintf_s(service->dir, _countof(service->dir), _TRUNCATE, _T("%s"), service->exe);
\r
301 strip_basename(service->dir);
\r
305 if (SendMessage(GetDlgItem(tablist[NSSM_TAB_APPLICATION], IDC_FLAGS), WM_GETTEXTLENGTH, 0, 0)) {
\r
306 if (! GetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_FLAGS, service->flags, _countof(service->flags))) {
\r
307 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_OPTIONS);
\r
314 if (SendMessage(GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_DISPLAYNAME), WM_GETTEXTLENGTH, 0, 0)) {
\r
315 if (! GetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DISPLAYNAME, service->displayname, _countof(service->displayname))) {
\r
316 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DISPLAYNAME);
\r
321 if (SendMessage(GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_DESCRIPTION), WM_GETTEXTLENGTH, 0, 0)) {
\r
322 if (! GetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DESCRIPTION, service->description, _countof(service->description))) {
\r
323 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DESCRIPTION);
\r
328 HWND combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP);
\r
329 service->startup = (unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0);
\r
330 if (service->startup == CB_ERR) service->startup = 0;
\r
332 /* Get logon stuff. */
\r
333 if (SendDlgItemMessage(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
334 if (SendDlgItemMessage(tablist[NSSM_TAB_LOGON], IDC_INTERACT, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
335 service->type |= SERVICE_INTERACTIVE_PROCESS;
\r
337 if (service->username) HeapFree(GetProcessHeap(), 0, service->username);
\r
338 service->username = 0;
\r
339 service->usernamelen = 0;
\r
340 if (service->password) {
\r
341 SecureZeroMemory(service->password, service->passwordlen);
\r
342 HeapFree(GetProcessHeap(), 0, service->password);
\r
344 service->password = 0;
\r
345 service->passwordlen = 0;
\r
349 service->usernamelen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_USERNAME), WM_GETTEXTLENGTH, 0, 0);
\r
350 if (! service->usernamelen) {
\r
351 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_USERNAME);
\r
354 service->usernamelen++;
\r
356 service->username = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->usernamelen * sizeof(TCHAR));
\r
357 if (! service->username) {
\r
358 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("account name"), _T("install()"));
\r
361 if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_USERNAME, service->username, (int) service->usernamelen)) {
\r
362 HeapFree(GetProcessHeap(), 0, service->username);
\r
363 service->username = 0;
\r
364 service->usernamelen = 0;
\r
365 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_USERNAME);
\r
370 Special case for well-known accounts.
\r
371 Ignore the password if we're editing and the username hasn't changed.
\r
373 const TCHAR *well_known = well_known_username(service->username);
375 if (str_equiv(well_known, NSSM_LOCALSYSTEM_ACCOUNT)) {
376 HeapFree(GetProcessHeap(), 0, service->username);
\r
377 service->username = 0;
\r
378 service->usernamelen = 0;
\r
381 service->usernamelen = _tcslen(well_known) + 1;
382 service->username = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->usernamelen * sizeof(TCHAR));
383 if (! service->username) {
384 print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("canon"), _T("install()"));
387 memmove(service->username, well_known, service->usernamelen * sizeof(TCHAR));
392 service->passwordlen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1), WM_GETTEXTLENGTH, 0, 0);
\r
393 size_t passwordlen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2), WM_GETTEXTLENGTH, 0, 0);
\r
395 if (! orig_service || ! orig_service->username || ! str_equiv(service->username, orig_service->username) || service->passwordlen || passwordlen) {
\r
396 if (! service->passwordlen) {
\r
397 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
400 if (passwordlen != service->passwordlen) {
\r
401 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
404 service->passwordlen++;
\r
406 /* Temporary buffer for password validation. */
\r
407 TCHAR *password = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->passwordlen * sizeof(TCHAR));
\r
409 HeapFree(GetProcessHeap(), 0, service->username);
\r
410 service->username = 0;
\r
411 service->usernamelen = 0;
\r
412 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("password confirmation"), _T("install()"));
\r
416 /* Actual password buffer. */
\r
417 service->password = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->passwordlen * sizeof(TCHAR));
\r
418 if (! service->password) {
\r
419 HeapFree(GetProcessHeap(), 0, password);
\r
420 HeapFree(GetProcessHeap(), 0, service->username);
\r
421 service->username = 0;
\r
422 service->usernamelen = 0;
\r
423 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("password"), _T("install()"));
\r
427 /* Get first password. */
\r
428 if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1, service->password, (int) service->passwordlen)) {
\r
429 HeapFree(GetProcessHeap(), 0, password);
\r
430 SecureZeroMemory(service->password, service->passwordlen);
\r
431 HeapFree(GetProcessHeap(), 0, service->password);
\r
432 service->password = 0;
\r
433 service->passwordlen = 0;
\r
434 HeapFree(GetProcessHeap(), 0, service->username);
\r
435 service->username = 0;
\r
436 service->usernamelen = 0;
\r
437 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_PASSWORD);
\r
441 /* Get confirmation. */
\r
442 if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2, password, (int) service->passwordlen)) {
\r
443 SecureZeroMemory(password, service->passwordlen);
\r
444 HeapFree(GetProcessHeap(), 0, password);
\r
445 SecureZeroMemory(service->password, service->passwordlen);
\r
446 HeapFree(GetProcessHeap(), 0, service->password);
\r
447 service->password = 0;
\r
448 service->passwordlen = 0;
\r
449 HeapFree(GetProcessHeap(), 0, service->username);
\r
450 service->username = 0;
\r
451 service->usernamelen = 0;
\r
452 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_PASSWORD);
\r
457 if (_tcsncmp(password, service->password, service->passwordlen)) {
\r
458 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
459 SecureZeroMemory(password, service->passwordlen);
\r
460 HeapFree(GetProcessHeap(), 0, password);
\r
461 SecureZeroMemory(service->password, service->passwordlen);
\r
462 HeapFree(GetProcessHeap(), 0, service->password);
\r
463 service->password = 0;
\r
464 service->passwordlen = 0;
\r
465 HeapFree(GetProcessHeap(), 0, service->username);
\r
466 service->username = 0;
\r
467 service->usernamelen = 0;
\r
474 /* Remaining tabs are only for services we manage. */
\r
475 if (service->native) return 0;
\r
477 /* Get process stuff. */
\r
478 combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY);
\r
479 service->priority = priority_index_to_constant((unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0));
\r
481 service->affinity = 0LL;
\r
482 if (! (SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_GETCHECK, 0, 0) & BST_CHECKED)) {
\r
483 HWND list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY);
\r
484 int selected = (int) SendMessage(list, LB_GETSELCOUNT, 0, 0);
\r
485 int count = (int) SendMessage(list, LB_GETCOUNT, 0, 0);
\r
487 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_WARN_AFFINITY_NONE);
\r
490 else if (selected < count) {
\r
491 for (int i = 0; i < count; i++) {
\r
492 if (SendMessage(list, LB_GETSEL, i, 0)) service->affinity |= (1LL << (__int64) i);
\r
497 if (SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_GETCHECK, 0, 0) & BST_CHECKED) service->no_console = 0;
498 else service->no_console = 1;
500 /* Get stop method stuff. */
\r
501 check_stop_method(service, NSSM_STOP_METHOD_CONSOLE, IDC_METHOD_CONSOLE);
\r
502 check_stop_method(service, NSSM_STOP_METHOD_WINDOW, IDC_METHOD_WINDOW);
\r
503 check_stop_method(service, NSSM_STOP_METHOD_THREADS, IDC_METHOD_THREADS);
\r
504 check_stop_method(service, NSSM_STOP_METHOD_TERMINATE, IDC_METHOD_TERMINATE);
\r
505 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, &service->kill_console_delay);
\r
506 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, &service->kill_window_delay);
\r
507 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, &service->kill_threads_delay);
\r
509 /* Get exit action stuff. */
\r
510 check_number(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, &service->throttle_delay);
\r
511 combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
\r
512 service->default_exit_action = (unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0);
\r
513 if (service->default_exit_action == CB_ERR) service->default_exit_action = 0;
\r
514 check_number(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, &service->restart_delay);
\r
516 /* Get I/O stuff. */
\r
517 check_io(window, _T("stdin"), service->stdin_path, _countof(service->stdin_path), IDC_STDIN);
\r
518 check_io(window, _T("stdout"), service->stdout_path, _countof(service->stdout_path), IDC_STDOUT);
\r
519 check_io(window, _T("stderr"), service->stderr_path, _countof(service->stderr_path), IDC_STDERR);
\r
521 /* Override stdout and/or stderr. */
\r
522 if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_TRUNCATE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
523 if (service->stdout_path[0]) service->stdout_disposition = CREATE_ALWAYS;
\r
524 if (service->stderr_path[0]) service->stderr_disposition = CREATE_ALWAYS;
\r
527 /* Get rotation stuff. */
\r
528 if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
529 service->rotate_files = true;
\r
530 if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_GETCHECK, 0, 0) & BST_CHECKED) service->rotate_stdout_online = service->rotate_stderr_online = NSSM_ROTATE_ONLINE;
531 check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, &service->rotate_seconds);
\r
532 check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, &service->rotate_bytes_low);
\r
535 /* Get environment. */
\r
536 unsigned long envlen = (unsigned long) SendMessage(GetDlgItem(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT), WM_GETTEXTLENGTH, 0, 0);
\r
538 TCHAR *env = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (envlen + 2) * sizeof(TCHAR));
\r
540 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("install()"));
\r
541 cleanup_nssm_service(service);
\r
545 if (! GetDlgItemText(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT, env, envlen + 1)) {
\r
546 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT);
\r
547 HeapFree(GetProcessHeap(), 0, env);
\r
548 cleanup_nssm_service(service);
\r
553 unsigned long newlen;
\r
554 if (unformat_environment(env, envlen, &newenv, &newlen)) {
\r
555 HeapFree(GetProcessHeap(), 0, env);
\r
556 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("install()"));
\r
557 cleanup_nssm_service(service);
\r
561 HeapFree(GetProcessHeap(), 0, env);
\r
565 /* Test the environment is valid. */
\r
566 if (test_environment(env)) {
\r
567 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT);
\r
568 HeapFree(GetProcessHeap(), 0, env);
\r
569 cleanup_nssm_service(service);
\r
573 if (SendDlgItemMessage(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT_REPLACE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
574 service->env = env;
\r
575 service->envlen = envlen;
\r
578 service->env_extra = env;
\r
579 service->env_extralen = envlen;
\r
586 /* Install the service. */
\r
587 int install(HWND window) {
\r
588 if (! window) return 1;
\r
590 nssm_service_t *service = alloc_nssm_service();
\r
592 int ret = configure(window, service, 0);
\r
593 if (ret) return ret;
\r
596 /* See if it works. */
\r
597 switch (install_service(service)) {
\r
599 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("install()"));
\r
600 cleanup_nssm_service(service);
\r
604 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);
\r
605 cleanup_nssm_service(service);
\r
609 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, NSSM);
\r
610 cleanup_nssm_service(service);
\r
614 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_OUT_OF_MEMORY_FOR_IMAGEPATH);
\r
615 cleanup_nssm_service(service);
\r
619 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INSTALL_SERVICE_FAILED);
\r
620 cleanup_nssm_service(service);
\r
624 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_CREATE_PARAMETERS_FAILED);
\r
625 cleanup_nssm_service(service);
\r
629 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_INSTALLED, service->name);
\r
630 cleanup_nssm_service(service);
\r
634 /* Remove the service */
\r
635 int remove(HWND window) {
\r
636 if (! window) return 1;
\r
638 /* See if it works */
\r
639 nssm_service_t *service = alloc_nssm_service();
\r
641 /* Get service name */
\r
642 if (! GetDlgItemText(window, IDC_NAME, service->name, _countof(service->name))) {
\r
643 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_SERVICE_NAME);
\r
644 cleanup_nssm_service(service);
\r
649 if (popup_message(window, MB_YESNO, NSSM_GUI_ASK_REMOVE_SERVICE, service->name) != IDYES) {
\r
650 cleanup_nssm_service(service);
\r
655 switch (remove_service(service)) {
\r
657 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("remove()"));
\r
658 cleanup_nssm_service(service);
\r
662 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);
\r
663 cleanup_nssm_service(service);
\r
667 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_SERVICE_NOT_INSTALLED);
\r
669 cleanup_nssm_service(service);
\r
672 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_REMOVE_SERVICE_FAILED);
\r
673 cleanup_nssm_service(service);
\r
677 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_REMOVED, service->name);
\r
678 cleanup_nssm_service(service);
\r
682 int edit(HWND window, nssm_service_t *orig_service) {
\r
683 if (! window) return 1;
\r
685 nssm_service_t *service = alloc_nssm_service();
\r
687 int ret = configure(window, service, orig_service);
\r
688 if (ret) return ret;
\r
691 switch (edit_service(service, true)) {
\r
693 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("edit()"));
\r
694 cleanup_nssm_service(service);
\r
698 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, NSSM);
\r
699 cleanup_nssm_service(service);
\r
703 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_OUT_OF_MEMORY_FOR_IMAGEPATH);
\r
704 cleanup_nssm_service(service);
\r
709 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_EDIT_PARAMETERS_FAILED);
\r
710 cleanup_nssm_service(service);
\r
714 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_EDITED, service->name);
\r
715 cleanup_nssm_service(service);
\r
719 static TCHAR *browse_filter(int message) {
\r
721 case NSSM_GUI_BROWSE_FILTER_APPLICATIONS: return _T("*.exe;*.bat;*.cmd");
\r
722 case NSSM_GUI_BROWSE_FILTER_DIRECTORIES: return _T(".");
\r
723 case NSSM_GUI_BROWSE_FILTER_ALL_FILES: /* Fall through. */
\r
724 default: return _T("*.*");
\r
728 UINT_PTR CALLBACK browse_hook(HWND dlg, UINT message, WPARAM w, LPARAM l) {
\r
730 case WM_INITDIALOG:
\r
737 /* Browse for application */
\r
738 void browse(HWND window, TCHAR *current, unsigned long flags, ...) {
\r
739 if (! window) return;
\r
742 size_t bufsize = 256;
\r
743 size_t len = bufsize;
\r
747 ZeroMemory(&ofn, sizeof(ofn));
\r
748 ofn.lStructSize = sizeof(ofn);
\r
749 ofn.lpstrFilter = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, bufsize * sizeof(TCHAR));
\r
750 /* XXX: Escaping nulls with FormatMessage is tricky */
\r
751 if (ofn.lpstrFilter) {
\r
752 ZeroMemory((void *) ofn.lpstrFilter, bufsize);
\r
754 /* "Applications" + NULL + "*.exe" + NULL */
\r
755 va_start(arg, flags);
\r
756 while (i = va_arg(arg, int)) {
\r
757 TCHAR *localised = message_string(i);
\r
758 _sntprintf_s((TCHAR *) ofn.lpstrFilter + len, bufsize, _TRUNCATE, localised);
\r
759 len += _tcslen(localised) + 1;
\r
760 LocalFree(localised);
\r
761 TCHAR *filter = browse_filter(i);
\r
762 _sntprintf_s((TCHAR *) ofn.lpstrFilter + len, bufsize - len, _TRUNCATE, _T("%s"), filter);
\r
763 len += _tcslen(filter) + 1;
\r
766 /* Remainder of the buffer is already zeroed */
\r
768 ofn.lpstrFile = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, PATH_LENGTH * sizeof(TCHAR));
\r
770 if (flags & OFN_NOVALIDATE) {
\r
771 /* Directory hack. */
\r
772 _sntprintf_s(ofn.lpstrFile, PATH_LENGTH, _TRUNCATE, _T(":%s:"), message_string(NSSM_GUI_BROWSE_FILTER_DIRECTORIES));
\r
773 ofn.nMaxFile = DIR_LENGTH;
\r
776 _sntprintf_s(ofn.lpstrFile, PATH_LENGTH, _TRUNCATE, _T("%s"), current);
\r
777 ofn.nMaxFile = PATH_LENGTH;
\r
780 ofn.lpstrTitle = message_string(NSSM_GUI_BROWSE_TITLE);
\r
781 ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | flags;
\r
783 if (GetOpenFileName(&ofn)) {
\r
784 /* Directory hack. */
\r
785 if (flags & OFN_NOVALIDATE) strip_basename(ofn.lpstrFile);
\r
786 SendMessage(window, WM_SETTEXT, 0, (LPARAM) ofn.lpstrFile);
\r
788 if (ofn.lpstrFilter) HeapFree(GetProcessHeap(), 0, (void *) ofn.lpstrFilter);
\r
789 if (ofn.lpstrFile) HeapFree(GetProcessHeap(), 0, ofn.lpstrFile);
792 INT_PTR CALLBACK tab_dlg(HWND tab, UINT message, WPARAM w, LPARAM l) {
\r
794 case WM_INITDIALOG:
\r
797 /* Button was pressed or control was controlled. */
\r
800 TCHAR buffer[PATH_LENGTH];
\r
801 unsigned char enabled;
\r
803 switch (LOWORD(w)) {
\r
804 /* Browse for application. */
\r
806 dlg = GetDlgItem(tab, IDC_PATH);
\r
807 GetDlgItemText(tab, IDC_PATH, buffer, _countof(buffer));
\r
808 browse(dlg, buffer, OFN_FILEMUSTEXIST, NSSM_GUI_BROWSE_FILTER_APPLICATIONS, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
809 /* Fill in startup directory if it wasn't already specified. */
\r
810 GetDlgItemText(tab, IDC_DIR, buffer, _countof(buffer));
\r
812 GetDlgItemText(tab, IDC_PATH, buffer, _countof(buffer));
\r
813 strip_basename(buffer);
\r
814 SetDlgItemText(tab, IDC_DIR, buffer);
\r
818 /* Browse for startup directory. */
\r
819 case IDC_BROWSE_DIR:
\r
820 dlg = GetDlgItem(tab, IDC_DIR);
\r
821 GetDlgItemText(tab, IDC_DIR, buffer, _countof(buffer));
\r
822 browse(dlg, buffer, OFN_NOVALIDATE, NSSM_GUI_BROWSE_FILTER_DIRECTORIES, 0);
\r
826 case IDC_LOCALSYSTEM:
\r
827 set_logon_enabled(0);
\r
831 set_logon_enabled(1);
\r
835 case IDC_AFFINITY_ALL:
\r
836 if (SendDlgItemMessage(tab, LOWORD(w), BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 0;
\r
838 set_affinity_enabled(enabled);
\r
841 /* Shutdown methods. */
\r
842 case IDC_METHOD_CONSOLE:
\r
843 set_timeout_enabled(LOWORD(w), IDC_KILL_CONSOLE);
\r
846 case IDC_METHOD_WINDOW:
\r
847 set_timeout_enabled(LOWORD(w), IDC_KILL_WINDOW);
\r
850 case IDC_METHOD_THREADS:
\r
851 set_timeout_enabled(LOWORD(w), IDC_KILL_THREADS);
\r
854 /* Browse for stdin. */
\r
855 case IDC_BROWSE_STDIN:
\r
856 dlg = GetDlgItem(tab, IDC_STDIN);
\r
857 GetDlgItemText(tab, IDC_STDIN, buffer, _countof(buffer));
\r
858 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
861 /* Browse for stdout. */
\r
862 case IDC_BROWSE_STDOUT:
\r
863 dlg = GetDlgItem(tab, IDC_STDOUT);
\r
864 GetDlgItemText(tab, IDC_STDOUT, buffer, _countof(buffer));
\r
865 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
866 /* Fill in stderr if it wasn't already specified. */
\r
867 GetDlgItemText(tab, IDC_STDERR, buffer, _countof(buffer));
\r
869 GetDlgItemText(tab, IDC_STDOUT, buffer, _countof(buffer));
\r
870 SetDlgItemText(tab, IDC_STDERR, buffer);
\r
874 /* Browse for stderr. */
\r
875 case IDC_BROWSE_STDERR:
\r
876 dlg = GetDlgItem(tab, IDC_STDERR);
\r
877 GetDlgItemText(tab, IDC_STDERR, buffer, _countof(buffer));
\r
878 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
883 if (SendDlgItemMessage(tab, LOWORD(w), BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 1;
\r
885 set_rotation_enabled(enabled);
\r
894 /* Install/remove dialogue callback */
\r
895 INT_PTR CALLBACK nssm_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {
\r
896 nssm_service_t *service;
\r
899 /* Creating the dialogue */
\r
900 case WM_INITDIALOG:
\r
901 service = (nssm_service_t *) l;
\r
903 SetFocus(GetDlgItem(window, IDC_NAME));
\r
909 tabs = GetDlgItem(window, IDC_TAB1);
\r
910 if (! tabs) return 0;
\r
914 ZeroMemory(&tab, sizeof(tab));
\r
915 tab.mask = TCIF_TEXT;
\r
919 /* Application tab. */
\r
920 if (service->native) tab.pszText = message_string(NSSM_GUI_TAB_NATIVE);
\r
921 else tab.pszText = message_string(NSSM_GUI_TAB_APPLICATION);
\r
922 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
923 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_APPLICATION, (LPARAM) &tab);
\r
924 if (service->native) {
\r
925 tablist[NSSM_TAB_APPLICATION] = dialog(MAKEINTRESOURCE(IDD_NATIVE), window, tab_dlg);
\r
926 EnableWindow(tablist[NSSM_TAB_APPLICATION], 0);
\r
927 EnableWindow(GetDlgItem(tablist[NSSM_TAB_APPLICATION], IDC_PATH), 0);
\r
929 else tablist[NSSM_TAB_APPLICATION] = dialog(MAKEINTRESOURCE(IDD_APPLICATION), window, tab_dlg);
\r
930 ShowWindow(tablist[NSSM_TAB_APPLICATION], SW_SHOW);
\r
933 tab.pszText = message_string(NSSM_GUI_TAB_DETAILS);
\r
934 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
935 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_DETAILS, (LPARAM) &tab);
\r
936 tablist[NSSM_TAB_DETAILS] = dialog(MAKEINTRESOURCE(IDD_DETAILS), window, tab_dlg);
\r
937 ShowWindow(tablist[NSSM_TAB_DETAILS], SW_HIDE);
\r
939 /* Set defaults. */
\r
940 combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP);
\r
941 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_AUTOMATIC, (LPARAM) message_string(NSSM_GUI_STARTUP_AUTOMATIC));
\r
942 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DELAYED, (LPARAM) message_string(NSSM_GUI_STARTUP_DELAYED));
\r
943 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_MANUAL, (LPARAM) message_string(NSSM_GUI_STARTUP_MANUAL));
\r
944 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DISABLED, (LPARAM) message_string(NSSM_GUI_STARTUP_DISABLED));
\r
945 SendMessage(combo, CB_SETCURSEL, NSSM_STARTUP_AUTOMATIC, 0);
\r
948 tab.pszText = message_string(NSSM_GUI_TAB_LOGON);
\r
949 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
950 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_LOGON, (LPARAM) &tab);
\r
951 tablist[NSSM_TAB_LOGON] = dialog(MAKEINTRESOURCE(IDD_LOGON), window, tab_dlg);
\r
952 ShowWindow(tablist[NSSM_TAB_LOGON], SW_HIDE);
\r
954 /* Set defaults. */
\r
955 CheckRadioButton(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, IDC_ACCOUNT, IDC_LOCALSYSTEM);
\r
956 set_logon_enabled(0);
\r
958 /* Remaining tabs are only for services we manage. */
\r
959 if (service->native) return 1;
\r
962 tab.pszText = message_string(NSSM_GUI_TAB_PROCESS);
\r
963 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
964 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_PROCESS, (LPARAM) &tab);
\r
965 tablist[NSSM_TAB_PROCESS] = dialog(MAKEINTRESOURCE(IDD_PROCESS), window, tab_dlg);
\r
966 ShowWindow(tablist[NSSM_TAB_PROCESS], SW_HIDE);
\r
968 /* Set defaults. */
\r
969 combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY);
\r
970 SendMessage(combo, CB_INSERTSTRING, NSSM_REALTIME_PRIORITY, (LPARAM) message_string(NSSM_GUI_REALTIME_PRIORITY_CLASS));
\r
971 SendMessage(combo, CB_INSERTSTRING, NSSM_HIGH_PRIORITY, (LPARAM) message_string(NSSM_GUI_HIGH_PRIORITY_CLASS));
\r
972 SendMessage(combo, CB_INSERTSTRING, NSSM_ABOVE_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_ABOVE_NORMAL_PRIORITY_CLASS));
\r
973 SendMessage(combo, CB_INSERTSTRING, NSSM_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_NORMAL_PRIORITY_CLASS));
\r
974 SendMessage(combo, CB_INSERTSTRING, NSSM_BELOW_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_BELOW_NORMAL_PRIORITY_CLASS));
\r
975 SendMessage(combo, CB_INSERTSTRING, NSSM_IDLE_PRIORITY, (LPARAM) message_string(NSSM_GUI_IDLE_PRIORITY_CLASS));
\r
976 SendMessage(combo, CB_SETCURSEL, NSSM_NORMAL_PRIORITY, 0);
\r
978 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_SETCHECK, BST_CHECKED, 0);
\r
980 list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY);
\r
982 SendMessage(list, LB_SETCOLUMNWIDTH, 16, 0);
\r
983 for (i = 0; i < n; i++) {
\r
985 _sntprintf_s(buffer, _countof(buffer), _TRUNCATE, _T("%d"), i);
\r
986 SendMessage(list, LB_ADDSTRING, 0, (LPARAM) buffer);
\r
991 The box is high enough for four rows. It is wide enough for eight
\r
992 columns without scrolling. With scrollbars it shrinks to two rows.
\r
993 Note that the above only holds if we set the column width BEFORE
997 int columns = (n - 1) / 4;
\r
999 GetWindowRect(list, &rect);
\r
1000 int width = rect.right - rect.left;
1001 width -= (7 - columns) * 16;
\r
1002 int height = rect.bottom - rect.top;
\r
1003 if (n < 4) height -= (int) SendMessage(list, LB_GETITEMHEIGHT, 0, 0) * (4 - n);
1004 SetWindowPos(list, 0, 0, 0, width, height, SWP_NOMOVE | SWP_NOOWNERZORDER);
\r
1006 SendMessage(list, LB_SELITEMRANGE, 1, MAKELPARAM(0, n));
\r
1008 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_SETCHECK, BST_CHECKED, 0);
\r
1009 set_affinity_enabled(0);
\r
1011 /* Shutdown tab. */
\r
1012 tab.pszText = message_string(NSSM_GUI_TAB_SHUTDOWN);
\r
1013 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1014 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_SHUTDOWN, (LPARAM) &tab);
\r
1015 tablist[NSSM_TAB_SHUTDOWN] = dialog(MAKEINTRESOURCE(IDD_SHUTDOWN), window, tab_dlg);
\r
1016 ShowWindow(tablist[NSSM_TAB_SHUTDOWN], SW_HIDE);
\r
1018 /* Set defaults. */
\r
1019 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_CONSOLE, BM_SETCHECK, BST_CHECKED, 0);
\r
1020 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, NSSM_KILL_CONSOLE_GRACE_PERIOD, 0);
\r
1021 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_WINDOW, BM_SETCHECK, BST_CHECKED, 0);
\r
1022 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, NSSM_KILL_WINDOW_GRACE_PERIOD, 0);
\r
1023 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_THREADS, BM_SETCHECK, BST_CHECKED, 0);
\r
1024 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, NSSM_KILL_THREADS_GRACE_PERIOD, 0);
\r
1025 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_TERMINATE, BM_SETCHECK, BST_CHECKED, 0);
\r
1027 /* Restart tab. */
\r
1028 tab.pszText = message_string(NSSM_GUI_TAB_EXIT);
\r
1029 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1030 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_EXIT, (LPARAM) &tab);
\r
1031 tablist[NSSM_TAB_EXIT] = dialog(MAKEINTRESOURCE(IDD_APPEXIT), window, tab_dlg);
\r
1032 ShowWindow(tablist[NSSM_TAB_EXIT], SW_HIDE);
\r
1034 /* Set defaults. */
\r
1035 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, NSSM_RESET_THROTTLE_RESTART, 0);
\r
1036 combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
\r
1037 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_RESTART, (LPARAM) message_string(NSSM_GUI_EXIT_RESTART));
\r
1038 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_IGNORE, (LPARAM) message_string(NSSM_GUI_EXIT_IGNORE));
\r
1039 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_REALLY, (LPARAM) message_string(NSSM_GUI_EXIT_REALLY));
\r
1040 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_UNCLEAN, (LPARAM) message_string(NSSM_GUI_EXIT_UNCLEAN));
\r
1041 SendMessage(combo, CB_SETCURSEL, NSSM_EXIT_RESTART, 0);
\r
1042 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, 0, 0);
\r
1045 tab.pszText = message_string(NSSM_GUI_TAB_IO);
\r
1046 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1047 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_IO, (LPARAM) &tab);
\r
1048 tablist[NSSM_TAB_IO] = dialog(MAKEINTRESOURCE(IDD_IO), window, tab_dlg);
\r
1049 ShowWindow(tablist[NSSM_TAB_IO], SW_HIDE);
\r
1051 /* Rotation tab. */
\r
1052 tab.pszText = message_string(NSSM_GUI_TAB_ROTATION);
\r
1053 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1054 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_ROTATION, (LPARAM) &tab);
\r
1055 tablist[NSSM_TAB_ROTATION] = dialog(MAKEINTRESOURCE(IDD_ROTATION), window, tab_dlg);
\r
1056 ShowWindow(tablist[NSSM_TAB_ROTATION], SW_HIDE);
\r
1058 /* Set defaults. */
\r
1059 SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_SETCHECK, BST_UNCHECKED, 0);
\r
1060 SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, 0, 0);
\r
1061 SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, 0, 0);
\r
1062 set_rotation_enabled(0);
\r
1064 /* Environment tab. */
\r
1065 tab.pszText = message_string(NSSM_GUI_TAB_ENVIRONMENT);
\r
1066 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1067 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_ENVIRONMENT, (LPARAM) &tab);
\r
1068 tablist[NSSM_TAB_ENVIRONMENT] = dialog(MAKEINTRESOURCE(IDD_ENVIRONMENT), window, tab_dlg);
\r
1069 ShowWindow(tablist[NSSM_TAB_ENVIRONMENT], SW_HIDE);
\r
1075 NMHDR *notification;
\r
1077 notification = (NMHDR *) l;
\r
1078 switch (notification->code) {
\r
1079 case TCN_SELCHANGE:
\r
1083 tabs = GetDlgItem(window, IDC_TAB1);
\r
1084 if (! tabs) return 0;
\r
1086 selection = (int) SendMessage(tabs, TCM_GETCURSEL, 0, 0);
\r
1087 if (selection != selected_tab) {
\r
1088 ShowWindow(tablist[selected_tab], SW_HIDE);
\r
1089 ShowWindow(tablist[selection], SW_SHOWDEFAULT);
\r
1090 SetFocus(GetDlgItem(window, IDOK));
\r
1091 selected_tab = selection;
\r
1098 /* Button was pressed or control was controlled */
\r
1100 switch (LOWORD(w)) {
\r
1103 if ((int) GetWindowLongPtr(window, GWLP_USERDATA) == IDD_EDIT) {
\r
1104 if (! edit(window, (nssm_service_t *) GetWindowLongPtr(window, DWLP_USER))) PostQuitMessage(0);
\r
1106 else if (! install(window)) PostQuitMessage(0);
\r
1109 /* Cancel button */
\r
1111 DestroyWindow(window);
\r
1114 /* Remove button */
\r
1116 if (! remove(window)) PostQuitMessage(0);
\r
1121 /* Window closing */
\r
1123 DestroyWindow(window);
\r
1126 PostQuitMessage(0);
\r