3 extern const TCHAR *hook_event_strings[];
\r
4 extern const TCHAR *hook_action_strings[];
\r
6 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_TAB_HOOKS, NSSM_NUM_TABS } nssm_tabs;
\r
7 static HWND tablist[NSSM_NUM_TABS];
\r
8 static int selected_tab;
\r
10 static HWND dialog(const TCHAR *templ, HWND parent, DLGPROC function, LPARAM l) {
\r
11 /* The caller will deal with GetLastError()... */
\r
12 HRSRC resource = FindResourceEx(0, RT_DIALOG, templ, GetUserDefaultLangID());
\r
14 if (GetLastError() != ERROR_RESOURCE_LANG_NOT_FOUND) return 0;
\r
15 resource = FindResourceEx(0, RT_DIALOG, templ, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
\r
16 if (! resource) return 0;
\r
19 HGLOBAL ret = LoadResource(0, resource);
\r
20 if (! ret) return 0;
\r
22 return CreateDialogIndirectParam(0, (DLGTEMPLATE *) ret, parent, function, l);
\r
25 static HWND dialog(const TCHAR *templ, HWND parent, DLGPROC function) {
\r
26 return dialog(templ, parent, function, 0);
\r
29 static inline void set_logon_enabled(unsigned char interact_enabled, unsigned char credentials_enabled) {
\r
30 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_INTERACT), interact_enabled);
\r
31 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_USERNAME), credentials_enabled);
\r
32 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1), credentials_enabled);
\r
33 EnableWindow(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2), credentials_enabled);
\r
36 int nssm_gui(int resource, nssm_service_t *service) {
\r
38 HWND dlg = dialog(MAKEINTRESOURCE(resource), 0, nssm_dlg, (LPARAM) service);
\r
40 popup_message(0, MB_OK, NSSM_GUI_CREATEDIALOG_FAILED, error_string(GetLastError()));
\r
44 /* Load the icon. */
\r
45 HANDLE icon = LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDI_NSSM), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);
\r
46 if (icon) SendMessage(dlg, WM_SETICON, ICON_SMALL, (LPARAM) icon);
\r
47 icon = LoadImage(GetModuleHandle(0), MAKEINTRESOURCE(IDI_NSSM), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0);
\r
48 if (icon) SendMessage(dlg, WM_SETICON, ICON_BIG, (LPARAM) icon);
\r
50 /* Remember what the window is for. */
\r
51 SetWindowLongPtr(dlg, GWLP_USERDATA, (LONG_PTR) resource);
\r
53 /* Display the window */
\r
55 ShowWindow(dlg, SW_SHOW);
\r
57 /* Set service name if given */
\r
58 if (service->name[0]) {
\r
59 SetDlgItemText(dlg, IDC_NAME, service->name);
\r
60 /* No point making user click remove if the name is already entered */
\r
61 if (resource == IDD_REMOVE) {
\r
62 HWND button = GetDlgItem(dlg, IDC_REMOVE);
\r
64 SendMessage(button, WM_LBUTTONDOWN, 0, 0);
\r
65 SendMessage(button, WM_LBUTTONUP, 0, 0);
\r
70 if (resource == IDD_EDIT) {
\r
71 /* We'll need the service handle later. */
\r
72 SetWindowLongPtr(dlg, DWLP_USER, (LONG_PTR) service);
\r
74 /* Service name can't be edited. */
\r
75 EnableWindow(GetDlgItem(dlg, IDC_NAME), 0);
\r
76 SetFocus(GetDlgItem(dlg, IDOK));
\r
78 /* Set existing details. */
\r
82 /* Application tab. */
\r
83 if (service->native) SetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_PATH, service->image);
\r
84 else SetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_PATH, service->exe);
\r
85 SetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_DIR, service->dir);
\r
86 SetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_FLAGS, service->flags);
\r
89 SetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DISPLAYNAME, service->displayname);
\r
90 SetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DESCRIPTION, service->description);
\r
91 combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP);
\r
92 SendMessage(combo, CB_SETCURSEL, service->startup, 0);
\r
95 if (service->username) {
\r
96 if (is_virtual_account(service->name, service->username)) {
\r
97 CheckRadioButton(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, IDC_VIRTUAL_SERVICE, IDC_VIRTUAL_SERVICE);
\r
98 set_logon_enabled(0, 0);
\r
101 CheckRadioButton(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, IDC_VIRTUAL_SERVICE, IDC_ACCOUNT);
\r
102 SetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_USERNAME, service->username);
\r
103 set_logon_enabled(0, 1);
\r
107 CheckRadioButton(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, IDC_VIRTUAL_SERVICE, IDC_LOCALSYSTEM);
\r
108 if (service->type & SERVICE_INTERACTIVE_PROCESS) SendDlgItemMessage(tablist[NSSM_TAB_LOGON], IDC_INTERACT, BM_SETCHECK, BST_CHECKED, 0);
\r
111 /* Dependencies tab. */
\r
112 if (service->dependencieslen) {
\r
114 unsigned long newlen;
\r
115 if (format_double_null(service->dependencies, service->dependencieslen, &formatted, &newlen)) {
\r
116 popup_message(dlg, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("dependencies"), _T("nssm_dlg()"));
\r
119 SetDlgItemText(tablist[NSSM_TAB_DEPENDENCIES], IDC_DEPENDENCIES, formatted);
\r
120 HeapFree(GetProcessHeap(), 0, formatted);
\r
125 if (service->priority) {
\r
126 int priority = priority_constant_to_index(service->priority);
\r
127 combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY);
\r
128 SendMessage(combo, CB_SETCURSEL, priority, 0);
\r
131 if (service->affinity) {
\r
132 list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY);
\r
133 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_SETCHECK, BST_UNCHECKED, 0);
\r
134 EnableWindow(GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY), 1);
\r
136 DWORD_PTR affinity, system_affinity;
\r
137 if (GetProcessAffinityMask(GetCurrentProcess(), &affinity, &system_affinity)) {
\r
138 if ((service->affinity & (__int64) system_affinity) != service->affinity) popup_message(dlg, MB_OK | MB_ICONWARNING, NSSM_GUI_WARN_AFFINITY);
\r
141 for (int i = 0; i < num_cpus(); i++) {
\r
142 if (! (service->affinity & (1LL << (__int64) i))) SendMessage(list, LB_SETSEL, 0, i);
\r
146 if (service->no_console) {
\r
147 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_SETCHECK, BST_UNCHECKED, 0);
\r
150 /* Shutdown tab. */
\r
151 if (! (service->stop_method & NSSM_STOP_METHOD_CONSOLE)) {
\r
152 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_CONSOLE, BM_SETCHECK, BST_UNCHECKED, 0);
\r
153 EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE), 0);
\r
155 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, service->kill_console_delay, 0);
\r
156 if (! (service->stop_method & NSSM_STOP_METHOD_WINDOW)) {
\r
157 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_WINDOW, BM_SETCHECK, BST_UNCHECKED, 0);
\r
158 EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW), 0);
\r
160 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, service->kill_window_delay, 0);
\r
161 if (! (service->stop_method & NSSM_STOP_METHOD_THREADS)) {
\r
162 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_THREADS, BM_SETCHECK, BST_UNCHECKED, 0);
\r
163 EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS), 0);
\r
165 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, service->kill_threads_delay, 0);
\r
166 if (! (service->stop_method & NSSM_STOP_METHOD_TERMINATE)) {
\r
167 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_TERMINATE, BM_SETCHECK, BST_UNCHECKED, 0);
\r
169 if (! service->kill_process_tree) {
\r
170 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_PROCESS_TREE, BM_SETCHECK, BST_UNCHECKED, 0);
\r
174 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, service->throttle_delay, 0);
\r
175 combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
\r
176 SendMessage(combo, CB_SETCURSEL, service->default_exit_action, 0);
\r
177 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, service->restart_delay, 0);
\r
180 SetDlgItemText(tablist[NSSM_TAB_IO], IDC_STDIN, service->stdin_path);
\r
181 SetDlgItemText(tablist[NSSM_TAB_IO], IDC_STDOUT, service->stdout_path);
\r
182 SetDlgItemText(tablist[NSSM_TAB_IO], IDC_STDERR, service->stderr_path);
\r
183 if (service->timestamp_log) SendDlgItemMessage(tablist[NSSM_TAB_IO], IDC_TIMESTAMP, BM_SETCHECK, BST_CHECKED, 0);
\r
185 /* Rotation tab. */
\r
186 if (service->stdout_disposition == CREATE_ALWAYS) SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_TRUNCATE, BM_SETCHECK, BST_CHECKED, 0);
\r
187 if (service->rotate_files) {
\r
188 SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE, BM_SETCHECK, BST_CHECKED, 0);
\r
189 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE), 1);
\r
190 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS), 1);
\r
191 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW), 1);
\r
193 if (service->rotate_stdout_online || service->rotate_stderr_online) SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_SETCHECK, BST_CHECKED, 0);
\r
194 SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, service->rotate_seconds, 0);
\r
195 if (! service->rotate_bytes_high) SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, service->rotate_bytes_low, 0);
\r
198 if (service->hook_share_output_handles) SendDlgItemMessage(tablist[NSSM_TAB_HOOKS], IDC_REDIRECT_HOOK, BM_SETCHECK, BST_CHECKED, 0);
\r
200 /* Check if advanced settings are in use. */
\r
201 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
202 if (service->rotate_bytes_high) popup_message(dlg, MB_OK | MB_ICONWARNING, NSSM_GUI_WARN_ROTATE_BYTES);
\r
204 /* Environment tab. */
\r
206 unsigned long envlen;
\r
207 if (service->env_extralen) {
\r
208 env = service->env_extra;
\r
209 envlen = service->env_extralen;
\r
212 env = service->env;
\r
213 envlen = service->envlen;
\r
214 if (envlen) SendDlgItemMessage(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT_REPLACE, BM_SETCHECK, BST_CHECKED, 0);
\r
219 unsigned long newlen;
\r
220 if (format_double_null(env, envlen, &formatted, &newlen)) {
\r
221 popup_message(dlg, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("nssm_dlg()"));
\r
224 SetDlgItemText(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT, formatted);
\r
225 HeapFree(GetProcessHeap(), 0, formatted);
\r
228 if (service->envlen && service->env_extralen) popup_message(dlg, MB_OK | MB_ICONWARNING, NSSM_GUI_WARN_ENVIRONMENT);
\r
233 while (GetMessage(&message, 0, 0, 0)) {
\r
234 if (IsDialogMessage(dlg, &message)) continue;
\r
235 TranslateMessage(&message);
\r
236 DispatchMessage(&message);
\r
239 return (int) message.wParam;
\r
242 void centre_window(HWND window) {
\r
244 RECT size, desktop_size;
\r
245 unsigned long x, y;
\r
247 if (! window) return;
\r
249 /* Find window size */
\r
250 if (! GetWindowRect(window, &size)) return;
\r
252 /* Find desktop window */
\r
253 desktop = GetDesktopWindow();
\r
254 if (! desktop) return;
\r
256 /* Find desktop window size */
\r
257 if (! GetWindowRect(desktop, &desktop_size)) return;
\r
259 /* Centre window */
\r
260 x = (desktop_size.right - size.right) / 2;
\r
261 y = (desktop_size.bottom - size.bottom) / 2;
\r
262 MoveWindow(window, x, y, size.right - size.left, size.bottom - size.top, 0);
\r
265 static inline void check_stop_method(nssm_service_t *service, unsigned long method, unsigned long control) {
\r
266 if (SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], control, BM_GETCHECK, 0, 0) & BST_CHECKED) return;
\r
267 service->stop_method &= ~method;
\r
270 static inline void check_number(HWND tab, unsigned long control, unsigned long *timeout) {
\r
272 unsigned long configured = GetDlgItemInt(tab, control, &translated, 0);
\r
273 if (translated) *timeout = configured;
\r
276 static inline void set_timeout_enabled(unsigned long control, unsigned long dependent) {
\r
277 unsigned char enabled = 0;
\r
278 if (SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], control, BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 1;
\r
279 EnableWindow(GetDlgItem(tablist[NSSM_TAB_SHUTDOWN], dependent), enabled);
\r
282 static inline void set_affinity_enabled(unsigned char enabled) {
\r
283 EnableWindow(GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY), enabled);
\r
286 static inline void set_rotation_enabled(unsigned char enabled) {
\r
287 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE), enabled);
\r
288 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS), enabled);
\r
289 EnableWindow(GetDlgItem(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW), enabled);
\r
292 static inline int hook_env(const TCHAR *hook_event, const TCHAR *hook_action, TCHAR *buffer, unsigned long buflen) {
\r
293 return _sntprintf_s(buffer, buflen, _TRUNCATE, _T("NSSM_HOOK_%s_%s"), hook_event, hook_action);
\r
296 static inline void set_hook_tab(int event_index, int action_index, bool changed) {
\r
297 int first_event = NSSM_GUI_HOOK_EVENT_START;
\r
299 combo = GetDlgItem(tablist[NSSM_TAB_HOOKS], IDC_HOOK_EVENT);
\r
300 SendMessage(combo, CB_SETCURSEL, event_index, 0);
\r
301 combo = GetDlgItem(tablist[NSSM_TAB_HOOKS], IDC_HOOK_ACTION);
\r
302 SendMessage(combo, CB_RESETCONTENT, 0, 0);
\r
304 const TCHAR *hook_event = hook_event_strings[event_index];
\r
305 TCHAR *hook_action;
\r
307 switch (event_index + first_event) {
\r
308 case NSSM_GUI_HOOK_EVENT_ROTATE:
\r
310 SendMessage(combo, CB_INSERTSTRING, i, (LPARAM) message_string(NSSM_GUI_HOOK_ACTION_ROTATE_PRE));
\r
311 if (action_index == i++) hook_action = NSSM_HOOK_ACTION_PRE;
\r
312 SendMessage(combo, CB_INSERTSTRING, i, (LPARAM) message_string(NSSM_GUI_HOOK_ACTION_ROTATE_POST));
\r
313 if (action_index == i++) hook_action = NSSM_HOOK_ACTION_POST;
\r
316 case NSSM_GUI_HOOK_EVENT_START:
\r
318 SendMessage(combo, CB_INSERTSTRING, i, (LPARAM) message_string(NSSM_GUI_HOOK_ACTION_START_PRE));
\r
319 if (action_index == i++) hook_action = NSSM_HOOK_ACTION_PRE;
\r
320 SendMessage(combo, CB_INSERTSTRING, i, (LPARAM) message_string(NSSM_GUI_HOOK_ACTION_START_POST));
\r
321 if (action_index == i++) hook_action = NSSM_HOOK_ACTION_POST;
\r
324 case NSSM_GUI_HOOK_EVENT_STOP:
\r
326 SendMessage(combo, CB_INSERTSTRING, i, (LPARAM) message_string(NSSM_GUI_HOOK_ACTION_STOP_PRE));
\r
327 if (action_index == i++) hook_action = NSSM_HOOK_ACTION_PRE;
\r
330 case NSSM_GUI_HOOK_EVENT_EXIT:
\r
332 SendMessage(combo, CB_INSERTSTRING, i, (LPARAM) message_string(NSSM_GUI_HOOK_ACTION_EXIT_POST));
\r
333 if (action_index == i++) hook_action = NSSM_HOOK_ACTION_POST;
\r
336 case NSSM_GUI_HOOK_EVENT_POWER:
\r
338 SendMessage(combo, CB_INSERTSTRING, i, (LPARAM) message_string(NSSM_GUI_HOOK_ACTION_POWER_CHANGE));
\r
339 if (action_index == i++) hook_action = NSSM_HOOK_ACTION_CHANGE;
\r
340 SendMessage(combo, CB_INSERTSTRING, i, (LPARAM) message_string(NSSM_GUI_HOOK_ACTION_POWER_RESUME));
\r
341 if (action_index == i++) hook_action = NSSM_HOOK_ACTION_RESUME;
\r
345 SendMessage(combo, CB_SETCURSEL, action_index, 0);
\r
347 TCHAR hook_name[HOOK_NAME_LENGTH];
\r
348 hook_env(hook_event, hook_action, hook_name, _countof(hook_name));
\r
350 if (! *hook_name) return;
\r
352 TCHAR cmd[CMD_LENGTH];
\r
354 GetDlgItemText(tablist[NSSM_TAB_HOOKS], IDC_HOOK, cmd, _countof(cmd));
\r
355 SetEnvironmentVariable(hook_name, cmd);
\r
358 if (! GetEnvironmentVariable(hook_name, cmd, _countof(cmd))) cmd[0] = _T('\0');
\r
359 SetDlgItemText(tablist[NSSM_TAB_HOOKS], IDC_HOOK, cmd);
\r
363 static inline int update_hook(TCHAR *service_name, const TCHAR *hook_event, const TCHAR *hook_action) {
\r
364 TCHAR hook_name[HOOK_NAME_LENGTH];
\r
365 if (hook_env(hook_event, hook_action, hook_name, _countof(hook_name)) < 0) return 1;
\r
366 TCHAR cmd[CMD_LENGTH];
\r
367 ZeroMemory(cmd, sizeof(cmd));
\r
368 GetEnvironmentVariable(hook_name, cmd, _countof(cmd));
\r
369 if (set_hook(service_name, hook_event, hook_action, cmd)) return 2;
\r
373 static inline int update_hooks(TCHAR *service_name) {
\r
375 ret += update_hook(service_name, NSSM_HOOK_EVENT_START, NSSM_HOOK_ACTION_PRE);
\r
376 ret += update_hook(service_name, NSSM_HOOK_EVENT_START, NSSM_HOOK_ACTION_POST);
\r
377 ret += update_hook(service_name, NSSM_HOOK_EVENT_STOP, NSSM_HOOK_ACTION_PRE);
\r
378 ret += update_hook(service_name, NSSM_HOOK_EVENT_EXIT, NSSM_HOOK_ACTION_POST);
\r
379 ret += update_hook(service_name, NSSM_HOOK_EVENT_POWER, NSSM_HOOK_ACTION_CHANGE);
\r
380 ret += update_hook(service_name, NSSM_HOOK_EVENT_POWER, NSSM_HOOK_ACTION_RESUME);
\r
381 ret += update_hook(service_name, NSSM_HOOK_EVENT_ROTATE, NSSM_HOOK_ACTION_PRE);
\r
382 ret += update_hook(service_name, NSSM_HOOK_EVENT_ROTATE, NSSM_HOOK_ACTION_POST);
\r
386 static inline void check_io(HWND owner, TCHAR *name, TCHAR *buffer, unsigned long len, unsigned long control) {
\r
387 if (! SendMessage(GetDlgItem(tablist[NSSM_TAB_IO], control), WM_GETTEXTLENGTH, 0, 0)) return;
\r
388 if (GetDlgItemText(tablist[NSSM_TAB_IO], control, buffer, (int) len)) return;
\r
389 popup_message(owner, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, name);
\r
390 ZeroMemory(buffer, len * sizeof(TCHAR));
\r
393 /* Set service parameters. */
\r
394 int configure(HWND window, nssm_service_t *service, nssm_service_t *orig_service) {
\r
395 if (! service) return 1;
\r
397 set_nssm_service_defaults(service);
\r
399 if (orig_service) {
\r
400 service->native = orig_service->native;
\r
401 service->handle = orig_service->handle;
\r
404 /* Get service name. */
\r
405 if (! GetDlgItemText(window, IDC_NAME, service->name, _countof(service->name))) {
\r
406 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_SERVICE_NAME);
\r
407 cleanup_nssm_service(service);
\r
411 /* Get executable name */
\r
412 if (! service->native) {
\r
413 if (! GetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_PATH, service->exe, _countof(service->exe))) {
\r
414 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PATH);
\r
418 /* Get startup directory. */
\r
419 if (! GetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_DIR, service->dir, _countof(service->dir))) {
\r
420 _sntprintf_s(service->dir, _countof(service->dir), _TRUNCATE, _T("%s"), service->exe);
\r
421 strip_basename(service->dir);
\r
425 if (SendMessage(GetDlgItem(tablist[NSSM_TAB_APPLICATION], IDC_FLAGS), WM_GETTEXTLENGTH, 0, 0)) {
\r
426 if (! GetDlgItemText(tablist[NSSM_TAB_APPLICATION], IDC_FLAGS, service->flags, _countof(service->flags))) {
\r
427 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_OPTIONS);
\r
434 if (SendMessage(GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_DISPLAYNAME), WM_GETTEXTLENGTH, 0, 0)) {
\r
435 if (! GetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DISPLAYNAME, service->displayname, _countof(service->displayname))) {
\r
436 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DISPLAYNAME);
\r
441 if (SendMessage(GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_DESCRIPTION), WM_GETTEXTLENGTH, 0, 0)) {
\r
442 if (! GetDlgItemText(tablist[NSSM_TAB_DETAILS], IDC_DESCRIPTION, service->description, _countof(service->description))) {
\r
443 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DESCRIPTION);
\r
448 HWND combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP);
\r
449 service->startup = (unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0);
\r
450 if (service->startup == CB_ERR) service->startup = 0;
\r
452 /* Get logon stuff. */
\r
453 if (SendDlgItemMessage(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
454 if (SendDlgItemMessage(tablist[NSSM_TAB_LOGON], IDC_INTERACT, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
455 service->type |= SERVICE_INTERACTIVE_PROCESS;
\r
457 if (service->username) HeapFree(GetProcessHeap(), 0, service->username);
\r
458 service->username = 0;
\r
459 service->usernamelen = 0;
\r
460 if (service->password) {
\r
461 SecureZeroMemory(service->password, service->passwordlen * sizeof(TCHAR));
\r
462 HeapFree(GetProcessHeap(), 0, service->password);
\r
464 service->password = 0;
\r
465 service->passwordlen = 0;
\r
467 else if (SendDlgItemMessage(tablist[NSSM_TAB_LOGON], IDC_VIRTUAL_SERVICE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
468 if (service->username) HeapFree(GetProcessHeap(), 0, service->username);
\r
469 service->username = virtual_account(service->name);
\r
470 if (! service->username) {
\r
471 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("account name"), _T("install()"));
\r
474 service->usernamelen = _tcslen(service->username) + 1;
\r
475 service->password = 0;
\r
476 service->passwordlen = 0;
\r
480 service->usernamelen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_USERNAME), WM_GETTEXTLENGTH, 0, 0);
\r
481 if (! service->usernamelen) {
\r
482 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_USERNAME);
\r
485 service->usernamelen++;
\r
487 service->username = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->usernamelen * sizeof(TCHAR));
\r
488 if (! service->username) {
\r
489 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("account name"), _T("install()"));
\r
492 if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_USERNAME, service->username, (int) service->usernamelen)) {
\r
493 HeapFree(GetProcessHeap(), 0, service->username);
\r
494 service->username = 0;
\r
495 service->usernamelen = 0;
\r
496 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_USERNAME);
\r
501 Special case for well-known accounts.
\r
502 Ignore the password if we're editing and the username hasn't changed.
\r
504 const TCHAR *well_known = well_known_username(service->username);
\r
506 if (str_equiv(well_known, NSSM_LOCALSYSTEM_ACCOUNT)) {
\r
507 HeapFree(GetProcessHeap(), 0, service->username);
\r
508 service->username = 0;
\r
509 service->usernamelen = 0;
\r
512 service->usernamelen = _tcslen(well_known) + 1;
\r
513 service->username = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->usernamelen * sizeof(TCHAR));
\r
514 if (! service->username) {
\r
515 print_message(stderr, NSSM_MESSAGE_OUT_OF_MEMORY, _T("canon"), _T("install()"));
\r
518 memmove(service->username, well_known, service->usernamelen * sizeof(TCHAR));
\r
523 service->passwordlen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1), WM_GETTEXTLENGTH, 0, 0);
\r
524 size_t passwordlen = SendMessage(GetDlgItem(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2), WM_GETTEXTLENGTH, 0, 0);
\r
526 if (! orig_service || ! orig_service->username || ! str_equiv(service->username, orig_service->username) || service->passwordlen || passwordlen) {
\r
527 if (! service->passwordlen) {
\r
528 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
531 if (passwordlen != service->passwordlen) {
\r
532 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
535 service->passwordlen++;
\r
537 /* Temporary buffer for password validation. */
\r
538 TCHAR *password = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->passwordlen * sizeof(TCHAR));
\r
540 HeapFree(GetProcessHeap(), 0, service->username);
\r
541 service->username = 0;
\r
542 service->usernamelen = 0;
\r
543 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("password confirmation"), _T("install()"));
\r
547 /* Actual password buffer. */
\r
548 service->password = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, service->passwordlen * sizeof(TCHAR));
\r
549 if (! service->password) {
\r
550 HeapFree(GetProcessHeap(), 0, password);
\r
551 HeapFree(GetProcessHeap(), 0, service->username);
\r
552 service->username = 0;
\r
553 service->usernamelen = 0;
\r
554 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("password"), _T("install()"));
\r
558 /* Get first password. */
\r
559 if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_PASSWORD1, service->password, (int) service->passwordlen)) {
\r
560 HeapFree(GetProcessHeap(), 0, password);
\r
561 SecureZeroMemory(service->password, service->passwordlen * sizeof(TCHAR));
\r
562 HeapFree(GetProcessHeap(), 0, service->password);
\r
563 service->password = 0;
\r
564 service->passwordlen = 0;
\r
565 HeapFree(GetProcessHeap(), 0, service->username);
\r
566 service->username = 0;
\r
567 service->usernamelen = 0;
\r
568 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_PASSWORD);
\r
572 /* Get confirmation. */
\r
573 if (! GetDlgItemText(tablist[NSSM_TAB_LOGON], IDC_PASSWORD2, password, (int) service->passwordlen)) {
\r
574 SecureZeroMemory(password, service->passwordlen * sizeof(TCHAR));
\r
575 HeapFree(GetProcessHeap(), 0, password);
\r
576 SecureZeroMemory(service->password, service->passwordlen * sizeof(TCHAR));
\r
577 HeapFree(GetProcessHeap(), 0, service->password);
\r
578 service->password = 0;
\r
579 service->passwordlen = 0;
\r
580 HeapFree(GetProcessHeap(), 0, service->username);
\r
581 service->username = 0;
\r
582 service->usernamelen = 0;
\r
583 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_PASSWORD);
\r
588 if (_tcsncmp(password, service->password, service->passwordlen)) {
\r
589 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PASSWORD);
\r
590 SecureZeroMemory(password, service->passwordlen * sizeof(TCHAR));
\r
591 HeapFree(GetProcessHeap(), 0, password);
\r
592 SecureZeroMemory(service->password, service->passwordlen * sizeof(TCHAR));
\r
593 HeapFree(GetProcessHeap(), 0, service->password);
\r
594 service->password = 0;
\r
595 service->passwordlen = 0;
\r
596 HeapFree(GetProcessHeap(), 0, service->username);
\r
597 service->username = 0;
\r
598 service->usernamelen = 0;
\r
605 /* Get dependencies. */
\r
606 unsigned long dependencieslen = (unsigned long) SendMessage(GetDlgItem(tablist[NSSM_TAB_DEPENDENCIES], IDC_DEPENDENCIES), WM_GETTEXTLENGTH, 0, 0);
\r
607 if (dependencieslen) {
\r
608 TCHAR *dependencies = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (dependencieslen + 2) * sizeof(TCHAR));
\r
609 if (! dependencies) {
\r
610 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("dependencies"), _T("install()"));
\r
611 cleanup_nssm_service(service);
\r
615 if (! GetDlgItemText(tablist[NSSM_TAB_DEPENDENCIES], IDC_DEPENDENCIES, dependencies, dependencieslen + 1)) {
\r
616 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_DEPENDENCIES);
\r
617 HeapFree(GetProcessHeap(), 0, dependencies);
\r
618 cleanup_nssm_service(service);
\r
622 if (unformat_double_null(dependencies, dependencieslen, &service->dependencies, &service->dependencieslen)) {
\r
623 HeapFree(GetProcessHeap(), 0, dependencies);
\r
624 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("dependencies"), _T("install()"));
\r
625 cleanup_nssm_service(service);
\r
629 HeapFree(GetProcessHeap(), 0, dependencies);
\r
632 /* Remaining tabs are only for services we manage. */
\r
633 if (service->native) return 0;
\r
635 /* Get process stuff. */
\r
636 combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY);
\r
637 service->priority = priority_index_to_constant((unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0));
\r
639 service->affinity = 0LL;
\r
640 if (! (SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_GETCHECK, 0, 0) & BST_CHECKED)) {
\r
641 HWND list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY);
\r
642 int selected = (int) SendMessage(list, LB_GETSELCOUNT, 0, 0);
\r
643 int count = (int) SendMessage(list, LB_GETCOUNT, 0, 0);
\r
645 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_WARN_AFFINITY_NONE);
\r
648 else if (selected < count) {
\r
649 for (int i = 0; i < count; i++) {
\r
650 if (SendMessage(list, LB_GETSEL, i, 0)) service->affinity |= (1LL << (__int64) i);
\r
655 if (SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_GETCHECK, 0, 0) & BST_CHECKED) service->no_console = 0;
\r
656 else service->no_console = 1;
\r
658 /* Get stop method stuff. */
\r
659 check_stop_method(service, NSSM_STOP_METHOD_CONSOLE, IDC_METHOD_CONSOLE);
\r
660 check_stop_method(service, NSSM_STOP_METHOD_WINDOW, IDC_METHOD_WINDOW);
\r
661 check_stop_method(service, NSSM_STOP_METHOD_THREADS, IDC_METHOD_THREADS);
\r
662 check_stop_method(service, NSSM_STOP_METHOD_TERMINATE, IDC_METHOD_TERMINATE);
\r
663 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, &service->kill_console_delay);
\r
664 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, &service->kill_window_delay);
\r
665 check_number(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, &service->kill_threads_delay);
\r
666 if (SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_PROCESS_TREE, BM_GETCHECK, 0, 0) & BST_CHECKED) service->kill_process_tree = 1;
\r
667 else service->kill_process_tree = 0;
\r
669 /* Get exit action stuff. */
\r
670 check_number(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, &service->throttle_delay);
\r
671 combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
\r
672 service->default_exit_action = (unsigned long) SendMessage(combo, CB_GETCURSEL, 0, 0);
\r
673 if (service->default_exit_action == CB_ERR) service->default_exit_action = 0;
\r
674 check_number(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, &service->restart_delay);
\r
676 /* Get I/O stuff. */
\r
677 check_io(window, _T("stdin"), service->stdin_path, _countof(service->stdin_path), IDC_STDIN);
\r
678 check_io(window, _T("stdout"), service->stdout_path, _countof(service->stdout_path), IDC_STDOUT);
\r
679 check_io(window, _T("stderr"), service->stderr_path, _countof(service->stderr_path), IDC_STDERR);
\r
680 if (SendDlgItemMessage(tablist[NSSM_TAB_IO], IDC_TIMESTAMP, BM_GETCHECK, 0, 0) & BST_CHECKED) service->timestamp_log = true;
\r
681 else service->timestamp_log = false;
\r
683 /* Override stdout and/or stderr. */
\r
684 if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_TRUNCATE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
685 if (service->stdout_path[0]) service->stdout_disposition = CREATE_ALWAYS;
\r
686 if (service->stderr_path[0]) service->stderr_disposition = CREATE_ALWAYS;
\r
689 /* Get rotation stuff. */
\r
690 if (SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
691 service->rotate_files = true;
\r
692 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
693 check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, &service->rotate_seconds);
\r
694 check_number(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, &service->rotate_bytes_low);
\r
697 /* Get hook stuff. */
\r
698 if (SendDlgItemMessage(tablist[NSSM_TAB_HOOKS], IDC_REDIRECT_HOOK, BM_GETCHECK, 0, 0) & BST_CHECKED) service->hook_share_output_handles = true;
\r
700 /* Get environment. */
\r
701 unsigned long envlen = (unsigned long) SendMessage(GetDlgItem(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT), WM_GETTEXTLENGTH, 0, 0);
\r
703 TCHAR *env = (TCHAR *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (envlen + 2) * sizeof(TCHAR));
\r
705 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("install()"));
\r
706 cleanup_nssm_service(service);
\r
710 if (! GetDlgItemText(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT, env, envlen + 1)) {
\r
711 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT);
\r
712 HeapFree(GetProcessHeap(), 0, env);
\r
713 cleanup_nssm_service(service);
\r
718 unsigned long newlen;
\r
719 if (unformat_double_null(env, envlen, &newenv, &newlen)) {
\r
720 HeapFree(GetProcessHeap(), 0, env);
\r
721 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("environment"), _T("install()"));
\r
722 cleanup_nssm_service(service);
\r
726 HeapFree(GetProcessHeap(), 0, env);
\r
730 /* Test the environment is valid. */
\r
731 if (test_environment(env)) {
\r
732 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_ENVIRONMENT);
\r
733 HeapFree(GetProcessHeap(), 0, env);
\r
734 cleanup_nssm_service(service);
\r
738 if (SendDlgItemMessage(tablist[NSSM_TAB_ENVIRONMENT], IDC_ENVIRONMENT_REPLACE, BM_GETCHECK, 0, 0) & BST_CHECKED) {
\r
739 service->env = env;
\r
740 service->envlen = envlen;
\r
743 service->env_extra = env;
\r
744 service->env_extralen = envlen;
\r
751 /* Install the service. */
\r
752 int install(HWND window) {
\r
753 if (! window) return 1;
\r
755 nssm_service_t *service = alloc_nssm_service();
\r
757 int ret = configure(window, service, 0);
\r
758 if (ret) return ret;
\r
761 /* See if it works. */
\r
762 switch (install_service(service)) {
\r
764 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("install()"));
\r
765 cleanup_nssm_service(service);
\r
769 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);
\r
770 cleanup_nssm_service(service);
\r
774 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, NSSM);
\r
775 cleanup_nssm_service(service);
\r
779 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_OUT_OF_MEMORY_FOR_IMAGEPATH);
\r
780 cleanup_nssm_service(service);
\r
784 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INSTALL_SERVICE_FAILED);
\r
785 cleanup_nssm_service(service);
\r
789 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_CREATE_PARAMETERS_FAILED);
\r
790 cleanup_nssm_service(service);
\r
794 update_hooks(service->name);
\r
796 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_INSTALLED, service->name);
\r
797 cleanup_nssm_service(service);
\r
801 /* Remove the service */
\r
802 int remove(HWND window) {
\r
803 if (! window) return 1;
\r
805 /* See if it works */
\r
806 nssm_service_t *service = alloc_nssm_service();
\r
808 /* Get service name */
\r
809 if (! GetDlgItemText(window, IDC_NAME, service->name, _countof(service->name))) {
\r
810 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_SERVICE_NAME);
\r
811 cleanup_nssm_service(service);
\r
816 if (popup_message(window, MB_YESNO, NSSM_GUI_ASK_REMOVE_SERVICE, service->name) != IDYES) {
\r
817 cleanup_nssm_service(service);
\r
822 switch (remove_service(service)) {
\r
824 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("remove()"));
\r
825 cleanup_nssm_service(service);
\r
829 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);
\r
830 cleanup_nssm_service(service);
\r
834 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_SERVICE_NOT_INSTALLED);
\r
835 cleanup_nssm_service(service);
\r
839 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_REMOVE_SERVICE_FAILED);
\r
840 cleanup_nssm_service(service);
\r
844 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_REMOVED, service->name);
\r
845 cleanup_nssm_service(service);
\r
849 int edit(HWND window, nssm_service_t *orig_service) {
\r
850 if (! window) return 1;
\r
852 nssm_service_t *service = alloc_nssm_service();
\r
854 int ret = configure(window, service, orig_service);
\r
855 if (ret) return ret;
\r
858 switch (edit_service(service, true)) {
\r
860 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_EVENT_OUT_OF_MEMORY, _T("service"), _T("edit()"));
\r
861 cleanup_nssm_service(service);
\r
865 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, NSSM);
\r
866 cleanup_nssm_service(service);
\r
870 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_OUT_OF_MEMORY_FOR_IMAGEPATH);
\r
871 cleanup_nssm_service(service);
\r
876 popup_message(window, MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_EDIT_PARAMETERS_FAILED);
\r
877 cleanup_nssm_service(service);
\r
881 update_hooks(service->name);
\r
883 popup_message(window, MB_OK, NSSM_MESSAGE_SERVICE_EDITED, service->name);
\r
884 cleanup_nssm_service(service);
\r
888 static TCHAR *browse_filter(int message) {
\r
890 case NSSM_GUI_BROWSE_FILTER_APPLICATIONS: return _T("*.exe;*.bat;*.cmd");
\r
891 case NSSM_GUI_BROWSE_FILTER_DIRECTORIES: return _T(".");
\r
892 case NSSM_GUI_BROWSE_FILTER_ALL_FILES: /* Fall through. */
\r
893 default: return _T("*.*");
\r
897 UINT_PTR CALLBACK browse_hook(HWND dlg, UINT message, WPARAM w, LPARAM l) {
\r
899 case WM_INITDIALOG:
\r
906 /* Browse for application */
\r
907 void browse(HWND window, TCHAR *current, unsigned long flags, ...) {
\r
908 if (! window) return;
\r
911 size_t bufsize = 256;
\r
912 size_t len = bufsize;
\r
916 ZeroMemory(&ofn, sizeof(ofn));
\r
917 ofn.lStructSize = sizeof(ofn);
\r
918 ofn.lpstrFilter = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, bufsize * sizeof(TCHAR));
\r
919 /* XXX: Escaping nulls with FormatMessage is tricky */
\r
920 if (ofn.lpstrFilter) {
\r
921 ZeroMemory((void *) ofn.lpstrFilter, bufsize);
\r
923 /* "Applications" + NULL + "*.exe" + NULL */
\r
924 va_start(arg, flags);
\r
925 while (i = va_arg(arg, int)) {
\r
926 TCHAR *localised = message_string(i);
\r
927 _sntprintf_s((TCHAR *) ofn.lpstrFilter + len, bufsize, _TRUNCATE, localised);
\r
928 len += _tcslen(localised) + 1;
\r
929 LocalFree(localised);
\r
930 TCHAR *filter = browse_filter(i);
\r
931 _sntprintf_s((TCHAR *) ofn.lpstrFilter + len, bufsize - len, _TRUNCATE, _T("%s"), filter);
\r
932 len += _tcslen(filter) + 1;
\r
935 /* Remainder of the buffer is already zeroed */
\r
937 ofn.lpstrFile = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, PATH_LENGTH * sizeof(TCHAR));
\r
938 if (ofn.lpstrFile) {
\r
939 if (flags & OFN_NOVALIDATE) {
\r
940 /* Directory hack. */
\r
941 _sntprintf_s(ofn.lpstrFile, PATH_LENGTH, _TRUNCATE, _T(":%s:"), message_string(NSSM_GUI_BROWSE_FILTER_DIRECTORIES));
\r
942 ofn.nMaxFile = DIR_LENGTH;
\r
945 _sntprintf_s(ofn.lpstrFile, PATH_LENGTH, _TRUNCATE, _T("%s"), current);
\r
946 ofn.nMaxFile = PATH_LENGTH;
\r
949 ofn.lpstrTitle = message_string(NSSM_GUI_BROWSE_TITLE);
\r
950 ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | flags;
\r
952 if (GetOpenFileName(&ofn)) {
\r
953 /* Directory hack. */
\r
954 if (flags & OFN_NOVALIDATE) strip_basename(ofn.lpstrFile);
\r
955 SendMessage(window, WM_SETTEXT, 0, (LPARAM) ofn.lpstrFile);
\r
957 if (ofn.lpstrFilter) HeapFree(GetProcessHeap(), 0, (void *) ofn.lpstrFilter);
\r
958 if (ofn.lpstrFile) HeapFree(GetProcessHeap(), 0, ofn.lpstrFile);
\r
961 INT_PTR CALLBACK tab_dlg(HWND tab, UINT message, WPARAM w, LPARAM l) {
\r
963 case WM_INITDIALOG:
\r
966 /* Button was pressed or control was controlled. */
\r
969 TCHAR buffer[PATH_LENGTH];
\r
970 unsigned char enabled;
\r
972 switch (LOWORD(w)) {
\r
973 /* Browse for application. */
\r
975 dlg = GetDlgItem(tab, IDC_PATH);
\r
976 GetDlgItemText(tab, IDC_PATH, buffer, _countof(buffer));
\r
977 browse(dlg, buffer, OFN_FILEMUSTEXIST, NSSM_GUI_BROWSE_FILTER_APPLICATIONS, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
978 /* Fill in startup directory if it wasn't already specified. */
\r
979 GetDlgItemText(tab, IDC_DIR, buffer, _countof(buffer));
\r
981 GetDlgItemText(tab, IDC_PATH, buffer, _countof(buffer));
\r
982 strip_basename(buffer);
\r
983 SetDlgItemText(tab, IDC_DIR, buffer);
\r
987 /* Browse for startup directory. */
\r
988 case IDC_BROWSE_DIR:
\r
989 dlg = GetDlgItem(tab, IDC_DIR);
\r
990 GetDlgItemText(tab, IDC_DIR, buffer, _countof(buffer));
\r
991 browse(dlg, buffer, OFN_NOVALIDATE, NSSM_GUI_BROWSE_FILTER_DIRECTORIES, 0);
\r
995 case IDC_LOCALSYSTEM:
\r
996 set_logon_enabled(1, 0);
\r
999 case IDC_VIRTUAL_SERVICE:
\r
1000 set_logon_enabled(0, 0);
\r
1004 set_logon_enabled(0, 1);
\r
1008 case IDC_AFFINITY_ALL:
\r
1009 if (SendDlgItemMessage(tab, LOWORD(w), BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 0;
\r
1011 set_affinity_enabled(enabled);
\r
1014 /* Shutdown methods. */
\r
1015 case IDC_METHOD_CONSOLE:
\r
1016 set_timeout_enabled(LOWORD(w), IDC_KILL_CONSOLE);
\r
1019 case IDC_METHOD_WINDOW:
\r
1020 set_timeout_enabled(LOWORD(w), IDC_KILL_WINDOW);
\r
1023 case IDC_METHOD_THREADS:
\r
1024 set_timeout_enabled(LOWORD(w), IDC_KILL_THREADS);
\r
1027 /* Browse for stdin. */
\r
1028 case IDC_BROWSE_STDIN:
\r
1029 dlg = GetDlgItem(tab, IDC_STDIN);
\r
1030 GetDlgItemText(tab, IDC_STDIN, buffer, _countof(buffer));
\r
1031 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
1034 /* Browse for stdout. */
\r
1035 case IDC_BROWSE_STDOUT:
\r
1036 dlg = GetDlgItem(tab, IDC_STDOUT);
\r
1037 GetDlgItemText(tab, IDC_STDOUT, buffer, _countof(buffer));
\r
1038 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
1039 /* Fill in stderr if it wasn't already specified. */
\r
1040 GetDlgItemText(tab, IDC_STDERR, buffer, _countof(buffer));
\r
1041 if (! buffer[0]) {
\r
1042 GetDlgItemText(tab, IDC_STDOUT, buffer, _countof(buffer));
\r
1043 SetDlgItemText(tab, IDC_STDERR, buffer);
\r
1047 /* Browse for stderr. */
\r
1048 case IDC_BROWSE_STDERR:
\r
1049 dlg = GetDlgItem(tab, IDC_STDERR);
\r
1050 GetDlgItemText(tab, IDC_STDERR, buffer, _countof(buffer));
\r
1051 browse(dlg, buffer, 0, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
1056 if (SendDlgItemMessage(tab, LOWORD(w), BM_GETCHECK, 0, 0) & BST_CHECKED) enabled = 1;
\r
1058 set_rotation_enabled(enabled);
\r
1062 case IDC_HOOK_EVENT:
\r
1063 if (HIWORD(w) == CBN_SELCHANGE) set_hook_tab((int) SendMessage(GetDlgItem(tab, IDC_HOOK_EVENT), CB_GETCURSEL, 0, 0), 0, false);
\r
1066 /* Hook action. */
\r
1067 case IDC_HOOK_ACTION:
\r
1068 if (HIWORD(w) == CBN_SELCHANGE) set_hook_tab((int) SendMessage(GetDlgItem(tab, IDC_HOOK_EVENT), CB_GETCURSEL, 0, 0), (int) SendMessage(GetDlgItem(tab, IDC_HOOK_ACTION), CB_GETCURSEL, 0, 0), false);
\r
1071 /* Browse for hook. */
\r
1072 case IDC_BROWSE_HOOK:
\r
1073 dlg = GetDlgItem(tab, IDC_HOOK);
\r
1074 GetDlgItemText(tab, IDC_HOOK, buffer, _countof(buffer));
\r
1075 browse(dlg, _T(""), OFN_FILEMUSTEXIST, NSSM_GUI_BROWSE_FILTER_ALL_FILES, 0);
\r
1080 set_hook_tab((int) SendMessage(GetDlgItem(tab, IDC_HOOK_EVENT), CB_GETCURSEL, 0, 0), (int) SendMessage(GetDlgItem(tab, IDC_HOOK_ACTION), CB_GETCURSEL, 0, 0), true);
\r
1089 /* Install/remove dialogue callback */
\r
1090 INT_PTR CALLBACK nssm_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {
\r
1091 nssm_service_t *service;
\r
1093 switch (message) {
\r
1094 /* Creating the dialogue */
\r
1095 case WM_INITDIALOG:
\r
1096 service = (nssm_service_t *) l;
\r
1098 SetFocus(GetDlgItem(window, IDC_NAME));
\r
1104 tabs = GetDlgItem(window, IDC_TAB1);
\r
1105 if (! tabs) return 0;
\r
1107 /* Set up tabs. */
\r
1109 ZeroMemory(&tab, sizeof(tab));
\r
1110 tab.mask = TCIF_TEXT;
\r
1114 /* Application tab. */
\r
1115 if (service->native) tab.pszText = message_string(NSSM_GUI_TAB_NATIVE);
\r
1116 else tab.pszText = message_string(NSSM_GUI_TAB_APPLICATION);
\r
1117 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1118 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_APPLICATION, (LPARAM) &tab);
\r
1119 if (service->native) {
\r
1120 tablist[NSSM_TAB_APPLICATION] = dialog(MAKEINTRESOURCE(IDD_NATIVE), window, tab_dlg);
\r
1121 EnableWindow(tablist[NSSM_TAB_APPLICATION], 0);
\r
1122 EnableWindow(GetDlgItem(tablist[NSSM_TAB_APPLICATION], IDC_PATH), 0);
\r
1124 else tablist[NSSM_TAB_APPLICATION] = dialog(MAKEINTRESOURCE(IDD_APPLICATION), window, tab_dlg);
\r
1125 ShowWindow(tablist[NSSM_TAB_APPLICATION], SW_SHOW);
\r
1127 /* Details tab. */
\r
1128 tab.pszText = message_string(NSSM_GUI_TAB_DETAILS);
\r
1129 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1130 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_DETAILS, (LPARAM) &tab);
\r
1131 tablist[NSSM_TAB_DETAILS] = dialog(MAKEINTRESOURCE(IDD_DETAILS), window, tab_dlg);
\r
1132 ShowWindow(tablist[NSSM_TAB_DETAILS], SW_HIDE);
\r
1134 /* Set defaults. */
\r
1135 combo = GetDlgItem(tablist[NSSM_TAB_DETAILS], IDC_STARTUP);
\r
1136 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_AUTOMATIC, (LPARAM) message_string(NSSM_GUI_STARTUP_AUTOMATIC));
\r
1137 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DELAYED, (LPARAM) message_string(NSSM_GUI_STARTUP_DELAYED));
\r
1138 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_MANUAL, (LPARAM) message_string(NSSM_GUI_STARTUP_MANUAL));
\r
1139 SendMessage(combo, CB_INSERTSTRING, NSSM_STARTUP_DISABLED, (LPARAM) message_string(NSSM_GUI_STARTUP_DISABLED));
\r
1140 SendMessage(combo, CB_SETCURSEL, NSSM_STARTUP_AUTOMATIC, 0);
\r
1143 tab.pszText = message_string(NSSM_GUI_TAB_LOGON);
\r
1144 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1145 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_LOGON, (LPARAM) &tab);
\r
1146 tablist[NSSM_TAB_LOGON] = dialog(MAKEINTRESOURCE(IDD_LOGON), window, tab_dlg);
\r
1147 ShowWindow(tablist[NSSM_TAB_LOGON], SW_HIDE);
\r
1149 /* Set defaults. */
\r
1150 CheckRadioButton(tablist[NSSM_TAB_LOGON], IDC_LOCALSYSTEM, IDC_ACCOUNT, IDC_LOCALSYSTEM);
\r
1151 set_logon_enabled(1, 0);
\r
1153 /* Dependencies tab. */
\r
1154 tab.pszText = message_string(NSSM_GUI_TAB_DEPENDENCIES);
\r
1155 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1156 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_DEPENDENCIES, (LPARAM) &tab);
\r
1157 tablist[NSSM_TAB_DEPENDENCIES] = dialog(MAKEINTRESOURCE(IDD_DEPENDENCIES), window, tab_dlg);
\r
1158 ShowWindow(tablist[NSSM_TAB_DEPENDENCIES], SW_HIDE);
\r
1160 /* Remaining tabs are only for services we manage. */
\r
1161 if (service->native) return 1;
\r
1163 /* Process tab. */
\r
1164 tab.pszText = message_string(NSSM_GUI_TAB_PROCESS);
\r
1165 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1166 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_PROCESS, (LPARAM) &tab);
\r
1167 tablist[NSSM_TAB_PROCESS] = dialog(MAKEINTRESOURCE(IDD_PROCESS), window, tab_dlg);
\r
1168 ShowWindow(tablist[NSSM_TAB_PROCESS], SW_HIDE);
\r
1170 /* Set defaults. */
\r
1171 combo = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_PRIORITY);
\r
1172 SendMessage(combo, CB_INSERTSTRING, NSSM_REALTIME_PRIORITY, (LPARAM) message_string(NSSM_GUI_REALTIME_PRIORITY_CLASS));
\r
1173 SendMessage(combo, CB_INSERTSTRING, NSSM_HIGH_PRIORITY, (LPARAM) message_string(NSSM_GUI_HIGH_PRIORITY_CLASS));
\r
1174 SendMessage(combo, CB_INSERTSTRING, NSSM_ABOVE_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_ABOVE_NORMAL_PRIORITY_CLASS));
\r
1175 SendMessage(combo, CB_INSERTSTRING, NSSM_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_NORMAL_PRIORITY_CLASS));
\r
1176 SendMessage(combo, CB_INSERTSTRING, NSSM_BELOW_NORMAL_PRIORITY, (LPARAM) message_string(NSSM_GUI_BELOW_NORMAL_PRIORITY_CLASS));
\r
1177 SendMessage(combo, CB_INSERTSTRING, NSSM_IDLE_PRIORITY, (LPARAM) message_string(NSSM_GUI_IDLE_PRIORITY_CLASS));
\r
1178 SendMessage(combo, CB_SETCURSEL, NSSM_NORMAL_PRIORITY, 0);
\r
1180 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_CONSOLE, BM_SETCHECK, BST_CHECKED, 0);
\r
1182 list = GetDlgItem(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY);
\r
1184 SendMessage(list, LB_SETCOLUMNWIDTH, 16, 0);
\r
1185 for (i = 0; i < n; i++) {
\r
1187 _sntprintf_s(buffer, _countof(buffer), _TRUNCATE, _T("%d"), i);
\r
1188 SendMessage(list, LB_ADDSTRING, 0, (LPARAM) buffer);
\r
1193 The box is high enough for four rows. It is wide enough for eight
\r
1194 columns without scrolling. With scrollbars it shrinks to two rows.
\r
1195 Note that the above only holds if we set the column width BEFORE
\r
1196 adding the strings.
\r
1199 int columns = (n - 1) / 4;
\r
1201 GetWindowRect(list, &rect);
\r
1202 int width = rect.right - rect.left;
\r
1203 width -= (7 - columns) * 16;
\r
1204 int height = rect.bottom - rect.top;
\r
1205 if (n < 4) height -= (int) SendMessage(list, LB_GETITEMHEIGHT, 0, 0) * (4 - n);
\r
1206 SetWindowPos(list, 0, 0, 0, width, height, SWP_NOMOVE | SWP_NOOWNERZORDER);
\r
1208 SendMessage(list, LB_SELITEMRANGE, 1, MAKELPARAM(0, n));
\r
1210 SendDlgItemMessage(tablist[NSSM_TAB_PROCESS], IDC_AFFINITY_ALL, BM_SETCHECK, BST_CHECKED, 0);
\r
1211 set_affinity_enabled(0);
\r
1213 /* Shutdown tab. */
\r
1214 tab.pszText = message_string(NSSM_GUI_TAB_SHUTDOWN);
\r
1215 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1216 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_SHUTDOWN, (LPARAM) &tab);
\r
1217 tablist[NSSM_TAB_SHUTDOWN] = dialog(MAKEINTRESOURCE(IDD_SHUTDOWN), window, tab_dlg);
\r
1218 ShowWindow(tablist[NSSM_TAB_SHUTDOWN], SW_HIDE);
\r
1220 /* Set defaults. */
\r
1221 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_CONSOLE, BM_SETCHECK, BST_CHECKED, 0);
\r
1222 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_CONSOLE, NSSM_KILL_CONSOLE_GRACE_PERIOD, 0);
\r
1223 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_WINDOW, BM_SETCHECK, BST_CHECKED, 0);
\r
1224 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_WINDOW, NSSM_KILL_WINDOW_GRACE_PERIOD, 0);
\r
1225 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_THREADS, BM_SETCHECK, BST_CHECKED, 0);
\r
1226 SetDlgItemInt(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_THREADS, NSSM_KILL_THREADS_GRACE_PERIOD, 0);
\r
1227 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_METHOD_TERMINATE, BM_SETCHECK, BST_CHECKED, 0);
\r
1228 SendDlgItemMessage(tablist[NSSM_TAB_SHUTDOWN], IDC_KILL_PROCESS_TREE, BM_SETCHECK, BST_CHECKED, 1);
\r
1230 /* Restart tab. */
\r
1231 tab.pszText = message_string(NSSM_GUI_TAB_EXIT);
\r
1232 tab.cchTextMax = (int) _tcslen(tab.pszText);
\r
1233 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_EXIT, (LPARAM) &tab);
\r
1234 tablist[NSSM_TAB_EXIT] = dialog(MAKEINTRESOURCE(IDD_APPEXIT), window, tab_dlg);
\r
1235 ShowWindow(tablist[NSSM_TAB_EXIT], SW_HIDE);
\r
1237 /* Set defaults. */
\r
1238 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_THROTTLE, NSSM_RESET_THROTTLE_RESTART, 0);
\r
1239 combo = GetDlgItem(tablist[NSSM_TAB_EXIT], IDC_APPEXIT);
\r
1240 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_RESTART, (LPARAM) message_string(NSSM_GUI_EXIT_RESTART));
\r
1241 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_IGNORE, (LPARAM) message_string(NSSM_GUI_EXIT_IGNORE));
\r
1242 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_REALLY, (LPARAM) message_string(NSSM_GUI_EXIT_REALLY));
\r
1243 SendMessage(combo, CB_INSERTSTRING, NSSM_EXIT_UNCLEAN, (LPARAM) message_string(NSSM_GUI_EXIT_UNCLEAN));
\r
1244 SendMessage(combo, CB_SETCURSEL, NSSM_EXIT_RESTART, 0);
\r
1245 SetDlgItemInt(tablist[NSSM_TAB_EXIT], IDC_RESTART_DELAY, 0, 0);
\r
1248 tab.pszText = message_string(NSSM_GUI_TAB_IO);
\r
1249 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1250 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_IO, (LPARAM) &tab);
\r
1251 tablist[NSSM_TAB_IO] = dialog(MAKEINTRESOURCE(IDD_IO), window, tab_dlg);
\r
1252 ShowWindow(tablist[NSSM_TAB_IO], SW_HIDE);
\r
1254 /* Set defaults. */
\r
1255 SendDlgItemMessage(tablist[NSSM_TAB_IO], IDC_TIMESTAMP, BM_SETCHECK, BST_UNCHECKED, 0);
\r
1257 /* Rotation tab. */
\r
1258 tab.pszText = message_string(NSSM_GUI_TAB_ROTATION);
\r
1259 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1260 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_ROTATION, (LPARAM) &tab);
\r
1261 tablist[NSSM_TAB_ROTATION] = dialog(MAKEINTRESOURCE(IDD_ROTATION), window, tab_dlg);
\r
1262 ShowWindow(tablist[NSSM_TAB_ROTATION], SW_HIDE);
\r
1264 /* Set defaults. */
\r
1265 SendDlgItemMessage(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_ONLINE, BM_SETCHECK, BST_UNCHECKED, 0);
\r
1266 SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_SECONDS, 0, 0);
\r
1267 SetDlgItemInt(tablist[NSSM_TAB_ROTATION], IDC_ROTATE_BYTES_LOW, 0, 0);
\r
1268 set_rotation_enabled(0);
\r
1270 /* Environment tab. */
\r
1271 tab.pszText = message_string(NSSM_GUI_TAB_ENVIRONMENT);
\r
1272 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1273 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_ENVIRONMENT, (LPARAM) &tab);
\r
1274 tablist[NSSM_TAB_ENVIRONMENT] = dialog(MAKEINTRESOURCE(IDD_ENVIRONMENT), window, tab_dlg);
\r
1275 ShowWindow(tablist[NSSM_TAB_ENVIRONMENT], SW_HIDE);
\r
1278 tab.pszText = message_string(NSSM_GUI_TAB_HOOKS);
\r
1279 tab.cchTextMax = (int) _tcslen(tab.pszText) + 1;
\r
1280 SendMessage(tabs, TCM_INSERTITEM, NSSM_TAB_HOOKS, (LPARAM) &tab);
\r
1281 tablist[NSSM_TAB_HOOKS] = dialog(MAKEINTRESOURCE(IDD_HOOKS), window, tab_dlg);
\r
1282 ShowWindow(tablist[NSSM_TAB_HOOKS], SW_HIDE);
\r
1284 /* Set defaults. */
\r
1285 combo = GetDlgItem(tablist[NSSM_TAB_HOOKS], IDC_HOOK_EVENT);
\r
1286 SendMessage(combo, CB_INSERTSTRING, -1, (LPARAM) message_string(NSSM_GUI_HOOK_EVENT_START));
\r
1287 SendMessage(combo, CB_INSERTSTRING, -1, (LPARAM) message_string(NSSM_GUI_HOOK_EVENT_STOP));
\r
1288 SendMessage(combo, CB_INSERTSTRING, -1, (LPARAM) message_string(NSSM_GUI_HOOK_EVENT_EXIT));
\r
1289 SendMessage(combo, CB_INSERTSTRING, -1, (LPARAM) message_string(NSSM_GUI_HOOK_EVENT_POWER));
\r
1290 SendMessage(combo, CB_INSERTSTRING, -1, (LPARAM) message_string(NSSM_GUI_HOOK_EVENT_ROTATE));
\r
1291 SendDlgItemMessage(tablist[NSSM_TAB_HOOKS], IDC_REDIRECT_HOOK, BM_SETCHECK, BST_UNCHECKED, 0);
\r
1292 if (_tcslen(service->name)) {
\r
1293 TCHAR hook_name[HOOK_NAME_LENGTH];
\r
1294 TCHAR cmd[CMD_LENGTH];
\r
1295 for (i = 0; hook_event_strings[i]; i++) {
\r
1296 const TCHAR *hook_event = hook_event_strings[i];
\r
1298 for (j = 0; hook_action_strings[j]; j++) {
\r
1299 const TCHAR *hook_action = hook_action_strings[j];
\r
1300 if (! valid_hook_name(hook_event, hook_action, true)) continue;
\r
1301 if (get_hook(service->name, hook_event, hook_action, cmd, sizeof(cmd))) continue;
\r
1302 if (hook_env(hook_event, hook_action, hook_name, _countof(hook_name)) < 0) continue;
\r
1303 SetEnvironmentVariable(hook_name, cmd);
\r
1307 set_hook_tab(0, 0, false);
\r
1313 NMHDR *notification;
\r
1315 notification = (NMHDR *) l;
\r
1316 switch (notification->code) {
\r
1317 case TCN_SELCHANGE:
\r
1321 tabs = GetDlgItem(window, IDC_TAB1);
\r
1322 if (! tabs) return 0;
\r
1324 selection = (int) SendMessage(tabs, TCM_GETCURSEL, 0, 0);
\r
1325 if (selection != selected_tab) {
\r
1326 ShowWindow(tablist[selected_tab], SW_HIDE);
\r
1327 ShowWindow(tablist[selection], SW_SHOWDEFAULT);
\r
1328 SetFocus(GetDlgItem(window, IDOK));
\r
1329 selected_tab = selection;
\r
1336 /* Button was pressed or control was controlled */
\r
1338 switch (LOWORD(w)) {
\r
1341 if ((int) GetWindowLongPtr(window, GWLP_USERDATA) == IDD_EDIT) {
\r
1342 if (! edit(window, (nssm_service_t *) GetWindowLongPtr(window, DWLP_USER))) PostQuitMessage(0);
\r
1344 else if (! install(window)) PostQuitMessage(0);
\r
1347 /* Cancel button */
\r
1349 DestroyWindow(window);
\r
1352 /* Remove button */
\r
1354 if (! remove(window)) PostQuitMessage(0);
\r
1359 /* Window closing */
\r
1361 DestroyWindow(window);
\r
1364 PostQuitMessage(0);
\r