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 if (! requires_password(service->username)) {
\r
374 if (is_localsystem(service->username)) {
375 HeapFree(GetProcessHeap(), 0, service->username);
\r
376 service->username = 0;
\r
377 service->usernamelen = 0;
\r
380 TCHAR *canon = canonical_username(service->username);
381 HeapFree(GetProcessHeap(), 0, service->username);
\r
382 service->username = 0;
\r
383 service->usernamelen = 0;
\r
385 service->usernamelen = _tcslen(canon) + 1;
386 service->username = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->usernamelen * sizeof(TCHAR));
387 if (! service->username) {
389 print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("canon"), _T("install()"));
392 memmove(service->username, canon, service->usernamelen * sizeof(TCHAR));
400 service->passwordlen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1), WM_GETTEXTLENGTH, 0, 0);
\r
401 size_t passwordlen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2), WM_GETTEXTLENGTH, 0, 0);
\r
403 if (! orig_service || ! orig_service->username || ! str_equiv(service->username, orig_service->username) || service->passwordlen || passwordlen) {
\r
404 if (! service->passwordlen) {
\r
405 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
408 if (passwordlen != service->passwordlen) {
\r
409 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
412 service->passwordlen++;
\r
414 /* Temporary buffer for password validation. */
\r
415 TCHAR *password = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->passwordlen * sizeof(TCHAR));
\r
417 HeapFree(GetProcessHeap(), 0, service->username);
\r
418 service->username = 0;
\r
419 service->usernamelen = 0;
\r
420 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("password confirmation"), _T("install()"));
\r
424 /* Actual password buffer. */
\r
425 service->password = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->passwordlen * sizeof(TCHAR));
\r
426 if (! service->password) {
\r
427 HeapFree(GetProcessHeap(), 0, password);
\r
428 HeapFree(GetProcessHeap(), 0, service->username);
\r
429 service->username = 0;
\r
430 service->usernamelen = 0;
\r
431 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("password"), _T("install()"));
\r
435 /* Get first password. */
\r
436 if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1, service->password, (int) service->passwordlen)) {
\r
437 HeapFree(GetProcessHeap(), 0, password);
\r
438 SecureZeroMemory(service->password, service->passwordlen);
\r
439 HeapFree(GetProcessHeap(), 0, service->password);
\r
440 service->password = 0;
\r
441 service->passwordlen = 0;
\r
442 HeapFree(GetProcessHeap(), 0, service->username);
\r
443 service->username = 0;
\r
444 service->usernamelen = 0;
\r
445 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_PASSWORD);
\r
449 /* Get confirmation. */
\r
450 if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2, password, (int) service->passwordlen)) {
\r
451 SecureZeroMemory(password, service->passwordlen);
\r
452 HeapFree(GetProcessHeap(), 0, password);
\r
453 SecureZeroMemory(service->password, service->passwordlen);
\r
454 HeapFree(GetProcessHeap(), 0, service->password);
\r
455 service->password = 0;
\r
456 service->passwordlen = 0;
\r
457 HeapFree(GetProcessHeap(), 0, service->username);
\r
458 service->username = 0;
\r
459 service->usernamelen = 0;
\r
460 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_PASSWORD);
\r
465 if (_tcsncmp(password, service->password, service->passwordlen)) {
\r
466 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
467 SecureZeroMemory(password, service->passwordlen);
\r
468 HeapFree(GetProcessHeap(), 0, password);
\r
469 SecureZeroMemory(service->password, service->passwordlen);
\r
470 HeapFree(GetProcessHeap(), 0, service->password);
\r
471 service->password = 0;
\r
472 service->passwordlen = 0;
\r
473 HeapFree(GetProcessHeap(), 0, service->username);
\r
474 service->username = 0;
\r
475 service->usernamelen = 0;
\r
482 /* Remaining tabs are only for services we manage. */
\r
483 if (service->native) return 0;
\r
485 /* Get process stuff. */
\r
486 combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY);
\r
487 service->priority = priority_index_to_constant((unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0));
\r
489 service->affinity = 0LL;
\r
490 if (! (SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_GETCHECK, 0, 0) & BST_CHECKED)) {
\r
491 HWND list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY);
\r
492 int selected = (int) SendMessage(list, LB_GETSELCOUNT, 0, 0);
\r
493 int count = (int) SendMessage(list, LB_GETCOUNT, 0, 0);
\r
495 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_WARN_AFFINITY_NONE);
\r
498 else if (selected < count) {
\r
499 for (int i = 0; i < count; i++) {
\r
500 if (SendMessage(list, LB_GETSEL, i, 0)) service->affinity |= (1LL << (__int64) i);
\r
505 if (SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_GETCHECK, 0, 0) & BST_CHECKED) service->no_console = 0;
506 else service->no_console = 1;
508 /* Get stop method stuff. */
\r
509 check_stop_method(service, NSSM_STOP_METHOD_CONSOLE, IDC_METHOD_CONSOLE);
\r
510 check_stop_method(service, NSSM_STOP_METHOD_WINDOW, IDC_METHOD_WINDOW);
\r
511 check_stop_method(service, NSSM_STOP_METHOD_THREADS, IDC_METHOD_THREADS);
\r
512 check_stop_method(service, NSSM_STOP_METHOD_TERMINATE, IDC_METHOD_TERMINATE);
\r
513 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, &service->kill_console_delay);
\r
514 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, &service->kill_window_delay);
\r
515 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, &service->kill_threads_delay);
\r
517 /* Get exit action stuff. */
\r
518 check_number(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, &service->throttle_delay);
\r
519 combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
\r
520 service->default_exit_action = (unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0);
\r
521 if (service->default_exit_action == CB_ERR) service->default_exit_action = 0;
\r
522 check_number(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, &service->restart_delay);
\r
524 /* Get I/O stuff. */
\r
525 check_io(window, _T("stdin"), service->stdin_path, _countof(service->stdin_path), IDC_STDIN);
\r
526 check_io(window, _T("stdout"), service->stdout_path, _countof(service->stdout_path), IDC_STDOUT);
\r
527 check_io(window, _T("stderr"), service->stderr_path, _countof(service->stderr_path), IDC_STDERR);
\r
529 /* Override stdout and/or stderr. */
\r
530 if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_TRUNCATE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
531 if (service->stdout_path[0]) service->stdout_disposition = CREATE_ALWAYS;
\r
532 if (service->stderr_path[0]) service->stderr_disposition = CREATE_ALWAYS;
\r
535 /* Get rotation stuff. */
\r
536 if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
537 service->rotate_files = true;
\r
538 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;
539 check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, &service->rotate_seconds);
\r
540 check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, &service->rotate_bytes_low);
\r
543 /* Get environment. */
\r
544 unsigned long envlen = (unsigned long) SendMessage(GetDlgItem(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT), WM_GETTEXTLENGTH, 0, 0);
\r
546 TCHAR *env = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (envlen + 2) * sizeof(TCHAR));
\r
548 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("install()"));
\r
549 cleanup_nssm_service(service);
\r
553 if (! GetDlgItemText(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT, env, envlen + 1)) {
\r
554 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT);
\r
555 HeapFree(GetProcessHeap(), 0, env);
\r
556 cleanup_nssm_service(service);
\r
561 unsigned long newlen;
\r
562 if (unformat_environment(env, envlen, &newenv, &newlen)) {
\r
563 HeapFree(GetProcessHeap(), 0, env);
\r
564 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("install()"));
\r
565 cleanup_nssm_service(service);
\r
569 HeapFree(GetProcessHeap(), 0, env);
\r
573 /* Test the environment is valid. */
\r
574 if (test_environment(env)) {
\r
575 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT);
\r
576 HeapFree(GetProcessHeap(), 0, env);
\r
577 cleanup_nssm_service(service);
\r
581 if (SendDlgItemMessage(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT_REPLACE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
582 service->env = env;
\r
583 service->envlen = envlen;
\r
586 service->env_extra = env;
\r
587 service->env_extralen = envlen;
\r
594 /* Install the service. */
\r
595 int install(HWND window) {
\r
596 if (! window) return 1;
\r
598 nssm_service_t *service = alloc_nssm_service();
\r
600 int ret = configure(window, service, 0);
\r
601 if (ret) return ret;
\r
604 /* See if it works. */
\r
605 switch (install_service(service)) {
\r
607 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("install()"));
\r
608 cleanup_nssm_service(service);
\r
612 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);
\r
613 cleanup_nssm_service(service);
\r
617 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, NSSM);
\r
618 cleanup_nssm_service(service);
\r
622 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_OUT_OF_MEMORY_FOR_IMAGEPATH);
\r
623 cleanup_nssm_service(service);
\r
627 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INSTALL_SERVICE_FAILED);
\r
628 cleanup_nssm_service(service);
\r
632 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_CREATE_PARAMETERS_FAILED);
\r
633 cleanup_nssm_service(service);
\r
637 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_INSTALLED, service->name);
\r
638 cleanup_nssm_service(service);
\r
642 /* Remove the service */
\r
643 int remove(HWND window) {
\r
644 if (! window) return 1;
\r
646 /* See if it works */
\r
647 nssm_service_t *service = alloc_nssm_service();
\r
649 /* Get service name */
\r
650 if (! GetDlgItemText(window, IDC_NAME, service->name, _countof(service->name))) {
\r
651 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_SERVICE_NAME);
\r
652 cleanup_nssm_service(service);
\r
657 if (popup_message(window, MB_YESNO, NSSM_GUI_ASK_REMOVE_SERVICE, service->name) != IDYES) {
\r
658 cleanup_nssm_service(service);
\r
663 switch (remove_service(service)) {
\r
665 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("remove()"));
\r
666 cleanup_nssm_service(service);
\r
670 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);
\r
671 cleanup_nssm_service(service);
\r
675 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_SERVICE_NOT_INSTALLED);
\r
677 cleanup_nssm_service(service);
\r
680 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_REMOVE_SERVICE_FAILED);
\r
681 cleanup_nssm_service(service);
\r
685 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_REMOVED, service->name);
\r
686 cleanup_nssm_service(service);
\r
690 int edit(HWND window, nssm_service_t *orig_service) {
\r
691 if (! window) return 1;
\r
693 nssm_service_t *service = alloc_nssm_service();
\r
695 int ret = configure(window, service, orig_service);
\r
696 if (ret) return ret;
\r
699 switch (edit_service(service, true)) {
\r
701 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("edit()"));
\r
702 cleanup_nssm_service(service);
\r
706 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, NSSM);
\r
707 cleanup_nssm_service(service);
\r
711 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_OUT_OF_MEMORY_FOR_IMAGEPATH);
\r
712 cleanup_nssm_service(service);
\r
717 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_EDIT_PARAMETERS_FAILED);
\r
718 cleanup_nssm_service(service);
\r
722 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_EDITED, service->name);
\r
723 cleanup_nssm_service(service);
\r
727 static TCHAR *browse_filter(int message) {
\r
729 case NSSM_GUI_BROWSE_FILTER_APPLICATIONS: return _T("*.exe;*.bat;*.cmd");
\r
730 case NSSM_GUI_BROWSE_FILTER_DIRECTORIES: return _T(".");
\r
731 case NSSM_GUI_BROWSE_FILTER_ALL_FILES: /* Fall through. */
\r
732 default: return _T("*.*");
\r
736 UINT_PTR CALLBACK browse_hook(HWND dlg, UINT message, WPARAM w, LPARAM l) {
\r
738 case WM_INITDIALOG:
\r
745 /* Browse for application */
\r
746 void browse(HWND window, TCHAR *current, unsigned long flags, ...) {
\r
747 if (! window) return;
\r
750 size_t bufsize = 256;
\r
751 size_t len = bufsize;
\r
755 ZeroMemory(&ofn, sizeof(ofn));
\r
756 ofn.lStructSize = sizeof(ofn);
\r
757 ofn.lpstrFilter = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, bufsize * sizeof(TCHAR));
\r
758 /* XXX: Escaping nulls with FormatMessage is tricky */
\r
759 if (ofn.lpstrFilter) {
\r
760 ZeroMemory((void *) ofn.lpstrFilter, bufsize);
\r
762 /* "Applications" + NULL + "*.exe" + NULL */
\r
763 va_start(arg, flags);
\r
764 while (i = va_arg(arg, int)) {
\r
765 TCHAR *localised = message_string(i);
\r
766 _sntprintf_s((TCHAR *) ofn.lpstrFilter + len, bufsize, _TRUNCATE, localised);
\r
767 len += _tcslen(localised) + 1;
\r
768 LocalFree(localised);
\r
769 TCHAR *filter = browse_filter(i);
\r
770 _sntprintf_s((TCHAR *) ofn.lpstrFilter + len, bufsize - len, _TRUNCATE, _T("%s"), filter);
\r
771 len += _tcslen(filter) + 1;
\r
774 /* Remainder of the buffer is already zeroed */
\r
776 ofn.lpstrFile = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, PATH_LENGTH * sizeof(TCHAR));
\r
778 if (flags & OFN_NOVALIDATE) {
\r
779 /* Directory hack. */
\r
780 _sntprintf_s(ofn.lpstrFile, PATH_LENGTH, _TRUNCATE, _T(":%s:"), message_string(NSSM_GUI_BROWSE_FILTER_DIRECTORIES));
\r
781 ofn.nMaxFile = DIR_LENGTH;
\r
784 _sntprintf_s(ofn.lpstrFile, PATH_LENGTH, _TRUNCATE, _T("%s"), current);
\r
785 ofn.nMaxFile = PATH_LENGTH;
\r
788 ofn.lpstrTitle = message_string(NSSM_GUI_BROWSE_TITLE);
\r
789 ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | flags;
\r
791 if (GetOpenFileName(&ofn)) {
\r
792 /* Directory hack. */
\r
793 if (flags & OFN_NOVALIDATE) strip_basename(ofn.lpstrFile);
\r
794 SendMessage(window, WM_SETTEXT, 0, (LPARAM) ofn.lpstrFile);
\r
796 if (ofn.lpstrFilter) HeapFree(GetProcessHeap(), 0, (void *) ofn.lpstrFilter);
\r
797 if (ofn.lpstrFile) HeapFree(GetProcessHeap(), 0, ofn.lpstrFile);
800 INT_PTR CALLBACK tab_dlg(HWND tab, UINT message, WPARAM w, LPARAM l) {
\r
802 case WM_INITDIALOG:
\r
805 /* Button was pressed or control was controlled. */
\r
808 TCHAR buffer[PATH_LENGTH];
\r
809 unsigned char enabled;
\r
811 switch (LOWORD(w)) {
\r
812 /* Browse for application. */
\r
814 dlg = GetDlgItem(tab, IDC_PATH);
\r
815 GetDlgItemText(tab, IDC_PATH, buffer, _countof(buffer));
\r
816 browse(dlg, buffer, OFN_FILEMUSTEXIST, NSSM_GUI_BROWSE_FILTER_APPLICATIONS, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
817 /* Fill in startup directory if it wasn't already specified. */
\r
818 GetDlgItemText(tab, IDC_DIR, buffer, _countof(buffer));
\r
820 GetDlgItemText(tab, IDC_PATH, buffer, _countof(buffer));
\r
821 strip_basename(buffer);
\r
822 SetDlgItemText(tab, IDC_DIR, buffer);
\r
826 /* Browse for startup directory. */
\r
827 case IDC_BROWSE_DIR:
\r
828 dlg = GetDlgItem(tab, IDC_DIR);
\r
829 GetDlgItemText(tab, IDC_DIR, buffer, _countof(buffer));
\r
830 browse(dlg, buffer, OFN_NOVALIDATE, NSSM_GUI_BROWSE_FILTER_DIRECTORIES, 0);
\r
834 case IDC_LOCALSYSTEM:
\r
835 set_logon_enabled(0);
\r
839 set_logon_enabled(1);
\r
843 case IDC_AFFINITY_ALL:
\r
844 if (SendDlgItemMessage(tab, LOWORD(w), BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 0;
\r
846 set_affinity_enabled(enabled);
\r
849 /* Shutdown methods. */
\r
850 case IDC_METHOD_CONSOLE:
\r
851 set_timeout_enabled(LOWORD(w), IDC_KILL_CONSOLE);
\r
854 case IDC_METHOD_WINDOW:
\r
855 set_timeout_enabled(LOWORD(w), IDC_KILL_WINDOW);
\r
858 case IDC_METHOD_THREADS:
\r
859 set_timeout_enabled(LOWORD(w), IDC_KILL_THREADS);
\r
862 /* Browse for stdin. */
\r
863 case IDC_BROWSE_STDIN:
\r
864 dlg = GetDlgItem(tab, IDC_STDIN);
\r
865 GetDlgItemText(tab, IDC_STDIN, buffer, _countof(buffer));
\r
866 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
869 /* Browse for stdout. */
\r
870 case IDC_BROWSE_STDOUT:
\r
871 dlg = GetDlgItem(tab, IDC_STDOUT);
\r
872 GetDlgItemText(tab, IDC_STDOUT, buffer, _countof(buffer));
\r
873 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
874 /* Fill in stderr if it wasn't already specified. */
\r
875 GetDlgItemText(tab, IDC_STDERR, buffer, _countof(buffer));
\r
877 GetDlgItemText(tab, IDC_STDOUT, buffer, _countof(buffer));
\r
878 SetDlgItemText(tab, IDC_STDERR, buffer);
\r
882 /* Browse for stderr. */
\r
883 case IDC_BROWSE_STDERR:
\r
884 dlg = GetDlgItem(tab, IDC_STDERR);
\r
885 GetDlgItemText(tab, IDC_STDERR, buffer, _countof(buffer));
\r
886 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
891 if (SendDlgItemMessage(tab, LOWORD(w), BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 1;
\r
893 set_rotation_enabled(enabled);
\r
902 /* Install/remove dialogue callback */
\r
903 INT_PTR CALLBACK nssm_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {
\r
904 nssm_service_t *service;
\r
907 /* Creating the dialogue */
\r
908 case WM_INITDIALOG:
\r
909 service = (nssm_service_t *) l;
\r
911 SetFocus(GetDlgItem(window, IDC_NAME));
\r
917 tabs = GetDlgItem(window, IDC_TAB1);
\r
918 if (! tabs) return 0;
\r
922 ZeroMemory(&tab, sizeof(tab));
\r
923 tab.mask = TCIF_TEXT;
\r
927 /* Application tab. */
\r
928 if (service->native) tab.pszText = message_string(NSSM_GUI_TAB_NATIVE);
\r
929 else tab.pszText = message_string(NSSM_GUI_TAB_APPLICATION);
\r
930 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
931 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_APPLICATION, (LPARAM) &tab);
\r
932 if (service->native) {
\r
933 tablist[NSSM_TAB_APPLICATION] = dialog(MAKEINTRESOURCE(IDD_NATIVE), window, tab_dlg);
\r
934 EnableWindow(tablist[NSSM_TAB_APPLICATION], 0);
\r
935 EnableWindow(GetDlgItem(tablist[NSSM_TAB_APPLICATION], IDC_PATH), 0);
\r
937 else tablist[NSSM_TAB_APPLICATION] = dialog(MAKEINTRESOURCE(IDD_APPLICATION), window, tab_dlg);
\r
938 ShowWindow(tablist[NSSM_TAB_APPLICATION], SW_SHOW);
\r
941 tab.pszText = message_string(NSSM_GUI_TAB_DETAILS);
\r
942 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
943 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_DETAILS, (LPARAM) &tab);
\r
944 tablist[NSSM_TAB_DETAILS] = dialog(MAKEINTRESOURCE(IDD_DETAILS), window, tab_dlg);
\r
945 ShowWindow(tablist[NSSM_TAB_DETAILS], SW_HIDE);
\r
947 /* Set defaults. */
\r
948 combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP);
\r
949 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_AUTOMATIC, (LPARAM) message_string(NSSM_GUI_STARTUP_AUTOMATIC));
\r
950 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DELAYED, (LPARAM) message_string(NSSM_GUI_STARTUP_DELAYED));
\r
951 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_MANUAL, (LPARAM) message_string(NSSM_GUI_STARTUP_MANUAL));
\r
952 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DISABLED, (LPARAM) message_string(NSSM_GUI_STARTUP_DISABLED));
\r
953 SendMessage(combo, CB_SETCURSEL, NSSM_STARTUP_AUTOMATIC, 0);
\r
956 tab.pszText = message_string(NSSM_GUI_TAB_LOGON);
\r
957 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
958 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_LOGON, (LPARAM) &tab);
\r
959 tablist[NSSM_TAB_LOGON] = dialog(MAKEINTRESOURCE(IDD_LOGON), window, tab_dlg);
\r
960 ShowWindow(tablist[NSSM_TAB_LOGON], SW_HIDE);
\r
962 /* Set defaults. */
\r
963 CheckRadioButton(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, IDC_ACCOUNT, IDC_LOCALSYSTEM);
\r
964 set_logon_enabled(0);
\r
966 /* Remaining tabs are only for services we manage. */
\r
967 if (service->native) return 1;
\r
970 tab.pszText = message_string(NSSM_GUI_TAB_PROCESS);
\r
971 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
972 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_PROCESS, (LPARAM) &tab);
\r
973 tablist[NSSM_TAB_PROCESS] = dialog(MAKEINTRESOURCE(IDD_PROCESS), window, tab_dlg);
\r
974 ShowWindow(tablist[NSSM_TAB_PROCESS], SW_HIDE);
\r
976 /* Set defaults. */
\r
977 combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY);
\r
978 SendMessage(combo, CB_INSERTSTRING, NSSM_REALTIME_PRIORITY, (LPARAM) message_string(NSSM_GUI_REALTIME_PRIORITY_CLASS));
\r
979 SendMessage(combo, CB_INSERTSTRING, NSSM_HIGH_PRIORITY, (LPARAM) message_string(NSSM_GUI_HIGH_PRIORITY_CLASS));
\r
980 SendMessage(combo, CB_INSERTSTRING, NSSM_ABOVE_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_ABOVE_NORMAL_PRIORITY_CLASS));
\r
981 SendMessage(combo, CB_INSERTSTRING, NSSM_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_NORMAL_PRIORITY_CLASS));
\r
982 SendMessage(combo, CB_INSERTSTRING, NSSM_BELOW_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_BELOW_NORMAL_PRIORITY_CLASS));
\r
983 SendMessage(combo, CB_INSERTSTRING, NSSM_IDLE_PRIORITY, (LPARAM) message_string(NSSM_GUI_IDLE_PRIORITY_CLASS));
\r
984 SendMessage(combo, CB_SETCURSEL, NSSM_NORMAL_PRIORITY, 0);
\r
986 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_SETCHECK, BST_CHECKED, 0);
\r
988 list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY);
\r
990 SendMessage(list, LB_SETCOLUMNWIDTH, 16, 0);
\r
991 for (i = 0; i < n; i++) {
\r
993 _sntprintf_s(buffer, _countof(buffer), _TRUNCATE, _T("%d"), i);
\r
994 SendMessage(list, LB_ADDSTRING, 0, (LPARAM) buffer);
\r
999 The box is high enough for four rows. It is wide enough for eight
\r
1000 columns without scrolling. With scrollbars it shrinks to two rows.
\r
1001 Note that the above only holds if we set the column width BEFORE
1005 int columns = (n - 1) / 4;
\r
1007 GetWindowRect(list, &rect);
\r
1008 int width = rect.right - rect.left;
1009 width -= (7 - columns) * 16;
\r
1010 int height = rect.bottom - rect.top;
\r
1011 if (n < 4) height -= (int) SendMessage(list, LB_GETITEMHEIGHT, 0, 0) * (4 - n);
1012 SetWindowPos(list, 0, 0, 0, width, height, SWP_NOMOVE | SWP_NOOWNERZORDER);
\r
1014 SendMessage(list, LB_SELITEMRANGE, 1, MAKELPARAM(0, n));
\r
1016 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_SETCHECK, BST_CHECKED, 0);
\r
1017 set_affinity_enabled(0);
\r
1019 /* Shutdown tab. */
\r
1020 tab.pszText = message_string(NSSM_GUI_TAB_SHUTDOWN);
\r
1021 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1022 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_SHUTDOWN, (LPARAM) &tab);
\r
1023 tablist[NSSM_TAB_SHUTDOWN] = dialog(MAKEINTRESOURCE(IDD_SHUTDOWN), window, tab_dlg);
\r
1024 ShowWindow(tablist[NSSM_TAB_SHUTDOWN], SW_HIDE);
\r
1026 /* Set defaults. */
\r
1027 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_CONSOLE, BM_SETCHECK, BST_CHECKED, 0);
\r
1028 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, NSSM_KILL_CONSOLE_GRACE_PERIOD, 0);
\r
1029 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_WINDOW, BM_SETCHECK, BST_CHECKED, 0);
\r
1030 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, NSSM_KILL_WINDOW_GRACE_PERIOD, 0);
\r
1031 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_THREADS, BM_SETCHECK, BST_CHECKED, 0);
\r
1032 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, NSSM_KILL_THREADS_GRACE_PERIOD, 0);
\r
1033 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_TERMINATE, BM_SETCHECK, BST_CHECKED, 0);
\r
1035 /* Restart tab. */
\r
1036 tab.pszText = message_string(NSSM_GUI_TAB_EXIT);
\r
1037 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1038 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_EXIT, (LPARAM) &tab);
\r
1039 tablist[NSSM_TAB_EXIT] = dialog(MAKEINTRESOURCE(IDD_APPEXIT), window, tab_dlg);
\r
1040 ShowWindow(tablist[NSSM_TAB_EXIT], SW_HIDE);
\r
1042 /* Set defaults. */
\r
1043 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, NSSM_RESET_THROTTLE_RESTART, 0);
\r
1044 combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
\r
1045 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_RESTART, (LPARAM) message_string(NSSM_GUI_EXIT_RESTART));
\r
1046 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_IGNORE, (LPARAM) message_string(NSSM_GUI_EXIT_IGNORE));
\r
1047 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_REALLY, (LPARAM) message_string(NSSM_GUI_EXIT_REALLY));
\r
1048 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_UNCLEAN, (LPARAM) message_string(NSSM_GUI_EXIT_UNCLEAN));
\r
1049 SendMessage(combo, CB_SETCURSEL, NSSM_EXIT_RESTART, 0);
\r
1050 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, 0, 0);
\r
1053 tab.pszText = message_string(NSSM_GUI_TAB_IO);
\r
1054 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1055 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_IO, (LPARAM) &tab);
\r
1056 tablist[NSSM_TAB_IO] = dialog(MAKEINTRESOURCE(IDD_IO), window, tab_dlg);
\r
1057 ShowWindow(tablist[NSSM_TAB_IO], SW_HIDE);
\r
1059 /* Rotation tab. */
\r
1060 tab.pszText = message_string(NSSM_GUI_TAB_ROTATION);
\r
1061 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1062 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_ROTATION, (LPARAM) &tab);
\r
1063 tablist[NSSM_TAB_ROTATION] = dialog(MAKEINTRESOURCE(IDD_ROTATION), window, tab_dlg);
\r
1064 ShowWindow(tablist[NSSM_TAB_ROTATION], SW_HIDE);
\r
1066 /* Set defaults. */
\r
1067 SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_SETCHECK, BST_UNCHECKED, 0);
\r
1068 SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, 0, 0);
\r
1069 SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, 0, 0);
\r
1070 set_rotation_enabled(0);
\r
1072 /* Environment tab. */
\r
1073 tab.pszText = message_string(NSSM_GUI_TAB_ENVIRONMENT);
\r
1074 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1075 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_ENVIRONMENT, (LPARAM) &tab);
\r
1076 tablist[NSSM_TAB_ENVIRONMENT] = dialog(MAKEINTRESOURCE(IDD_ENVIRONMENT), window, tab_dlg);
\r
1077 ShowWindow(tablist[NSSM_TAB_ENVIRONMENT], SW_HIDE);
\r
1083 NMHDR *notification;
\r
1085 notification = (NMHDR *) l;
\r
1086 switch (notification->code) {
\r
1087 case TCN_SELCHANGE:
\r
1091 tabs = GetDlgItem(window, IDC_TAB1);
\r
1092 if (! tabs) return 0;
\r
1094 selection = (int) SendMessage(tabs, TCM_GETCURSEL, 0, 0);
\r
1095 if (selection != selected_tab) {
\r
1096 ShowWindow(tablist[selected_tab], SW_HIDE);
\r
1097 ShowWindow(tablist[selection], SW_SHOWDEFAULT);
\r
1098 SetFocus(GetDlgItem(window, IDOK));
\r
1099 selected_tab = selection;
\r
1106 /* Button was pressed or control was controlled */
\r
1108 switch (LOWORD(w)) {
\r
1111 if ((int) GetWindowLongPtr(window, GWLP_USERDATA) == IDD_EDIT) {
\r
1112 if (! edit(window, (nssm_service_t *) GetWindowLongPtr(window, DWLP_USER))) PostQuitMessage(0);
\r
1114 else if (! install(window)) PostQuitMessage(0);
\r
1117 /* Cancel button */
\r
1119 DestroyWindow(window);
\r
1122 /* Remove button */
\r
1124 if (! remove(window)) PostQuitMessage(0);
\r
1129 /* Window closing */
\r
1131 DestroyWindow(window);
\r
1134 PostQuitMessage(0);
\r