3 static enum { NSSM_TAB_APPLICATION, NSSM_TAB_DETAILS, NSSM_TAB_LOGON, NSSM_TAB_DEPENDENCIES, 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
98 /* Dependencies tab. */
\r
99 if (service->dependencieslen) {
\r
101 unsigned long newlen;
\r
102 if (format_double_null(service->dependencies, service->dependencieslen, &formatted, &newlen)) {
\r
103 popup_message(dlg, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("dependencies"), _T("nssm_dlg()"));
\r
106 SetDlgItemText(tablist[NSSM_TAB_DEPENDENCIES], IDC_DEPENDENCIES, formatted);
\r
107 HeapFree(GetProcessHeap(), 0, formatted);
\r
112 if (service->priority) {
\r
113 int priority = priority_constant_to_index(service->priority);
\r
114 combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY);
\r
115 SendMessage(combo, CB_SETCURSEL, priority, 0);
\r
118 if (service->affinity) {
\r
119 list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY);
\r
120 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_SETCHECK, BST_UNCHECKED, 0);
\r
121 EnableWindow(GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY), 1);
\r
123 DWORD_PTR affinity, system_affinity;
\r
124 if (GetProcessAffinityMask(GetCurrentProcess(), &affinity, &system_affinity)) {
\r
125 if ((service->affinity & (__int64) system_affinity) != service->affinity) popup_message(dlg, MB_OK | MB_ICONWARNING, NSSM_GUI_WARN_AFFINITY);
\r
128 for (int i = 0; i < num_cpus(); i++) {
\r
129 if (! (service->affinity & (1LL << (__int64) i))) SendMessage(list, LB_SETSEL, 0, i);
\r
133 if (service->no_console) {
134 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_SETCHECK, BST_UNCHECKED, 0);
\r
137 /* Shutdown tab. */
\r
138 if (! (service->stop_method & NSSM_STOP_METHOD_CONSOLE)) {
\r
139 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_CONSOLE, BM_SETCHECK, BST_UNCHECKED, 0);
\r
140 EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE), 0);
\r
142 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, service->kill_console_delay, 0);
\r
143 if (! (service->stop_method & NSSM_STOP_METHOD_WINDOW)) {
\r
144 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_WINDOW, BM_SETCHECK, BST_UNCHECKED, 0);
\r
145 EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW), 0);
\r
147 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, service->kill_window_delay, 0);
\r
148 if (! (service->stop_method & NSSM_STOP_METHOD_THREADS)) {
\r
149 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_THREADS, BM_SETCHECK, BST_UNCHECKED, 0);
\r
150 EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS), 0);
\r
152 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, service->kill_threads_delay, 0);
\r
153 if (! (service->stop_method & NSSM_STOP_METHOD_TERMINATE)) {
\r
154 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_TERMINATE, BM_SETCHECK, BST_UNCHECKED, 0);
\r
158 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, service->throttle_delay, 0);
\r
159 combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
\r
160 SendMessage(combo, CB_SETCURSEL, service->default_exit_action, 0);
\r
161 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, service->restart_delay, 0);
\r
164 SetDlgItemText(tablist[NSSM_TAB_IO], IDC_STDIN, service->stdin_path);
\r
165 SetDlgItemText(tablist[NSSM_TAB_IO], IDC_STDOUT, service->stdout_path);
\r
166 SetDlgItemText(tablist[NSSM_TAB_IO], IDC_STDERR, service->stderr_path);
\r
168 /* Rotation tab. */
\r
169 if (service->stdout_disposition == CREATE_ALWAYS) SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_TRUNCATE, BM_SETCHECK, BST_CHECKED, 0);
\r
170 if (service->rotate_files) {
\r
171 SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE, BM_SETCHECK, BST_CHECKED, 0);
\r
172 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE), 1);
\r
173 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS), 1);
\r
174 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW), 1);
\r
176 if (service->rotate_stdout_online || service->rotate_stderr_online) SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_SETCHECK, BST_CHECKED, 0);
\r
177 SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, service->rotate_seconds, 0);
\r
178 if (! service->rotate_bytes_high) SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, service->rotate_bytes_low, 0);
\r
180 /* Check if advanced settings are in use. */
\r
181 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
182 if (service->rotate_bytes_high) popup_message(dlg, MB_OK | MB_ICONWARNING, NSSM_GUI_WARN_ROTATE_BYTES);
\r
184 /* Environment tab. */
\r
186 unsigned long envlen;
\r
187 if (service->env_extralen) {
\r
188 env = service->env_extra;
\r
189 envlen = service->env_extralen;
\r
192 env = service->env;
\r
193 envlen = service->envlen;
\r
194 if (envlen) SendDlgItemMessage(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT_REPLACE, BM_SETCHECK, BST_CHECKED, 0);
\r
199 unsigned long newlen;
\r
200 if (format_double_null(env, envlen, &formatted, &newlen)) {
\r
201 popup_message(dlg, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("nssm_dlg()"));
\r
204 SetDlgItemText(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT, formatted);
\r
205 HeapFree(GetProcessHeap(), 0, formatted);
\r
208 if (service->envlen && service->env_extralen) popup_message(dlg, MB_OK | MB_ICONWARNING, NSSM_GUI_WARN_ENVIRONMENT);
\r
213 while (GetMessage(&message, 0, 0, 0)) {
\r
214 if (IsDialogMessage(dlg, &message)) continue;
\r
215 TranslateMessage(&message);
\r
216 DispatchMessage(&message);
\r
219 return (int) message.wParam;
\r
222 void centre_window(HWND window) {
\r
224 RECT size, desktop_size;
\r
225 unsigned long x, y;
\r
227 if (! window) return;
\r
229 /* Find window size */
\r
230 if (! GetWindowRect(window, &size)) return;
\r
232 /* Find desktop window */
\r
233 desktop = GetDesktopWindow();
\r
234 if (! desktop) return;
\r
236 /* Find desktop window size */
\r
237 if (! GetWindowRect(desktop, &desktop_size)) return;
\r
239 /* Centre window */
\r
240 x = (desktop_size.right - size.right) / 2;
\r
241 y = (desktop_size.bottom - size.bottom) / 2;
\r
242 MoveWindow(window, x, y, size.right - size.left, size.bottom - size.top, 0);
\r
245 static inline void check_stop_method(nssm_service_t *service, unsigned long method, unsigned long control) {
\r
246 if (SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], control, BM_GETCHECK, 0, 0) & BST_CHECKED) return;
\r
247 service->stop_method &= ~method;
\r
250 static inline void check_number(HWND tab, unsigned long control, unsigned long *timeout) {
\r
252 unsigned long configured = GetDlgItemInt(tab, control, &translated, 0);
\r
253 if (translated) *timeout = configured;
\r
256 static inline void set_timeout_enabled(unsigned long control, unsigned long dependent) {
\r
257 unsigned char enabled = 0;
\r
258 if (SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], control, BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 1;
\r
259 EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], dependent), enabled);
\r
262 static inline void set_logon_enabled(unsigned char enabled) {
\r
263 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_INTERACT), ! enabled);
\r
264 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_USERNAME), enabled);
\r
265 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1), enabled);
\r
266 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2), enabled);
\r
269 static inline void set_affinity_enabled(unsigned char enabled) {
\r
270 EnableWindow(GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY), enabled);
\r
273 static inline void set_rotation_enabled(unsigned char enabled) {
\r
274 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE), enabled);
\r
275 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS), enabled);
\r
276 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW), enabled);
\r
279 static inline void check_io(HWND owner, TCHAR *name, TCHAR *buffer, unsigned long len, unsigned long control) {
\r
280 if (! SendMessage(GetDlgItem(tablist[NSSM_TAB_IO], control), WM_GETTEXTLENGTH, 0, 0)) return;
\r
281 if (GetDlgItemText(tablist[NSSM_TAB_IO], control, buffer, (int) len)) return;
\r
282 popup_message(owner, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, name);
\r
283 ZeroMemory(buffer, len * sizeof(TCHAR));
\r
286 /* Set service parameters. */
\r
287 int configure(HWND window, nssm_service_t *service, nssm_service_t *orig_service) {
\r
288 if (! service) return 1;
\r
290 set_nssm_service_defaults(service);
\r
292 if (orig_service) {
\r
293 service->native = orig_service->native;
\r
294 service->handle = orig_service->handle;
\r
297 /* Get service name. */
\r
298 if (! GetDlgItemText(window, IDC_NAME, service->name, _countof(service->name))) {
\r
299 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_SERVICE_NAME);
\r
300 cleanup_nssm_service(service);
\r
304 /* Get executable name */
\r
305 if (! service->native) {
\r
306 if (! GetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_PATH, service->exe, _countof(service->exe))) {
\r
307 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PATH);
\r
311 /* Get startup directory. */
\r
312 if (! GetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_DIR, service->dir, _countof(service->dir))) {
\r
313 _sntprintf_s(service->dir, _countof(service->dir), _TRUNCATE, _T("%s"), service->exe);
\r
314 strip_basename(service->dir);
\r
318 if (SendMessage(GetDlgItem(tablist[NSSM_TAB_APPLICATION], IDC_FLAGS), WM_GETTEXTLENGTH, 0, 0)) {
\r
319 if (! GetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_FLAGS, service->flags, _countof(service->flags))) {
\r
320 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_OPTIONS);
\r
327 if (SendMessage(GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_DISPLAYNAME), WM_GETTEXTLENGTH, 0, 0)) {
\r
328 if (! GetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DISPLAYNAME, service->displayname, _countof(service->displayname))) {
\r
329 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DISPLAYNAME);
\r
334 if (SendMessage(GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_DESCRIPTION), WM_GETTEXTLENGTH, 0, 0)) {
\r
335 if (! GetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DESCRIPTION, service->description, _countof(service->description))) {
\r
336 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DESCRIPTION);
\r
341 HWND combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP);
\r
342 service->startup = (unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0);
\r
343 if (service->startup == CB_ERR) service->startup = 0;
\r
345 /* Get logon stuff. */
\r
346 if (SendDlgItemMessage(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
347 if (SendDlgItemMessage(tablist[NSSM_TAB_LOGON], IDC_INTERACT, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
348 service->type |= SERVICE_INTERACTIVE_PROCESS;
\r
350 if (service->username) HeapFree(GetProcessHeap(), 0, service->username);
\r
351 service->username = 0;
\r
352 service->usernamelen = 0;
\r
353 if (service->password) {
\r
354 SecureZeroMemory(service->password, service->passwordlen);
\r
355 HeapFree(GetProcessHeap(), 0, service->password);
\r
357 service->password = 0;
\r
358 service->passwordlen = 0;
\r
362 service->usernamelen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_USERNAME), WM_GETTEXTLENGTH, 0, 0);
\r
363 if (! service->usernamelen) {
\r
364 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_USERNAME);
\r
367 service->usernamelen++;
\r
369 service->username = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->usernamelen * sizeof(TCHAR));
\r
370 if (! service->username) {
\r
371 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("account name"), _T("install()"));
\r
374 if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_USERNAME, service->username, (int) service->usernamelen)) {
\r
375 HeapFree(GetProcessHeap(), 0, service->username);
\r
376 service->username = 0;
\r
377 service->usernamelen = 0;
\r
378 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_USERNAME);
\r
383 Special case for well-known accounts.
\r
384 Ignore the password if we're editing and the username hasn't changed.
\r
386 const TCHAR *well_known = well_known_username(service->username);
388 if (str_equiv(well_known, NSSM_LOCALSYSTEM_ACCOUNT)) {
389 HeapFree(GetProcessHeap(), 0, service->username);
\r
390 service->username = 0;
\r
391 service->usernamelen = 0;
\r
394 service->usernamelen = _tcslen(well_known) + 1;
395 service->username = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->usernamelen * sizeof(TCHAR));
396 if (! service->username) {
397 print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("canon"), _T("install()"));
400 memmove(service->username, well_known, service->usernamelen * sizeof(TCHAR));
405 service->passwordlen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1), WM_GETTEXTLENGTH, 0, 0);
\r
406 size_t passwordlen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2), WM_GETTEXTLENGTH, 0, 0);
\r
408 if (! orig_service || ! orig_service->username || ! str_equiv(service->username, orig_service->username) || service->passwordlen || passwordlen) {
\r
409 if (! service->passwordlen) {
\r
410 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
413 if (passwordlen != service->passwordlen) {
\r
414 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
417 service->passwordlen++;
\r
419 /* Temporary buffer for password validation. */
\r
420 TCHAR *password = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->passwordlen * sizeof(TCHAR));
\r
422 HeapFree(GetProcessHeap(), 0, service->username);
\r
423 service->username = 0;
\r
424 service->usernamelen = 0;
\r
425 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("password confirmation"), _T("install()"));
\r
429 /* Actual password buffer. */
\r
430 service->password = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->passwordlen * sizeof(TCHAR));
\r
431 if (! service->password) {
\r
432 HeapFree(GetProcessHeap(), 0, password);
\r
433 HeapFree(GetProcessHeap(), 0, service->username);
\r
434 service->username = 0;
\r
435 service->usernamelen = 0;
\r
436 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("password"), _T("install()"));
\r
440 /* Get first password. */
\r
441 if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1, service->password, (int) service->passwordlen)) {
\r
442 HeapFree(GetProcessHeap(), 0, password);
\r
443 SecureZeroMemory(service->password, service->passwordlen);
\r
444 HeapFree(GetProcessHeap(), 0, service->password);
\r
445 service->password = 0;
\r
446 service->passwordlen = 0;
\r
447 HeapFree(GetProcessHeap(), 0, service->username);
\r
448 service->username = 0;
\r
449 service->usernamelen = 0;
\r
450 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_PASSWORD);
\r
454 /* Get confirmation. */
\r
455 if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2, password, (int) service->passwordlen)) {
\r
456 SecureZeroMemory(password, service->passwordlen);
\r
457 HeapFree(GetProcessHeap(), 0, password);
\r
458 SecureZeroMemory(service->password, service->passwordlen);
\r
459 HeapFree(GetProcessHeap(), 0, service->password);
\r
460 service->password = 0;
\r
461 service->passwordlen = 0;
\r
462 HeapFree(GetProcessHeap(), 0, service->username);
\r
463 service->username = 0;
\r
464 service->usernamelen = 0;
\r
465 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_PASSWORD);
\r
470 if (_tcsncmp(password, service->password, service->passwordlen)) {
\r
471 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
472 SecureZeroMemory(password, service->passwordlen);
\r
473 HeapFree(GetProcessHeap(), 0, password);
\r
474 SecureZeroMemory(service->password, service->passwordlen);
\r
475 HeapFree(GetProcessHeap(), 0, service->password);
\r
476 service->password = 0;
\r
477 service->passwordlen = 0;
\r
478 HeapFree(GetProcessHeap(), 0, service->username);
\r
479 service->username = 0;
\r
480 service->usernamelen = 0;
\r
487 /* Get dependencies. */
\r
488 unsigned long dependencieslen = (unsigned long) SendMessage(GetDlgItem(tablist[NSSM_TAB_DEPENDENCIES], IDC_DEPENDENCIES), WM_GETTEXTLENGTH, 0, 0);
\r
489 if (dependencieslen) {
\r
490 TCHAR *dependencies = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (dependencieslen + 2) * sizeof(TCHAR));
\r
491 if (! dependencies) {
\r
492 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("dependencies"), _T("install()"));
\r
493 cleanup_nssm_service(service);
\r
497 if (! GetDlgItemText(tablist[NSSM_TAB_DEPENDENCIES], IDC_DEPENDENCIES, dependencies, dependencieslen + 1)) {
\r
498 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DEPENDENCIES);
\r
499 HeapFree(GetProcessHeap(), 0, dependencies);
\r
500 cleanup_nssm_service(service);
\r
504 if (unformat_double_null(dependencies, dependencieslen, &service->dependencies, &service->dependencieslen)) {
\r
505 HeapFree(GetProcessHeap(), 0, dependencies);
\r
506 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("dependencies"), _T("install()"));
\r
507 cleanup_nssm_service(service);
\r
511 HeapFree(GetProcessHeap(), 0, dependencies);
\r
514 /* Remaining tabs are only for services we manage. */
\r
515 if (service->native) return 0;
\r
517 /* Get process stuff. */
\r
518 combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY);
\r
519 service->priority = priority_index_to_constant((unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0));
\r
521 service->affinity = 0LL;
\r
522 if (! (SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_GETCHECK, 0, 0) & BST_CHECKED)) {
\r
523 HWND list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY);
\r
524 int selected = (int) SendMessage(list, LB_GETSELCOUNT, 0, 0);
\r
525 int count = (int) SendMessage(list, LB_GETCOUNT, 0, 0);
\r
527 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_WARN_AFFINITY_NONE);
\r
530 else if (selected < count) {
\r
531 for (int i = 0; i < count; i++) {
\r
532 if (SendMessage(list, LB_GETSEL, i, 0)) service->affinity |= (1LL << (__int64) i);
\r
537 if (SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_GETCHECK, 0, 0) & BST_CHECKED) service->no_console = 0;
538 else service->no_console = 1;
540 /* Get stop method stuff. */
\r
541 check_stop_method(service, NSSM_STOP_METHOD_CONSOLE, IDC_METHOD_CONSOLE);
\r
542 check_stop_method(service, NSSM_STOP_METHOD_WINDOW, IDC_METHOD_WINDOW);
\r
543 check_stop_method(service, NSSM_STOP_METHOD_THREADS, IDC_METHOD_THREADS);
\r
544 check_stop_method(service, NSSM_STOP_METHOD_TERMINATE, IDC_METHOD_TERMINATE);
\r
545 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, &service->kill_console_delay);
\r
546 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, &service->kill_window_delay);
\r
547 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, &service->kill_threads_delay);
\r
549 /* Get exit action stuff. */
\r
550 check_number(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, &service->throttle_delay);
\r
551 combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
\r
552 service->default_exit_action = (unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0);
\r
553 if (service->default_exit_action == CB_ERR) service->default_exit_action = 0;
\r
554 check_number(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, &service->restart_delay);
\r
556 /* Get I/O stuff. */
\r
557 check_io(window, _T("stdin"), service->stdin_path, _countof(service->stdin_path), IDC_STDIN);
\r
558 check_io(window, _T("stdout"), service->stdout_path, _countof(service->stdout_path), IDC_STDOUT);
\r
559 check_io(window, _T("stderr"), service->stderr_path, _countof(service->stderr_path), IDC_STDERR);
\r
561 /* Override stdout and/or stderr. */
\r
562 if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_TRUNCATE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
563 if (service->stdout_path[0]) service->stdout_disposition = CREATE_ALWAYS;
\r
564 if (service->stderr_path[0]) service->stderr_disposition = CREATE_ALWAYS;
\r
567 /* Get rotation stuff. */
\r
568 if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
569 service->rotate_files = true;
\r
570 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;
571 check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, &service->rotate_seconds);
\r
572 check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, &service->rotate_bytes_low);
\r
575 /* Get environment. */
\r
576 unsigned long envlen = (unsigned long) SendMessage(GetDlgItem(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT), WM_GETTEXTLENGTH, 0, 0);
\r
578 TCHAR *env = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (envlen + 2) * sizeof(TCHAR));
\r
580 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("install()"));
\r
581 cleanup_nssm_service(service);
\r
585 if (! GetDlgItemText(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT, env, envlen + 1)) {
\r
586 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT);
\r
587 HeapFree(GetProcessHeap(), 0, env);
\r
588 cleanup_nssm_service(service);
\r
593 unsigned long newlen;
\r
594 if (unformat_double_null(env, envlen, &newenv, &newlen)) {
\r
595 HeapFree(GetProcessHeap(), 0, env);
\r
596 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("install()"));
\r
597 cleanup_nssm_service(service);
\r
601 HeapFree(GetProcessHeap(), 0, env);
\r
605 /* Test the environment is valid. */
\r
606 if (test_environment(env)) {
\r
607 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT);
\r
608 HeapFree(GetProcessHeap(), 0, env);
\r
609 cleanup_nssm_service(service);
\r
613 if (SendDlgItemMessage(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT_REPLACE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
614 service->env = env;
\r
615 service->envlen = envlen;
\r
618 service->env_extra = env;
\r
619 service->env_extralen = envlen;
\r
626 /* Install the service. */
\r
627 int install(HWND window) {
\r
628 if (! window) return 1;
\r
630 nssm_service_t *service = alloc_nssm_service();
\r
632 int ret = configure(window, service, 0);
\r
633 if (ret) return ret;
\r
636 /* See if it works. */
\r
637 switch (install_service(service)) {
\r
639 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("install()"));
\r
640 cleanup_nssm_service(service);
\r
644 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);
\r
645 cleanup_nssm_service(service);
\r
649 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, NSSM);
\r
650 cleanup_nssm_service(service);
\r
654 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_OUT_OF_MEMORY_FOR_IMAGEPATH);
\r
655 cleanup_nssm_service(service);
\r
659 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INSTALL_SERVICE_FAILED);
\r
660 cleanup_nssm_service(service);
\r
664 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_CREATE_PARAMETERS_FAILED);
\r
665 cleanup_nssm_service(service);
\r
669 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_INSTALLED, service->name);
\r
670 cleanup_nssm_service(service);
\r
674 /* Remove the service */
\r
675 int remove(HWND window) {
\r
676 if (! window) return 1;
\r
678 /* See if it works */
\r
679 nssm_service_t *service = alloc_nssm_service();
\r
681 /* Get service name */
\r
682 if (! GetDlgItemText(window, IDC_NAME, service->name, _countof(service->name))) {
\r
683 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_SERVICE_NAME);
\r
684 cleanup_nssm_service(service);
\r
689 if (popup_message(window, MB_YESNO, NSSM_GUI_ASK_REMOVE_SERVICE, service->name) != IDYES) {
\r
690 cleanup_nssm_service(service);
\r
695 switch (remove_service(service)) {
\r
697 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("remove()"));
\r
698 cleanup_nssm_service(service);
\r
702 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);
\r
703 cleanup_nssm_service(service);
\r
707 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_SERVICE_NOT_INSTALLED);
\r
709 cleanup_nssm_service(service);
\r
712 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_REMOVE_SERVICE_FAILED);
\r
713 cleanup_nssm_service(service);
\r
717 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_REMOVED, service->name);
\r
718 cleanup_nssm_service(service);
\r
722 int edit(HWND window, nssm_service_t *orig_service) {
\r
723 if (! window) return 1;
\r
725 nssm_service_t *service = alloc_nssm_service();
\r
727 int ret = configure(window, service, orig_service);
\r
728 if (ret) return ret;
\r
731 switch (edit_service(service, true)) {
\r
733 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("edit()"));
\r
734 cleanup_nssm_service(service);
\r
738 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, NSSM);
\r
739 cleanup_nssm_service(service);
\r
743 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_OUT_OF_MEMORY_FOR_IMAGEPATH);
\r
744 cleanup_nssm_service(service);
\r
749 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_EDIT_PARAMETERS_FAILED);
\r
750 cleanup_nssm_service(service);
\r
754 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_EDITED, service->name);
\r
755 cleanup_nssm_service(service);
\r
759 static TCHAR *browse_filter(int message) {
\r
761 case NSSM_GUI_BROWSE_FILTER_APPLICATIONS: return _T("*.exe;*.bat;*.cmd");
\r
762 case NSSM_GUI_BROWSE_FILTER_DIRECTORIES: return _T(".");
\r
763 case NSSM_GUI_BROWSE_FILTER_ALL_FILES: /* Fall through. */
\r
764 default: return _T("*.*");
\r
768 UINT_PTR CALLBACK browse_hook(HWND dlg, UINT message, WPARAM w, LPARAM l) {
\r
770 case WM_INITDIALOG:
\r
777 /* Browse for application */
\r
778 void browse(HWND window, TCHAR *current, unsigned long flags, ...) {
\r
779 if (! window) return;
\r
782 size_t bufsize = 256;
\r
783 size_t len = bufsize;
\r
787 ZeroMemory(&ofn, sizeof(ofn));
\r
788 ofn.lStructSize = sizeof(ofn);
\r
789 ofn.lpstrFilter = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, bufsize * sizeof(TCHAR));
\r
790 /* XXX: Escaping nulls with FormatMessage is tricky */
\r
791 if (ofn.lpstrFilter) {
\r
792 ZeroMemory((void *) ofn.lpstrFilter, bufsize);
\r
794 /* "Applications" + NULL + "*.exe" + NULL */
\r
795 va_start(arg, flags);
\r
796 while (i = va_arg(arg, int)) {
\r
797 TCHAR *localised = message_string(i);
\r
798 _sntprintf_s((TCHAR *) ofn.lpstrFilter + len, bufsize, _TRUNCATE, localised);
\r
799 len += _tcslen(localised) + 1;
\r
800 LocalFree(localised);
\r
801 TCHAR *filter = browse_filter(i);
\r
802 _sntprintf_s((TCHAR *) ofn.lpstrFilter + len, bufsize - len, _TRUNCATE, _T("%s"), filter);
\r
803 len += _tcslen(filter) + 1;
\r
806 /* Remainder of the buffer is already zeroed */
\r
808 ofn.lpstrFile = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, PATH_LENGTH * sizeof(TCHAR));
\r
810 if (flags & OFN_NOVALIDATE) {
\r
811 /* Directory hack. */
\r
812 _sntprintf_s(ofn.lpstrFile, PATH_LENGTH, _TRUNCATE, _T(":%s:"), message_string(NSSM_GUI_BROWSE_FILTER_DIRECTORIES));
\r
813 ofn.nMaxFile = DIR_LENGTH;
\r
816 _sntprintf_s(ofn.lpstrFile, PATH_LENGTH, _TRUNCATE, _T("%s"), current);
\r
817 ofn.nMaxFile = PATH_LENGTH;
\r
820 ofn.lpstrTitle = message_string(NSSM_GUI_BROWSE_TITLE);
\r
821 ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | flags;
\r
823 if (GetOpenFileName(&ofn)) {
\r
824 /* Directory hack. */
\r
825 if (flags & OFN_NOVALIDATE) strip_basename(ofn.lpstrFile);
\r
826 SendMessage(window, WM_SETTEXT, 0, (LPARAM) ofn.lpstrFile);
\r
828 if (ofn.lpstrFilter) HeapFree(GetProcessHeap(), 0, (void *) ofn.lpstrFilter);
\r
829 if (ofn.lpstrFile) HeapFree(GetProcessHeap(), 0, ofn.lpstrFile);
832 INT_PTR CALLBACK tab_dlg(HWND tab, UINT message, WPARAM w, LPARAM l) {
\r
834 case WM_INITDIALOG:
\r
837 /* Button was pressed or control was controlled. */
\r
840 TCHAR buffer[PATH_LENGTH];
\r
841 unsigned char enabled;
\r
843 switch (LOWORD(w)) {
\r
844 /* Browse for application. */
\r
846 dlg = GetDlgItem(tab, IDC_PATH);
\r
847 GetDlgItemText(tab, IDC_PATH, buffer, _countof(buffer));
\r
848 browse(dlg, buffer, OFN_FILEMUSTEXIST, NSSM_GUI_BROWSE_FILTER_APPLICATIONS, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
849 /* Fill in startup directory if it wasn't already specified. */
\r
850 GetDlgItemText(tab, IDC_DIR, buffer, _countof(buffer));
\r
852 GetDlgItemText(tab, IDC_PATH, buffer, _countof(buffer));
\r
853 strip_basename(buffer);
\r
854 SetDlgItemText(tab, IDC_DIR, buffer);
\r
858 /* Browse for startup directory. */
\r
859 case IDC_BROWSE_DIR:
\r
860 dlg = GetDlgItem(tab, IDC_DIR);
\r
861 GetDlgItemText(tab, IDC_DIR, buffer, _countof(buffer));
\r
862 browse(dlg, buffer, OFN_NOVALIDATE, NSSM_GUI_BROWSE_FILTER_DIRECTORIES, 0);
\r
866 case IDC_LOCALSYSTEM:
\r
867 set_logon_enabled(0);
\r
871 set_logon_enabled(1);
\r
875 case IDC_AFFINITY_ALL:
\r
876 if (SendDlgItemMessage(tab, LOWORD(w), BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 0;
\r
878 set_affinity_enabled(enabled);
\r
881 /* Shutdown methods. */
\r
882 case IDC_METHOD_CONSOLE:
\r
883 set_timeout_enabled(LOWORD(w), IDC_KILL_CONSOLE);
\r
886 case IDC_METHOD_WINDOW:
\r
887 set_timeout_enabled(LOWORD(w), IDC_KILL_WINDOW);
\r
890 case IDC_METHOD_THREADS:
\r
891 set_timeout_enabled(LOWORD(w), IDC_KILL_THREADS);
\r
894 /* Browse for stdin. */
\r
895 case IDC_BROWSE_STDIN:
\r
896 dlg = GetDlgItem(tab, IDC_STDIN);
\r
897 GetDlgItemText(tab, IDC_STDIN, buffer, _countof(buffer));
\r
898 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
901 /* Browse for stdout. */
\r
902 case IDC_BROWSE_STDOUT:
\r
903 dlg = GetDlgItem(tab, IDC_STDOUT);
\r
904 GetDlgItemText(tab, IDC_STDOUT, buffer, _countof(buffer));
\r
905 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
906 /* Fill in stderr if it wasn't already specified. */
\r
907 GetDlgItemText(tab, IDC_STDERR, buffer, _countof(buffer));
\r
909 GetDlgItemText(tab, IDC_STDOUT, buffer, _countof(buffer));
\r
910 SetDlgItemText(tab, IDC_STDERR, buffer);
\r
914 /* Browse for stderr. */
\r
915 case IDC_BROWSE_STDERR:
\r
916 dlg = GetDlgItem(tab, IDC_STDERR);
\r
917 GetDlgItemText(tab, IDC_STDERR, buffer, _countof(buffer));
\r
918 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
923 if (SendDlgItemMessage(tab, LOWORD(w), BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 1;
\r
925 set_rotation_enabled(enabled);
\r
934 /* Install/remove dialogue callback */
\r
935 INT_PTR CALLBACK nssm_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {
\r
936 nssm_service_t *service;
\r
939 /* Creating the dialogue */
\r
940 case WM_INITDIALOG:
\r
941 service = (nssm_service_t *) l;
\r
943 SetFocus(GetDlgItem(window, IDC_NAME));
\r
949 tabs = GetDlgItem(window, IDC_TAB1);
\r
950 if (! tabs) return 0;
\r
954 ZeroMemory(&tab, sizeof(tab));
\r
955 tab.mask = TCIF_TEXT;
\r
959 /* Application tab. */
\r
960 if (service->native) tab.pszText = message_string(NSSM_GUI_TAB_NATIVE);
\r
961 else tab.pszText = message_string(NSSM_GUI_TAB_APPLICATION);
\r
962 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
963 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_APPLICATION, (LPARAM) &tab);
\r
964 if (service->native) {
\r
965 tablist[NSSM_TAB_APPLICATION] = dialog(MAKEINTRESOURCE(IDD_NATIVE), window, tab_dlg);
\r
966 EnableWindow(tablist[NSSM_TAB_APPLICATION], 0);
\r
967 EnableWindow(GetDlgItem(tablist[NSSM_TAB_APPLICATION], IDC_PATH), 0);
\r
969 else tablist[NSSM_TAB_APPLICATION] = dialog(MAKEINTRESOURCE(IDD_APPLICATION), window, tab_dlg);
\r
970 ShowWindow(tablist[NSSM_TAB_APPLICATION], SW_SHOW);
\r
973 tab.pszText = message_string(NSSM_GUI_TAB_DETAILS);
\r
974 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
975 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_DETAILS, (LPARAM) &tab);
\r
976 tablist[NSSM_TAB_DETAILS] = dialog(MAKEINTRESOURCE(IDD_DETAILS), window, tab_dlg);
\r
977 ShowWindow(tablist[NSSM_TAB_DETAILS], SW_HIDE);
\r
979 /* Set defaults. */
\r
980 combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP);
\r
981 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_AUTOMATIC, (LPARAM) message_string(NSSM_GUI_STARTUP_AUTOMATIC));
\r
982 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DELAYED, (LPARAM) message_string(NSSM_GUI_STARTUP_DELAYED));
\r
983 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_MANUAL, (LPARAM) message_string(NSSM_GUI_STARTUP_MANUAL));
\r
984 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DISABLED, (LPARAM) message_string(NSSM_GUI_STARTUP_DISABLED));
\r
985 SendMessage(combo, CB_SETCURSEL, NSSM_STARTUP_AUTOMATIC, 0);
\r
988 tab.pszText = message_string(NSSM_GUI_TAB_LOGON);
\r
989 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
990 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_LOGON, (LPARAM) &tab);
\r
991 tablist[NSSM_TAB_LOGON] = dialog(MAKEINTRESOURCE(IDD_LOGON), window, tab_dlg);
\r
992 ShowWindow(tablist[NSSM_TAB_LOGON], SW_HIDE);
\r
994 /* Set defaults. */
\r
995 CheckRadioButton(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, IDC_ACCOUNT, IDC_LOCALSYSTEM);
\r
996 set_logon_enabled(0);
\r
998 /* Dependencies tab. */
999 tab.pszText = message_string(NSSM_GUI_TAB_DEPENDENCIES);
\r
1000 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1001 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_DEPENDENCIES, (LPARAM) &tab);
\r
1002 tablist[NSSM_TAB_DEPENDENCIES] = dialog(MAKEINTRESOURCE(IDD_DEPENDENCIES), window, tab_dlg);
\r
1003 ShowWindow(tablist[NSSM_TAB_DEPENDENCIES], SW_HIDE);
\r
1005 /* Remaining tabs are only for services we manage. */
\r
1006 if (service->native) return 1;
\r
1008 /* Process tab. */
\r
1009 tab.pszText = message_string(NSSM_GUI_TAB_PROCESS);
\r
1010 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1011 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_PROCESS, (LPARAM) &tab);
\r
1012 tablist[NSSM_TAB_PROCESS] = dialog(MAKEINTRESOURCE(IDD_PROCESS), window, tab_dlg);
\r
1013 ShowWindow(tablist[NSSM_TAB_PROCESS], SW_HIDE);
\r
1015 /* Set defaults. */
\r
1016 combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY);
\r
1017 SendMessage(combo, CB_INSERTSTRING, NSSM_REALTIME_PRIORITY, (LPARAM) message_string(NSSM_GUI_REALTIME_PRIORITY_CLASS));
\r
1018 SendMessage(combo, CB_INSERTSTRING, NSSM_HIGH_PRIORITY, (LPARAM) message_string(NSSM_GUI_HIGH_PRIORITY_CLASS));
\r
1019 SendMessage(combo, CB_INSERTSTRING, NSSM_ABOVE_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_ABOVE_NORMAL_PRIORITY_CLASS));
\r
1020 SendMessage(combo, CB_INSERTSTRING, NSSM_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_NORMAL_PRIORITY_CLASS));
\r
1021 SendMessage(combo, CB_INSERTSTRING, NSSM_BELOW_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_BELOW_NORMAL_PRIORITY_CLASS));
\r
1022 SendMessage(combo, CB_INSERTSTRING, NSSM_IDLE_PRIORITY, (LPARAM) message_string(NSSM_GUI_IDLE_PRIORITY_CLASS));
\r
1023 SendMessage(combo, CB_SETCURSEL, NSSM_NORMAL_PRIORITY, 0);
\r
1025 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_SETCHECK, BST_CHECKED, 0);
\r
1027 list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY);
\r
1029 SendMessage(list, LB_SETCOLUMNWIDTH, 16, 0);
\r
1030 for (i = 0; i < n; i++) {
\r
1032 _sntprintf_s(buffer, _countof(buffer), _TRUNCATE, _T("%d"), i);
\r
1033 SendMessage(list, LB_ADDSTRING, 0, (LPARAM) buffer);
\r
1038 The box is high enough for four rows. It is wide enough for eight
\r
1039 columns without scrolling. With scrollbars it shrinks to two rows.
\r
1040 Note that the above only holds if we set the column width BEFORE
1044 int columns = (n - 1) / 4;
\r
1046 GetWindowRect(list, &rect);
\r
1047 int width = rect.right - rect.left;
1048 width -= (7 - columns) * 16;
\r
1049 int height = rect.bottom - rect.top;
\r
1050 if (n < 4) height -= (int) SendMessage(list, LB_GETITEMHEIGHT, 0, 0) * (4 - n);
1051 SetWindowPos(list, 0, 0, 0, width, height, SWP_NOMOVE | SWP_NOOWNERZORDER);
\r
1053 SendMessage(list, LB_SELITEMRANGE, 1, MAKELPARAM(0, n));
\r
1055 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_SETCHECK, BST_CHECKED, 0);
\r
1056 set_affinity_enabled(0);
\r
1058 /* Shutdown tab. */
\r
1059 tab.pszText = message_string(NSSM_GUI_TAB_SHUTDOWN);
\r
1060 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1061 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_SHUTDOWN, (LPARAM) &tab);
\r
1062 tablist[NSSM_TAB_SHUTDOWN] = dialog(MAKEINTRESOURCE(IDD_SHUTDOWN), window, tab_dlg);
\r
1063 ShowWindow(tablist[NSSM_TAB_SHUTDOWN], SW_HIDE);
\r
1065 /* Set defaults. */
\r
1066 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_CONSOLE, BM_SETCHECK, BST_CHECKED, 0);
\r
1067 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, NSSM_KILL_CONSOLE_GRACE_PERIOD, 0);
\r
1068 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_WINDOW, BM_SETCHECK, BST_CHECKED, 0);
\r
1069 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, NSSM_KILL_WINDOW_GRACE_PERIOD, 0);
\r
1070 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_THREADS, BM_SETCHECK, BST_CHECKED, 0);
\r
1071 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, NSSM_KILL_THREADS_GRACE_PERIOD, 0);
\r
1072 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_TERMINATE, BM_SETCHECK, BST_CHECKED, 0);
\r
1074 /* Restart tab. */
\r
1075 tab.pszText = message_string(NSSM_GUI_TAB_EXIT);
\r
1076 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1077 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_EXIT, (LPARAM) &tab);
\r
1078 tablist[NSSM_TAB_EXIT] = dialog(MAKEINTRESOURCE(IDD_APPEXIT), window, tab_dlg);
\r
1079 ShowWindow(tablist[NSSM_TAB_EXIT], SW_HIDE);
\r
1081 /* Set defaults. */
\r
1082 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, NSSM_RESET_THROTTLE_RESTART, 0);
\r
1083 combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
\r
1084 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_RESTART, (LPARAM) message_string(NSSM_GUI_EXIT_RESTART));
\r
1085 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_IGNORE, (LPARAM) message_string(NSSM_GUI_EXIT_IGNORE));
\r
1086 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_REALLY, (LPARAM) message_string(NSSM_GUI_EXIT_REALLY));
\r
1087 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_UNCLEAN, (LPARAM) message_string(NSSM_GUI_EXIT_UNCLEAN));
\r
1088 SendMessage(combo, CB_SETCURSEL, NSSM_EXIT_RESTART, 0);
\r
1089 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, 0, 0);
\r
1092 tab.pszText = message_string(NSSM_GUI_TAB_IO);
\r
1093 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1094 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_IO, (LPARAM) &tab);
\r
1095 tablist[NSSM_TAB_IO] = dialog(MAKEINTRESOURCE(IDD_IO), window, tab_dlg);
\r
1096 ShowWindow(tablist[NSSM_TAB_IO], SW_HIDE);
\r
1098 /* Rotation tab. */
\r
1099 tab.pszText = message_string(NSSM_GUI_TAB_ROTATION);
\r
1100 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1101 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_ROTATION, (LPARAM) &tab);
\r
1102 tablist[NSSM_TAB_ROTATION] = dialog(MAKEINTRESOURCE(IDD_ROTATION), window, tab_dlg);
\r
1103 ShowWindow(tablist[NSSM_TAB_ROTATION], SW_HIDE);
\r
1105 /* Set defaults. */
\r
1106 SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_SETCHECK, BST_UNCHECKED, 0);
\r
1107 SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, 0, 0);
\r
1108 SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, 0, 0);
\r
1109 set_rotation_enabled(0);
\r
1111 /* Environment tab. */
\r
1112 tab.pszText = message_string(NSSM_GUI_TAB_ENVIRONMENT);
\r
1113 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1114 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_ENVIRONMENT, (LPARAM) &tab);
\r
1115 tablist[NSSM_TAB_ENVIRONMENT] = dialog(MAKEINTRESOURCE(IDD_ENVIRONMENT), window, tab_dlg);
\r
1116 ShowWindow(tablist[NSSM_TAB_ENVIRONMENT], SW_HIDE);
\r
1122 NMHDR *notification;
\r
1124 notification = (NMHDR *) l;
\r
1125 switch (notification->code) {
\r
1126 case TCN_SELCHANGE:
\r
1130 tabs = GetDlgItem(window, IDC_TAB1);
\r
1131 if (! tabs) return 0;
\r
1133 selection = (int) SendMessage(tabs, TCM_GETCURSEL, 0, 0);
\r
1134 if (selection != selected_tab) {
\r
1135 ShowWindow(tablist[selected_tab], SW_HIDE);
\r
1136 ShowWindow(tablist[selection], SW_SHOWDEFAULT);
\r
1137 SetFocus(GetDlgItem(window, IDOK));
\r
1138 selected_tab = selection;
\r
1145 /* Button was pressed or control was controlled */
\r
1147 switch (LOWORD(w)) {
\r
1150 if ((int) GetWindowLongPtr(window, GWLP_USERDATA) == IDD_EDIT) {
\r
1151 if (! edit(window, (nssm_service_t *) GetWindowLongPtr(window, DWLP_USER))) PostQuitMessage(0);
\r
1153 else if (! install(window)) PostQuitMessage(0);
\r
1156 /* Cancel button */
\r
1158 DestroyWindow(window);
\r
1161 /* Remove button */
\r
1163 if (! remove(window)) PostQuitMessage(0);
\r
1168 /* Window closing */
\r
1170 DestroyWindow(window);
\r
1173 PostQuitMessage(0);
\r