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