Added strip_basename() function.
[nssm.git] / gui.cpp
1 #include "nssm.h"\r
2 \r
3 static void strip_basename(char *buffer) {\r
4   size_t len = strlen(buffer);\r
5   size_t i;\r
6   for (i = len; i && buffer[i] != '\\' && buffer[i] != '/'; i--);\r
7   /* X:\ is OK. */\r
8   if (i && buffer[i-1] == ':') i++;\r
9   buffer[i] = '\0';\r
10 }\r
11 \r
12 int nssm_gui(int resource, char *name) {\r
13   /* Create window */\r
14   HWND dlg = CreateDialog(0, MAKEINTRESOURCE(resource), 0, install_dlg);\r
15   if (! dlg) {\r
16     popup_message(MB_OK, NSSM_GUI_CREATEDIALOG_FAILED, error_string(GetLastError()));\r
17     return 1;\r
18   }\r
19 \r
20   /* Display the window */\r
21   centre_window(dlg);\r
22   ShowWindow(dlg, SW_SHOW);\r
23 \r
24   /* Set service name if given */\r
25   if (name) {\r
26     SetDlgItemText(dlg, IDC_NAME, name);\r
27     /* No point making user click remove if the name is already entered */\r
28     if (resource == IDD_REMOVE) {\r
29       HWND button = GetDlgItem(dlg, IDC_REMOVE);\r
30       if (button) {\r
31         SendMessage(button, WM_LBUTTONDOWN, 0, 0);\r
32         SendMessage(button, WM_LBUTTONUP, 0, 0);\r
33       }\r
34     }\r
35   }\r
36 \r
37   /* Go! */\r
38   MSG message;\r
39   while (GetMessage(&message, 0, 0, 0)) {\r
40     if (IsDialogMessage(dlg, &message)) continue;\r
41     TranslateMessage(&message);\r
42     DispatchMessage(&message);\r
43   }\r
44 \r
45   return (int) message.wParam;\r
46 }\r
47 \r
48 void centre_window(HWND window) {\r
49   HWND desktop;\r
50   RECT size, desktop_size;\r
51   unsigned long x, y;\r
52 \r
53   if (! window) return;\r
54 \r
55   /* Find window size */\r
56   if (! GetWindowRect(window, &size)) return;\r
57   \r
58   /* Find desktop window */\r
59   desktop = GetDesktopWindow();\r
60   if (! desktop) return;\r
61 \r
62   /* Find desktop window size */\r
63   if (! GetWindowRect(desktop, &desktop_size)) return;\r
64 \r
65   /* Centre window */\r
66   x = (desktop_size.right - size.right) / 2;\r
67   y = (desktop_size.bottom - size.bottom) / 2;\r
68   MoveWindow(window, x, y, size.right - size.left, size.bottom - size.top, 0);\r
69 }\r
70 \r
71 /* Install the service */\r
72 int install(HWND window) {\r
73   if (! window) return 1;\r
74 \r
75   /* Check parameters in the window */\r
76   char name[VALUE_LENGTH];\r
77   char exe[EXE_LENGTH];\r
78   char flags[VALUE_LENGTH];\r
79 \r
80   /* Get service name */\r
81   if (! GetDlgItemText(window, IDC_NAME, name, sizeof(name))) {\r
82     popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_SERVICE_NAME);\r
83     return 2;\r
84   }\r
85 \r
86   /* Get executable name */\r
87   if (! GetDlgItemText(window, IDC_PATH, exe, sizeof(exe))) {\r
88     popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_PATH);\r
89     return 3;\r
90   }\r
91 \r
92   /* Get flags */\r
93   if (SendMessage(GetDlgItem(window, IDC_FLAGS), WM_GETTEXTLENGTH, 0, 0)) {\r
94     if (! GetDlgItemText(window, IDC_FLAGS, flags, sizeof(flags))) {\r
95       popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INVALID_OPTIONS);\r
96       return 4;\r
97     }\r
98   }\r
99   else ZeroMemory(&flags, sizeof(flags));\r
100 \r
101   /* See if it works */\r
102   switch (install_service(name, exe, flags)) {\r
103     case 2:\r
104       popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);\r
105       return 2;\r
106 \r
107     case 3:\r
108       popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_PATH_TOO_LONG, NSSM);\r
109       return 3;\r
110 \r
111     case 4:\r
112       popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_OUT_OF_MEMORY_FOR_IMAGEPATH);\r
113       return 4;\r
114 \r
115     case 5:\r
116       popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_INSTALL_SERVICE_FAILED);\r
117       return 5;\r
118 \r
119     case 6:\r
120       popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_CREATE_PARAMETERS_FAILED);\r
121       return 6;\r
122   }\r
123 \r
124   popup_message(MB_OK, NSSM_MESSAGE_SERVICE_INSTALLED, name);\r
125   return 0;\r
126 }\r
127 \r
128 /* Remove the service */\r
129 int remove(HWND window) {\r
130   if (! window) return 1;\r
131 \r
132   /* Check parameters in the window */\r
133   char name[VALUE_LENGTH];\r
134 \r
135   /* Get service name */\r
136   if (! GetDlgItemText(window, IDC_NAME, name, sizeof(name))) {\r
137     popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_MISSING_SERVICE_NAME);\r
138     return 2;\r
139   }\r
140 \r
141   /* Confirm */\r
142   if (popup_message(MB_YESNO, NSSM_GUI_ASK_REMOVE_SERVICE, name) != IDYES) return 0;\r
143 \r
144   /* See if it works */\r
145   switch (remove_service(name)) {\r
146     case 2:\r
147       popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_MESSAGE_OPEN_SERVICE_MANAGER_FAILED);\r
148       return 2;\r
149 \r
150     case 3:\r
151       popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_SERVICE_NOT_INSTALLED);\r
152       return 3;\r
153 \r
154     case 4:\r
155       popup_message(MB_OK | MB_ICONEXCLAMATION, NSSM_GUI_REMOVE_SERVICE_FAILED);\r
156       return 4;\r
157   }\r
158 \r
159   popup_message(MB_OK, NSSM_MESSAGE_SERVICE_REMOVED, name);\r
160   return 0;\r
161 }\r
162 \r
163 /* Browse for application */\r
164 void browse(HWND window) {\r
165   if (! window) return;\r
166 \r
167   size_t bufsize = 256;\r
168   size_t len = bufsize;\r
169   OPENFILENAME ofn;\r
170   ZeroMemory(&ofn, sizeof(ofn));\r
171   ofn.lStructSize = sizeof(ofn);\r
172   ofn.lpstrFilter = (char *) HeapAlloc(GetProcessHeap(), 0, bufsize);\r
173   /* XXX: Escaping nulls with FormatMessage is tricky */\r
174   if (ofn.lpstrFilter) {\r
175     ZeroMemory((void *) ofn.lpstrFilter, bufsize);\r
176     char *localised = message_string(NSSM_GUI_BROWSE_FILTER_APPLICATIONS);\r
177     _snprintf_s((char *) ofn.lpstrFilter, bufsize, _TRUNCATE, localised);\r
178     /* "Applications" + NULL + "*.exe" + NULL */\r
179     len = strlen(localised) + 1;\r
180     LocalFree(localised);\r
181     _snprintf_s((char *) ofn.lpstrFilter + len, bufsize - len, _TRUNCATE, "*.exe");\r
182     /* "All files" + NULL + "*.*" + NULL */\r
183     len += 6;\r
184     localised = message_string(NSSM_GUI_BROWSE_FILTER_ALL_FILES);\r
185     _snprintf_s((char *) ofn.lpstrFilter + len, bufsize - len, _TRUNCATE, localised);\r
186     len += strlen(localised) + 1;\r
187     LocalFree(localised);\r
188     _snprintf_s((char *) ofn.lpstrFilter + len, bufsize - len, _TRUNCATE, "*.*");\r
189     /* Remainder of the buffer is already zeroed */\r
190   }\r
191   ofn.lpstrFile = new char[MAX_PATH];\r
192   ofn.lpstrFile[0] = '\0';\r
193   ofn.lpstrTitle = message_string(NSSM_GUI_BROWSE_TITLE);\r
194   ofn.nMaxFile = MAX_PATH;\r
195   ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;\r
196 \r
197   if (GetOpenFileName(&ofn)) {\r
198     SendMessage(window, WM_SETTEXT, 0, (LPARAM) ofn.lpstrFile);\r
199   }\r
200   if (ofn.lpstrFilter) HeapFree(GetProcessHeap(), 0, (void *) ofn.lpstrFilter);\r
201 \r
202   delete[] ofn.lpstrFile;\r
203 }\r
204 \r
205 /* Install/remove dialogue callback */\r
206 INT_PTR CALLBACK install_dlg(HWND window, UINT message, WPARAM w, LPARAM l) {\r
207   switch (message) {\r
208     /* Creating the dialogue */\r
209     case WM_INITDIALOG:\r
210       return 1;\r
211 \r
212     /* Button was pressed or control was controlled */\r
213     case WM_COMMAND:\r
214       switch (LOWORD(w)) {\r
215         /* OK button */\r
216         case IDC_OK:\r
217           if (! install(window)) PostQuitMessage(0);\r
218           break;\r
219 \r
220         /* Cancel button */\r
221         case IDCANCEL:\r
222           DestroyWindow(window);\r
223           break;\r
224 \r
225         /* Browse button */\r
226         case IDC_BROWSE:\r
227           browse(GetDlgItem(window, IDC_PATH));\r
228           break;\r
229 \r
230         /* Remove button */\r
231         case IDC_REMOVE:\r
232           if (! remove(window)) PostQuitMessage(0);\r
233           break;\r
234       }\r
235       return 1;\r
236 \r
237     /* Window closing */\r
238     case WM_CLOSE:\r
239       DestroyWindow(window);\r
240       return 0;\r
241     case WM_DESTROY:\r
242       PostQuitMessage(0);\r
243   }\r
244   return 0;\r
245 }\r