37 #include <versionhelpers.h>
44 #define IO_TIMEOUT 2000
46 #define ERROR_OPENVPN_STARTUP 0x20000000
47 #define ERROR_STARTUP_DATA 0x20000001
48 #define ERROR_MESSAGE_DATA 0x20000002
49 #define ERROR_MESSAGE_TYPE 0x20000003
52 static SERVICE_STATUS
status = { .dwServiceType = SERVICE_WIN32_SHARE_PROCESS };
56 #define RDNS_TIMEOUT 600
58 #define TUN_IOCTL_REGISTER_RINGS CTL_CODE(51820U, 0x970U, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
114 if (new_item == NULL)
116 return ERROR_OUTOFMEMORY;
119 new_item->
next = *pfirst;
134 for (pnext = pfirst; *pnext; pnext = &(*pnext)->
next)
137 if (!match(item->
data, ctx))
155 if (handle && *handle && *handle != INVALID_HANDLE_VALUE)
157 CloseHandle(*handle);
158 *handle = INVALID_HANDLE_VALUE;
160 return INVALID_HANDLE_VALUE;
168 UnmapViewOfFile(*ring);
183 ZeroMemory(overlapped,
sizeof(OVERLAPPED));
184 overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
185 return overlapped->hEvent;
192 HANDLE io_event = overlapped->hEvent;
193 if (!ResetEvent(io_event))
197 ZeroMemory(overlapped,
sizeof(OVERLAPPED));
198 overlapped->hEvent = io_event;
215 DWORD res, bytes = 0;
216 OVERLAPPED overlapped;
217 LPHANDLE handles = NULL;
225 handles = malloc((count + 1) *
sizeof(HANDLE));
233 success = WriteFile(pipe,
buffer, size, NULL, &overlapped);
237 success = ReadFile(pipe,
buffer, size, NULL, &overlapped);
239 if (!success && GetLastError() != ERROR_IO_PENDING && GetLastError() != ERROR_MORE_DATA)
244 handles[0] = io_event;
245 for (i = 0; i < count; i++)
247 handles[i + 1] = events[i];
250 res = WaitForMultipleObjects(count + 1, handles, FALSE,
252 if (res != WAIT_OBJECT_0)
260 PeekNamedPipe(pipe, NULL, 0, NULL, &bytes, NULL);
264 GetOverlappedResult(pipe, &overlapped, &bytes, TRUE);
294 const WCHAR
msg[] = L
"Process ID";
295 WCHAR buf[22 + _countof(
msg)];
303 WritePipeAsync(pipe, buf, (DWORD)(wcslen(buf) * 2), count, events);
307 ReturnError(HANDLE pipe, DWORD error, LPCWSTR func, DWORD count, LPHANDLE events)
310 LPWSTR result = L
"0xffffffff\nFormatMessage failed\nCould not return result";
319 FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM
320 |FORMAT_MESSAGE_ALLOCATE_BUFFER
321 |FORMAT_MESSAGE_IGNORE_INSERTS,
322 0, error, 0, (LPWSTR) &args[2], 0, NULL);
325 result_len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING
326 |FORMAT_MESSAGE_ALLOCATE_BUFFER
327 |FORMAT_MESSAGE_ARGUMENT_ARRAY,
328 L
"0x%1!08x!\n%2!s!\n%3!s!", 0, 0,
329 (LPWSTR) &result, 0, (va_list *) args);
331 WritePipeAsync(pipe, result, (DWORD)(wcslen(result) * 2), count, events);
336 LocalFree((LPVOID) args[2]);
363 const WCHAR *msg1 = L
"You have specified a config file location (%ls relative to %ls)"
364 L
" that requires admin approval. This error may be avoided"
365 L
" by adding your account to the \"%ls\" group";
367 const WCHAR *msg2 = L
"You have specified an option (%ls) that may be used"
368 L
" only with admin approval. This error may be avoided"
369 L
" by adding your account to the \"%ls\" group";
376 L
"Cannot validate options: CommandLineToArgvW failed with error = 0x%08x",
393 WCHAR *argv_tmp[2] = { L
"--config",
argv[0] };
403 for (i = 0; i < argc; ++i)
412 if (wcscmp(L
"--config",
argv[i]) == 0 && argc-i > 1)
452 size = bytes /
sizeof(*data);
460 data = malloc(bytes);
476 if (
data[size - 1] != 0)
494 len = wcslen(sud->
options) + 1;
523 SOCKADDR_INET sa_inet;
524 ZeroMemory(&sa_inet,
sizeof(sa_inet));
525 sa_inet.si_family = family;
526 if (family == AF_INET)
528 sa_inet.Ipv4.sin_addr = addr->
ipv4;
530 else if (family == AF_INET6)
532 sa_inet.Ipv6.sin6_addr = addr->
ipv6;
541 LPWSTR wide_name =
utf8to16(iface_name);
545 status = ConvertInterfaceAliasToLuid(wide_name, luid);
550 status = ERROR_OUTOFMEMORY;
561 err = ConvertInterfaceAliasToLuid(ifname, &luid);
562 if (err == ERROR_SUCCESS)
564 err = ConvertInterfaceLuidToIndex(&luid, index);
566 if (err != ERROR_SUCCESS)
576 return memcmp(item,
address,
sizeof(MIB_UNICASTIPADDRESS_ROW)) == 0 ? TRUE : FALSE;
582 return DeleteUnicastIpAddressEntry(addr_row);
589 PMIB_UNICASTIPADDRESS_ROW addr_row;
592 addr_row = malloc(
sizeof(*addr_row));
593 if (addr_row == NULL)
595 return ERROR_OUTOFMEMORY;
598 InitializeUnicastIpAddressEntry(addr_row);
600 addr_row->OnLinkPrefixLength = (UINT8)
msg->prefix_len;
602 if (
msg->iface.index != -1)
604 addr_row->InterfaceIndex =
msg->iface.index;
614 addr_row->InterfaceLuid = luid;
619 err = CreateUnicastIpAddressEntry(addr_row);
654 return memcmp(item,
route,
sizeof(MIB_IPFORWARD_ROW2)) == 0 ? TRUE : FALSE;
660 return DeleteIpForwardEntry2(fwd_row);
667 PMIB_IPFORWARD_ROW2 fwd_row;
670 fwd_row = malloc(
sizeof(*fwd_row));
673 return ERROR_OUTOFMEMORY;
676 ZeroMemory(fwd_row,
sizeof(*fwd_row));
677 fwd_row->ValidLifetime = 0xffffffff;
678 fwd_row->PreferredLifetime = 0xffffffff;
679 fwd_row->Protocol = MIB_IPPROTO_NETMGMT;
680 fwd_row->Metric =
msg->metric;
682 fwd_row->DestinationPrefix.PrefixLength = (UINT8)
msg->prefix_len;
685 if (
msg->iface.index != -1)
687 fwd_row->InterfaceIndex =
msg->iface.index;
689 else if (strlen(
msg->iface.name))
697 fwd_row->InterfaceLuid = luid;
702 err = CreateIpForwardEntry2(fwd_row);
738 if (
msg->family == AF_INET)
740 return FlushIpNetTable(
msg->iface.index);
743 return FlushIpNetTable2(
msg->family,
msg->iface.index);
757 err_str = TEXT(
"Unknown Win32 Error");
759 if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM
760 | FORMAT_MESSAGE_ARGUMENT_ARRAY,
761 NULL, err, 0, buf,
sizeof(buf), NULL))
795 free(interface_data);
810 HANDLE engine = NULL;
821 err = ERROR_OUTOFMEMORY;
824 interface_data->
engine = engine;
825 interface_data->
index =
msg->iface.index;
868 free(interface_data);
893 ExecCommand(
const WCHAR *argv0,
const WCHAR *cmdline, DWORD timeout)
897 PROCESS_INFORMATION pi;
898 DWORD proc_flags = CREATE_NO_WINDOW|CREATE_UNICODE_ENVIRONMENT;
899 WCHAR *cmdline_dup = NULL;
901 ZeroMemory(&si,
sizeof(si));
902 ZeroMemory(&pi,
sizeof(pi));
907 cmdline_dup = _wcsdup(cmdline);
908 if (cmdline_dup && CreateProcessW(argv0, cmdline_dup, NULL, NULL, FALSE,
909 proc_flags, NULL, NULL, &si, &pi) )
911 WaitForSingleObject(pi.hProcess, timeout ? timeout : INFINITE);
912 if (!GetExitCodeProcess(pi.hProcess, &exit_code))
915 exit_code = GetLastError();
917 else if (exit_code == STILL_ACTIVE)
919 exit_code = WAIT_TIMEOUT;
922 TerminateProcess(pi.hProcess, exit_code);
929 argv0, cmdline, exit_code);
936 CloseHandle(pi.hProcess);
937 CloseHandle(pi.hThread);
941 exit_code = GetLastError();
961 WCHAR ipcfg[MAX_PATH];
969 { ipcfg, L
"ipconfig /flushdns", timeout },
970 { ipcfg, L
"ipconfig /registerdns", timeout },
977 if (WaitForMultipleObjects(2, wait_handles, FALSE, timeout) == WAIT_OBJECT_0)
980 for (i = 0; i < _countof(cmds); ++i)
982 ExecCommand(cmds[i].argv0, cmds[i].cmdline, cmds[i].timeout);
993 err = ERROR_SEM_TIMEOUT;
1002 HANDLE thread = NULL;
1005 thread = CreateThread(NULL, 0,
RegisterDNS, NULL, 0, NULL);
1014 CloseHandle(thread);
1018 err = GetLastError();
1034 netsh_dns_cmd(
const wchar_t *action,
const wchar_t *proto,
const wchar_t *if_name,
const wchar_t *addr)
1037 int timeout = 30000;
1038 wchar_t argv0[MAX_PATH];
1039 wchar_t *cmdline = NULL;
1043 if (wcscmp(action, L
"delete") == 0)
1059 const wchar_t *fmt = L
"netsh interface %ls %ls dns \"%ls\" %ls";
1062 size_t ncmdline = wcslen(fmt) + wcslen(if_name) + wcslen(addr) + 32 + 1;
1063 cmdline = malloc(ncmdline*
sizeof(
wchar_t));
1066 err = ERROR_OUTOFMEMORY;
1072 if (IsWindows7OrGreater())
1074 wcscat_s(cmdline, ncmdline, L
" validate=no");
1096 int timeout = 30000;
1097 wchar_t argv0[MAX_PATH];
1098 wchar_t *cmdline = NULL;
1099 const wchar_t *addr_static = (wcscmp(action, L
"set") == 0) ? L
"static" : L
"";
1103 if (wcscmp(action, L
"delete") == 0)
1119 const wchar_t *fmt = L
"netsh interface ip %ls wins \"%ls\" %ls %ls";
1122 size_t ncmdline = wcslen(fmt) + wcslen(if_name) + wcslen(action) + wcslen(addr)
1123 +wcslen(addr_static) + 32 + 1;
1124 cmdline = malloc(ncmdline *
sizeof(
wchar_t));
1127 err = ERROR_OUTOFMEMORY;
1131 openvpn_swprintf(cmdline, ncmdline, fmt, action, if_name, addr_static, addr);
1150 const wchar_t *
data)
1153 wchar_t argv0[MAX_PATH];
1154 wchar_t *cmdline = NULL;
1155 int timeout = 10000;
1163 fmt = L
"wmic nicconfig where (InterfaceIndex=%ld) call %ls (%ls)";
1167 fmt = L
"wmic nicconfig where (InterfaceIndex=%ld) call %ls \"%ls\"";
1170 size_t ncmdline = wcslen(fmt) + 20 + wcslen(action)
1172 cmdline = malloc(ncmdline*
sizeof(
wchar_t));
1175 return ERROR_OUTOFMEMORY;
1190 wchar_t *proto = (family == AF_INET6) ? L
"ipv6" : L
"ip";
1196 AddDNS(
short family,
wchar_t *if_name,
wchar_t *addr)
1198 wchar_t *proto = (family == AF_INET6) ? L
"ipv6" : L
"ip";
1205 return (wcscmp(item, str) == 0) ? TRUE : FALSE;
1219 NET_IFINDEX if_index;
1222 if (err != ERROR_SUCCESS)
1227 wchar_t *wdomain =
utf8to16(domain);
1230 return ERROR_OUTOFMEMORY;
1242 if (err == 0 && wdomain[0] && lists)
1244 wchar_t *tmp_name = _wcsdup(if_name);
1248 err = ERROR_OUTOFMEMORY;
1262 int addr_len =
msg->addr_len;
1265 if (addr_len > _countof(
msg->addr))
1267 addr_len = _countof(
msg->addr);
1270 if (!
msg->iface.name[0])
1278 msgptr->
iface.
name[_countof(
msg->iface.name)-1] =
'\0';
1279 msgptr->
domains[_countof(
msg->domains)-1] =
'\0';
1285 return ERROR_OUTOFMEMORY;
1303 if (
msg->domains[0])
1311 for (
int i = 0; i < addr_len; ++i)
1313 if (
msg->family == AF_INET6)
1315 RtlIpv6AddressToStringW(&
msg->addr[i].ipv6, addr);
1319 RtlIpv4AddressToStringW(&
msg->addr[i].ipv4, addr);
1321 err =
AddDNS(
msg->family, wide_name, addr);
1333 if (
msg->addr_len > 0)
1335 wchar_t *tmp_name = _wcsdup(wide_name);
1336 if (!tmp_name ||
AddListItem(&(*lists)[undo_type], tmp_name))
1340 err = ERROR_OUTOFMEMORY;
1345 if (
msg->domains[0])
1360 int addr_len =
msg->addr_len;
1363 if (addr_len > _countof(
msg->addr))
1365 addr_len = _countof(
msg->addr);
1368 if (!
msg->iface.name[0])
1376 msgptr->
iface.
name[_countof(
msg->iface.name) - 1] =
'\0';
1382 return ERROR_OUTOFMEMORY;
1403 for (
int i = 0; i < addr_len; ++i)
1405 RtlIpv4AddressToStringW(&
msg->addr[i].ipv4, addr);
1420 wchar_t *tmp_name = _wcsdup(wide_name);
1425 err = ERROR_OUTOFMEMORY;
1439 DWORD timeout = 5000;
1440 wchar_t argv0[MAX_PATH];
1448 const wchar_t *fmt = L
"netsh interface ipv4 set address name=\"%d\" source=dhcp";
1453 size_t ncmdline = wcslen(fmt) + 10 + 1;
1454 wchar_t *cmdline = malloc(ncmdline*
sizeof(
wchar_t));
1457 err = ERROR_OUTOFMEMORY;
1476 DWORD err = ERROR_SUCCESS;
1478 if (!DuplicateHandle(ovpn_proc, orig_handle, GetCurrentProcess(), new_handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
1480 err = GetLastError();
1491 DWORD err = ERROR_SUCCESS;
1493 HANDLE dup_handle = NULL;
1496 if (err != ERROR_SUCCESS)
1500 *ring = (
struct tun_ring *)MapViewOfFile(dup_handle, FILE_MAP_ALL_ACCESS, 0, 0,
sizeof(
struct tun_ring));
1504 err = GetLastError();
1520 if (ring_buffer_maps)
1524 else if ((ring_buffer_maps = calloc(1,
sizeof(*ring_buffer_maps))) == NULL)
1526 return ERROR_OUTOFMEMORY;
1529 HANDLE device = NULL;
1530 HANDLE send_tail_moved = NULL;
1531 HANDLE receive_tail_moved = NULL;
1534 if (err != ERROR_SUCCESS)
1540 if (err != ERROR_SUCCESS)
1546 if (err != ERROR_SUCCESS)
1552 if (err != ERROR_SUCCESS)
1558 if (err != ERROR_SUCCESS)
1565 send_tail_moved, receive_tail_moved))
1567 err = GetLastError();
1575 if (err != ERROR_SUCCESS && ring_buffer_maps)
1578 free(ring_buffer_maps);
1590 MIB_IPINTERFACE_ROW ipiface;
1591 InitializeIpInterfaceEntry(&ipiface);
1592 ipiface.Family = mtu->
family;
1594 err = GetIpInterfaceEntry(&ipiface);
1595 if (err != NO_ERROR)
1599 if (mtu->
family == AF_INET)
1601 ipiface.SitePrefixLength = 0;
1603 ipiface.NlMtu = mtu->
mtu;
1605 err = SetIpInterfaceEntry(&ipiface);
1611 DWORD bytes, DWORD count, LPHANDLE events,
undo_lists_t *lists)
1629 .size =
sizeof(ack),
1643 switch (
msg.header.type)
1647 if (
msg.header.size ==
sizeof(
msg.address))
1655 if (
msg.header.size ==
sizeof(
msg.route))
1662 if (
msg.header.size ==
sizeof(
msg.flush_neighbors))
1670 if (
msg.header.size ==
sizeof(
msg.block_dns))
1691 if (
msg.header.size ==
sizeof(
msg.dhcp))
1698 if (
msg.header.size ==
sizeof(
msg.rrb))
1705 if (
msg.header.size ==
sizeof(
msg.mtu))
1784 *pnext = item->
next;
1795 HANDLE ovpn_pipe = NULL, svc_pipe = NULL;
1796 PTOKEN_USER svc_user = NULL, ovpn_user = NULL;
1797 HANDLE svc_token = NULL, imp_token = NULL, pri_token = NULL;
1798 HANDLE stdin_read = NULL, stdin_write = NULL;
1799 HANDLE stdout_write = NULL;
1800 DWORD pipe_mode, len, exit_code = 0;
1802 STARTUPINFOW startup_info;
1803 PROCESS_INFORMATION proc_info;
1804 LPVOID user_env = NULL;
1805 TCHAR ovpn_pipe_name[256];
1807 WCHAR *cmdline = NULL;
1808 size_t cmdline_size;
1810 WCHAR errmsg[512] = L
"";
1812 SECURITY_ATTRIBUTES inheritable = {
1813 .nLength =
sizeof(inheritable),
1814 .lpSecurityDescriptor = NULL,
1815 .bInheritHandle = TRUE
1819 EXPLICIT_ACCESS ea[2];
1820 SECURITY_DESCRIPTOR ovpn_sd;
1821 SECURITY_ATTRIBUTES ovpn_sa = {
1822 .nLength =
sizeof(ovpn_sa),
1823 .lpSecurityDescriptor = &ovpn_sd,
1824 .bInheritHandle = FALSE
1827 ZeroMemory(&ea,
sizeof(ea));
1828 ZeroMemory(&startup_info,
sizeof(startup_info));
1829 ZeroMemory(&undo_lists,
sizeof(undo_lists));
1830 ZeroMemory(&proc_info,
sizeof(proc_info));
1837 if (!InitializeSecurityDescriptor(&ovpn_sd, SECURITY_DESCRIPTOR_REVISION))
1844 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &svc_token))
1850 while (!GetTokenInformation(svc_token, TokenUser, svc_user, len, &len))
1852 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1858 svc_user = malloc(len);
1859 if (svc_user == NULL)
1865 if (!IsValidSid(svc_user->User.Sid))
1871 if (!ImpersonateNamedPipeClient(pipe))
1876 if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &imp_token))
1882 while (!GetTokenInformation(imp_token, TokenUser, ovpn_user, len, &len))
1884 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1890 ovpn_user = malloc(len);
1891 if (ovpn_user == NULL)
1897 if (!IsValidSid(ovpn_user->User.Sid))
1918 ea[0].grfAccessPermissions = SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL;
1919 ea[0].grfAccessMode = SET_ACCESS;
1920 ea[0].grfInheritance = NO_INHERITANCE;
1921 ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
1922 ea[0].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1923 ea[0].Trustee.ptstrName = (LPTSTR) svc_user->User.Sid;
1924 ea[1].grfAccessPermissions = READ_CONTROL | SYNCHRONIZE | PROCESS_VM_READ
1925 |SYNCHRONIZE | PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION;
1926 ea[1].grfAccessMode = SET_ACCESS;
1927 ea[1].grfInheritance = NO_INHERITANCE;
1928 ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
1929 ea[1].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1930 ea[1].Trustee.ptstrName = (LPTSTR) ovpn_user->User.Sid;
1933 if (!SetSecurityDescriptorOwner(&ovpn_sd, svc_user->User.Sid, FALSE))
1938 if (SetEntriesInAcl(2, ea, NULL, &ovpn_dacl) != ERROR_SUCCESS)
1943 if (!SetSecurityDescriptorDacl(&ovpn_sd, TRUE, ovpn_dacl, FALSE))
1950 if (!DuplicateTokenEx(imp_token, TOKEN_ALL_ACCESS, NULL, 0, TokenPrimary, &pri_token))
1957 stdout_write = CreateFile(_T(
"NUL"), GENERIC_WRITE, FILE_SHARE_WRITE,
1958 &inheritable, OPEN_EXISTING, 0, NULL);
1959 if (stdout_write == INVALID_HANDLE_VALUE)
1965 if (!CreatePipe(&stdin_read, &stdin_write, &inheritable, 0)
1966 || !SetHandleInformation(stdin_write, HANDLE_FLAG_INHERIT, 0))
1974 ovpn_pipe = CreateNamedPipe(ovpn_pipe_name,
1975 PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED,
1976 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, 128, 128, 0, NULL);
1977 if (ovpn_pipe == INVALID_HANDLE_VALUE)
1983 svc_pipe = CreateFile(ovpn_pipe_name, GENERIC_READ | GENERIC_WRITE, 0,
1984 &inheritable, OPEN_EXISTING, 0, NULL);
1985 if (svc_pipe == INVALID_HANDLE_VALUE)
1991 pipe_mode = PIPE_READMODE_MESSAGE;
1992 if (!SetNamedPipeHandleState(svc_pipe, &pipe_mode, NULL, NULL))
1998 cmdline_size = wcslen(sud.
options) + 128;
1999 cmdline = malloc(cmdline_size *
sizeof(*cmdline));
2000 if (cmdline == NULL)
2008 if (!CreateEnvironmentBlock(&user_env, imp_token, FALSE))
2014 startup_info.cb =
sizeof(startup_info);
2015 startup_info.dwFlags = STARTF_USESTDHANDLES;
2016 startup_info.hStdInput = stdin_read;
2017 startup_info.hStdOutput = stdout_write;
2018 startup_info.hStdError = stdout_write;
2023 if (!CreateProcessAsUserW(pri_token, exe_path, cmdline, &ovpn_sa, NULL, TRUE,
2025 user_env, sud.
directory, &startup_info, &proc_info))
2031 if (!RevertToSelf())
2033 TerminateProcess(proc_info.hProcess, 1);
2044 DWORD input_size = WideCharToMultiByte(CP_UTF8, 0, sud.
std_input, -1, NULL, 0, NULL, NULL);
2046 if (input_size && (input = malloc(input_size)))
2049 WideCharToMultiByte(CP_UTF8, 0, sud.
std_input, -1, input, input_size, NULL, NULL);
2050 WriteFile(stdin_write, input, (DWORD)strlen(input), &written, NULL);
2065 WaitForSingleObject(proc_info.hProcess,
IO_TIMEOUT);
2066 GetExitCodeProcess(proc_info.hProcess, &exit_code);
2067 if (exit_code == STILL_ACTIVE)
2069 TerminateProcess(proc_info.hProcess, 1);
2071 else if (exit_code != 0)
2075 L
"OpenVPN exited with error: exit code = %lu", exit_code);
2081 FlushFileBuffers(pipe);
2082 DisconnectNamedPipe(pipe);
2087 DestroyEnvironmentBlock(user_env);
2108 SERVICE_STATUS *
status = ctx;
2111 case SERVICE_CONTROL_STOP:
2112 status->dwCurrentState = SERVICE_STOP_PENDING;
2120 case SERVICE_CONTROL_INTERROGATE:
2124 return ERROR_CALL_NOT_IMPLEMENTED;
2132 TCHAR pipe_name[256];
2134 PACL old_dacl, new_dacl;
2135 PSECURITY_DESCRIPTOR sd;
2136 static EXPLICIT_ACCESS ea[2];
2137 static BOOL initialized = FALSE;
2138 DWORD flags = PIPE_ACCESS_DUPLEX | WRITE_DAC | FILE_FLAG_OVERLAPPED;
2142 PSID everyone, anonymous;
2144 ConvertStringSidToSid(TEXT(
"S-1-1-0"), &everyone);
2145 ConvertStringSidToSid(TEXT(
"S-1-5-7"), &anonymous);
2147 ea[0].grfAccessPermissions = FILE_GENERIC_WRITE;
2148 ea[0].grfAccessMode = GRANT_ACCESS;
2149 ea[0].grfInheritance = NO_INHERITANCE;
2150 ea[0].Trustee.pMultipleTrustee = NULL;
2151 ea[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2152 ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
2153 ea[0].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
2154 ea[0].Trustee.ptstrName = (LPTSTR) everyone;
2156 ea[1].grfAccessPermissions = 0;
2157 ea[1].grfAccessMode = REVOKE_ACCESS;
2158 ea[1].grfInheritance = NO_INHERITANCE;
2159 ea[1].Trustee.pMultipleTrustee = NULL;
2160 ea[1].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
2161 ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
2162 ea[1].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
2163 ea[1].Trustee.ptstrName = (LPTSTR) anonymous;
2165 flags |= FILE_FLAG_FIRST_PIPE_INSTANCE;
2170 pipe = CreateNamedPipe(pipe_name, flags,
2171 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
2172 PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, NULL);
2173 if (pipe == INVALID_HANDLE_VALUE)
2176 return INVALID_HANDLE_VALUE;
2179 if (GetSecurityInfo(pipe, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
2180 NULL, NULL, &old_dacl, NULL, &sd) != ERROR_SUCCESS)
2186 if (SetEntriesInAcl(2, ea, old_dacl, &new_dacl) != ERROR_SUCCESS)
2192 if (SetSecurityInfo(pipe, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
2193 NULL, NULL, new_dacl, NULL) != ERROR_SUCCESS)
2207 static DWORD size = 10;
2208 static LPHANDLE handles = NULL;
2211 if (handles == NULL)
2213 handles = malloc(size *
sizeof(HANDLE));
2214 *handles_ptr = handles;
2215 if (handles == NULL)
2217 return ERROR_OUTOFMEMORY;
2221 handles[
pos++] = io_event;
2234 tmp = realloc(handles, size *
sizeof(HANDLE));
2239 return ERROR_OUTOFMEMORY;
2242 *handles_ptr = handles;
2244 handles[
pos++] = threads->
data;
2245 threads = threads->
next;
2269 status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
2277 HANDLE pipe, io_event = NULL;
2278 OVERLAPPED overlapped;
2279 DWORD error = NO_ERROR;
2281 PHANDLE handles = NULL;
2290 status.dwCurrentState = SERVICE_START_PENDING;
2291 status.dwServiceSpecificExitCode = NO_ERROR;
2292 status.dwWin32ExitCode = NO_ERROR;
2293 status.dwWaitHint = 3000;
2298 if (error != ERROR_SUCCESS)
2304 exit_event = CreateEvent(NULL, TRUE, FALSE, NULL);
2319 if (error != NO_ERROR)
2325 if (pipe == INVALID_HANDLE_VALUE)
2330 status.dwCurrentState = SERVICE_RUNNING;
2336 if (ConnectNamedPipe(pipe, &overlapped) == FALSE
2337 && GetLastError() != ERROR_PIPE_CONNECTED
2338 && GetLastError() != ERROR_IO_PENDING)
2344 error = WaitForMultipleObjects(handle_count, handles, FALSE, INFINITE);
2345 if (error == WAIT_OBJECT_0)
2349 HANDLE thread = CreateThread(NULL, 0,
RunOpenvpn, pipe, CREATE_SUSPENDED, NULL);
2363 TerminateThread(thread, 1);
2369 ResumeThread(thread);
2383 if (error == WAIT_FAILED)
2413 status.dwCurrentState = SERVICE_STOPPED;
2414 status.dwWin32ExitCode = error;