OpenVPN
service.c
Go to the documentation of this file.
1/*
2 * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
3 * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
4 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
5 * PARTICULAR PURPOSE.
6 *
7 * Copyright (C) 1993 - 2000. Microsoft Corporation. All rights reserved.
8 * 2013 Heiko Hund <heiko.hund@sophos.com>
9 */
10
11#include "service.h"
12
13#include <windows.h>
14#include <stdio.h>
15#include <process.h>
16
17
19
20
21BOOL
22ReportStatusToSCMgr(SERVICE_STATUS_HANDLE service, SERVICE_STATUS *status)
23{
24 static DWORD dwCheckPoint = 1;
25 BOOL res = TRUE;
26
27 if (status->dwCurrentState == SERVICE_START_PENDING)
28 {
29 status->dwControlsAccepted = 0;
30 }
31 else
32 {
33 status->dwControlsAccepted = SERVICE_ACCEPT_STOP;
34 }
35
36 if (status->dwCurrentState == SERVICE_RUNNING || status->dwCurrentState == SERVICE_STOPPED)
37 {
38 status->dwCheckPoint = 0;
39 }
40 else
41 {
42 status->dwCheckPoint = dwCheckPoint++;
43 }
44
45 /* Report the status of the service to the service control manager. */
46 res = SetServiceStatus(service, status);
47 if (!res)
48 {
49 MsgToEventLog(MSG_FLAGS_ERROR, L"SetServiceStatus");
50 }
51
52 return res;
53}
54
55static int
57{
58 SC_HANDLE service;
59 SC_HANDLE svc_ctl_mgr;
60 WCHAR path[512];
61 int i, ret = _service_max;
62
63 if (GetModuleFileName(NULL, path + 1, _countof(path) - 2) == 0)
64 {
65 wprintf(L"Unable to install service - %ls\n", GetLastErrorText());
66 return 1;
67 }
68
69 path[0] = L'\"';
70 wcscat_s(path, _countof(path), L"\"");
71
72 svc_ctl_mgr = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE);
73 if (svc_ctl_mgr == NULL)
74 {
75 wprintf(L"OpenSCManager failed - %ls\n", GetLastErrorText());
76 return 1;
77 }
78
79 for (i = 0; i < _service_max; i++)
80 {
81 service = CreateService(
82 svc_ctl_mgr, openvpn_service[i].name, openvpn_service[i].display_name,
83 SERVICE_QUERY_STATUS, SERVICE_WIN32_SHARE_PROCESS, openvpn_service[i].start_type,
84 SERVICE_ERROR_NORMAL, path, NULL, NULL, openvpn_service[i].dependencies, NULL, NULL);
85 if (service)
86 {
87 wprintf(L"%ls installed.\n", openvpn_service[i].display_name);
88 CloseServiceHandle(service);
89 --ret;
90 }
91 else
92 {
93 wprintf(L"CreateService failed - %ls\n", GetLastErrorText());
94 }
95 }
96
97 CloseServiceHandle(svc_ctl_mgr);
98 return ret;
99}
100
101
102static int
104{
105 int ret = 1;
106 SC_HANDLE svc_ctl_mgr;
107 SC_HANDLE service;
108
109 svc_ctl_mgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
110 if (svc_ctl_mgr == NULL)
111 {
112 wprintf(L"OpenSCManager failed - %ls\n", GetLastErrorText());
113 return 1;
114 }
115
116 service = OpenService(svc_ctl_mgr, openvpn_service[type].name, SERVICE_ALL_ACCESS);
117 if (service)
118 {
119 if (StartService(service, 0, NULL))
120 {
121 wprintf(L"Service Started\n");
122 ret = 0;
123 }
124 else
125 {
126 wprintf(L"StartService failed - %ls\n", GetLastErrorText());
127 }
128
129 CloseServiceHandle(service);
130 }
131 else
132 {
133 wprintf(L"OpenService failed - %ls\n", GetLastErrorText());
134 }
135
136 CloseServiceHandle(svc_ctl_mgr);
137 return ret;
138}
139
140
141static int
143{
144 SC_HANDLE service;
145 SC_HANDLE svc_ctl_mgr;
146 SERVICE_STATUS status;
147 int i, ret = _service_max;
148
149 svc_ctl_mgr = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
150 if (svc_ctl_mgr == NULL)
151 {
152 wprintf(L"OpenSCManager failed - %ls\n", GetLastErrorText());
153 return 1;
154 }
155
156 for (i = 0; i < _service_max; i++)
157 {
158 openvpn_service_t *ovpn_svc = &openvpn_service[i];
159 service =
160 OpenService(svc_ctl_mgr, ovpn_svc->name, DELETE | SERVICE_STOP | SERVICE_QUERY_STATUS);
161 if (service == NULL)
162 {
163 wprintf(L"OpenService failed - %ls\n", GetLastErrorText());
164 goto out;
165 }
166
167 /* try to stop the service */
168 if (ControlService(service, SERVICE_CONTROL_STOP, &status))
169 {
170 wprintf(L"Stopping %ls.", ovpn_svc->display_name);
171 Sleep(1000);
172
173 while (QueryServiceStatus(service, &status))
174 {
175 if (status.dwCurrentState == SERVICE_STOP_PENDING)
176 {
177 wprintf(L".");
178 Sleep(1000);
179 }
180 else
181 {
182 break;
183 }
184 }
185
186 if (status.dwCurrentState == SERVICE_STOPPED)
187 {
188 wprintf(L"\n%ls stopped.\n", ovpn_svc->display_name);
189 }
190 else
191 {
192 wprintf(L"\n%ls failed to stop.\n", ovpn_svc->display_name);
193 }
194 }
195
196 /* now remove the service */
197 if (DeleteService(service))
198 {
199 wprintf(L"%ls removed.\n", ovpn_svc->display_name);
200 --ret;
201 }
202 else
203 {
204 wprintf(L"DeleteService failed - %ls\n", GetLastErrorText());
205 }
206
207 CloseServiceHandle(service);
208 }
209
210out:
211 CloseServiceHandle(svc_ctl_mgr);
212 return ret;
213}
214
215
216int
217wmain(int argc, WCHAR *argv[])
218{
219 /*
220 * Interactive service (as a SERVICE_WIN32_SHARE_PROCESS)
221 * This is the default.
222 */
223 const SERVICE_TABLE_ENTRY dispatchTable_shared[] = {
225 };
226
227 /* Interactive service only (as a SERVICE_WIN32_OWN_PROCESS) */
228 const SERVICE_TABLE_ENTRY dispatchTable_interactive[] = { { L"", ServiceStartInteractiveOwn },
229 { NULL, NULL } };
230
231 const SERVICE_TABLE_ENTRY *dispatchTable = dispatchTable_shared;
232
234
235 for (int i = 1; i < argc; i++)
236 {
237 if (*argv[i] == L'-' || *argv[i] == L'/')
238 {
239 if (_wcsicmp(L"install", argv[i] + 1) == 0)
240 {
241 return CmdInstallServices();
242 }
243 else if (_wcsicmp(L"remove", argv[i] + 1) == 0)
244 {
245 return CmdRemoveServices();
246 }
247 else if (_wcsicmp(L"start", argv[i] + 1) == 0)
248 {
250 }
251 else if (argc > i + 2 && _wcsicmp(L"instance", argv[i] + 1) == 0)
252 {
253 if (_wcsicmp(L"interactive", argv[i + 1]) == 0)
254 {
255 dispatchTable = dispatchTable_interactive;
256 service_instance = argv[i + 2];
257 i += 2;
258 }
259 else
260 {
262 L"Invalid argument to -instance <%s>. Service not started.",
263 argv[i + 1]);
264 return 1;
265 }
266 }
267 else
268 {
269 wprintf(L"%ls -install to install the interactive service\n", APPNAME);
270 wprintf(
271 L"%ls -start [name] to start the service (name = \"interactive\") is optional\n",
272 APPNAME);
273 wprintf(L"%ls -remove to remove the service\n", APPNAME);
274
275 wprintf(L"\nService run-time parameters:\n");
276 wprintf(L"-instance interactive <id>\n"
277 L" Runs the service as an alternate instance.\n"
278 L" The service settings will be loaded from\n"
279 L" HKLM\\Software\\" _L(
280 PACKAGE_NAME) L"<id> registry key, and the service will accept\n"
281 L" requests on \\\\.\\pipe\\" _L(
282 PACKAGE) L"<id>\\service named pipe.\n");
283
284 return 0;
285 }
286 }
287 }
288
289 /* If it doesn't match any of the above parameters
290 * the service control manager may be starting the service
291 * so we must call StartServiceCtrlDispatcher
292 */
293 wprintf(L"\nStartServiceCtrlDispatcher being called.\n");
294 wprintf(L"This may take several seconds. Please wait.\n");
295
296 if (!StartServiceCtrlDispatcher(dispatchTable))
297 {
298 MsgToEventLog(MSG_FLAGS_ERROR, L"StartServiceCtrlDispatcher failed.");
299 }
300
301 return 0;
302}
DWORD MsgToEventLog(DWORD flags, LPCWSTR format,...)
Definition common.c:230
LPCWSTR service_instance
Definition common.c:26
LPCWSTR GetLastErrorText(void)
Definition common.c:198
VOID WINAPI ServiceStartInteractive(DWORD dwArgc, LPWSTR *lpszArgv)
static SERVICE_STATUS status
Definition interactive.c:51
openvpn_service_t interactive_service
Definition interactive.c:60
VOID WINAPI ServiceStartInteractiveOwn(DWORD dwArgc, LPWSTR *lpszArgv)
static SERVICE_STATUS_HANDLE service
Definition interactive.c:50
#define M_ERR
Definition error.h:104
static int CmdStartService(openvpn_service_type type)
Definition service.c:103
static int CmdInstallServices(void)
Definition service.c:56
static int CmdRemoveServices(void)
Definition service.c:142
BOOL ReportStatusToSCMgr(SERVICE_STATUS_HANDLE service, SERVICE_STATUS *status)
Definition service.c:22
openvpn_service_t openvpn_service[_service_max]
Definition service.c:18
int wmain(int argc, WCHAR *argv[])
Definition service.c:217
#define APPNAME
Definition service.h:36
#define MSG_FLAGS_ERROR
Definition service.h:42
openvpn_service_type
Definition service.h:49
@ _service_max
Definition service.h:51
@ interactive
Definition service.h:50
Definition argv.h:35
WCHAR * display_name
Definition service.h:58
#define _L(q)
Definition basic.h:38
char ** res