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 LOCALSYSTEM.
\r
371 Ignore the password if we're editing and the username hasn't changed.
\r
373 if (str_equiv(service->username, NSSM_LOCALSYSTEM_ACCOUNT)) {
\r
374 HeapFree(GetProcessHeap(), 0, service->username);
\r
375 service->username = 0;
\r
376 service->usernamelen = 0;
\r
380 service->passwordlen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1), WM_GETTEXTLENGTH, 0, 0);
\r
381 size_t passwordlen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2), WM_GETTEXTLENGTH, 0, 0);
\r
383 if (! orig_service || ! orig_service->username || ! str_equiv(service->username, orig_service->username) || service->passwordlen || passwordlen) {
\r
384 if (! service->passwordlen) {
\r
385 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
388 if (passwordlen != service->passwordlen) {
\r
389 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
392 service->passwordlen++;
\r
394 /* Temporary buffer for password validation. */
\r
395 TCHAR *password = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->passwordlen * sizeof(TCHAR));
\r
397 HeapFree(GetProcessHeap(), 0, service->username);
\r
398 service->username = 0;
\r
399 service->usernamelen = 0;
\r
400 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("password confirmation"), _T("install()"));
\r
404 /* Actual password buffer. */
\r
405 service->password = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->passwordlen * sizeof(TCHAR));
\r
406 if (! service->password) {
\r
407 HeapFree(GetProcessHeap(), 0, password);
\r
408 HeapFree(GetProcessHeap(), 0, service->username);
\r
409 service->username = 0;
\r
410 service->usernamelen = 0;
\r
411 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("password"), _T("install()"));
\r
415 /* Get first password. */
\r
416 if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1, service->password, (int) service->passwordlen)) {
\r
417 HeapFree(GetProcessHeap(), 0, password);
\r
418 SecureZeroMemory(service->password, service->passwordlen);
\r
419 HeapFree(GetProcessHeap(), 0, service->password);
\r
420 service->password = 0;
\r
421 service->passwordlen = 0;
\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_GUI_INVALID_PASSWORD);
\r
429 /* Get confirmation. */
\r
430 if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2, password, (int) service->passwordlen)) {
\r
431 SecureZeroMemory(password, service->passwordlen);
\r
432 HeapFree(GetProcessHeap(), 0, password);
\r
433 SecureZeroMemory(service->password, service->passwordlen);
\r
434 HeapFree(GetProcessHeap(), 0, service->password);
\r
435 service->password = 0;
\r
436 service->passwordlen = 0;
\r
437 HeapFree(GetProcessHeap(), 0, service->username);
\r
438 service->username = 0;
\r
439 service->usernamelen = 0;
\r
440 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_PASSWORD);
\r
445 if (_tcsncmp(password, service->password, service->passwordlen)) {
\r
446 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
447 SecureZeroMemory(password, service->passwordlen);
\r
448 HeapFree(GetProcessHeap(), 0, password);
\r
449 SecureZeroMemory(service->password, service->passwordlen);
\r
450 HeapFree(GetProcessHeap(), 0, service->password);
\r
451 service->password = 0;
\r
452 service->passwordlen = 0;
\r
453 HeapFree(GetProcessHeap(), 0, service->username);
\r
454 service->username = 0;
\r
455 service->usernamelen = 0;
\r
462 /* Remaining tabs are only for services we manage. */
\r
463 if (service->native) return 0;
\r
465 /* Get process stuff. */
\r
466 combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY);
\r
467 service->priority = priority_index_to_constant((unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0));
\r
469 service->affinity = 0LL;
\r
470 if (! (SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_GETCHECK, 0, 0) & BST_CHECKED)) {
\r
471 HWND list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY);
\r
472 int selected = (int) SendMessage(list, LB_GETSELCOUNT, 0, 0);
\r
473 int count = (int) SendMessage(list, LB_GETCOUNT, 0, 0);
\r
475 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_WARN_AFFINITY_NONE);
\r
478 else if (selected < count) {
\r
479 for (int i = 0; i < count; i++) {
\r
480 if (SendMessage(list, LB_GETSEL, i, 0)) service->affinity |= (1LL << (__int64) i);
\r
485 if (SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_GETCHECK, 0, 0) & BST_CHECKED) service->no_console = 0;
486 else service->no_console = 1;
488 /* Get stop method stuff. */
\r
489 check_stop_method(service, NSSM_STOP_METHOD_CONSOLE, IDC_METHOD_CONSOLE);
\r
490 check_stop_method(service, NSSM_STOP_METHOD_WINDOW, IDC_METHOD_WINDOW);
\r
491 check_stop_method(service, NSSM_STOP_METHOD_THREADS, IDC_METHOD_THREADS);
\r
492 check_stop_method(service, NSSM_STOP_METHOD_TERMINATE, IDC_METHOD_TERMINATE);
\r
493 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, &service->kill_console_delay);
\r
494 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, &service->kill_window_delay);
\r
495 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, &service->kill_threads_delay);
\r
497 /* Get exit action stuff. */
\r
498 check_number(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, &service->throttle_delay);
\r
499 combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
\r
500 service->default_exit_action = (unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0);
\r
501 if (service->default_exit_action == CB_ERR) service->default_exit_action = 0;
\r
502 check_number(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, &service->restart_delay);
\r
504 /* Get I/O stuff. */
\r
505 check_io(window, _T("stdin"), service->stdin_path, _countof(service->stdin_path), IDC_STDIN);
\r
506 check_io(window, _T("stdout"), service->stdout_path, _countof(service->stdout_path), IDC_STDOUT);
\r
507 check_io(window, _T("stderr"), service->stderr_path, _countof(service->stderr_path), IDC_STDERR);
\r
509 /* Override stdout and/or stderr. */
\r
510 if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_TRUNCATE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
511 if (service->stdout_path[0]) service->stdout_disposition = CREATE_ALWAYS;
\r
512 if (service->stderr_path[0]) service->stderr_disposition = CREATE_ALWAYS;
\r
515 /* Get rotation stuff. */
\r
516 if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
517 service->rotate_files = true;
\r
518 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;
519 check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, &service->rotate_seconds);
\r
520 check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, &service->rotate_bytes_low);
\r
523 /* Get environment. */
\r
524 unsigned long envlen = (unsigned long) SendMessage(GetDlgItem(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT), WM_GETTEXTLENGTH, 0, 0);
\r
526 TCHAR *env = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (envlen + 2) * sizeof(TCHAR));
\r
528 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("install()"));
\r
529 cleanup_nssm_service(service);
\r
533 if (! GetDlgItemText(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT, env, envlen + 1)) {
\r
534 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT);
\r
535 HeapFree(GetProcessHeap(), 0, env);
\r
536 cleanup_nssm_service(service);
\r
541 unsigned long newlen;
\r
542 if (unformat_environment(env, envlen, &newenv, &newlen)) {
\r
543 HeapFree(GetProcessHeap(), 0, env);
\r
544 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("install()"));
\r
545 cleanup_nssm_service(service);
\r
549 HeapFree(GetProcessHeap(), 0, env);
\r
553 /* Test the environment is valid. */
\r
554 if (test_environment(env)) {
\r
555 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT);
\r
556 HeapFree(GetProcessHeap(), 0, env);
\r
557 cleanup_nssm_service(service);
\r
561 if (SendDlgItemMessage(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT_REPLACE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
562 service->env = env;
\r
563 service->envlen = envlen;
\r
566 service->env_extra = env;
\r
567 service->env_extralen = envlen;
\r
574 /* Install the service. */
\r
575 int install(HWND window) {
\r
576 if (! window) return 1;
\r
578 nssm_service_t *service = alloc_nssm_service();
\r
580 int ret = configure(window, service, 0);
\r
581 if (ret) return ret;
\r
584 /* See if it works. */
\r
585 switch (install_service(service)) {
\r
587 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("install()"));
\r
588 cleanup_nssm_service(service);
\r
592 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);
\r
593 cleanup_nssm_service(service);
\r
597 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, NSSM);
\r
598 cleanup_nssm_service(service);
\r
602 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_OUT_OF_MEMORY_FOR_IMAGEPATH);
\r
603 cleanup_nssm_service(service);
\r
607 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INSTALL_SERVICE_FAILED);
\r
608 cleanup_nssm_service(service);
\r
612 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_CREATE_PARAMETERS_FAILED);
\r
613 cleanup_nssm_service(service);
\r
617 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_INSTALLED, service->name);
\r
618 cleanup_nssm_service(service);
\r
622 /* Remove the service */
\r
623 int remove(HWND window) {
\r
624 if (! window) return 1;
\r
626 /* See if it works */
\r
627 nssm_service_t *service = alloc_nssm_service();
\r
629 /* Get service name */
\r
630 if (! GetDlgItemText(window, IDC_NAME, service->name, _countof(service->name))) {
\r
631 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_SERVICE_NAME);
\r
632 cleanup_nssm_service(service);
\r
637 if (popup_message(window, MB_YESNO, NSSM_GUI_ASK_REMOVE_SERVICE, service->name) != IDYES) {
\r
638 cleanup_nssm_service(service);
\r
643 switch (remove_service(service)) {
\r
645 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("remove()"));
\r
646 cleanup_nssm_service(service);
\r
650 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);
\r
651 cleanup_nssm_service(service);
\r
655 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_SERVICE_NOT_INSTALLED);
\r
657 cleanup_nssm_service(service);
\r
660 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_REMOVE_SERVICE_FAILED);
\r
661 cleanup_nssm_service(service);
\r
665 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_REMOVED, service->name);
\r
666 cleanup_nssm_service(service);
\r
670 int edit(HWND window, nssm_service_t *orig_service) {
\r
671 if (! window) return 1;
\r
673 nssm_service_t *service = alloc_nssm_service();
\r
675 int ret = configure(window, service, orig_service);
\r
676 if (ret) return ret;
\r
679 switch (edit_service(service, true)) {
\r
681 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("edit()"));
\r
682 cleanup_nssm_service(service);
\r
686 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, NSSM);
\r
687 cleanup_nssm_service(service);
\r
691 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_OUT_OF_MEMORY_FOR_IMAGEPATH);
\r
692 cleanup_nssm_service(service);
\r
697 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_EDIT_PARAMETERS_FAILED);
\r
698 cleanup_nssm_service(service);
\r
702 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_EDITED, service->name);
\r
703 cleanup_nssm_service(service);
\r
707 static TCHAR *browse_filter(int message) {
\r
709 case NSSM_GUI_BROWSE_FILTER_APPLICATIONS: return _T("*.exe;*.bat;*.cmd");
\r
710 case NSSM_GUI_BROWSE_FILTER_DIRECTORIES: return _T(".");
\r
711 case NSSM_GUI_BROWSE_FILTER_ALL_FILES: /* Fall through. */
\r
712 default: return _T("*.*");
\r
716 UINT_PTR CALLBACK browse_hook(HWND dlg, UINT message, WPARAM w, LPARAM l) {
\r
718 case WM_INITDIALOG:
\r
725 /* Browse for application */
\r
726 void browse(HWND window, TCHAR *current, unsigned long flags, ...) {
\r
727 if (! window) return;
\r
730 size_t bufsize = 256;
\r
731 size_t len = bufsize;
\r
735 ZeroMemory(&ofn, sizeof(ofn));
\r
736 ofn.lStructSize = sizeof(ofn);
\r
737 ofn.lpstrFilter = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, bufsize * sizeof(TCHAR));
\r
738 /* XXX: Escaping nulls with FormatMessage is tricky */
\r
739 if (ofn.lpstrFilter) {
\r
740 ZeroMemory((void *) ofn.lpstrFilter, bufsize);
\r
742 /* "Applications" + NULL + "*.exe" + NULL */
\r
743 va_start(arg, flags);
\r
744 while (i = va_arg(arg, int)) {
\r
745 TCHAR *localised = message_string(i);
\r
746 _sntprintf_s((TCHAR *) ofn.lpstrFilter + len, bufsize, _TRUNCATE, localised);
\r
747 len += _tcslen(localised) + 1;
\r
748 LocalFree(localised);
\r
749 TCHAR *filter = browse_filter(i);
\r
750 _sntprintf_s((TCHAR *) ofn.lpstrFilter + len, bufsize - len, _TRUNCATE, _T("%s"), filter);
\r
751 len += _tcslen(filter) + 1;
\r
754 /* Remainder of the buffer is already zeroed */
\r
756 ofn.lpstrFile = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, PATH_LENGTH * sizeof(TCHAR));
\r
758 if (flags & OFN_NOVALIDATE) {
\r
759 /* Directory hack. */
\r
760 _sntprintf_s(ofn.lpstrFile, PATH_LENGTH, _TRUNCATE, _T(":%s:"), message_string(NSSM_GUI_BROWSE_FILTER_DIRECTORIES));
\r
761 ofn.nMaxFile = DIR_LENGTH;
\r
764 _sntprintf_s(ofn.lpstrFile, PATH_LENGTH, _TRUNCATE, _T("%s"), current);
\r
765 ofn.nMaxFile = PATH_LENGTH;
\r
768 ofn.lpstrTitle = message_string(NSSM_GUI_BROWSE_TITLE);
\r
769 ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | flags;
\r
771 if (GetOpenFileName(&ofn)) {
\r
772 /* Directory hack. */
\r
773 if (flags & OFN_NOVALIDATE) strip_basename(ofn.lpstrFile);
\r
774 SendMessage(window, WM_SETTEXT, 0, (LPARAM) ofn.lpstrFile);
\r
776 if (ofn.lpstrFilter) HeapFree(GetProcessHeap(), 0, (void *) ofn.lpstrFilter);
\r
777 if (ofn.lpstrFile) HeapFree(GetProcessHeap(), 0, ofn.lpstrFile);
780 INT_PTR CALLBACK tab_dlg(HWND tab, UINT message, WPARAM w, LPARAM l) {
\r
782 case WM_INITDIALOG:
\r
785 /* Button was pressed or control was controlled. */
\r
788 TCHAR buffer[PATH_LENGTH];
\r
789 unsigned char enabled;
\r
791 switch (LOWORD(w)) {
\r
792 /* Browse for application. */
\r
794 dlg = GetDlgItem(tab, IDC_PATH);
\r
795 GetDlgItemText(tab, IDC_PATH, buffer, _countof(buffer));
\r
796 browse(dlg, buffer, OFN_FILEMUSTEXIST, NSSM_GUI_BROWSE_FILTER_APPLICATIONS, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
797 /* Fill in startup directory if it wasn't already specified. */
\r
798 GetDlgItemText(tab, IDC_DIR, buffer, _countof(buffer));
\r
800 GetDlgItemText(tab, IDC_PATH, buffer, _countof(buffer));
\r
801 strip_basename(buffer);
\r
802 SetDlgItemText(tab, IDC_DIR, buffer);
\r
806 /* Browse for startup directory. */
\r
807 case IDC_BROWSE_DIR:
\r
808 dlg = GetDlgItem(tab, IDC_DIR);
\r
809 GetDlgItemText(tab, IDC_DIR, buffer, _countof(buffer));
\r
810 browse(dlg, buffer, OFN_NOVALIDATE, NSSM_GUI_BROWSE_FILTER_DIRECTORIES, 0);
\r
814 case IDC_LOCALSYSTEM:
\r
815 set_logon_enabled(0);
\r
819 set_logon_enabled(1);
\r
823 case IDC_AFFINITY_ALL:
\r
824 if (SendDlgItemMessage(tab, LOWORD(w), BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 0;
\r
826 set_affinity_enabled(enabled);
\r
829 /* Shutdown methods. */
\r
830 case IDC_METHOD_CONSOLE:
\r
831 set_timeout_enabled(LOWORD(w), IDC_KILL_CONSOLE);
\r
834 case IDC_METHOD_WINDOW:
\r
835 set_timeout_enabled(LOWORD(w), IDC_KILL_WINDOW);
\r
838 case IDC_METHOD_THREADS:
\r
839 set_timeout_enabled(LOWORD(w), IDC_KILL_THREADS);
\r
842 /* Browse for stdin. */
\r
843 case IDC_BROWSE_STDIN:
\r
844 dlg = GetDlgItem(tab, IDC_STDIN);
\r
845 GetDlgItemText(tab, IDC_STDIN, buffer, _countof(buffer));
\r
846 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
849 /* Browse for stdout. */
\r
850 case IDC_BROWSE_STDOUT:
\r
851 dlg = GetDlgItem(tab, IDC_STDOUT);
\r
852 GetDlgItemText(tab, IDC_STDOUT, buffer, _countof(buffer));
\r
853 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
854 /* Fill in stderr if it wasn't already specified. */
\r
855 GetDlgItemText(tab, IDC_STDERR, buffer, _countof(buffer));
\r
857 GetDlgItemText(tab, IDC_STDOUT, buffer, _countof(buffer));
\r
858 SetDlgItemText(tab, IDC_STDERR, buffer);
\r
862 /* Browse for stderr. */
\r
863 case IDC_BROWSE_STDERR:
\r
864 dlg = GetDlgItem(tab, IDC_STDERR);
\r
865 GetDlgItemText(tab, IDC_STDERR, buffer, _countof(buffer));
\r
866 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
871 if (SendDlgItemMessage(tab, LOWORD(w), BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 1;
\r
873 set_rotation_enabled(enabled);
\r
882 /* Install/remove dialogue callback */
\r
883 INT_PTR CALLBACK nssm_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {
\r
884 nssm_service_t *service;
\r
887 /* Creating the dialogue */
\r
888 case WM_INITDIALOG:
\r
889 service = (nssm_service_t *) l;
\r
891 SetFocus(GetDlgItem(window, IDC_NAME));
\r
897 tabs = GetDlgItem(window, IDC_TAB1);
\r
898 if (! tabs) return 0;
\r
902 ZeroMemory(&tab, sizeof(tab));
\r
903 tab.mask = TCIF_TEXT;
\r
907 /* Application tab. */
\r
908 if (service->native) tab.pszText = message_string(NSSM_GUI_TAB_NATIVE);
\r
909 else tab.pszText = message_string(NSSM_GUI_TAB_APPLICATION);
\r
910 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
911 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_APPLICATION, (LPARAM) &tab);
\r
912 if (service->native) {
\r
913 tablist[NSSM_TAB_APPLICATION] = dialog(MAKEINTRESOURCE(IDD_NATIVE), window, tab_dlg);
\r
914 EnableWindow(tablist[NSSM_TAB_APPLICATION], 0);
\r
915 EnableWindow(GetDlgItem(tablist[NSSM_TAB_APPLICATION], IDC_PATH), 0);
\r
917 else tablist[NSSM_TAB_APPLICATION] = dialog(MAKEINTRESOURCE(IDD_APPLICATION), window, tab_dlg);
\r
918 ShowWindow(tablist[NSSM_TAB_APPLICATION], SW_SHOW);
\r
921 tab.pszText = message_string(NSSM_GUI_TAB_DETAILS);
\r
922 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
923 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_DETAILS, (LPARAM) &tab);
\r
924 tablist[NSSM_TAB_DETAILS] = dialog(MAKEINTRESOURCE(IDD_DETAILS), window, tab_dlg);
\r
925 ShowWindow(tablist[NSSM_TAB_DETAILS], SW_HIDE);
\r
927 /* Set defaults. */
\r
928 combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP);
\r
929 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_AUTOMATIC, (LPARAM) message_string(NSSM_GUI_STARTUP_AUTOMATIC));
\r
930 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DELAYED, (LPARAM) message_string(NSSM_GUI_STARTUP_DELAYED));
\r
931 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_MANUAL, (LPARAM) message_string(NSSM_GUI_STARTUP_MANUAL));
\r
932 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DISABLED, (LPARAM) message_string(NSSM_GUI_STARTUP_DISABLED));
\r
933 SendMessage(combo, CB_SETCURSEL, NSSM_STARTUP_AUTOMATIC, 0);
\r
936 tab.pszText = message_string(NSSM_GUI_TAB_LOGON);
\r
937 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
938 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_LOGON, (LPARAM) &tab);
\r
939 tablist[NSSM_TAB_LOGON] = dialog(MAKEINTRESOURCE(IDD_LOGON), window, tab_dlg);
\r
940 ShowWindow(tablist[NSSM_TAB_LOGON], SW_HIDE);
\r
942 /* Set defaults. */
\r
943 CheckRadioButton(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, IDC_ACCOUNT, IDC_LOCALSYSTEM);
\r
944 set_logon_enabled(0);
\r
946 /* Remaining tabs are only for services we manage. */
\r
947 if (service->native) return 1;
\r
950 tab.pszText = message_string(NSSM_GUI_TAB_PROCESS);
\r
951 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
952 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_PROCESS, (LPARAM) &tab);
\r
953 tablist[NSSM_TAB_PROCESS] = dialog(MAKEINTRESOURCE(IDD_PROCESS), window, tab_dlg);
\r
954 ShowWindow(tablist[NSSM_TAB_PROCESS], SW_HIDE);
\r
956 /* Set defaults. */
\r
957 combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY);
\r
958 SendMessage(combo, CB_INSERTSTRING, NSSM_REALTIME_PRIORITY, (LPARAM) message_string(NSSM_GUI_REALTIME_PRIORITY_CLASS));
\r
959 SendMessage(combo, CB_INSERTSTRING, NSSM_HIGH_PRIORITY, (LPARAM) message_string(NSSM_GUI_HIGH_PRIORITY_CLASS));
\r
960 SendMessage(combo, CB_INSERTSTRING, NSSM_ABOVE_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_ABOVE_NORMAL_PRIORITY_CLASS));
\r
961 SendMessage(combo, CB_INSERTSTRING, NSSM_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_NORMAL_PRIORITY_CLASS));
\r
962 SendMessage(combo, CB_INSERTSTRING, NSSM_BELOW_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_BELOW_NORMAL_PRIORITY_CLASS));
\r
963 SendMessage(combo, CB_INSERTSTRING, NSSM_IDLE_PRIORITY, (LPARAM) message_string(NSSM_GUI_IDLE_PRIORITY_CLASS));
\r
964 SendMessage(combo, CB_SETCURSEL, NSSM_NORMAL_PRIORITY, 0);
\r
966 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_SETCHECK, BST_CHECKED, 0);
\r
968 list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY);
\r
970 SendMessage(list, LB_SETCOLUMNWIDTH, 16, 0);
\r
971 for (i = 0; i < n; i++) {
\r
973 _sntprintf_s(buffer, _countof(buffer), _TRUNCATE, _T("%d"), i);
\r
974 SendMessage(list, LB_ADDSTRING, 0, (LPARAM) buffer);
\r
979 The box is high enough for four rows. It is wide enough for eight
\r
980 columns without scrolling. With scrollbars it shrinks to two rows.
\r
981 Note that the above only holds if we set the column width BEFORE
985 int columns = (n - 1) / 4;
\r
987 GetWindowRect(list, &rect);
\r
988 int width = rect.right - rect.left;
989 width -= (7 - columns) * 16;
\r
990 int height = rect.bottom - rect.top;
\r
991 if (n < 4) height -= (int) SendMessage(list, LB_GETITEMHEIGHT, 0, 0) * (4 - n);
992 SetWindowPos(list, 0, 0, 0, width, height, SWP_NOMOVE | SWP_NOOWNERZORDER);
\r
994 SendMessage(list, LB_SELITEMRANGE, 1, MAKELPARAM(0, n));
\r
996 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_SETCHECK, BST_CHECKED, 0);
\r
997 set_affinity_enabled(0);
\r
999 /* Shutdown tab. */
\r
1000 tab.pszText = message_string(NSSM_GUI_TAB_SHUTDOWN);
\r
1001 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1002 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_SHUTDOWN, (LPARAM) &tab);
\r
1003 tablist[NSSM_TAB_SHUTDOWN] = dialog(MAKEINTRESOURCE(IDD_SHUTDOWN), window, tab_dlg);
\r
1004 ShowWindow(tablist[NSSM_TAB_SHUTDOWN], SW_HIDE);
\r
1006 /* Set defaults. */
\r
1007 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_CONSOLE, BM_SETCHECK, BST_CHECKED, 0);
\r
1008 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, NSSM_KILL_CONSOLE_GRACE_PERIOD, 0);
\r
1009 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_WINDOW, BM_SETCHECK, BST_CHECKED, 0);
\r
1010 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, NSSM_KILL_WINDOW_GRACE_PERIOD, 0);
\r
1011 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_THREADS, BM_SETCHECK, BST_CHECKED, 0);
\r
1012 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, NSSM_KILL_THREADS_GRACE_PERIOD, 0);
\r
1013 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_TERMINATE, BM_SETCHECK, BST_CHECKED, 0);
\r
1015 /* Restart tab. */
\r
1016 tab.pszText = message_string(NSSM_GUI_TAB_EXIT);
\r
1017 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1018 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_EXIT, (LPARAM) &tab);
\r
1019 tablist[NSSM_TAB_EXIT] = dialog(MAKEINTRESOURCE(IDD_APPEXIT), window, tab_dlg);
\r
1020 ShowWindow(tablist[NSSM_TAB_EXIT], SW_HIDE);
\r
1022 /* Set defaults. */
\r
1023 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, NSSM_RESET_THROTTLE_RESTART, 0);
\r
1024 combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
\r
1025 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_RESTART, (LPARAM) message_string(NSSM_GUI_EXIT_RESTART));
\r
1026 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_IGNORE, (LPARAM) message_string(NSSM_GUI_EXIT_IGNORE));
\r
1027 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_REALLY, (LPARAM) message_string(NSSM_GUI_EXIT_REALLY));
\r
1028 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_UNCLEAN, (LPARAM) message_string(NSSM_GUI_EXIT_UNCLEAN));
\r
1029 SendMessage(combo, CB_SETCURSEL, NSSM_EXIT_RESTART, 0);
\r
1030 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, 0, 0);
\r
1033 tab.pszText = message_string(NSSM_GUI_TAB_IO);
\r
1034 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1035 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_IO, (LPARAM) &tab);
\r
1036 tablist[NSSM_TAB_IO] = dialog(MAKEINTRESOURCE(IDD_IO), window, tab_dlg);
\r
1037 ShowWindow(tablist[NSSM_TAB_IO], SW_HIDE);
\r
1039 /* Rotation tab. */
\r
1040 tab.pszText = message_string(NSSM_GUI_TAB_ROTATION);
\r
1041 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1042 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_ROTATION, (LPARAM) &tab);
\r
1043 tablist[NSSM_TAB_ROTATION] = dialog(MAKEINTRESOURCE(IDD_ROTATION), window, tab_dlg);
\r
1044 ShowWindow(tablist[NSSM_TAB_ROTATION], SW_HIDE);
\r
1046 /* Set defaults. */
\r
1047 SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_SETCHECK, BST_UNCHECKED, 0);
\r
1048 SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, 0, 0);
\r
1049 SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, 0, 0);
\r
1050 set_rotation_enabled(0);
\r
1052 /* Environment tab. */
\r
1053 tab.pszText = message_string(NSSM_GUI_TAB_ENVIRONMENT);
\r
1054 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1055 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_ENVIRONMENT, (LPARAM) &tab);
\r
1056 tablist[NSSM_TAB_ENVIRONMENT] = dialog(MAKEINTRESOURCE(IDD_ENVIRONMENT), window, tab_dlg);
\r
1057 ShowWindow(tablist[NSSM_TAB_ENVIRONMENT], SW_HIDE);
\r
1063 NMHDR *notification;
\r
1065 notification = (NMHDR *) l;
\r
1066 switch (notification->code) {
\r
1067 case TCN_SELCHANGE:
\r
1071 tabs = GetDlgItem(window, IDC_TAB1);
\r
1072 if (! tabs) return 0;
\r
1074 selection = (int) SendMessage(tabs, TCM_GETCURSEL, 0, 0);
\r
1075 if (selection != selected_tab) {
\r
1076 ShowWindow(tablist[selected_tab], SW_HIDE);
\r
1077 ShowWindow(tablist[selection], SW_SHOWDEFAULT);
\r
1078 SetFocus(GetDlgItem(window, IDOK));
\r
1079 selected_tab = selection;
\r
1086 /* Button was pressed or control was controlled */
\r
1088 switch (LOWORD(w)) {
\r
1091 if ((int) GetWindowLongPtr(window, GWLP_USERDATA) == IDD_EDIT) {
\r
1092 if (! edit(window, (nssm_service_t *) GetWindowLongPtr(window, DWLP_USER))) PostQuitMessage(0);
\r
1094 else if (! install(window)) PostQuitMessage(0);
\r
1097 /* Cancel button */
\r
1099 DestroyWindow(window);
\r
1102 /* Remove button */
\r
1104 if (! remove(window)) PostQuitMessage(0);
\r
1109 /* Window closing */
\r
1111 DestroyWindow(window);
\r
1114 PostQuitMessage(0);
\r