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