43 static SERVICE_STATUS
status = { .dwServiceType = SERVICE_WIN32_SHARE_PROCESS };
55 SECURITY_ATTRIBUTES
sa;
56 SECURITY_DESCRIPTOR
sd;
62 #define CLEAR(x) memset(&(x), 0, sizeof(x)) 70 obj->
sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
71 obj->
sa.lpSecurityDescriptor = &obj->
sd;
72 obj->
sa.bInheritHandle = TRUE;
73 if (!InitializeSecurityDescriptor(&obj->
sd, SECURITY_DESCRIPTOR_REVISION))
77 if (!SetSecurityDescriptorDacl(&obj->
sd, TRUE, NULL, FALSE))
85 create_event(LPCTSTR name,
bool allow_all,
bool initial_state,
bool manual_reset)
94 return CreateEvent(&sa.
sa, (BOOL)manual_reset, (BOOL)initial_state, name);
98 return CreateEvent(NULL, (BOOL)manual_reset, (BOOL)initial_state, name);
112 match(
const WIN32_FIND_DATA *find, LPCTSTR ext)
114 if (find->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
119 if (*ext == TEXT(
'\0'))
126 const TCHAR *p = _tcsrchr(find->cFileName, TEXT(
'.'));
127 return p && p != find->cFileName && _tcsicmp(p + 1, ext) == 0;
134 modext(LPTSTR dest,
size_t size, LPCTSTR src, LPCTSTR newext)
138 if (size > 0 && (_tcslen(src) + 1) <= size)
140 _tcscpy_s(dest, size, src);
141 dest [size - 1] = TEXT(
'\0');
145 if (dest[i] == TEXT(
'\\'))
149 if (dest[i] == TEXT(
'.'))
151 dest[i] = TEXT(
'\0');
155 if (_tcslen(dest) + _tcslen(newext) + 2 <= size)
157 _tcscat_s(dest, size, TEXT(
"."));
158 _tcscat_s(dest, size, newext);
161 dest[0] = TEXT(
'\0');
169 SERVICE_STATUS *
status = ctx;
172 case SERVICE_CONTROL_STOP:
173 status->dwCurrentState = SERVICE_STOP_PENDING;
181 case SERVICE_CONTROL_INTERROGATE:
185 return ERROR_CALL_NOT_IMPLEMENTED;
193 status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
201 DWORD error = NO_ERROR;
203 TCHAR event_name[256];
211 status.dwCurrentState = SERVICE_START_PENDING;
212 status.dwServiceSpecificExitCode = NO_ERROR;
213 status.dwWin32ExitCode = NO_ERROR;
243 if (WaitForSingleObject(
exit_event, 0) != WAIT_TIMEOUT)
245 MsgToEventLog(
M_ERR, TEXT(
"Exit event is already signaled -- we were not shut down properly"));
259 if (error != ERROR_SUCCESS)
269 WIN32_FIND_DATA find_obj;
272 TCHAR find_string[MAX_PATH];
276 find_handle = FindFirstFile(find_string, &find_obj);
277 if (find_handle == INVALID_HANDLE_VALUE)
279 MsgToEventLog(
M_ERR, TEXT(
"Cannot get configuration file list using: %s"), find_string);
288 HANDLE log_handle = NULL;
289 STARTUPINFO start_info;
290 PROCESS_INFORMATION proc_info;
292 TCHAR log_file[MAX_PATH];
293 TCHAR log_path[MAX_PATH];
303 FindClose(find_handle);
311 if (!
modext(log_file, _countof(log_file), find_obj.cFileName, TEXT(
"log")))
313 MsgToEventLog(
M_ERR, TEXT(
"Cannot construct logfile name based on: %s"), find_obj.cFileName);
314 FindClose(find_handle);
318 TEXT(
"%s\\%s"), settings.
log_dir, log_file);
321 openvpn_sntprintf(command_line, _countof(command_line), TEXT(
"openvpn --service \"" PACKAGE "%s_exit_1\" 1 --config \"%s\""),
334 log_handle = CreateFile(log_path,
338 settings.
append ? OPEN_ALWAYS : CREATE_ALWAYS,
339 FILE_ATTRIBUTE_NORMAL,
342 if (log_handle == INVALID_HANDLE_VALUE)
345 FindClose(find_handle);
352 if (SetFilePointer(log_handle, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)
355 FindClose(find_handle);
361 GetStartupInfo(&start_info);
362 start_info.cb =
sizeof(start_info);
363 start_info.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
364 start_info.wShowWindow = SW_HIDE;
365 start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
366 start_info.hStdOutput = start_info.hStdError = log_handle;
369 if (!CreateProcess(settings.
exe_path,
374 settings.
priority | CREATE_NEW_CONSOLE,
385 FindClose(find_handle);
386 CloseHandle(log_handle);
393 if (!CloseHandle(proc_info.hProcess)
394 || !CloseHandle(proc_info.hThread)
395 || !CloseHandle(log_handle))
403 more_files = FindNextFile(find_handle, &find_obj);
405 }
while (more_files);
407 FindClose(find_handle);
411 status.dwCurrentState = SERVICE_RUNNING;
420 if (WaitForSingleObject(
exit_event, INFINITE) != WAIT_OBJECT_0)
431 status.dwCurrentState = SERVICE_STOPPED;
432 status.dwWin32ExitCode = error;
BOOL openvpn_sntprintf(LPTSTR str, size_t size, LPCTSTR format,...)
VOID WINAPI ServiceStartAutomatic(DWORD dwArgc, LPTSTR *lpszArgv)
DWORD MsgToEventLog(DWORD flags, LPCTSTR format,...)
openvpn_service_t automatic_service
TCHAR config_dir[MAX_PATH]
VOID WINAPI ServiceStartAutomaticOwn(DWORD dwArgc, LPTSTR *lpszArgv)
static bool match(const WIN32_FIND_DATA *find, LPCTSTR ext)
static bool modext(LPTSTR dest, size_t size, LPCTSTR src, LPCTSTR newext)
#define SERVICE_DEPENDENCIES
static DWORD WINAPI ServiceCtrlAutomatic(DWORD ctrl_code, DWORD event, LPVOID data, LPVOID ctx)
static SERVICE_STATUS status
DWORD GetOpenvpnSettings(settings_t *s)
static SERVICE_STATUS_HANDLE service
HANDLE create_event(LPCTSTR name, bool allow_all, bool initial_state, bool manual_reset)
static settings_t settings
static int finish(RSA *rsa)
void close_if_open(HANDLE h)
BOOL ReportStatusToSCMgr(SERVICE_STATUS_HANDLE service, SERVICE_STATUS *status)
bool init_security_attributes_allow_all(struct security_attributes *obj)