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) {
\r
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
156 if (! service->kill_process_tree) {
\r
157 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_PROCESS_TREE, BM_SETCHECK, BST_UNCHECKED, 0);
\r
161 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, service->throttle_delay, 0);
\r
162 combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
\r
163 SendMessage(combo, CB_SETCURSEL, service->default_exit_action, 0);
\r
164 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, service->restart_delay, 0);
\r
167 SetDlgItemText(tablist[NSSM_TAB_IO], IDC_STDIN, service->stdin_path);
\r
168 SetDlgItemText(tablist[NSSM_TAB_IO], IDC_STDOUT, service->stdout_path);
\r
169 SetDlgItemText(tablist[NSSM_TAB_IO], IDC_STDERR, service->stderr_path);
\r
171 /* Rotation tab. */
\r
172 if (service->stdout_disposition == CREATE_ALWAYS) SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_TRUNCATE, BM_SETCHECK, BST_CHECKED, 0);
\r
173 if (service->rotate_files) {
\r
174 SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE, BM_SETCHECK, BST_CHECKED, 0);
\r
175 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE), 1);
\r
176 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS), 1);
\r
177 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW), 1);
\r
179 if (service->rotate_stdout_online || service->rotate_stderr_online) SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_SETCHECK, BST_CHECKED, 0);
\r
180 SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, service->rotate_seconds, 0);
\r
181 if (! service->rotate_bytes_high) SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, service->rotate_bytes_low, 0);
\r
183 /* Check if advanced settings are in use. */
\r
184 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
185 if (service->rotate_bytes_high) popup_message(dlg, MB_OK | MB_ICONWARNING, NSSM_GUI_WARN_ROTATE_BYTES);
\r
187 /* Environment tab. */
\r
189 unsigned long envlen;
\r
190 if (service->env_extralen) {
\r
191 env = service->env_extra;
\r
192 envlen = service->env_extralen;
\r
195 env = service->env;
\r
196 envlen = service->envlen;
\r
197 if (envlen) SendDlgItemMessage(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT_REPLACE, BM_SETCHECK, BST_CHECKED, 0);
\r
202 unsigned long newlen;
\r
203 if (format_double_null(env, envlen, &formatted, &newlen)) {
\r
204 popup_message(dlg, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("nssm_dlg()"));
\r
207 SetDlgItemText(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT, formatted);
\r
208 HeapFree(GetProcessHeap(), 0, formatted);
\r
211 if (service->envlen && service->env_extralen) popup_message(dlg, MB_OK | MB_ICONWARNING, NSSM_GUI_WARN_ENVIRONMENT);
\r
216 while (GetMessage(&message, 0, 0, 0)) {
\r
217 if (IsDialogMessage(dlg, &message)) continue;
\r
218 TranslateMessage(&message);
\r
219 DispatchMessage(&message);
\r
222 return (int) message.wParam;
\r
225 void centre_window(HWND window) {
\r
227 RECT size, desktop_size;
\r
228 unsigned long x, y;
\r
230 if (! window) return;
\r
232 /* Find window size */
\r
233 if (! GetWindowRect(window, &size)) return;
\r
235 /* Find desktop window */
\r
236 desktop = GetDesktopWindow();
\r
237 if (! desktop) return;
\r
239 /* Find desktop window size */
\r
240 if (! GetWindowRect(desktop, &desktop_size)) return;
\r
242 /* Centre window */
\r
243 x = (desktop_size.right - size.right) / 2;
\r
244 y = (desktop_size.bottom - size.bottom) / 2;
\r
245 MoveWindow(window, x, y, size.right - size.left, size.bottom - size.top, 0);
\r
248 static inline void check_stop_method(nssm_service_t *service, unsigned long method, unsigned long control) {
\r
249 if (SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], control, BM_GETCHECK, 0, 0) & BST_CHECKED) return;
\r
250 service->stop_method &= ~method;
\r
253 static inline void check_number(HWND tab, unsigned long control, unsigned long *timeout) {
\r
255 unsigned long configured = GetDlgItemInt(tab, control, &translated, 0);
\r
256 if (translated) *timeout = configured;
\r
259 static inline void set_timeout_enabled(unsigned long control, unsigned long dependent) {
\r
260 unsigned char enabled = 0;
\r
261 if (SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], control, BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 1;
\r
262 EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], dependent), enabled);
\r
265 static inline void set_logon_enabled(unsigned char enabled) {
\r
266 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_INTERACT), ! enabled);
\r
267 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_USERNAME), enabled);
\r
268 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1), enabled);
\r
269 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2), enabled);
\r
272 static inline void set_affinity_enabled(unsigned char enabled) {
\r
273 EnableWindow(GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY), enabled);
\r
276 static inline void set_rotation_enabled(unsigned char enabled) {
\r
277 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE), enabled);
\r
278 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS), enabled);
\r
279 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW), enabled);
\r
282 static inline void check_io(HWND owner, TCHAR *name, TCHAR *buffer, unsigned long len, unsigned long control) {
\r
283 if (! SendMessage(GetDlgItem(tablist[NSSM_TAB_IO], control), WM_GETTEXTLENGTH, 0, 0)) return;
\r
284 if (GetDlgItemText(tablist[NSSM_TAB_IO], control, buffer, (int) len)) return;
\r
285 popup_message(owner, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, name);
\r
286 ZeroMemory(buffer, len * sizeof(TCHAR));
\r
289 /* Set service parameters. */
\r
290 int configure(HWND window, nssm_service_t *service, nssm_service_t *orig_service) {
\r
291 if (! service) return 1;
\r
293 set_nssm_service_defaults(service);
\r
295 if (orig_service) {
\r
296 service->native = orig_service->native;
\r
297 service->handle = orig_service->handle;
\r
300 /* Get service name. */
\r
301 if (! GetDlgItemText(window, IDC_NAME, service->name, _countof(service->name))) {
\r
302 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_SERVICE_NAME);
\r
303 cleanup_nssm_service(service);
\r
307 /* Get executable name */
\r
308 if (! service->native) {
\r
309 if (! GetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_PATH, service->exe, _countof(service->exe))) {
\r
310 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PATH);
\r
314 /* Get startup directory. */
\r
315 if (! GetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_DIR, service->dir, _countof(service->dir))) {
\r
316 _sntprintf_s(service->dir, _countof(service->dir), _TRUNCATE, _T("%s"), service->exe);
\r
317 strip_basename(service->dir);
\r
321 if (SendMessage(GetDlgItem(tablist[NSSM_TAB_APPLICATION], IDC_FLAGS), WM_GETTEXTLENGTH, 0, 0)) {
\r
322 if (! GetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_FLAGS, service->flags, _countof(service->flags))) {
\r
323 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_OPTIONS);
\r
330 if (SendMessage(GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_DISPLAYNAME), WM_GETTEXTLENGTH, 0, 0)) {
\r
331 if (! GetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DISPLAYNAME, service->displayname, _countof(service->displayname))) {
\r
332 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DISPLAYNAME);
\r
337 if (SendMessage(GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_DESCRIPTION), WM_GETTEXTLENGTH, 0, 0)) {
\r
338 if (! GetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DESCRIPTION, service->description, _countof(service->description))) {
\r
339 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DESCRIPTION);
\r
344 HWND combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP);
\r
345 service->startup = (unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0);
\r
346 if (service->startup == CB_ERR) service->startup = 0;
\r
348 /* Get logon stuff. */
\r
349 if (SendDlgItemMessage(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
350 if (SendDlgItemMessage(tablist[NSSM_TAB_LOGON], IDC_INTERACT, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
351 service->type |= SERVICE_INTERACTIVE_PROCESS;
\r
353 if (service->username) HeapFree(GetProcessHeap(), 0, service->username);
\r
354 service->username = 0;
\r
355 service->usernamelen = 0;
\r
356 if (service->password) {
\r
357 SecureZeroMemory(service->password, service->passwordlen);
\r
358 HeapFree(GetProcessHeap(), 0, service->password);
\r
360 service->password = 0;
\r
361 service->passwordlen = 0;
\r
365 service->usernamelen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_USERNAME), WM_GETTEXTLENGTH, 0, 0);
\r
366 if (! service->usernamelen) {
\r
367 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_USERNAME);
\r
370 service->usernamelen++;
\r
372 service->username = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->usernamelen * sizeof(TCHAR));
\r
373 if (! service->username) {
\r
374 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("account name"), _T("install()"));
\r
377 if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_USERNAME, service->username, (int) service->usernamelen)) {
\r
378 HeapFree(GetProcessHeap(), 0, service->username);
\r
379 service->username = 0;
\r
380 service->usernamelen = 0;
\r
381 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_USERNAME);
\r
386 Special case for well-known accounts.
\r
387 Ignore the password if we're editing and the username hasn't changed.
\r
389 const TCHAR *well_known = well_known_username(service->username);
\r
391 if (str_equiv(well_known, NSSM_LOCALSYSTEM_ACCOUNT)) {
\r
392 HeapFree(GetProcessHeap(), 0, service->username);
\r
393 service->username = 0;
\r
394 service->usernamelen = 0;
\r
397 service->usernamelen = _tcslen(well_known) + 1;
\r
398 service->username = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->usernamelen * sizeof(TCHAR));
\r
399 if (! service->username) {
\r
400 print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("canon"), _T("install()"));
\r
403 memmove(service->username, well_known, service->usernamelen * sizeof(TCHAR));
\r
408 service->passwordlen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1), WM_GETTEXTLENGTH, 0, 0);
\r
409 size_t passwordlen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2), WM_GETTEXTLENGTH, 0, 0);
\r
411 if (! orig_service || ! orig_service->username || ! str_equiv(service->username, orig_service->username) || service->passwordlen || passwordlen) {
\r
412 if (! service->passwordlen) {
\r
413 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
416 if (passwordlen != service->passwordlen) {
\r
417 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
420 service->passwordlen++;
\r
422 /* Temporary buffer for password validation. */
\r
423 TCHAR *password = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->passwordlen * sizeof(TCHAR));
\r
425 HeapFree(GetProcessHeap(), 0, service->username);
\r
426 service->username = 0;
\r
427 service->usernamelen = 0;
\r
428 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("password confirmation"), _T("install()"));
\r
432 /* Actual password buffer. */
\r
433 service->password = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->passwordlen * sizeof(TCHAR));
\r
434 if (! service->password) {
\r
435 HeapFree(GetProcessHeap(), 0, password);
\r
436 HeapFree(GetProcessHeap(), 0, service->username);
\r
437 service->username = 0;
\r
438 service->usernamelen = 0;
\r
439 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("password"), _T("install()"));
\r
443 /* Get first password. */
\r
444 if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1, service->password, (int) service->passwordlen)) {
\r
445 HeapFree(GetProcessHeap(), 0, password);
\r
446 SecureZeroMemory(service->password, service->passwordlen);
\r
447 HeapFree(GetProcessHeap(), 0, service->password);
\r
448 service->password = 0;
\r
449 service->passwordlen = 0;
\r
450 HeapFree(GetProcessHeap(), 0, service->username);
\r
451 service->username = 0;
\r
452 service->usernamelen = 0;
\r
453 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_PASSWORD);
\r
457 /* Get confirmation. */
\r
458 if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2, password, (int) service->passwordlen)) {
\r
459 SecureZeroMemory(password, service->passwordlen);
\r
460 HeapFree(GetProcessHeap(), 0, password);
\r
461 SecureZeroMemory(service->password, service->passwordlen);
\r
462 HeapFree(GetProcessHeap(), 0, service->password);
\r
463 service->password = 0;
\r
464 service->passwordlen = 0;
\r
465 HeapFree(GetProcessHeap(), 0, service->username);
\r
466 service->username = 0;
\r
467 service->usernamelen = 0;
\r
468 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_PASSWORD);
\r
473 if (_tcsncmp(password, service->password, service->passwordlen)) {
\r
474 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
475 SecureZeroMemory(password, service->passwordlen);
\r
476 HeapFree(GetProcessHeap(), 0, password);
\r
477 SecureZeroMemory(service->password, service->passwordlen);
\r
478 HeapFree(GetProcessHeap(), 0, service->password);
\r
479 service->password = 0;
\r
480 service->passwordlen = 0;
\r
481 HeapFree(GetProcessHeap(), 0, service->username);
\r
482 service->username = 0;
\r
483 service->usernamelen = 0;
\r
490 /* Get dependencies. */
\r
491 unsigned long dependencieslen = (unsigned long) SendMessage(GetDlgItem(tablist[NSSM_TAB_DEPENDENCIES], IDC_DEPENDENCIES), WM_GETTEXTLENGTH, 0, 0);
\r
492 if (dependencieslen) {
\r
493 TCHAR *dependencies = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (dependencieslen + 2) * sizeof(TCHAR));
\r
494 if (! dependencies) {
\r
495 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("dependencies"), _T("install()"));
\r
496 cleanup_nssm_service(service);
\r
500 if (! GetDlgItemText(tablist[NSSM_TAB_DEPENDENCIES], IDC_DEPENDENCIES, dependencies, dependencieslen + 1)) {
\r
501 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DEPENDENCIES);
\r
502 HeapFree(GetProcessHeap(), 0, dependencies);
\r
503 cleanup_nssm_service(service);
\r
507 if (unformat_double_null(dependencies, dependencieslen, &service->dependencies, &service->dependencieslen)) {
\r
508 HeapFree(GetProcessHeap(), 0, dependencies);
\r
509 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("dependencies"), _T("install()"));
\r
510 cleanup_nssm_service(service);
\r
514 HeapFree(GetProcessHeap(), 0, dependencies);
\r
517 /* Remaining tabs are only for services we manage. */
\r
518 if (service->native) return 0;
\r
520 /* Get process stuff. */
\r
521 combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY);
\r
522 service->priority = priority_index_to_constant((unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0));
\r
524 service->affinity = 0LL;
\r
525 if (! (SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_GETCHECK, 0, 0) & BST_CHECKED)) {
\r
526 HWND list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY);
\r
527 int selected = (int) SendMessage(list, LB_GETSELCOUNT, 0, 0);
\r
528 int count = (int) SendMessage(list, LB_GETCOUNT, 0, 0);
\r
530 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_WARN_AFFINITY_NONE);
\r
533 else if (selected < count) {
\r
534 for (int i = 0; i < count; i++) {
\r
535 if (SendMessage(list, LB_GETSEL, i, 0)) service->affinity |= (1LL << (__int64) i);
\r
540 if (SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_GETCHECK, 0, 0) & BST_CHECKED) service->no_console = 0;
\r
541 else service->no_console = 1;
\r
543 /* Get stop method stuff. */
\r
544 check_stop_method(service, NSSM_STOP_METHOD_CONSOLE, IDC_METHOD_CONSOLE);
\r
545 check_stop_method(service, NSSM_STOP_METHOD_WINDOW, IDC_METHOD_WINDOW);
\r
546 check_stop_method(service, NSSM_STOP_METHOD_THREADS, IDC_METHOD_THREADS);
\r
547 check_stop_method(service, NSSM_STOP_METHOD_TERMINATE, IDC_METHOD_TERMINATE);
\r
548 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, &service->kill_console_delay);
\r
549 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, &service->kill_window_delay);
\r
550 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, &service->kill_threads_delay);
\r
551 if (SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_PROCESS_TREE, BM_GETCHECK, 0, 0) & BST_CHECKED) service->kill_process_tree = 1;
\r
552 else service->kill_process_tree = 0;
\r
554 /* Get exit action stuff. */
\r
555 check_number(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, &service->throttle_delay);
\r
556 combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
\r
557 service->default_exit_action = (unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0);
\r
558 if (service->default_exit_action == CB_ERR) service->default_exit_action = 0;
\r
559 check_number(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, &service->restart_delay);
\r
561 /* Get I/O stuff. */
\r
562 check_io(window, _T("stdin"), service->stdin_path, _countof(service->stdin_path), IDC_STDIN);
\r
563 check_io(window, _T("stdout"), service->stdout_path, _countof(service->stdout_path), IDC_STDOUT);
\r
564 check_io(window, _T("stderr"), service->stderr_path, _countof(service->stderr_path), IDC_STDERR);
\r
566 /* Override stdout and/or stderr. */
\r
567 if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_TRUNCATE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
568 if (service->stdout_path[0]) service->stdout_disposition = CREATE_ALWAYS;
\r
569 if (service->stderr_path[0]) service->stderr_disposition = CREATE_ALWAYS;
\r
572 /* Get rotation stuff. */
\r
573 if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
574 service->rotate_files = true;
\r
575 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;
\r
576 check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, &service->rotate_seconds);
\r
577 check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, &service->rotate_bytes_low);
\r
580 /* Get environment. */
\r
581 unsigned long envlen = (unsigned long) SendMessage(GetDlgItem(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT), WM_GETTEXTLENGTH, 0, 0);
\r
583 TCHAR *env = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (envlen + 2) * sizeof(TCHAR));
\r
585 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("install()"));
\r
586 cleanup_nssm_service(service);
\r
590 if (! GetDlgItemText(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT, env, envlen + 1)) {
\r
591 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT);
\r
592 HeapFree(GetProcessHeap(), 0, env);
\r
593 cleanup_nssm_service(service);
\r
598 unsigned long newlen;
\r
599 if (unformat_double_null(env, envlen, &newenv, &newlen)) {
\r
600 HeapFree(GetProcessHeap(), 0, env);
\r
601 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("install()"));
\r
602 cleanup_nssm_service(service);
\r
606 HeapFree(GetProcessHeap(), 0, env);
\r
610 /* Test the environment is valid. */
\r
611 if (test_environment(env)) {
\r
612 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT);
\r
613 HeapFree(GetProcessHeap(), 0, env);
\r
614 cleanup_nssm_service(service);
\r
618 if (SendDlgItemMessage(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT_REPLACE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
619 service->env = env;
\r
620 service->envlen = envlen;
\r
623 service->env_extra = env;
\r
624 service->env_extralen = envlen;
\r
631 /* Install the service. */
\r
632 int install(HWND window) {
\r
633 if (! window) return 1;
\r
635 nssm_service_t *service = alloc_nssm_service();
\r
637 int ret = configure(window, service, 0);
\r
638 if (ret) return ret;
\r
641 /* See if it works. */
\r
642 switch (install_service(service)) {
\r
644 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("install()"));
\r
645 cleanup_nssm_service(service);
\r
649 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);
\r
650 cleanup_nssm_service(service);
\r
654 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, NSSM);
\r
655 cleanup_nssm_service(service);
\r
659 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_OUT_OF_MEMORY_FOR_IMAGEPATH);
\r
660 cleanup_nssm_service(service);
\r
664 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INSTALL_SERVICE_FAILED);
\r
665 cleanup_nssm_service(service);
\r
669 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_CREATE_PARAMETERS_FAILED);
\r
670 cleanup_nssm_service(service);
\r
674 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_INSTALLED, service->name);
\r
675 cleanup_nssm_service(service);
\r
679 /* Remove the service */
\r
680 int remove(HWND window) {
\r
681 if (! window) return 1;
\r
683 /* See if it works */
\r
684 nssm_service_t *service = alloc_nssm_service();
\r
686 /* Get service name */
\r
687 if (! GetDlgItemText(window, IDC_NAME, service->name, _countof(service->name))) {
\r
688 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_SERVICE_NAME);
\r
689 cleanup_nssm_service(service);
\r
694 if (popup_message(window, MB_YESNO, NSSM_GUI_ASK_REMOVE_SERVICE, service->name) != IDYES) {
\r
695 cleanup_nssm_service(service);
\r
700 switch (remove_service(service)) {
\r
702 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("remove()"));
\r
703 cleanup_nssm_service(service);
\r
707 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);
\r
708 cleanup_nssm_service(service);
\r
712 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_SERVICE_NOT_INSTALLED);
\r
714 cleanup_nssm_service(service);
\r
717 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_REMOVE_SERVICE_FAILED);
\r
718 cleanup_nssm_service(service);
\r
722 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_REMOVED, service->name);
\r
723 cleanup_nssm_service(service);
\r
727 int edit(HWND window, nssm_service_t *orig_service) {
\r
728 if (! window) return 1;
\r
730 nssm_service_t *service = alloc_nssm_service();
\r
732 int ret = configure(window, service, orig_service);
\r
733 if (ret) return ret;
\r
736 switch (edit_service(service, true)) {
\r
738 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("edit()"));
\r
739 cleanup_nssm_service(service);
\r
743 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, NSSM);
\r
744 cleanup_nssm_service(service);
\r
748 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_OUT_OF_MEMORY_FOR_IMAGEPATH);
\r
749 cleanup_nssm_service(service);
\r
754 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_EDIT_PARAMETERS_FAILED);
\r
755 cleanup_nssm_service(service);
\r
759 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_EDITED, service->name);
\r
760 cleanup_nssm_service(service);
\r
764 static TCHAR *browse_filter(int message) {
\r
766 case NSSM_GUI_BROWSE_FILTER_APPLICATIONS: return _T("*.exe;*.bat;*.cmd");
\r
767 case NSSM_GUI_BROWSE_FILTER_DIRECTORIES: return _T(".");
\r
768 case NSSM_GUI_BROWSE_FILTER_ALL_FILES: /* Fall through. */
\r
769 default: return _T("*.*");
\r
773 UINT_PTR CALLBACK browse_hook(HWND dlg, UINT message, WPARAM w, LPARAM l) {
\r
775 case WM_INITDIALOG:
\r
782 /* Browse for application */
\r
783 void browse(HWND window, TCHAR *current, unsigned long flags, ...) {
\r
784 if (! window) return;
\r
787 size_t bufsize = 256;
\r
788 size_t len = bufsize;
\r
792 ZeroMemory(&ofn, sizeof(ofn));
\r
793 ofn.lStructSize = sizeof(ofn);
\r
794 ofn.lpstrFilter = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, bufsize * sizeof(TCHAR));
\r
795 /* XXX: Escaping nulls with FormatMessage is tricky */
\r
796 if (ofn.lpstrFilter) {
\r
797 ZeroMemory((void *) ofn.lpstrFilter, bufsize);
\r
799 /* "Applications" + NULL + "*.exe" + NULL */
\r
800 va_start(arg, flags);
\r
801 while (i = va_arg(arg, int)) {
\r
802 TCHAR *localised = message_string(i);
\r
803 _sntprintf_s((TCHAR *) ofn.lpstrFilter + len, bufsize, _TRUNCATE, localised);
\r
804 len += _tcslen(localised) + 1;
\r
805 LocalFree(localised);
\r
806 TCHAR *filter = browse_filter(i);
\r
807 _sntprintf_s((TCHAR *) ofn.lpstrFilter + len, bufsize - len, _TRUNCATE, _T("%s"), filter);
\r
808 len += _tcslen(filter) + 1;
\r
811 /* Remainder of the buffer is already zeroed */
\r
813 ofn.lpstrFile = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, PATH_LENGTH * sizeof(TCHAR));
\r
814 if (ofn.lpstrFile) {
\r
815 if (flags & OFN_NOVALIDATE) {
\r
816 /* Directory hack. */
\r
817 _sntprintf_s(ofn.lpstrFile, PATH_LENGTH, _TRUNCATE, _T(":%s:"), message_string(NSSM_GUI_BROWSE_FILTER_DIRECTORIES));
\r
818 ofn.nMaxFile = DIR_LENGTH;
\r
821 _sntprintf_s(ofn.lpstrFile, PATH_LENGTH, _TRUNCATE, _T("%s"), current);
\r
822 ofn.nMaxFile = PATH_LENGTH;
\r
825 ofn.lpstrTitle = message_string(NSSM_GUI_BROWSE_TITLE);
\r
826 ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | flags;
\r
828 if (GetOpenFileName(&ofn)) {
\r
829 /* Directory hack. */
\r
830 if (flags & OFN_NOVALIDATE) strip_basename(ofn.lpstrFile);
\r
831 SendMessage(window, WM_SETTEXT, 0, (LPARAM) ofn.lpstrFile);
\r
833 if (ofn.lpstrFilter) HeapFree(GetProcessHeap(), 0, (void *) ofn.lpstrFilter);
\r
834 if (ofn.lpstrFile) HeapFree(GetProcessHeap(), 0, ofn.lpstrFile);
\r
837 INT_PTR CALLBACK tab_dlg(HWND tab, UINT message, WPARAM w, LPARAM l) {
\r
839 case WM_INITDIALOG:
\r
842 /* Button was pressed or control was controlled. */
\r
845 TCHAR buffer[PATH_LENGTH];
\r
846 unsigned char enabled;
\r
848 switch (LOWORD(w)) {
\r
849 /* Browse for application. */
\r
851 dlg = GetDlgItem(tab, IDC_PATH);
\r
852 GetDlgItemText(tab, IDC_PATH, buffer, _countof(buffer));
\r
853 browse(dlg, buffer, OFN_FILEMUSTEXIST, NSSM_GUI_BROWSE_FILTER_APPLICATIONS, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
854 /* Fill in startup directory if it wasn't already specified. */
\r
855 GetDlgItemText(tab, IDC_DIR, buffer, _countof(buffer));
\r
857 GetDlgItemText(tab, IDC_PATH, buffer, _countof(buffer));
\r
858 strip_basename(buffer);
\r
859 SetDlgItemText(tab, IDC_DIR, buffer);
\r
863 /* Browse for startup directory. */
\r
864 case IDC_BROWSE_DIR:
\r
865 dlg = GetDlgItem(tab, IDC_DIR);
\r
866 GetDlgItemText(tab, IDC_DIR, buffer, _countof(buffer));
\r
867 browse(dlg, buffer, OFN_NOVALIDATE, NSSM_GUI_BROWSE_FILTER_DIRECTORIES, 0);
\r
871 case IDC_LOCALSYSTEM:
\r
872 set_logon_enabled(0);
\r
876 set_logon_enabled(1);
\r
880 case IDC_AFFINITY_ALL:
\r
881 if (SendDlgItemMessage(tab, LOWORD(w), BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 0;
\r
883 set_affinity_enabled(enabled);
\r
886 /* Shutdown methods. */
\r
887 case IDC_METHOD_CONSOLE:
\r
888 set_timeout_enabled(LOWORD(w), IDC_KILL_CONSOLE);
\r
891 case IDC_METHOD_WINDOW:
\r
892 set_timeout_enabled(LOWORD(w), IDC_KILL_WINDOW);
\r
895 case IDC_METHOD_THREADS:
\r
896 set_timeout_enabled(LOWORD(w), IDC_KILL_THREADS);
\r
899 /* Browse for stdin. */
\r
900 case IDC_BROWSE_STDIN:
\r
901 dlg = GetDlgItem(tab, IDC_STDIN);
\r
902 GetDlgItemText(tab, IDC_STDIN, buffer, _countof(buffer));
\r
903 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
906 /* Browse for stdout. */
\r
907 case IDC_BROWSE_STDOUT:
\r
908 dlg = GetDlgItem(tab, IDC_STDOUT);
\r
909 GetDlgItemText(tab, IDC_STDOUT, buffer, _countof(buffer));
\r
910 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
911 /* Fill in stderr if it wasn't already specified. */
\r
912 GetDlgItemText(tab, IDC_STDERR, buffer, _countof(buffer));
\r
914 GetDlgItemText(tab, IDC_STDOUT, buffer, _countof(buffer));
\r
915 SetDlgItemText(tab, IDC_STDERR, buffer);
\r
919 /* Browse for stderr. */
\r
920 case IDC_BROWSE_STDERR:
\r
921 dlg = GetDlgItem(tab, IDC_STDERR);
\r
922 GetDlgItemText(tab, IDC_STDERR, buffer, _countof(buffer));
\r
923 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
928 if (SendDlgItemMessage(tab, LOWORD(w), BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 1;
\r
930 set_rotation_enabled(enabled);
\r
939 /* Install/remove dialogue callback */
\r
940 INT_PTR CALLBACK nssm_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {
\r
941 nssm_service_t *service;
\r
944 /* Creating the dialogue */
\r
945 case WM_INITDIALOG:
\r
946 service = (nssm_service_t *) l;
\r
948 SetFocus(GetDlgItem(window, IDC_NAME));
\r
954 tabs = GetDlgItem(window, IDC_TAB1);
\r
955 if (! tabs) return 0;
\r
959 ZeroMemory(&tab, sizeof(tab));
\r
960 tab.mask = TCIF_TEXT;
\r
964 /* Application tab. */
\r
965 if (service->native) tab.pszText = message_string(NSSM_GUI_TAB_NATIVE);
\r
966 else tab.pszText = message_string(NSSM_GUI_TAB_APPLICATION);
\r
967 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
968 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_APPLICATION, (LPARAM) &tab);
\r
969 if (service->native) {
\r
970 tablist[NSSM_TAB_APPLICATION] = dialog(MAKEINTRESOURCE(IDD_NATIVE), window, tab_dlg);
\r
971 EnableWindow(tablist[NSSM_TAB_APPLICATION], 0);
\r
972 EnableWindow(GetDlgItem(tablist[NSSM_TAB_APPLICATION], IDC_PATH), 0);
\r
974 else tablist[NSSM_TAB_APPLICATION] = dialog(MAKEINTRESOURCE(IDD_APPLICATION), window, tab_dlg);
\r
975 ShowWindow(tablist[NSSM_TAB_APPLICATION], SW_SHOW);
\r
978 tab.pszText = message_string(NSSM_GUI_TAB_DETAILS);
\r
979 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
980 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_DETAILS, (LPARAM) &tab);
\r
981 tablist[NSSM_TAB_DETAILS] = dialog(MAKEINTRESOURCE(IDD_DETAILS), window, tab_dlg);
\r
982 ShowWindow(tablist[NSSM_TAB_DETAILS], SW_HIDE);
\r
984 /* Set defaults. */
\r
985 combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP);
\r
986 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_AUTOMATIC, (LPARAM) message_string(NSSM_GUI_STARTUP_AUTOMATIC));
\r
987 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DELAYED, (LPARAM) message_string(NSSM_GUI_STARTUP_DELAYED));
\r
988 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_MANUAL, (LPARAM) message_string(NSSM_GUI_STARTUP_MANUAL));
\r
989 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DISABLED, (LPARAM) message_string(NSSM_GUI_STARTUP_DISABLED));
\r
990 SendMessage(combo, CB_SETCURSEL, NSSM_STARTUP_AUTOMATIC, 0);
\r
993 tab.pszText = message_string(NSSM_GUI_TAB_LOGON);
\r
994 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
995 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_LOGON, (LPARAM) &tab);
\r
996 tablist[NSSM_TAB_LOGON] = dialog(MAKEINTRESOURCE(IDD_LOGON), window, tab_dlg);
\r
997 ShowWindow(tablist[NSSM_TAB_LOGON], SW_HIDE);
\r
999 /* Set defaults. */
\r
1000 CheckRadioButton(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, IDC_ACCOUNT, IDC_LOCALSYSTEM);
\r
1001 set_logon_enabled(0);
\r
1003 /* Dependencies tab. */
\r
1004 tab.pszText = message_string(NSSM_GUI_TAB_DEPENDENCIES);
\r
1005 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1006 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_DEPENDENCIES, (LPARAM) &tab);
\r
1007 tablist[NSSM_TAB_DEPENDENCIES] = dialog(MAKEINTRESOURCE(IDD_DEPENDENCIES), window, tab_dlg);
\r
1008 ShowWindow(tablist[NSSM_TAB_DEPENDENCIES], SW_HIDE);
\r
1010 /* Remaining tabs are only for services we manage. */
\r
1011 if (service->native) return 1;
\r
1013 /* Process tab. */
\r
1014 tab.pszText = message_string(NSSM_GUI_TAB_PROCESS);
\r
1015 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1016 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_PROCESS, (LPARAM) &tab);
\r
1017 tablist[NSSM_TAB_PROCESS] = dialog(MAKEINTRESOURCE(IDD_PROCESS), window, tab_dlg);
\r
1018 ShowWindow(tablist[NSSM_TAB_PROCESS], SW_HIDE);
\r
1020 /* Set defaults. */
\r
1021 combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY);
\r
1022 SendMessage(combo, CB_INSERTSTRING, NSSM_REALTIME_PRIORITY, (LPARAM) message_string(NSSM_GUI_REALTIME_PRIORITY_CLASS));
\r
1023 SendMessage(combo, CB_INSERTSTRING, NSSM_HIGH_PRIORITY, (LPARAM) message_string(NSSM_GUI_HIGH_PRIORITY_CLASS));
\r
1024 SendMessage(combo, CB_INSERTSTRING, NSSM_ABOVE_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_ABOVE_NORMAL_PRIORITY_CLASS));
\r
1025 SendMessage(combo, CB_INSERTSTRING, NSSM_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_NORMAL_PRIORITY_CLASS));
\r
1026 SendMessage(combo, CB_INSERTSTRING, NSSM_BELOW_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_BELOW_NORMAL_PRIORITY_CLASS));
\r
1027 SendMessage(combo, CB_INSERTSTRING, NSSM_IDLE_PRIORITY, (LPARAM) message_string(NSSM_GUI_IDLE_PRIORITY_CLASS));
\r
1028 SendMessage(combo, CB_SETCURSEL, NSSM_NORMAL_PRIORITY, 0);
\r
1030 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_SETCHECK, BST_CHECKED, 0);
\r
1032 list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY);
\r
1034 SendMessage(list, LB_SETCOLUMNWIDTH, 16, 0);
\r
1035 for (i = 0; i < n; i++) {
\r
1037 _sntprintf_s(buffer, _countof(buffer), _TRUNCATE, _T("%d"), i);
\r
1038 SendMessage(list, LB_ADDSTRING, 0, (LPARAM) buffer);
\r
1043 The box is high enough for four rows. It is wide enough for eight
\r
1044 columns without scrolling. With scrollbars it shrinks to two rows.
\r
1045 Note that the above only holds if we set the column width BEFORE
\r
1046 adding the strings.
\r
1049 int columns = (n - 1) / 4;
\r
1051 GetWindowRect(list, &rect);
\r
1052 int width = rect.right - rect.left;
\r
1053 width -= (7 - columns) * 16;
\r
1054 int height = rect.bottom - rect.top;
\r
1055 if (n < 4) height -= (int) SendMessage(list, LB_GETITEMHEIGHT, 0, 0) * (4 - n);
\r
1056 SetWindowPos(list, 0, 0, 0, width, height, SWP_NOMOVE | SWP_NOOWNERZORDER);
\r
1058 SendMessage(list, LB_SELITEMRANGE, 1, MAKELPARAM(0, n));
\r
1060 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_SETCHECK, BST_CHECKED, 0);
\r
1061 set_affinity_enabled(0);
\r
1063 /* Shutdown tab. */
\r
1064 tab.pszText = message_string(NSSM_GUI_TAB_SHUTDOWN);
\r
1065 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1066 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_SHUTDOWN, (LPARAM) &tab);
\r
1067 tablist[NSSM_TAB_SHUTDOWN] = dialog(MAKEINTRESOURCE(IDD_SHUTDOWN), window, tab_dlg);
\r
1068 ShowWindow(tablist[NSSM_TAB_SHUTDOWN], SW_HIDE);
\r
1070 /* Set defaults. */
\r
1071 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_CONSOLE, BM_SETCHECK, BST_CHECKED, 0);
\r
1072 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, NSSM_KILL_CONSOLE_GRACE_PERIOD, 0);
\r
1073 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_WINDOW, BM_SETCHECK, BST_CHECKED, 0);
\r
1074 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, NSSM_KILL_WINDOW_GRACE_PERIOD, 0);
\r
1075 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_THREADS, BM_SETCHECK, BST_CHECKED, 0);
\r
1076 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, NSSM_KILL_THREADS_GRACE_PERIOD, 0);
\r
1077 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_TERMINATE, BM_SETCHECK, BST_CHECKED, 0);
\r
1078 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_PROCESS_TREE, BM_SETCHECK, BST_CHECKED, 1);
\r
1080 /* Restart tab. */
\r
1081 tab.pszText = message_string(NSSM_GUI_TAB_EXIT);
\r
1082 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1083 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_EXIT, (LPARAM) &tab);
\r
1084 tablist[NSSM_TAB_EXIT] = dialog(MAKEINTRESOURCE(IDD_APPEXIT), window, tab_dlg);
\r
1085 ShowWindow(tablist[NSSM_TAB_EXIT], SW_HIDE);
\r
1087 /* Set defaults. */
\r
1088 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, NSSM_RESET_THROTTLE_RESTART, 0);
\r
1089 combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
\r
1090 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_RESTART, (LPARAM) message_string(NSSM_GUI_EXIT_RESTART));
\r
1091 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_IGNORE, (LPARAM) message_string(NSSM_GUI_EXIT_IGNORE));
\r
1092 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_REALLY, (LPARAM) message_string(NSSM_GUI_EXIT_REALLY));
\r
1093 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_UNCLEAN, (LPARAM) message_string(NSSM_GUI_EXIT_UNCLEAN));
\r
1094 SendMessage(combo, CB_SETCURSEL, NSSM_EXIT_RESTART, 0);
\r
1095 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, 0, 0);
\r
1098 tab.pszText = message_string(NSSM_GUI_TAB_IO);
\r
1099 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1100 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_IO, (LPARAM) &tab);
\r
1101 tablist[NSSM_TAB_IO] = dialog(MAKEINTRESOURCE(IDD_IO), window, tab_dlg);
\r
1102 ShowWindow(tablist[NSSM_TAB_IO], SW_HIDE);
\r
1104 /* Rotation tab. */
\r
1105 tab.pszText = message_string(NSSM_GUI_TAB_ROTATION);
\r
1106 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1107 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_ROTATION, (LPARAM) &tab);
\r
1108 tablist[NSSM_TAB_ROTATION] = dialog(MAKEINTRESOURCE(IDD_ROTATION), window, tab_dlg);
\r
1109 ShowWindow(tablist[NSSM_TAB_ROTATION], SW_HIDE);
\r
1111 /* Set defaults. */
\r
1112 SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_SETCHECK, BST_UNCHECKED, 0);
\r
1113 SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, 0, 0);
\r
1114 SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, 0, 0);
\r
1115 set_rotation_enabled(0);
\r
1117 /* Environment tab. */
\r
1118 tab.pszText = message_string(NSSM_GUI_TAB_ENVIRONMENT);
\r
1119 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1120 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_ENVIRONMENT, (LPARAM) &tab);
\r
1121 tablist[NSSM_TAB_ENVIRONMENT] = dialog(MAKEINTRESOURCE(IDD_ENVIRONMENT), window, tab_dlg);
\r
1122 ShowWindow(tablist[NSSM_TAB_ENVIRONMENT], SW_HIDE);
\r
1128 NMHDR *notification;
\r
1130 notification = (NMHDR *) l;
\r
1131 switch (notification->code) {
\r
1132 case TCN_SELCHANGE:
\r
1136 tabs = GetDlgItem(window, IDC_TAB1);
\r
1137 if (! tabs) return 0;
\r
1139 selection = (int) SendMessage(tabs, TCM_GETCURSEL, 0, 0);
\r
1140 if (selection != selected_tab) {
\r
1141 ShowWindow(tablist[selected_tab], SW_HIDE);
\r
1142 ShowWindow(tablist[selection], SW_SHOWDEFAULT);
\r
1143 SetFocus(GetDlgItem(window, IDOK));
\r
1144 selected_tab = selection;
\r
1151 /* Button was pressed or control was controlled */
\r
1153 switch (LOWORD(w)) {
\r
1156 if ((int) GetWindowLongPtr(window, GWLP_USERDATA) == IDD_EDIT) {
\r
1157 if (! edit(window, (nssm_service_t *) GetWindowLongPtr(window, DWLP_USER))) PostQuitMessage(0);
\r
1159 else if (! install(window)) PostQuitMessage(0);
\r
1162 /* Cancel button */
\r
1164 DestroyWindow(window);
\r
1167 /* Remove button */
\r
1169 if (! remove(window)) PostQuitMessage(0);
\r
1174 /* Window closing */
\r
1176 DestroyWindow(window);
\r
1179 PostQuitMessage(0);
\r