37 #ifdef HAVE_VERSIONHELPERS_H
38 #include <versionhelpers.h>
48 #define IO_TIMEOUT 2000
50 #define ERROR_OPENVPN_STARTUP 0x20000000
51 #define ERROR_STARTUP_DATA 0x20000001
52 #define ERROR_MESSAGE_DATA 0x20000002
53 #define ERROR_MESSAGE_TYPE 0x20000003
56 static SERVICE_STATUS
status = { .dwServiceType = SERVICE_WIN32_SHARE_PROCESS };
60 #define RDNS_TIMEOUT 600
62 #define TUN_IOCTL_REGISTER_RINGS CTL_CODE(51820U, 0x970U, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
118 if (new_item == NULL)
120 return ERROR_OUTOFMEMORY;
123 new_item->
next = *pfirst;
138 for (pnext = pfirst; *pnext; pnext = &(*pnext)->
next)
141 if (!match(item->
data, ctx))
159 if (handle && *handle && *handle != INVALID_HANDLE_VALUE)
161 CloseHandle(*handle);
162 *handle = INVALID_HANDLE_VALUE;
164 return INVALID_HANDLE_VALUE;
172 UnmapViewOfFile(*ring);
187 ZeroMemory(overlapped,
sizeof(OVERLAPPED));
188 overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
189 return overlapped->hEvent;
196 HANDLE io_event = overlapped->hEvent;
197 if (!ResetEvent(io_event))
201 ZeroMemory(overlapped,
sizeof(OVERLAPPED));
202 overlapped->hEvent = io_event;
219 DWORD res, bytes = 0;
220 OVERLAPPED overlapped;
221 LPHANDLE handles = NULL;
229 handles = malloc((count + 1) *
sizeof(HANDLE));
237 success = WriteFile(pipe,
buffer, size, NULL, &overlapped);
241 success = ReadFile(pipe,
buffer, size, NULL, &overlapped);
243 if (!success && GetLastError() != ERROR_IO_PENDING && GetLastError() != ERROR_MORE_DATA)
248 handles[0] = io_event;
249 for (i = 0; i < count; i++)
251 handles[i + 1] = events[i];
254 res = WaitForMultipleObjects(count + 1, handles, FALSE,
256 if (res != WAIT_OBJECT_0)
264 PeekNamedPipe(pipe, NULL, 0, NULL, &bytes, NULL);
268 GetOverlappedResult(pipe, &overlapped, &bytes, TRUE);
298 const WCHAR
msg[] = L
"Process ID";
299 WCHAR buf[22 + _countof(
msg)];
307 WritePipeAsync(pipe, buf, (DWORD)(wcslen(buf) * 2), count, events);
311 ReturnError(HANDLE pipe, DWORD error, LPCWSTR func, DWORD count, LPHANDLE events)
314 LPWSTR result = L
"0xffffffff\nFormatMessage failed\nCould not return result";
323 FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM
324 |FORMAT_MESSAGE_ALLOCATE_BUFFER
325 |FORMAT_MESSAGE_IGNORE_INSERTS,
326 0, error, 0, (LPWSTR) &args[2], 0, NULL);
329 result_len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING
330 |FORMAT_MESSAGE_ALLOCATE_BUFFER
331 |FORMAT_MESSAGE_ARGUMENT_ARRAY,
332 L
"0x%1!08x!\n%2!s!\n%3!s!", 0, 0,
333 (LPWSTR) &result, 0, (va_list *) args);
335 WritePipeAsync(pipe, result, (DWORD)(wcslen(result) * 2), count, events);
340 LocalFree((LPVOID) args[2]);
367 const WCHAR *msg1 = L
"You have specified a config file location (%ls relative to %ls)"
368 L
" that requires admin approval. This error may be avoided"
369 L
" by adding your account to the \"%ls\" group";
371 const WCHAR *msg2 = L
"You have specified an option (%ls) that may be used"
372 L
" only with admin approval. This error may be avoided"
373 L
" by adding your account to the \"%ls\" group";
380 L
"Cannot validate options: CommandLineToArgvW failed with error = 0x%08x",
397 WCHAR *argv_tmp[2] = { L
"--config",
argv[0] };
407 for (i = 0; i < argc; ++i)
416 if (wcscmp(L
"--config",
argv[i]) == 0 && argc-i > 1)
456 size = bytes /
sizeof(*data);
464 data = malloc(bytes);
480 if (
data[size - 1] != 0)
498 len = wcslen(sud->
options) + 1;
527 SOCKADDR_INET sa_inet;
528 ZeroMemory(&sa_inet,
sizeof(sa_inet));
529 sa_inet.si_family = family;
530 if (family == AF_INET)
532 sa_inet.Ipv4.sin_addr = addr->
ipv4;
534 else if (family == AF_INET6)
536 sa_inet.Ipv6.sin6_addr = addr->
ipv6;
545 LPWSTR wide_name =
utf8to16(iface_name);
549 status = ConvertInterfaceAliasToLuid(wide_name, luid);
554 status = ERROR_OUTOFMEMORY;
565 err = ConvertInterfaceAliasToLuid(ifname, &luid);
566 if (err == ERROR_SUCCESS)
568 err = ConvertInterfaceLuidToIndex(&luid, index);
570 if (err != ERROR_SUCCESS)
580 return memcmp(item,
address,
sizeof(MIB_UNICASTIPADDRESS_ROW)) == 0 ? TRUE : FALSE;
586 return DeleteUnicastIpAddressEntry(addr_row);
593 PMIB_UNICASTIPADDRESS_ROW addr_row;
596 addr_row = malloc(
sizeof(*addr_row));
597 if (addr_row == NULL)
599 return ERROR_OUTOFMEMORY;
602 InitializeUnicastIpAddressEntry(addr_row);
604 addr_row->OnLinkPrefixLength = (UINT8)
msg->prefix_len;
606 if (
msg->iface.index != -1)
608 addr_row->InterfaceIndex =
msg->iface.index;
618 addr_row->InterfaceLuid = luid;
623 err = CreateUnicastIpAddressEntry(addr_row);
658 return memcmp(item,
route,
sizeof(MIB_IPFORWARD_ROW2)) == 0 ? TRUE : FALSE;
664 return DeleteIpForwardEntry2(fwd_row);
671 PMIB_IPFORWARD_ROW2 fwd_row;
674 fwd_row = malloc(
sizeof(*fwd_row));
677 return ERROR_OUTOFMEMORY;
680 ZeroMemory(fwd_row,
sizeof(*fwd_row));
681 fwd_row->ValidLifetime = 0xffffffff;
682 fwd_row->PreferredLifetime = 0xffffffff;
683 fwd_row->Protocol = MIB_IPPROTO_NETMGMT;
684 fwd_row->Metric =
msg->metric;
686 fwd_row->DestinationPrefix.PrefixLength = (UINT8)
msg->prefix_len;
689 if (
msg->iface.index != -1)
691 fwd_row->InterfaceIndex =
msg->iface.index;
693 else if (strlen(
msg->iface.name))
701 fwd_row->InterfaceLuid = luid;
706 err = CreateIpForwardEntry2(fwd_row);
742 if (
msg->family == AF_INET)
744 return FlushIpNetTable(
msg->iface.index);
747 return FlushIpNetTable2(
msg->family,
msg->iface.index);
761 err_str = TEXT(
"Unknown Win32 Error");
763 if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM
764 | FORMAT_MESSAGE_ARGUMENT_ARRAY,
765 NULL, err, 0, buf,
sizeof(buf), NULL))
799 free(interface_data);
814 HANDLE engine = NULL;
825 err = ERROR_OUTOFMEMORY;
828 interface_data->
engine = engine;
829 interface_data->
index =
msg->iface.index;
872 free(interface_data);
897 ExecCommand(
const WCHAR *argv0,
const WCHAR *cmdline, DWORD timeout)
901 PROCESS_INFORMATION pi;
902 DWORD proc_flags = CREATE_NO_WINDOW|CREATE_UNICODE_ENVIRONMENT;
903 WCHAR *cmdline_dup = NULL;
905 ZeroMemory(&si,
sizeof(si));
906 ZeroMemory(&pi,
sizeof(pi));
911 cmdline_dup = _wcsdup(cmdline);
912 if (cmdline_dup && CreateProcessW(argv0, cmdline_dup, NULL, NULL, FALSE,
913 proc_flags, NULL, NULL, &si, &pi) )
915 WaitForSingleObject(pi.hProcess, timeout ? timeout : INFINITE);
916 if (!GetExitCodeProcess(pi.hProcess, &exit_code))
919 exit_code = GetLastError();
921 else if (exit_code == STILL_ACTIVE)
923 exit_code = WAIT_TIMEOUT;
926 TerminateProcess(pi.hProcess, exit_code);
933 argv0, cmdline, exit_code);
940 CloseHandle(pi.hProcess);
941 CloseHandle(pi.hThread);
945 exit_code = GetLastError();
965 WCHAR ipcfg[MAX_PATH];
973 { ipcfg, L
"ipconfig /flushdns", timeout },
974 { ipcfg, L
"ipconfig /registerdns", timeout },
981 if (WaitForMultipleObjects(2, wait_handles, FALSE, timeout) == WAIT_OBJECT_0)
984 for (i = 0; i < _countof(cmds); ++i)
986 ExecCommand(cmds[i].argv0, cmds[i].cmdline, cmds[i].timeout);
997 err = ERROR_SEM_TIMEOUT;
1006 HANDLE thread = NULL;
1009 thread = CreateThread(NULL, 0,
RegisterDNS, NULL, 0, NULL);
1018 CloseHandle(thread);
1022 err = GetLastError();
1038 netsh_dns_cmd(
const wchar_t *action,
const wchar_t *proto,
const wchar_t *if_name,
const wchar_t *addr)
1041 int timeout = 30000;
1042 wchar_t argv0[MAX_PATH];
1043 wchar_t *cmdline = NULL;
1047 if (wcscmp(action, L
"delete") == 0)
1063 const wchar_t *fmt = L
"netsh interface %ls %ls dns \"%ls\" %ls";
1066 size_t ncmdline = wcslen(fmt) + wcslen(if_name) + wcslen(addr) + 32 + 1;
1067 cmdline = malloc(ncmdline*
sizeof(
wchar_t));
1070 err = ERROR_OUTOFMEMORY;
1076 if (IsWindows7OrGreater())
1078 wcscat_s(cmdline, ncmdline, L
" validate=no");
1100 int timeout = 30000;
1101 wchar_t argv0[MAX_PATH];
1102 wchar_t *cmdline = NULL;
1103 const wchar_t *addr_static = (wcscmp(action, L
"set") == 0) ? L
"static" : L
"";
1107 if (wcscmp(action, L
"delete") == 0)
1123 const wchar_t *fmt = L
"netsh interface ip %ls wins \"%ls\" %ls %ls";
1126 size_t ncmdline = wcslen(fmt) + wcslen(if_name) + wcslen(action) + wcslen(addr)
1127 +wcslen(addr_static) + 32 + 1;
1128 cmdline = malloc(ncmdline *
sizeof(
wchar_t));
1131 err = ERROR_OUTOFMEMORY;
1135 openvpn_swprintf(cmdline, ncmdline, fmt, action, if_name, addr_static, addr);
1154 const wchar_t *
data)
1157 wchar_t argv0[MAX_PATH];
1158 wchar_t *cmdline = NULL;
1159 int timeout = 10000;
1167 fmt = L
"wmic nicconfig where (InterfaceIndex=%ld) call %ls (%ls)";
1171 fmt = L
"wmic nicconfig where (InterfaceIndex=%ld) call %ls \"%ls\"";
1174 size_t ncmdline = wcslen(fmt) + 20 + wcslen(action)
1176 cmdline = malloc(ncmdline*
sizeof(
wchar_t));
1179 return ERROR_OUTOFMEMORY;
1194 wchar_t *proto = (family == AF_INET6) ? L
"ipv6" : L
"ip";
1200 AddDNS(
short family,
wchar_t *if_name,
wchar_t *addr)
1202 wchar_t *proto = (family == AF_INET6) ? L
"ipv6" : L
"ip";
1209 return (wcscmp(item, str) == 0) ? TRUE : FALSE;
1223 NET_IFINDEX if_index;
1226 if (err != ERROR_SUCCESS)
1231 wchar_t *wdomain =
utf8to16(domain);
1234 return ERROR_OUTOFMEMORY;
1246 if (err == 0 && wdomain[0] && lists)
1248 wchar_t *tmp_name = _wcsdup(if_name);
1252 err = ERROR_OUTOFMEMORY;
1266 int addr_len =
msg->addr_len;
1269 if (addr_len > _countof(
msg->addr))
1271 addr_len = _countof(
msg->addr);
1274 if (!
msg->iface.name[0])
1282 msgptr->
iface.
name[_countof(
msg->iface.name)-1] =
'\0';
1283 msgptr->
domains[_countof(
msg->domains)-1] =
'\0';
1289 return ERROR_OUTOFMEMORY;
1307 if (
msg->domains[0])
1315 for (
int i = 0; i < addr_len; ++i)
1317 if (
msg->family == AF_INET6)
1319 RtlIpv6AddressToStringW(&
msg->addr[i].ipv6, addr);
1323 RtlIpv4AddressToStringW(&
msg->addr[i].ipv4, addr);
1325 err =
AddDNS(
msg->family, wide_name, addr);
1337 if (
msg->addr_len > 0)
1339 wchar_t *tmp_name = _wcsdup(wide_name);
1340 if (!tmp_name ||
AddListItem(&(*lists)[undo_type], tmp_name))
1344 err = ERROR_OUTOFMEMORY;
1349 if (
msg->domains[0])
1364 int addr_len =
msg->addr_len;
1367 if (addr_len > _countof(
msg->addr))
1369 addr_len = _countof(
msg->addr);
1372 if (!
msg->iface.name[0])
1380 msgptr->
iface.
name[_countof(
msg->iface.name) - 1] =
'\0';
1386 return ERROR_OUTOFMEMORY;
1407 for (
int i = 0; i < addr_len; ++i)
1409 RtlIpv4AddressToStringW(&
msg->addr[i].ipv4, addr);
1424 wchar_t *tmp_name = _wcsdup(wide_name);
1429 err = ERROR_OUTOFMEMORY;
1443 DWORD timeout = 5000;
1444 wchar_t argv0[MAX_PATH];
1452 const wchar_t *fmt = L
"netsh interface ipv4 set address name=\"%d\" source=dhcp";
1457 size_t ncmdline = wcslen(fmt) + 10 + 1;
1458 wchar_t *cmdline = malloc(ncmdline*
sizeof(
wchar_t));
1461 err = ERROR_OUTOFMEMORY;
1480 DWORD err = ERROR_SUCCESS;
1482 if (!DuplicateHandle(ovpn_proc, orig_handle, GetCurrentProcess(), new_handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
1484 err = GetLastError();
1495 DWORD err = ERROR_SUCCESS;
1497 HANDLE dup_handle = NULL;
1500 if (err != ERROR_SUCCESS)
1504 *ring = (
struct tun_ring *)MapViewOfFile(dup_handle, FILE_MAP_ALL_ACCESS, 0, 0,
sizeof(
struct tun_ring));
1508 err = GetLastError();
1524 if (ring_buffer_maps)
1528 else if ((ring_buffer_maps = calloc(1,
sizeof(*ring_buffer_maps))) == NULL)
1530 return ERROR_OUTOFMEMORY;
1533 HANDLE device = NULL;
1534 HANDLE send_tail_moved = NULL;
1535 HANDLE receive_tail_moved = NULL;
1538 if (err != ERROR_SUCCESS)
1544 if (err != ERROR_SUCCESS)
1550 if (err != ERROR_SUCCESS)
1556 if (err != ERROR_SUCCESS)
1562 if (err != ERROR_SUCCESS)
1569 send_tail_moved, receive_tail_moved))
1571 err = GetLastError();
1579 if (err != ERROR_SUCCESS && ring_buffer_maps)
1582 free(ring_buffer_maps);
1594 MIB_IPINTERFACE_ROW ipiface;
1595 InitializeIpInterfaceEntry(&ipiface);
1596 ipiface.Family = mtu->
family;
1598 err = GetIpInterfaceEntry(&ipiface);
1599 if (err != NO_ERROR)
1603 if (mtu->
family == AF_INET)
1605 ipiface.SitePrefixLength = 0;
1607 ipiface.NlMtu = mtu->
mtu;
1609 err = SetIpInterfaceEntry(&ipiface);
1615 DWORD bytes, DWORD count, LPHANDLE events,
undo_lists_t *lists)
1633 .size =
sizeof(ack),
1647 switch (
msg.header.type)
1651 if (
msg.header.size ==
sizeof(
msg.address))
1659 if (
msg.header.size ==
sizeof(
msg.route))
1666 if (
msg.header.size ==
sizeof(
msg.flush_neighbors))
1674 if (
msg.header.size ==
sizeof(
msg.block_dns))
1695 if (
msg.header.size ==
sizeof(
msg.dhcp))
1702 if (
msg.header.size ==
sizeof(
msg.rrb))
1709 if (
msg.header.size ==
sizeof(
msg.mtu))
1788 *pnext = item->
next;
1799 HANDLE ovpn_pipe = NULL, svc_pipe = NULL;
1800 PTOKEN_USER svc_user = NULL, ovpn_user = NULL;
1801 HANDLE svc_token = NULL, imp_token = NULL, pri_token = NULL;
1802 HANDLE stdin_read = NULL, stdin_write = NULL;
1803 HANDLE stdout_write = NULL;
1804 DWORD pipe_mode, len, exit_code = 0;
1806 STARTUPINFOW startup_info;
1807 PROCESS_INFORMATION proc_info;
1808 LPVOID user_env = NULL;
1809 TCHAR ovpn_pipe_name[256];
1811 WCHAR *cmdline = NULL;
1812 size_t cmdline_size;
1814 WCHAR errmsg[512] = L
"";
1816 SECURITY_ATTRIBUTES inheritable = {
1817 .nLength =
sizeof(inheritable),
1818 .lpSecurityDescriptor = NULL,
1819 .bInheritHandle = TRUE
1823 EXPLICIT_ACCESS ea[2];
1824 SECURITY_DESCRIPTOR ovpn_sd;
1825 SECURITY_ATTRIBUTES ovpn_sa = {
1826 .nLength =
sizeof(ovpn_sa),
1827 .lpSecurityDescriptor = &ovpn_sd,
1828 .bInheritHandle = FALSE
1831 ZeroMemory(&ea,
sizeof(ea));
1832 ZeroMemory(&startup_info,
sizeof(startup_info));
1833 ZeroMemory(&undo_lists,
sizeof(undo_lists));
1834 ZeroMemory(&proc_info,
sizeof(proc_info));
1841 if (!InitializeSecurityDescriptor(&ovpn_sd, SECURITY_DESCRIPTOR_REVISION))
1848 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &svc_token))
1854 while (!GetTokenInformation(svc_token, TokenUser, svc_user, len, &len))
1856 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1862 svc_user = malloc(len);
1863 if (svc_user == NULL)
1869 if (!IsValidSid(svc_user->User.Sid))
1875 if (!ImpersonateNamedPipeClient(pipe))
1880 if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &imp_token))
1886 while (!GetTokenInformation(imp_token, TokenUser, ovpn_user, len, &len))
1888 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1894 ovpn_user = malloc(len);
1895 if (ovpn_user == NULL)
1901 if (!IsValidSid(ovpn_user->User.Sid))
1922 ea[0].grfAccessPermissions = SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL;
1923 ea[0].grfAccessMode = SET_ACCESS;
1924 ea[0].grfInheritance = NO_INHERITANCE;
1925 ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
1926 ea[0].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1927 ea[0].Trustee.ptstrName = (LPTSTR) svc_user->User.Sid;
1928 ea[1].grfAccessPermissions = READ_CONTROL | SYNCHRONIZE | PROCESS_VM_READ
1929 |SYNCHRONIZE | PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION;
1930 ea[1].grfAccessMode = SET_ACCESS;
1931 ea[1].grfInheritance = NO_INHERITANCE;
1932 ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
1933 ea[1].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1934 ea[1].Trustee.ptstrName = (LPTSTR) ovpn_user->User.Sid;
1937 if (!SetSecurityDescriptorOwner(&ovpn_sd, svc_user->User.Sid, FALSE))
1942 if (SetEntriesInAcl(2, ea, NULL, &ovpn_dacl) != ERROR_SUCCESS)
1947 if (!SetSecurityDescriptorDacl(&ovpn_sd, TRUE, ovpn_dacl, FALSE))
1954 if (!DuplicateTokenEx(imp_token, TOKEN_ALL_ACCESS, NULL, 0, TokenPrimary, &pri_token))
1961 stdout_write = CreateFile(_T(
"NUL"), GENERIC_WRITE, FILE_SHARE_WRITE,
1962 &inheritable, OPEN_EXISTING, 0, NULL);
1963 if (stdout_write == INVALID_HANDLE_VALUE)
1969 if (!CreatePipe(&stdin_read, &stdin_write, &inheritable, 0)
1970 || !SetHandleInformation(stdin_write, HANDLE_FLAG_INHERIT, 0))
1978 ovpn_pipe = CreateNamedPipe(ovpn_pipe_name,
1979 PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED,
1980 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, 128, 128, 0, NULL);
1981 if (ovpn_pipe == INVALID_HANDLE_VALUE)
1987 svc_pipe = CreateFile(ovpn_pipe_name, GENERIC_READ | GENERIC_WRITE, 0,
1988 &inheritable, OPEN_EXISTING, 0, NULL);
1989 if (svc_pipe == INVALID_HANDLE_VALUE)
1995 pipe_mode = PIPE_READMODE_MESSAGE;
1996 if (!SetNamedPipeHandleState(svc_pipe, &pipe_mode, NULL, NULL))
2002 cmdline_size = wcslen(sud.
options) + 128;
2003 cmdline = malloc(cmdline_size *
sizeof(*cmdline));
2004 if (cmdline == NULL)
2012 if (!CreateEnvironmentBlock(&user_env, imp_token, FALSE))
2018 startup_info.cb =
sizeof(startup_info);
2019 startup_info.dwFlags = STARTF_USESTDHANDLES;
2020 startup_info.hStdInput = stdin_read;
2021 startup_info.hStdOutput = stdout_write;
2022 startup_info.hStdError = stdout_write;
2027 if (!CreateProcessAsUserW(pri_token, exe_path, cmdline, &ovpn_sa, NULL, TRUE,
2029 user_env, sud.
directory, &startup_info, &proc_info))
2035 if (!RevertToSelf())
2037 TerminateProcess(proc_info.hProcess, 1);
2048 DWORD input_size = WideCharToMultiByte(CP_UTF8, 0, sud.
std_input, -1, NULL, 0, NULL, NULL);
2050 if (input_size && (input = malloc(input_size)))
2053 WideCharToMultiByte(CP_UTF8, 0, sud.
std_input, -1, input, input_size, NULL, NULL);
2054 WriteFile(stdin_write, input, (DWORD)strlen(input), &written, NULL);
2069 WaitForSingleObject(proc_info.hProcess,
IO_TIMEOUT);
2070 GetExitCodeProcess(proc_info.hProcess, &exit_code);
2071 if (exit_code == STILL_ACTIVE)
2073 TerminateProcess(proc_info.hProcess, 1);
2075 else if (exit_code != 0)
2079 L
"OpenVPN exited with error: exit code = %lu", exit_code);
2085 FlushFileBuffers(pipe);
2086 DisconnectNamedPipe(pipe);
2091 DestroyEnvironmentBlock(user_env);
2112 SERVICE_STATUS *
status = ctx;
2115 case SERVICE_CONTROL_STOP:
2116 status->dwCurrentState = SERVICE_STOP_PENDING;
2124 case SERVICE_CONTROL_INTERROGATE:
2128 return ERROR_CALL_NOT_IMPLEMENTED;
2136 TCHAR pipe_name[256];
2138 PACL old_dacl, new_dacl;
2139 PSECURITY_DESCRIPTOR sd;
2140 static EXPLICIT_ACCESS ea[2];
2141 static BOOL initialized = FALSE;
2142 DWORD flags = PIPE_ACCESS_DUPLEX | WRITE_DAC | FILE_FLAG_OVERLAPPED;
2146 PSID everyone, anonymous;
2148 ConvertStringSidToSid(TEXT(
"S-1-1-0"), &everyone);
2149 ConvertStringSidToSid(TEXT(
"S-1-5-7"), &anonymous);
2151 ea[0].grfAccessPermissions = FILE_GENERIC_WRITE;
2152 ea[0].grfAccessMode = GRANT_ACCESS;
2153 ea[0].grfInheritance = NO_INHERITANCE;
2154 ea[0].Trustee.pMultipleTrustee = NULL;
2155 ea[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2156 ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
2157 ea[0].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
2158 ea[0].Trustee.ptstrName = (LPTSTR) everyone;
2160 ea[1].grfAccessPermissions = 0;
2161 ea[1].grfAccessMode = REVOKE_ACCESS;
2162 ea[1].grfInheritance = NO_INHERITANCE;
2163 ea[1].Trustee.pMultipleTrustee = NULL;
2164 ea[1].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2165 ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
2166 ea[1].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
2167 ea[1].Trustee.ptstrName = (LPTSTR) anonymous;
2169 flags |= FILE_FLAG_FIRST_PIPE_INSTANCE;
2174 pipe = CreateNamedPipe(pipe_name, flags,
2175 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
2176 PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, NULL);
2177 if (pipe == INVALID_HANDLE_VALUE)
2180 return INVALID_HANDLE_VALUE;
2183 if (GetSecurityInfo(pipe, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
2184 NULL, NULL, &old_dacl, NULL, &sd) != ERROR_SUCCESS)
2190 if (SetEntriesInAcl(2, ea, old_dacl, &new_dacl) != ERROR_SUCCESS)
2196 if (SetSecurityInfo(pipe, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
2197 NULL, NULL, new_dacl, NULL) != ERROR_SUCCESS)
2211 static DWORD size = 10;
2212 static LPHANDLE handles = NULL;
2215 if (handles == NULL)
2217 handles = malloc(size *
sizeof(HANDLE));
2218 *handles_ptr = handles;
2219 if (handles == NULL)
2221 return ERROR_OUTOFMEMORY;
2225 handles[
pos++] = io_event;
2238 tmp = realloc(handles, size *
sizeof(HANDLE));
2243 return ERROR_OUTOFMEMORY;
2246 *handles_ptr = handles;
2248 handles[
pos++] = threads->
data;
2249 threads = threads->
next;
2273 status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
2281 HANDLE pipe, io_event = NULL;
2282 OVERLAPPED overlapped;
2283 DWORD error = NO_ERROR;
2285 PHANDLE handles = NULL;
2294 status.dwCurrentState = SERVICE_START_PENDING;
2295 status.dwServiceSpecificExitCode = NO_ERROR;
2296 status.dwWin32ExitCode = NO_ERROR;
2297 status.dwWaitHint = 3000;
2302 if (error != ERROR_SUCCESS)
2308 exit_event = CreateEvent(NULL, TRUE, FALSE, NULL);
2323 if (error != NO_ERROR)
2329 if (pipe == INVALID_HANDLE_VALUE)
2334 status.dwCurrentState = SERVICE_RUNNING;
2340 if (ConnectNamedPipe(pipe, &overlapped) == FALSE
2341 && GetLastError() != ERROR_PIPE_CONNECTED
2342 && GetLastError() != ERROR_IO_PENDING)
2348 error = WaitForMultipleObjects(handle_count, handles, FALSE, INFINITE);
2349 if (error == WAIT_OBJECT_0)
2353 HANDLE thread = CreateThread(NULL, 0,
RunOpenvpn, pipe, CREATE_SUSPENDED, NULL);
2367 TerminateThread(thread, 1);
2373 ResumeThread(thread);
2387 if (error == WAIT_FAILED)
2417 status.dwCurrentState = SERVICE_STOPPED;
2418 status.dwWin32ExitCode = error;