aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorng0 <ng0@n0.is>2019-09-10 16:59:32 +0000
committerng0 <ng0@n0.is>2019-09-10 16:59:32 +0000
commit04b6df21cd281e8cd540139f8d9ae85defc1961c (patch)
tree6357199445df8d5c0c631bc8f10aef838b1f9f1e /src/util
parent483b0139a218a5f8a8311bda3eb23bcd88f57688 (diff)
downloadgnunet-04b6df21cd281e8cd540139f8d9ae85defc1961c.tar.gz
gnunet-04b6df21cd281e8cd540139f8d9ae85defc1961c.zip
remove CYGWIN codeblocks, drop vendored Windows openvpn, drop win32 specific files.
configures and builds okay. testsuite wasn't checked, will be checked. diff including the plibc removal is now around 14370 lines of code less.
Diffstat (limited to 'src/util')
-rw-r--r--src/util/Makefile.am43
-rw-r--r--src/util/disk.c88
-rw-r--r--src/util/dnsstub.c6
-rw-r--r--src/util/gnunet-timeout-w32.c193
-rw-r--r--src/util/network.c866
-rw-r--r--src/util/os_installation.c78
-rw-r--r--src/util/os_network.c29
-rw-r--r--src/util/os_priority.c615
-rw-r--r--src/util/scheduler.c46
-rw-r--r--src/util/service.c110
-rw-r--r--src/util/strings.c35
-rw-r--r--src/util/test_common_logging_runtime_loglevels.c4
-rw-r--r--src/util/test_configuration.c6
-rw-r--r--src/util/test_getopt.c4
-rw-r--r--src/util/test_resolver_api.c5
-rw-r--r--src/util/test_scheduler.c4
-rw-r--r--src/util/test_service.c3
-rw-r--r--src/util/test_strings.c6
-rw-r--r--src/util/w32cat.c154
-rw-r--r--src/util/win.c1365
-rw-r--r--src/util/winproc.c340
21 files changed, 24 insertions, 3976 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 647f09224..c240053ff 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -13,27 +13,7 @@ dist_pkgcfg_DATA = \
13pkgcfg_DATA = \ 13pkgcfg_DATA = \
14 resolver.conf 14 resolver.conf
15 15
16if MINGW 16TEST_CLIENT_UNIX_NC = test_client_unix.nc
17noinst_LTLIBRARIES = \
18 libgnunetutilwin.la
19libgnunetutilwin_la_SOURCES = \
20 win.c \
21 winproc.c
22libgnunetutilwin_la_LDFLAGS = \
23 -no-undefined -Wl,--export-all-symbols
24libgnunetutilwin_la_LIBADD = \
25 -lshell32 -liconv -lstdc++ \
26 -lcomdlg32 -lgdi32 -liphlpapi
27WINLIB = libgnunetutilwin.la
28W32CAT = w32cat
29W32CONSOLEHELPER = gnunet-helper-w32-console
30endif
31
32if !MINGW
33 TEST_CLIENT_UNIX_NC = test_client_unix.nc
34else
35 TEST_CLIENT_UNIX_NC =
36endif
37 17
38if USE_COVERAGE 18if USE_COVERAGE
39 AM_CFLAGS = --coverage -O0 19 AM_CFLAGS = --coverage -O0
@@ -45,14 +25,6 @@ if ENABLE_BENCHMARK
45 PTHREAD = -lpthread 25 PTHREAD = -lpthread
46endif 26endif
47 27
48w32cat_SOURCES = w32cat.c
49
50gnunet_helper_w32_console_SOURCES = \
51 gnunet-helper-w32-console.c \
52 gnunet-helper-w32-console.h
53gnunet_helper_w32_console_LDADD = \
54 libgnunetutil.la
55
56gnunet_config_diff_SOURCES = \ 28gnunet_config_diff_SOURCES = \
57 gnunet-config-diff.c 29 gnunet-config-diff.c
58gnunet_config_diff_LDADD = \ 30gnunet_config_diff_LDADD = \
@@ -202,8 +174,7 @@ lib_LTLIBRARIES = libgnunetutil.la
202 174
203libexec_PROGRAMS = \ 175libexec_PROGRAMS = \
204 gnunet-service-resolver \ 176 gnunet-service-resolver \
205 gnunet-timeout \ 177 gnunet-timeout
206 $(W32CONSOLEHELPER)
207 178
208bin_PROGRAMS = \ 179bin_PROGRAMS = \
209 gnunet-resolver \ 180 gnunet-resolver \
@@ -217,7 +188,6 @@ endif
217 188
218noinst_PROGRAMS = \ 189noinst_PROGRAMS = \
219 gnunet-config-diff \ 190 gnunet-config-diff \
220 $(W32CAT) \
221 test_common_logging_dummy 191 test_common_logging_dummy
222 192
223 193
@@ -228,14 +198,8 @@ endif
228 198
229endif 199endif
230 200
231
232if !MINGW
233gnunet_timeout_SOURCES = \ 201gnunet_timeout_SOURCES = \
234 gnunet-timeout.c 202 gnunet-timeout.c
235else
236gnunet_timeout_SOURCES = \
237 gnunet-timeout-w32.c
238endif
239 203
240gnunet_service_resolver_SOURCES = \ 204gnunet_service_resolver_SOURCES = \
241 gnunet-service-resolver.c 205 gnunet-service-resolver.c
@@ -393,8 +357,7 @@ test_os_start_process_SOURCES = \
393test_os_start_process_LDADD = \ 357test_os_start_process_LDADD = \
394 libgnunetutil.la 358 libgnunetutil.la
395test_os_start_process_DEPENDENCIES = \ 359test_os_start_process_DEPENDENCIES = \
396 libgnunetutil.la \ 360 libgnunetutil.la
397 $(WINCAT)
398 361
399test_client_nc_SOURCES = \ 362test_client_nc_SOURCES = \
400 test_client.c 363 test_client.c
diff --git a/src/util/disk.c b/src/util/disk.c
index 01d5efbe2..8b474542b 100644
--- a/src/util/disk.c
+++ b/src/util/disk.c
@@ -96,7 +96,6 @@ struct GetFileSizeData {
96}; 96};
97 97
98 98
99#ifndef MINGW
100/** 99/**
101 * Translate GNUnet-internal permission bitmap to UNIX file 100 * Translate GNUnet-internal permission bitmap to UNIX file
102 * access permission bitmap. 101 * access permission bitmap.
@@ -131,7 +130,6 @@ translate_unix_perms(enum GNUNET_DISK_AccessPermissions perm)
131 130
132 return mode; 131 return mode;
133} 132}
134#endif
135 133
136 134
137/** 135/**
@@ -191,11 +189,7 @@ getSizeRec(void *cls, const char *fn)
191int 189int
192GNUNET_DISK_handle_invalid(const struct GNUNET_DISK_FileHandle *h) 190GNUNET_DISK_handle_invalid(const struct GNUNET_DISK_FileHandle *h)
193{ 191{
194#ifdef MINGW
195 return ((!h) || (h->h == INVALID_HANDLE_VALUE)) ? GNUNET_YES : GNUNET_NO;
196#else
197 return ((!h) || (h->fd == -1)) ? GNUNET_YES : GNUNET_NO; 192 return ((!h) || (h->fd == -1)) ? GNUNET_YES : GNUNET_NO;
198#endif
199} 193}
200 194
201/** 195/**
@@ -236,26 +230,9 @@ GNUNET_DISK_file_seek(const struct GNUNET_DISK_FileHandle *h,
236 return GNUNET_SYSERR; 230 return GNUNET_SYSERR;
237 } 231 }
238 232
239#ifdef MINGW
240 LARGE_INTEGER li;
241 LARGE_INTEGER new_pos;
242 BOOL b;
243
244 static DWORD t[] = { FILE_BEGIN, FILE_CURRENT, FILE_END };
245 li.QuadPart = offset;
246
247 b = SetFilePointerEx(h->h, li, &new_pos, t[whence]);
248 if (b == 0)
249 {
250 SetErrnoFromWinError(GetLastError());
251 return GNUNET_SYSERR;
252 }
253 return (off_t)new_pos.QuadPart;
254#else
255 static int t[] = { SEEK_SET, SEEK_CUR, SEEK_END }; 233 static int t[] = { SEEK_SET, SEEK_CUR, SEEK_END };
256 234
257 return lseek(h->fd, offset, t[whence]); 235 return lseek(h->fd, offset, t[whence]);
258#endif
259} 236}
260 237
261 238
@@ -1296,7 +1273,7 @@ GNUNET_DISK_file_open(const char *fn,
1296 expfn = GNUNET_STRINGS_filename_expand(fn); 1273 expfn = GNUNET_STRINGS_filename_expand(fn);
1297 if (NULL == expfn) 1274 if (NULL == expfn)
1298 return NULL; 1275 return NULL;
1299#ifndef MINGW 1276
1300 mode = 0; 1277 mode = 0;
1301 if (GNUNET_DISK_OPEN_READWRITE == (flags & GNUNET_DISK_OPEN_READWRITE)) 1278 if (GNUNET_DISK_OPEN_READWRITE == (flags & GNUNET_DISK_OPEN_READWRITE))
1302 oflags = O_RDWR; /* note: O_RDWR is NOT always O_RDONLY | O_WRONLY */ 1279 oflags = O_RDWR; /* note: O_RDWR is NOT always O_RDONLY | O_WRONLY */
@@ -1342,69 +1319,6 @@ GNUNET_DISK_file_open(const char *fn,
1342 GNUNET_free(expfn); 1319 GNUNET_free(expfn);
1343 return NULL; 1320 return NULL;
1344 } 1321 }
1345#else
1346 access = 0;
1347 disp = OPEN_ALWAYS;
1348
1349 if (GNUNET_DISK_OPEN_READWRITE == (flags & GNUNET_DISK_OPEN_READWRITE))
1350 access = FILE_READ_DATA | FILE_WRITE_DATA;
1351 else if (flags & GNUNET_DISK_OPEN_READ)
1352 access = FILE_READ_DATA;
1353 else if (flags & GNUNET_DISK_OPEN_WRITE)
1354 access = FILE_WRITE_DATA;
1355
1356 if (flags & GNUNET_DISK_OPEN_FAILIFEXISTS)
1357 {
1358 disp = CREATE_NEW;
1359 }
1360 else if (flags & GNUNET_DISK_OPEN_CREATE)
1361 {
1362 (void)GNUNET_DISK_directory_create_for_file(expfn);
1363 if (flags & GNUNET_DISK_OPEN_TRUNCATE)
1364 disp = CREATE_ALWAYS;
1365 else
1366 disp = OPEN_ALWAYS;
1367 }
1368 else if (flags & GNUNET_DISK_OPEN_TRUNCATE)
1369 {
1370 disp = TRUNCATE_EXISTING;
1371 }
1372 else
1373 {
1374 disp = OPEN_EXISTING;
1375 }
1376
1377 if (ERROR_SUCCESS == plibc_conv_to_win_pathwconv(expfn, wexpfn))
1378 h = CreateFileW(wexpfn,
1379 access,
1380 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
1381 NULL,
1382 disp,
1383 FILE_ATTRIBUTE_NORMAL,
1384 NULL);
1385 else
1386 h = INVALID_HANDLE_VALUE;
1387 if (h == INVALID_HANDLE_VALUE)
1388 {
1389 int err;
1390 SetErrnoFromWinError(GetLastError());
1391 err = errno;
1392 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_INFO, "open", expfn);
1393 GNUNET_free(expfn);
1394 errno = err;
1395 return NULL;
1396 }
1397
1398 if (flags & GNUNET_DISK_OPEN_APPEND)
1399 if (SetFilePointer(h, 0, 0, FILE_END) == INVALID_SET_FILE_POINTER)
1400 {
1401 SetErrnoFromWinError(GetLastError());
1402 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_WARNING, "SetFilePointer", expfn);
1403 CloseHandle(h);
1404 GNUNET_free(expfn);
1405 return NULL;
1406 }
1407#endif
1408 1322
1409 ret = GNUNET_new(struct GNUNET_DISK_FileHandle); 1323 ret = GNUNET_new(struct GNUNET_DISK_FileHandle);
1410 1324
diff --git a/src/util/dnsstub.c b/src/util/dnsstub.c
index ab7a08318..fef4b5f5d 100644
--- a/src/util/dnsstub.c
+++ b/src/util/dnsstub.c
@@ -291,16 +291,12 @@ do_dns_read(struct GNUNET_DNSSTUB_RequestSocket *rs,
291 ssize_t r; 291 ssize_t r;
292 int len; 292 int len;
293 293
294#ifndef MINGW
295 if (0 != ioctl(GNUNET_NETWORK_get_fd(dnsout), FIONREAD, &len)) 294 if (0 != ioctl(GNUNET_NETWORK_get_fd(dnsout), FIONREAD, &len))
296 { 295 {
297 /* conservative choice: */ 296 /* conservative choice: */
298 len = UINT16_MAX; 297 len = UINT16_MAX;
299 } 298 }
300#else 299
301 /* port the code above? */
302 len = UINT16_MAX;
303#endif
304 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving %d byte DNS reply\n", len); 300 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving %d byte DNS reply\n", len);
305 { 301 {
306 unsigned char buf[len] GNUNET_ALIGN; 302 unsigned char buf[len] GNUNET_ALIGN;
diff --git a/src/util/gnunet-timeout-w32.c b/src/util/gnunet-timeout-w32.c
deleted file mode 100644
index 3e579714c..000000000
--- a/src/util/gnunet-timeout-w32.c
+++ /dev/null
@@ -1,193 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file src/util/gnunet-timeout-w32.c
23 * @brief small tool starting a child process, waiting that it terminates or killing it after a given timeout period
24 * @author LRN
25 */
26
27#include <windows.h>
28#include <sys/types.h>
29#include <stdio.h>
30
31int
32main(int argc, char *argv[])
33{
34 int i;
35 DWORD wait_result;
36 wchar_t *commandline;
37 wchar_t **wargv;
38 wchar_t *arg;
39 unsigned int cmdlen;
40 STARTUPINFOW start;
41 PROCESS_INFORMATION proc;
42
43 wchar_t wpath[MAX_PATH + 1];
44
45 wchar_t *pathbuf;
46 DWORD pathbuf_len, alloc_len;
47 wchar_t *ptr;
48 wchar_t *non_const_filename;
49 wchar_t *wcmd;
50 int wargc;
51 int timeout = 0;
52 ssize_t wrote;
53
54 HANDLE job;
55
56 if (argc < 3)
57 {
58 printf
59 ("arg 1: timeout in sec., arg 2: executable, arg<n> arguments\n");
60 exit(1);
61 }
62
63 timeout = atoi(argv[1]);
64
65 if (timeout == 0)
66 timeout = 600;
67
68 commandline = GetCommandLineW();
69 if (commandline == NULL)
70 {
71 printf("Failed to get commandline: %lu\n", GetLastError());
72 exit(2);
73 }
74
75 wargv = CommandLineToArgvW(commandline, &wargc);
76 if (wargv == NULL || wargc <= 1)
77 {
78 printf("Failed to get parse commandline: %lu\n", GetLastError());
79 exit(3);
80 }
81
82 job = CreateJobObject(NULL, NULL);
83 if (job == NULL)
84 {
85 printf("Failed to create a job: %lu\n", GetLastError());
86 exit(4);
87 }
88
89 pathbuf_len = GetEnvironmentVariableW(L"PATH", (wchar_t *)&pathbuf, 0);
90
91 alloc_len = pathbuf_len + 1;
92
93 pathbuf = malloc(alloc_len * sizeof(wchar_t));
94
95 ptr = pathbuf;
96
97 alloc_len = GetEnvironmentVariableW(L"PATH", ptr, pathbuf_len);
98
99 cmdlen = wcslen(wargv[2]);
100 if (cmdlen < 5 || wcscmp(&wargv[2][cmdlen - 4], L".exe") != 0)
101 {
102 non_const_filename = malloc(sizeof(wchar_t) * (cmdlen + 5));
103 swprintf(non_const_filename, cmdlen + 5, L"%S.exe", wargv[2]);
104 }
105 else
106 {
107 non_const_filename = wcsdup(wargv[2]);
108 }
109
110 /* Check that this is the full path. If it isn't, search. */
111 if (non_const_filename[1] == L':')
112 swprintf(wpath, sizeof(wpath) / sizeof(wchar_t), L"%S", non_const_filename);
113 else if (!SearchPathW
114 (pathbuf, non_const_filename, NULL, sizeof(wpath) / sizeof(wchar_t),
115 wpath, NULL))
116 {
117 printf("Failed to get find executable: %lu\n", GetLastError());
118 exit(5);
119 }
120 free(pathbuf);
121 free(non_const_filename);
122
123 cmdlen = wcslen(wpath) + 4;
124 i = 3;
125 while (NULL != (arg = wargv[i++]))
126 cmdlen += wcslen(arg) + 4;
127
128 wcmd = malloc(sizeof(wchar_t) * (cmdlen + 1));
129 wrote = 0;
130 i = 2;
131 while (NULL != (arg = wargv[i++]))
132 {
133 /* This is to escape trailing slash */
134 wchar_t arg_lastchar = arg[wcslen(arg) - 1];
135 if (wrote == 0)
136 {
137 wrote += swprintf(&wcmd[wrote], cmdlen + 1 - wrote, L"\"%S%S\" ", wpath,
138 arg_lastchar == L'\\' ? L"\\" : L"");
139 }
140 else
141 {
142 if (wcschr(arg, L' ') != NULL)
143 wrote += swprintf(&wcmd[wrote], cmdlen + 1 - wrote, L"\"%S%S\"%S", arg,
144 arg_lastchar == L'\\' ? L"\\" : L"", i == wargc ? L"" : L" ");
145 else
146 wrote += swprintf(&wcmd[wrote], cmdlen + 1 - wrote, L"%S%S%S", arg,
147 arg_lastchar == L'\\' ? L"\\" : L"", i == wargc ? L"" : L" ");
148 }
149 }
150
151 LocalFree(wargv);
152
153 memset(&start, 0, sizeof(start));
154 start.cb = sizeof(start);
155
156 if (!CreateProcessW(wpath, wcmd, NULL, NULL, TRUE, CREATE_SUSPENDED,
157 NULL, NULL, &start, &proc))
158 {
159 wprintf(L"Failed to get spawn process `%S' with arguments `%S': %lu\n", wpath, wcmd, GetLastError());
160 exit(6);
161 }
162
163 AssignProcessToJobObject(job, proc.hProcess);
164
165 ResumeThread(proc.hThread);
166 CloseHandle(proc.hThread);
167
168 free(wcmd);
169
170 wait_result = WaitForSingleObject(proc.hProcess, timeout * 1000);
171 if (wait_result == WAIT_OBJECT_0)
172 {
173 DWORD status;
174 wait_result = GetExitCodeProcess(proc.hProcess, &status);
175 CloseHandle(proc.hProcess);
176 if (wait_result != 0)
177 {
178 printf("Test process exited with result %lu\n", status);
179 TerminateJobObject(job, status);
180 exit(status);
181 }
182 printf("Test process exited (failed to obtain exit status)\n");
183 TerminateJobObject(job, 0);
184 exit(0);
185 }
186 printf("Child processes were killed after timeout of %u seconds\n",
187 timeout);
188 TerminateJobObject(job, 1);
189 CloseHandle(proc.hProcess);
190 exit(1);
191}
192
193/* end of timeout_watchdog_w32.c */
diff --git a/src/util/network.c b/src/util/network.c
index ec76424eb..6f8a8ff5a 100644
--- a/src/util/network.c
+++ b/src/util/network.c
@@ -759,10 +759,6 @@ GNUNET_NETWORK_socket_recvfrom(const struct GNUNET_NETWORK_Handle *desc,
759 flags, 759 flags,
760 src_addr, 760 src_addr,
761 addrlen); 761 addrlen);
762#ifdef MINGW
763 if (SOCKET_ERROR == ret)
764 SetErrnoFromWinsockError(WSAGetLastError());
765#endif
766 return ret; 762 return ret;
767} 763}
768 764
@@ -792,10 +788,6 @@ GNUNET_NETWORK_socket_recv(const struct GNUNET_NETWORK_Handle *desc,
792 buffer, 788 buffer,
793 length, 789 length,
794 flags); 790 flags);
795#ifdef MINGW
796 if (SOCKET_ERROR == ret)
797 SetErrnoFromWinsockError(WSAGetLastError());
798#endif
799 return ret; 791 return ret;
800} 792}
801 793
@@ -827,10 +819,6 @@ GNUNET_NETWORK_socket_send(const struct GNUNET_NETWORK_Handle *desc,
827 buffer, 819 buffer,
828 length, 820 length,
829 flags); 821 flags);
830#ifdef MINGW
831 if (SOCKET_ERROR == ret)
832 SetErrnoFromWinsockError(WSAGetLastError());
833#endif
834 return ret; 822 return ret;
835} 823}
836 824
@@ -865,10 +853,6 @@ GNUNET_NETWORK_socket_sendto(const struct GNUNET_NETWORK_Handle *desc,
865 flags |= MSG_NOSIGNAL; 853 flags |= MSG_NOSIGNAL;
866#endif 854#endif
867 ret = sendto(desc->fd, message, length, flags, dest_addr, dest_len); 855 ret = sendto(desc->fd, message, length, flags, dest_addr, dest_len);
868#ifdef MINGW
869 if (SOCKET_ERROR == ret)
870 SetErrnoFromWinsockError(WSAGetLastError());
871#endif
872 return ret; 856 return ret;
873} 857}
874 858
@@ -897,10 +881,7 @@ GNUNET_NETWORK_socket_setsockopt(struct GNUNET_NETWORK_Handle *fd,
897 option_name, 881 option_name,
898 option_value, 882 option_value,
899 option_len); 883 option_len);
900#ifdef MINGW 884
901 if (SOCKET_ERROR == ret)
902 SetErrnoFromWinsockError(WSAGetLastError());
903#endif
904 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR; 885 return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
905} 886}
906 887
@@ -950,10 +931,7 @@ GNUNET_NETWORK_socket_shutdown(struct GNUNET_NETWORK_Handle *desc,
950 int ret; 931 int ret;
951 932
952 ret = shutdown(desc->fd, how); 933 ret = shutdown(desc->fd, how);
953#ifdef MINGW 934
954 if (0 != ret)
955 SetErrnoFromWinsockError(WSAGetLastError());
956#endif
957 return (0 == ret) ? GNUNET_OK : GNUNET_SYSERR; 935 return (0 == ret) ? GNUNET_OK : GNUNET_SYSERR;
958} 936}
959 937
@@ -1054,7 +1032,6 @@ void
1054GNUNET_NETWORK_fdset_add(struct GNUNET_NETWORK_FDSet *dst, 1032GNUNET_NETWORK_fdset_add(struct GNUNET_NETWORK_FDSet *dst,
1055 const struct GNUNET_NETWORK_FDSet *src) 1033 const struct GNUNET_NETWORK_FDSet *src)
1056{ 1034{
1057#ifndef MINGW
1058 int nfds; 1035 int nfds;
1059 1036
1060 for (nfds = src->nsds; nfds >= 0; nfds--) 1037 for (nfds = src->nsds; nfds >= 0; nfds--)
@@ -1062,31 +1039,6 @@ GNUNET_NETWORK_fdset_add(struct GNUNET_NETWORK_FDSet *dst,
1062 FD_SET(nfds, &dst->sds); 1039 FD_SET(nfds, &dst->sds);
1063 dst->nsds = GNUNET_MAX(dst->nsds, 1040 dst->nsds = GNUNET_MAX(dst->nsds,
1064 src->nsds); 1041 src->nsds);
1065#else
1066 /* This is MinGW32-specific implementation that relies on the code that
1067 * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
1068 * that fd being added is not already in the set.
1069 * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
1070 *
1071 * NOTE: I don't understand why the UNIX-logic wouldn't work
1072 * for the first part here as well. -CG
1073 */
1074 unsigned int i;
1075
1076 for (i = 0; i < src->sds.fd_count; i++)
1077 FD_SET(src->sds.fd_array[i],
1078 &dst->sds);
1079 dst->nsds = GNUNET_MAX(src->nsds,
1080 dst->nsds);
1081
1082 /* also copy over `struct GNUNET_DISK_FileHandle` array */
1083 if (dst->handles_pos + src->handles_pos > dst->handles_size)
1084 GNUNET_array_grow(dst->handles,
1085 dst->handles_size,
1086 ((dst->handles_pos + src->handles_pos) << 1));
1087 for (i = 0; i < src->handles_pos; i++)
1088 dst->handles[dst->handles_pos++] = src->handles[i];
1089#endif
1090} 1042}
1091 1043
1092 1044
@@ -1103,16 +1055,6 @@ GNUNET_NETWORK_fdset_copy(struct GNUNET_NETWORK_FDSet *to,
1103 FD_COPY(&from->sds, 1055 FD_COPY(&from->sds,
1104 &to->sds); 1056 &to->sds);
1105 to->nsds = from->nsds; 1057 to->nsds = from->nsds;
1106#ifdef MINGW
1107 if (from->handles_pos > to->handles_size)
1108 GNUNET_array_grow(to->handles,
1109 to->handles_size,
1110 from->handles_pos * 2);
1111 GNUNET_memcpy(to->handles,
1112 from->handles,
1113 from->handles_pos * sizeof(struct GNUNET_NETWORK_Handle *));
1114 to->handles_pos = from->handles_pos;
1115#endif
1116} 1058}
1117 1059
1118 1060
@@ -1217,13 +1159,6 @@ void
1217GNUNET_NETWORK_fdset_handle_set(struct GNUNET_NETWORK_FDSet *fds, 1159GNUNET_NETWORK_fdset_handle_set(struct GNUNET_NETWORK_FDSet *fds,
1218 const struct GNUNET_DISK_FileHandle *h) 1160 const struct GNUNET_DISK_FileHandle *h)
1219{ 1161{
1220#ifdef MINGW
1221 if (fds->handles_pos == fds->handles_size)
1222 GNUNET_array_grow(fds->handles,
1223 fds->handles_size,
1224 fds->handles_size * 2 + 2);
1225 fds->handles[fds->handles_pos++] = h;
1226#else
1227 int fd; 1162 int fd;
1228 1163
1229 GNUNET_assert(GNUNET_OK == 1164 GNUNET_assert(GNUNET_OK ==
@@ -1234,7 +1169,6 @@ GNUNET_NETWORK_fdset_handle_set(struct GNUNET_NETWORK_FDSet *fds,
1234 &fds->sds); 1169 &fds->sds);
1235 fds->nsds = GNUNET_MAX(fd + 1, 1170 fds->nsds = GNUNET_MAX(fd + 1,
1236 fds->nsds); 1171 fds->nsds);
1237#endif
1238} 1172}
1239 1173
1240 1174
@@ -1247,22 +1181,7 @@ void
1247GNUNET_NETWORK_fdset_handle_set_first(struct GNUNET_NETWORK_FDSet *fds, 1181GNUNET_NETWORK_fdset_handle_set_first(struct GNUNET_NETWORK_FDSet *fds,
1248 const struct GNUNET_DISK_FileHandle *h) 1182 const struct GNUNET_DISK_FileHandle *h)
1249{ 1183{
1250#ifdef MINGW
1251 if (fds->handles_pos == fds->handles_size)
1252 GNUNET_array_grow(fds->handles,
1253 fds->handles_size,
1254 fds->handles_size * 2 + 2);
1255 fds->handles[fds->handles_pos] = h;
1256 if (fds->handles[0] != h)
1257 {
1258 const struct GNUNET_DISK_FileHandle *bak = fds->handles[0];
1259 fds->handles[0] = h;
1260 fds->handles[fds->handles_pos] = bak;
1261 }
1262 fds->handles_pos++;
1263#else
1264 GNUNET_NETWORK_fdset_handle_set(fds, h); 1184 GNUNET_NETWORK_fdset_handle_set(fds, h);
1265#endif
1266} 1185}
1267 1186
1268 1187
@@ -1277,42 +1196,11 @@ int
1277GNUNET_NETWORK_fdset_handle_isset(const struct GNUNET_NETWORK_FDSet *fds, 1196GNUNET_NETWORK_fdset_handle_isset(const struct GNUNET_NETWORK_FDSet *fds,
1278 const struct GNUNET_DISK_FileHandle *h) 1197 const struct GNUNET_DISK_FileHandle *h)
1279{ 1198{
1280#ifdef MINGW
1281 unsigned int i;
1282
1283 for (i = 0; i < fds->handles_pos; i++)
1284 if (fds->handles[i] == h)
1285 return GNUNET_YES;
1286 return GNUNET_NO;
1287#else
1288 return FD_ISSET(h->fd, 1199 return FD_ISSET(h->fd,
1289 &fds->sds); 1200 &fds->sds);
1290#endif
1291} 1201}
1292 1202
1293 1203
1294#ifdef MINGW
1295/**
1296 * Numerically compare pointers to sort them.
1297 * Used to test for overlap in the arrays.
1298 *
1299 * @param p1 a pointer
1300 * @param p2 a pointer
1301 * @return -1, 0 or 1, if the p1 < p2, p1==p2 or p1 > p2.
1302 */
1303static int
1304ptr_cmp(const void *p1,
1305 const void *p2)
1306{
1307 if (p1 == p2)
1308 return 0;
1309 if ((intptr_t)p1 < (intptr_t)p2)
1310 return -1;
1311 return 1;
1312}
1313#endif
1314
1315
1316/** 1204/**
1317 * Checks if two fd sets overlap 1205 * Checks if two fd sets overlap
1318 * 1206 *
@@ -1324,7 +1212,6 @@ int
1324GNUNET_NETWORK_fdset_overlap(const struct GNUNET_NETWORK_FDSet *fds1, 1212GNUNET_NETWORK_fdset_overlap(const struct GNUNET_NETWORK_FDSet *fds1,
1325 const struct GNUNET_NETWORK_FDSet *fds2) 1213 const struct GNUNET_NETWORK_FDSet *fds2)
1326{ 1214{
1327#ifndef MINGW
1328 int nfds; 1215 int nfds;
1329 1216
1330 nfds = GNUNET_MIN(fds1->nsds, 1217 nfds = GNUNET_MIN(fds1->nsds,
@@ -1339,53 +1226,6 @@ GNUNET_NETWORK_fdset_overlap(const struct GNUNET_NETWORK_FDSet *fds1,
1339 return GNUNET_YES; 1226 return GNUNET_YES;
1340 } 1227 }
1341 return GNUNET_NO; 1228 return GNUNET_NO;
1342#else
1343 unsigned int i;
1344 unsigned int j;
1345
1346 /* This code is somewhat hacky, we are not supposed to know what's
1347 * inside of fd_set; also the O(n^2) is really bad... */
1348 for (i = 0; i < fds1->sds.fd_count; i++)
1349 for (j = 0; j < fds2->sds.fd_count; j++)
1350 if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1351 return GNUNET_YES;
1352
1353 /* take a short cut if possible */
1354 if ((0 == fds1->handles_pos) ||
1355 (0 == fds2->handles_pos))
1356 return GNUNET_NO;
1357
1358 /* Sort file handles array to avoid quadratic complexity when
1359 checking for overlap */
1360 qsort(fds1->handles,
1361 fds1->handles_pos,
1362 sizeof(void *),
1363 &ptr_cmp);
1364 qsort(fds2->handles,
1365 fds2->handles_pos,
1366 sizeof(void *),
1367 &ptr_cmp);
1368 i = 0;
1369 j = 0;
1370 while ((i < fds1->handles_pos) &&
1371 (j < fds2->handles_pos))
1372 {
1373 switch (ptr_cmp(fds1->handles[i],
1374 fds2->handles[j]))
1375 {
1376 case -1:
1377 i++;
1378 break;
1379
1380 case 0:
1381 return GNUNET_YES;
1382
1383 case 1:
1384 j++;
1385 }
1386 }
1387 return GNUNET_NO;
1388#endif
1389} 1229}
1390 1230
1391 1231
@@ -1413,192 +1253,10 @@ GNUNET_NETWORK_fdset_create()
1413void 1253void
1414GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds) 1254GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds)
1415{ 1255{
1416#ifdef MINGW
1417 GNUNET_array_grow(fds->handles,
1418 fds->handles_size,
1419 0);
1420#endif
1421 GNUNET_free(fds); 1256 GNUNET_free(fds);
1422} 1257}
1423 1258
1424 1259
1425#if MINGW
1426/**
1427 * FIXME.
1428 */
1429struct _select_params {
1430 /**
1431 * Read set.
1432 */
1433 fd_set *r;
1434
1435 /**
1436 * Write set.
1437 */
1438 fd_set *w;
1439
1440 /**
1441 * Except set.
1442 */
1443 fd_set *e;
1444
1445 /**
1446 * Timeout for select().
1447 */
1448 struct timeval *tv;
1449
1450 /**
1451 * FIXME.
1452 */
1453 HANDLE wakeup;
1454
1455 /**
1456 * FIXME.
1457 */
1458 HANDLE standby;
1459
1460 /**
1461 * FIXME.
1462 */
1463 _win_socket wakeup_socket;
1464
1465 /**
1466 * Set to return value from select.
1467 */
1468 int status;
1469};
1470
1471
1472/**
1473 * FIXME.
1474 */
1475static DWORD WINAPI
1476_selector(LPVOID p)
1477{
1478 struct _select_params *sp = p;
1479
1480 while (1)
1481 {
1482 WaitForSingleObject(sp->standby,
1483 INFINITE);
1484 ResetEvent(sp->standby);
1485 sp->status = select(1,
1486 sp->r,
1487 sp->w,
1488 sp->e,
1489 sp->tv);
1490 if (FD_ISSET(sp->wakeup_socket,
1491 sp->r))
1492 {
1493 FD_CLR(sp->wakeup_socket,
1494 sp->r);
1495 sp->status -= 1;
1496 }
1497 SetEvent(sp->wakeup);
1498 }
1499 return 0;
1500}
1501
1502
1503static HANDLE hEventPipeWrite;
1504
1505static HANDLE hEventReadReady;
1506
1507static struct _select_params sp;
1508
1509static HANDLE select_thread;
1510
1511static HANDLE select_finished_event;
1512
1513static HANDLE select_standby_event;
1514
1515static _win_socket select_wakeup_socket = -1;
1516
1517static _win_socket select_send_socket = -1;
1518
1519static struct timeval select_timeout;
1520
1521
1522/**
1523 * On W32, we actually use a thread to help with the
1524 * event loop due to W32-API limitations. This function
1525 * initializes that thread.
1526 */
1527static void
1528initialize_select_thread()
1529{
1530 _win_socket select_listening_socket = -1;
1531 struct sockaddr_in s_in;
1532 int alen;
1533 int res;
1534 unsigned long p;
1535
1536 select_standby_event = CreateEvent(NULL, TRUE, FALSE, NULL);
1537 select_finished_event = CreateEvent(NULL, TRUE, FALSE, NULL);
1538
1539 select_wakeup_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1540
1541 select_listening_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1542
1543 p = 1;
1544 res = ioctlsocket(select_wakeup_socket, FIONBIO, &p);
1545 LOG(GNUNET_ERROR_TYPE_DEBUG,
1546 "Select thread initialization: ioctlsocket() returns %d\n",
1547 res);
1548
1549 alen = sizeof(s_in);
1550 s_in.sin_family = AF_INET;
1551 s_in.sin_port = 0;
1552 s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1553 s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1554 s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1555 s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1556 res = bind(select_listening_socket,
1557 (const struct sockaddr *)&s_in,
1558 sizeof(s_in));
1559 LOG(GNUNET_ERROR_TYPE_DEBUG,
1560 "Select thread initialization: bind() returns %d\n",
1561 res);
1562
1563 res = getsockname(select_listening_socket,
1564 (struct sockaddr *)&s_in,
1565 &alen);
1566 LOG(GNUNET_ERROR_TYPE_DEBUG,
1567 "Select thread initialization: getsockname() returns %d\n",
1568 res);
1569
1570 res = listen(select_listening_socket,
1571 SOMAXCONN);
1572 LOG(GNUNET_ERROR_TYPE_DEBUG,
1573 "Select thread initialization: listen() returns %d\n",
1574 res);
1575 res = connect(select_wakeup_socket,
1576 (const struct sockaddr *)&s_in,
1577 sizeof(s_in));
1578 LOG(GNUNET_ERROR_TYPE_DEBUG,
1579 "Select thread initialization: connect() returns %d\n",
1580 res);
1581
1582 select_send_socket = accept(select_listening_socket,
1583 (struct sockaddr *)&s_in,
1584 &alen);
1585
1586 closesocket(select_listening_socket);
1587
1588 sp.wakeup = select_finished_event;
1589 sp.standby = select_standby_event;
1590 sp.wakeup_socket = select_wakeup_socket;
1591
1592 select_thread = CreateThread(NULL,
1593 0,
1594 _selector,
1595 &sp,
1596 0, NULL);
1597}
1598
1599
1600#endif
1601
1602/** 1260/**
1603 * Test if the given @a port is available. 1261 * Test if the given @a port is available.
1604 * 1262 *
@@ -1657,7 +1315,6 @@ GNUNET_NETWORK_test_port_free(int ipproto,
1657} 1315}
1658 1316
1659 1317
1660#ifndef MINGW
1661/** 1318/**
1662 * Check if sockets or pipes meet certain conditions 1319 * Check if sockets or pipes meet certain conditions
1663 * 1320 *
@@ -1714,523 +1371,4 @@ GNUNET_NETWORK_socket_select(struct GNUNET_NETWORK_FDSet *rfds,
1714 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv); 1371 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us) ? NULL : &tv);
1715} 1372}
1716 1373
1717
1718#else
1719/* MINGW */
1720
1721
1722/**
1723 * Non-blocking test if a pipe is ready for reading.
1724 *
1725 * @param fh pipe handle
1726 * @return #GNUNET_YES if the pipe is ready for reading
1727 */
1728static int
1729pipe_read_ready(const struct GNUNET_DISK_FileHandle *fh)
1730{
1731 DWORD error;
1732 BOOL bret;
1733 DWORD waitstatus = 0;
1734
1735 SetLastError(0);
1736 bret = PeekNamedPipe(fh->h, NULL, 0, NULL, &waitstatus, NULL);
1737 error = GetLastError();
1738 if (0 == bret)
1739 {
1740 /* TODO: either add more errors to this condition, or eliminate it
1741 * entirely (failed to peek -> pipe is in serious trouble, should
1742 * be selected as readable).
1743 */
1744 if ((error != ERROR_BROKEN_PIPE) &&
1745 (error != ERROR_INVALID_HANDLE))
1746 return GNUNET_NO;
1747 }
1748 else if (waitstatus <= 0)
1749 return GNUNET_NO;
1750 return GNUNET_YES;
1751}
1752
1753
1754/**
1755 * Non-blocking test if a pipe is having an IO exception.
1756 *
1757 * @param fh pipe handle
1758 * @return #GNUNET_YES if the pipe is having an IO exception.
1759 */
1760static int
1761pipe_except_ready(const struct GNUNET_DISK_FileHandle *fh)
1762{
1763 DWORD dwBytes;
1764
1765 if (PeekNamedPipe(fh->h, NULL, 0, NULL, &dwBytes, NULL))
1766 return GNUNET_NO;
1767 return GNUNET_YES;
1768}
1769
1770
1771/**
1772 * Iterate over handles in fds, destructively rewrite the
1773 * handles array contents of fds so that it starts with the
1774 * handles that are ready, and update handles_pos accordingly.
1775 *
1776 * @param fds set of handles (usually pipes) to be checked for readiness
1777 * @param except GNUNET_NO if fds should be checked for readiness to read,
1778 * GNUNET_YES if fds should be checked for exceptions
1779 * (there is no way to check for write-readiness - pipes are always write-ready)
1780 * @param set_for_sure a HANDLE that is known to be set already,
1781 * because WaitForMultipleObjects() returned its index.
1782 * @return number of ready handles
1783 */
1784static int
1785check_handles_status(struct GNUNET_NETWORK_FDSet *fds,
1786 int except,
1787 HANDLE set_for_sure)
1788{
1789 const struct GNUNET_DISK_FileHandle *fh;
1790 unsigned int roff;
1791 unsigned int woff;
1792
1793 for (woff = 0, roff = 0; roff < fds->handles_pos; roff++)
1794 {
1795 fh = fds->handles[roff];
1796 if (fh == set_for_sure)
1797 {
1798 fds->handles[woff++] = fh;
1799 }
1800 else if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1801 {
1802 if ((except && pipe_except_ready(fh)) ||
1803 (!except && pipe_read_ready(fh)))
1804 fds->handles[woff++] = fh;
1805 }
1806 else if (fh->type == GNUNET_DISK_HANLDE_TYPE_FILE)
1807 {
1808 if (!except)
1809 fds->handles[woff++] = fh;
1810 }
1811 else
1812 {
1813 if (WAIT_OBJECT_0 == WaitForSingleObject(fh->h, 0))
1814 fds->handles[woff++] = fh;
1815 }
1816 }
1817 fds->handles_pos = woff;
1818 return woff;
1819}
1820
1821
1822/**
1823 * Check if sockets or pipes meet certain conditions, version for W32.
1824 *
1825 * @param rfds set of sockets or pipes to be checked for readability
1826 * @param wfds set of sockets or pipes to be checked for writability
1827 * @param efds set of sockets or pipes to be checked for exceptions
1828 * @param timeout relative value when to return
1829 * @return number of selected sockets or pipes, #GNUNET_SYSERR on error
1830 */
1831int
1832GNUNET_NETWORK_socket_select(struct GNUNET_NETWORK_FDSet *rfds,
1833 struct GNUNET_NETWORK_FDSet *wfds,
1834 struct GNUNET_NETWORK_FDSet *efds,
1835 const struct GNUNET_TIME_Relative timeout)
1836{
1837 const struct GNUNET_DISK_FileHandle *fh;
1838 int nfds;
1839 int handles;
1840 unsigned int i;
1841 int retcode;
1842 uint64_t mcs_total;
1843 DWORD ms_rounded;
1844 int nhandles = 0;
1845 int read_pipes_off;
1846 HANDLE handle_array[FD_SETSIZE + 2];
1847 int returncode;
1848 int returnedpos = 0;
1849 int selectret;
1850 fd_set aread;
1851 fd_set awrite;
1852 fd_set aexcept;
1853
1854 nfds = 0;
1855 handles = 0;
1856 if (NULL != rfds)
1857 {
1858 nfds = GNUNET_MAX(nfds, rfds->nsds);
1859 handles += rfds->handles_pos;
1860 }
1861 if (NULL != wfds)
1862 {
1863 nfds = GNUNET_MAX(nfds, wfds->nsds);
1864 handles += wfds->handles_pos;
1865 }
1866 if (NULL != efds)
1867 {
1868 nfds = GNUNET_MAX(nfds, efds->nsds);
1869 handles += efds->handles_pos;
1870 }
1871
1872 if ((0 == nfds) &&
1873 (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == timeout.rel_value_us) &&
1874 (0 == handles))
1875 {
1876 GNUNET_break(0);
1877 LOG(GNUNET_ERROR_TYPE_ERROR,
1878 _("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1879 "select");
1880 }
1881#define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))
1882 /* calculate how long we need to wait in microseconds */
1883 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1884 {
1885 mcs_total = INFINITE;
1886 ms_rounded = INFINITE;
1887 }
1888 else
1889 {
1890 mcs_total = timeout.rel_value_us / GNUNET_TIME_UNIT_MICROSECONDS.rel_value_us;
1891 ms_rounded = (DWORD)(mcs_total / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us);
1892 if (mcs_total > 0 && ms_rounded == 0)
1893 ms_rounded = 1;
1894 }
1895 /* select() may be used as a portable way to sleep */
1896 if (!(rfds || wfds || efds))
1897 {
1898 Sleep(ms_rounded);
1899 return 0;
1900 }
1901
1902 if (NULL == select_thread)
1903 initialize_select_thread();
1904
1905 FD_ZERO(&aread);
1906 FD_ZERO(&awrite);
1907 FD_ZERO(&aexcept);
1908 if (rfds)
1909 FD_COPY(&rfds->sds, &aread);
1910 if (wfds)
1911 FD_COPY(&wfds->sds, &awrite);
1912 if (efds)
1913 FD_COPY(&efds->sds, &aexcept);
1914
1915 /* Start by doing a fast check on sockets and pipes (without
1916 waiting). It is cheap, and is sufficient most of the time. By
1917 profiling we detected that to be true in 90% of the cases.
1918 */
1919
1920 /* Do the select now */
1921 select_timeout.tv_sec = 0;
1922 select_timeout.tv_usec = 0;
1923
1924 /* Copy all the writes to the except, so we can detect connect() errors */
1925 for (i = 0; i < awrite.fd_count; i++)
1926 FD_SET(awrite.fd_array[i],
1927 &aexcept);
1928 if ((aread.fd_count > 0) ||
1929 (awrite.fd_count > 0) ||
1930 (aexcept.fd_count > 0))
1931 selectret = select(1,
1932 (NULL != rfds) ? &aread : NULL,
1933 (NULL != wfds) ? &awrite : NULL,
1934 &aexcept,
1935 &select_timeout);
1936 else
1937 selectret = 0;
1938 if (-1 == selectret)
1939 {
1940 /* Throw an error early on, while we still have the context. */
1941 LOG(GNUNET_ERROR_TYPE_ERROR,
1942 "W32 select(%d, %d, %d) failed: %lu\n",
1943 rfds ? aread.fd_count : 0,
1944 wfds ? awrite.fd_count : 0,
1945 aexcept.fd_count,
1946 GetLastError());
1947 GNUNET_assert(0);
1948 }
1949
1950 /* Check aexcept, if something is in there and we copied that
1951 FD before to detect connect() errors, add it back to the
1952 write set to report errors. */
1953 if (NULL != wfds)
1954 for (i = 0; i < aexcept.fd_count; i++)
1955 if (FD_ISSET(aexcept.fd_array[i],
1956 &wfds->sds))
1957 FD_SET(aexcept.fd_array[i],
1958 &awrite);
1959
1960
1961 /* If our select returned something or is a 0-timed request, then
1962 also check the pipes and get out of here! */
1963 /* Sadly, it means code duplication :( */
1964 if ((selectret > 0) || (0 == mcs_total))
1965 {
1966 retcode = 0;
1967
1968 /* Read Pipes */
1969 if (rfds && (rfds->handles_pos > 0))
1970 retcode += check_handles_status(rfds, GNUNET_NO, NULL);
1971
1972 /* wfds handles remain untouched, on W32
1973 we pretend our pipes are "always" write-ready */
1974
1975 /* except pipes */
1976 if (efds && (efds->handles_pos > 0))
1977 retcode += check_handles_status(efds, GNUNET_YES, NULL);
1978
1979 if (rfds)
1980 {
1981 GNUNET_NETWORK_fdset_zero(rfds);
1982 if (selectret != -1)
1983 GNUNET_NETWORK_fdset_copy_native(rfds, &aread, selectret);
1984 }
1985 if (wfds)
1986 {
1987 GNUNET_NETWORK_fdset_zero(wfds);
1988 if (selectret != -1)
1989 GNUNET_NETWORK_fdset_copy_native(wfds, &awrite, selectret);
1990 }
1991 if (efds)
1992 {
1993 GNUNET_NETWORK_fdset_zero(efds);
1994 if (selectret != -1)
1995 GNUNET_NETWORK_fdset_copy_native(efds, &aexcept, selectret);
1996 }
1997 if (-1 == selectret)
1998 return -1;
1999 /* Add our select() FDs to the total return value */
2000 retcode += selectret;
2001 return retcode;
2002 }
2003
2004 /* If we got this far, use slower implementation that is able to do a waiting select
2005 on both sockets and pipes simultaneously */
2006
2007 /* Events for pipes */
2008 if (!hEventReadReady)
2009 hEventReadReady = CreateEvent(NULL, TRUE, TRUE, NULL);
2010 if (!hEventPipeWrite)
2011 hEventPipeWrite = CreateEvent(NULL, TRUE, TRUE, NULL);
2012 retcode = 0;
2013
2014 FD_ZERO(&aread);
2015 FD_ZERO(&awrite);
2016 FD_ZERO(&aexcept);
2017 if (rfds)
2018 FD_COPY(&rfds->sds, &aread);
2019 if (wfds)
2020 FD_COPY(&wfds->sds, &awrite);
2021 if (efds)
2022 FD_COPY(&efds->sds, &aexcept);
2023 /* We will first Add the PIPES to the events */
2024 /* Track how far in `handle_array` the read pipes go,
2025 so we may by-pass them quickly if none of them
2026 are selected. */
2027 read_pipes_off = 0;
2028 if (rfds && (rfds->handles_pos > 0))
2029 {
2030 for (i = 0; i < rfds->handles_pos; i++)
2031 {
2032 fh = rfds->handles[i];
2033 if (fh->type == GNUNET_DISK_HANLDE_TYPE_EVENT)
2034 {
2035 handle_array[nhandles++] = fh->h;
2036 continue;
2037 }
2038 if (fh->type != GNUNET_DISK_HANLDE_TYPE_PIPE)
2039 continue;
2040 /* Read zero bytes to check the status of the pipe */
2041 if (!ReadFile(fh->h, NULL, 0, NULL, fh->oOverlapRead))
2042 {
2043 DWORD error_code = GetLastError();
2044
2045 if (error_code == ERROR_IO_PENDING)
2046 {
2047 /* add as unready */
2048 handle_array[nhandles++] = fh->oOverlapRead->hEvent;
2049 read_pipes_off++;
2050 }
2051 else
2052 {
2053 /* add as ready */
2054 handle_array[nhandles++] = hEventReadReady;
2055 read_pipes_off++;
2056 }
2057 }
2058 else
2059 {
2060 /* error also counts as ready */
2061 handle_array[nhandles++] = hEventReadReady;
2062 read_pipes_off++;
2063 }
2064 }
2065 }
2066
2067 if (wfds && (wfds->handles_pos > 0))
2068 {
2069 LOG(GNUNET_ERROR_TYPE_DEBUG,
2070 "Adding the write ready event to the array as %d\n",
2071 nhandles);
2072 handle_array[nhandles++] = hEventPipeWrite;
2073 }
2074
2075 sp.status = 0;
2076 if (nfds > 0)
2077 {
2078 LOG(GNUNET_ERROR_TYPE_DEBUG,
2079 "Adding the socket event to the array as %d\n",
2080 nhandles);
2081 handle_array[nhandles++] = select_finished_event;
2082 if (timeout.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
2083 {
2084 sp.tv = NULL;
2085 }
2086 else
2087 {
2088 select_timeout.tv_sec = timeout.rel_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
2089 select_timeout.tv_usec = (timeout.rel_value_us -
2090 (select_timeout.tv_sec *
2091 GNUNET_TIME_UNIT_SECONDS.rel_value_us));
2092 sp.tv = &select_timeout;
2093 }
2094 FD_SET(select_wakeup_socket, &aread);
2095 do
2096 {
2097 i = recv(select_wakeup_socket,
2098 (char *)&returnedpos,
2099 1,
2100 0);
2101 }
2102 while (i == 1);
2103 sp.r = &aread;
2104 sp.w = &awrite;
2105 sp.e = &aexcept;
2106 /* Failed connections cause sockets to be set in errorfds on W32,
2107 * but on POSIX it should set them in writefds.
2108 * First copy all awrite sockets to aexcept, later we'll
2109 * check aexcept and set its contents in awrite as well
2110 * Sockets are also set in errorfds when OOB data is available,
2111 * but we don't use OOB data.
2112 */
2113 for (i = 0; i < awrite.fd_count; i++)
2114 FD_SET(awrite.fd_array[i],
2115 &aexcept);
2116 ResetEvent(select_finished_event);
2117 SetEvent(select_standby_event);
2118 }
2119
2120 /* NULL-terminate array */
2121 handle_array[nhandles] = NULL;
2122 LOG(GNUNET_ERROR_TYPE_DEBUG,
2123 "nfds: %d, handles: %d, will wait: %llu mcs\n",
2124 nfds,
2125 nhandles,
2126 mcs_total);
2127 if (nhandles)
2128 {
2129 returncode
2130 = WaitForMultipleObjects(nhandles,
2131 handle_array,
2132 FALSE,
2133 ms_rounded);
2134 LOG(GNUNET_ERROR_TYPE_DEBUG,
2135 "WaitForMultipleObjects Returned: %d\n",
2136 returncode);
2137 }
2138 else if (nfds > 0)
2139 {
2140 GNUNET_break(0); /* This branch shouldn't actually be executed...*/
2141 i = (int)WaitForSingleObject(select_finished_event,
2142 INFINITE);
2143 returncode = WAIT_TIMEOUT;
2144 }
2145 else
2146 {
2147 /* Shouldn't come this far. If it does - investigate. */
2148 GNUNET_assert(0);
2149 }
2150
2151 if (nfds > 0)
2152 {
2153 /* Don't wake up select-thread when delay is 0, it should return immediately
2154 * and wake up by itself.
2155 */
2156 if (0 != mcs_total)
2157 i = send(select_send_socket,
2158 (const char *)&returnedpos,
2159 1,
2160 0);
2161 i = (int)WaitForSingleObject(select_finished_event,
2162 INFINITE);
2163 LOG(GNUNET_ERROR_TYPE_DEBUG,
2164 "Finished waiting for the select thread: %d %d\n",
2165 i,
2166 sp.status);
2167 if (0 != mcs_total)
2168 {
2169 do
2170 {
2171 i = recv(select_wakeup_socket,
2172 (char *)&returnedpos,
2173 1, 0);
2174 }
2175 while (1 == i);
2176 }
2177 /* Check aexcept, add its contents to awrite */
2178 for (i = 0; i < aexcept.fd_count; i++)
2179 FD_SET(aexcept.fd_array[i], &awrite);
2180 }
2181
2182 returnedpos = returncode - WAIT_OBJECT_0;
2183 LOG(GNUNET_ERROR_TYPE_DEBUG,
2184 "return pos is: %d\n",
2185 returnedpos);
2186
2187 if (rfds)
2188 {
2189 /* We queued a zero-long read on each pipe to check
2190 * its state, now we must cancel these read operations.
2191 * This must be done while rfds->handles_pos is still
2192 * intact and matches the number of read handles that we
2193 * got from the caller.
2194 */
2195 for (i = 0; i < rfds->handles_pos; i++)
2196 {
2197 fh = rfds->handles[i];
2198 if (GNUNET_DISK_HANLDE_TYPE_PIPE == fh->type)
2199 CancelIo(fh->h);
2200 }
2201
2202 /* We may have some pipes ready for reading. */
2203 if (returnedpos < read_pipes_off)
2204 retcode += check_handles_status(rfds, GNUNET_NO, handle_array[returnedpos]);
2205 else
2206 rfds->handles_pos = 0;
2207
2208 if (-1 != sp.status)
2209 GNUNET_NETWORK_fdset_copy_native(rfds, &aread, retcode);
2210 }
2211 if (wfds)
2212 {
2213 retcode += wfds->handles_pos;
2214 /* wfds handles remain untouched */
2215 if (-1 != sp.status)
2216 GNUNET_NETWORK_fdset_copy_native(wfds, &awrite, retcode);
2217 }
2218 if (efds)
2219 {
2220 retcode += check_handles_status(rfds,
2221 GNUNET_YES,
2222 returnedpos < nhandles ? handle_array[returnedpos] : NULL);
2223 if (-1 != sp.status)
2224 GNUNET_NETWORK_fdset_copy_native(efds, &aexcept, retcode);
2225 }
2226
2227 if (sp.status > 0)
2228 retcode += sp.status;
2229
2230 return retcode;
2231}
2232
2233/* MINGW */
2234#endif
2235
2236/* end of network.c */ 1374/* end of network.c */
diff --git a/src/util/os_installation.c b/src/util/os_installation.c
index 104a98da6..c8590c8fb 100644
--- a/src/util/os_installation.c
+++ b/src/util/os_installation.c
@@ -764,26 +764,6 @@ GNUNET_OS_check_helper_binary(const char *binary,
764 char *p; 764 char *p;
765 char *pf; 765 char *pf;
766 766
767#ifdef MINGW
768 char *binaryexe;
769
770 GNUNET_asprintf(&binaryexe, "%s.exe", binary);
771 if ((GNUNET_YES ==
772 GNUNET_STRINGS_path_is_absolute(binaryexe, GNUNET_NO, NULL, NULL)) ||
773 (0 == strncmp(binary, "./", 2)))
774 p = GNUNET_strdup(binaryexe);
775 else
776 {
777 p = get_path_from_PATH(binaryexe);
778 if (NULL != p)
779 {
780 GNUNET_asprintf(&pf, "%s/%s", p, binaryexe);
781 GNUNET_free(p);
782 p = pf;
783 }
784 }
785 GNUNET_free(binaryexe);
786#else
787 if ((GNUNET_YES == 767 if ((GNUNET_YES ==
788 GNUNET_STRINGS_path_is_absolute(binary, GNUNET_NO, NULL, NULL)) || 768 GNUNET_STRINGS_path_is_absolute(binary, GNUNET_NO, NULL, NULL)) ||
789 (0 == strncmp(binary, "./", 2))) 769 (0 == strncmp(binary, "./", 2)))
@@ -800,7 +780,7 @@ GNUNET_OS_check_helper_binary(const char *binary,
800 p = pf; 780 p = pf;
801 } 781 }
802 } 782 }
803#endif 783
804 if (NULL == p) 784 if (NULL == p)
805 { 785 {
806 LOG(GNUNET_ERROR_TYPE_INFO, 786 LOG(GNUNET_ERROR_TYPE_INFO,
@@ -814,14 +794,14 @@ GNUNET_OS_check_helper_binary(const char *binary,
814 GNUNET_free(p); 794 GNUNET_free(p);
815 return GNUNET_SYSERR; 795 return GNUNET_SYSERR;
816 } 796 }
817#ifndef MINGW 797
818 if (0 == getuid()) 798 if (0 == getuid())
819 { 799 {
820 /* as we run as root, we don't insist on SUID */ 800 /* as we run as root, we don't insist on SUID */
821 GNUNET_free(p); 801 GNUNET_free(p);
822 return GNUNET_YES; 802 return GNUNET_YES;
823 } 803 }
824#endif 804
825 if (0 != stat(p, &statbuf)) 805 if (0 != stat(p, &statbuf))
826 { 806 {
827 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_WARNING, "stat", p); 807 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_WARNING, "stat", p);
@@ -830,7 +810,6 @@ GNUNET_OS_check_helper_binary(const char *binary,
830 } 810 }
831 if (check_suid) 811 if (check_suid)
832 { 812 {
833#ifndef MINGW
834 (void)params; 813 (void)params;
835 if ((0 != (statbuf.st_mode & S_ISUID)) && (0 == statbuf.st_uid)) 814 if ((0 != (statbuf.st_mode & S_ISUID)) && (0 == statbuf.st_uid))
836 { 815 {
@@ -841,57 +820,6 @@ GNUNET_OS_check_helper_binary(const char *binary,
841 _("Binary `%s' exists, but is not SUID\n"), 820 _("Binary `%s' exists, but is not SUID\n"),
842 p); 821 p);
843 /* binary exists, but not SUID */ 822 /* binary exists, but not SUID */
844#else
845 STARTUPINFO start;
846 char parameters[512];
847 PROCESS_INFORMATION proc;
848 DWORD exit_value;
849
850 GNUNET_snprintf(parameters, sizeof(parameters), "-d %s", params);
851 memset(&start, 0, sizeof(start));
852 start.cb = sizeof(start);
853 memset(&proc, 0, sizeof(proc));
854
855
856 // Start the child process.
857 if (!(CreateProcess(
858 p, // current windows (2k3 and up can handle / instead of \ in paths))
859 parameters, // execute dryrun/priviliege checking mode
860 NULL, // Process handle not inheritable
861 NULL, // Thread handle not inheritable
862 FALSE, // Set handle inheritance to FALSE
863 CREATE_DEFAULT_ERROR_MODE, // No creation flags
864 NULL, // Use parent's environment block
865 NULL, // Use parent's starting directory
866 &start, // Pointer to STARTUPINFO structure
867 &proc) // Pointer to PROCESS_INFORMATION structure
868 ))
869 {
870 LOG(GNUNET_ERROR_TYPE_ERROR,
871 _("CreateProcess failed for binary %s (%d).\n"),
872 p,
873 GetLastError());
874 return GNUNET_SYSERR;
875 }
876
877 // Wait until child process exits.
878 WaitForSingleObject(proc.hProcess, INFINITE);
879
880 if (!GetExitCodeProcess(proc.hProcess, &exit_value))
881 {
882 LOG(GNUNET_ERROR_TYPE_ERROR,
883 _("GetExitCodeProcess failed for binary %s (%d).\n"),
884 p,
885 GetLastError());
886 return GNUNET_SYSERR;
887 }
888 // Close process and thread handles.
889 CloseHandle(proc.hProcess);
890 CloseHandle(proc.hThread);
891
892 if (!exit_value)
893 return GNUNET_YES;
894#endif
895 } 823 }
896 GNUNET_free(p); 824 GNUNET_free(p);
897 return GNUNET_NO; 825 return GNUNET_NO;
diff --git a/src/util/os_network.c b/src/util/os_network.c
index 4df37b9e5..526678047 100644
--- a/src/util/os_network.c
+++ b/src/util/os_network.c
@@ -35,7 +35,7 @@
35#define LOG_STRERROR_FILE(kind, syscall, filename) GNUNET_log_from_strerror_file(kind, "util-os-network", syscall, filename) 35#define LOG_STRERROR_FILE(kind, syscall, filename) GNUNET_log_from_strerror_file(kind, "util-os-network", syscall, filename)
36 36
37 37
38#if !(HAVE_GETIFADDRS && HAVE_FREEIFADDRS) && !MINGW 38#if !(HAVE_GETIFADDRS && HAVE_FREEIFADDRS)
39/** 39/**
40 * Try to enumerate all network interfaces using 'ifconfig'. 40 * Try to enumerate all network interfaces using 'ifconfig'.
41 * 41 *
@@ -388,32 +388,7 @@ void
388GNUNET_OS_network_interfaces_list(GNUNET_OS_NetworkInterfaceProcessor proc, 388GNUNET_OS_network_interfaces_list(GNUNET_OS_NetworkInterfaceProcessor proc,
389 void *proc_cls) 389 void *proc_cls)
390{ 390{
391#ifdef MINGW 391#if HAVE_GETIFADDRS && HAVE_FREEIFADDRS
392 int r;
393 int i;
394 struct EnumNICs3_results *results = NULL;
395 int results_count;
396
397 r = EnumNICs3(&results, &results_count);
398 if (r != GNUNET_OK)
399 return;
400
401 for (i = 0; i < results_count; i++)
402 {
403 if (GNUNET_OK !=
404 proc(proc_cls, results[i].pretty_name, results[i].is_default,
405 (const struct sockaddr *)&results[i].address,
406 results[i].
407 flags & ENUMNICS3_BCAST_OK ?
408 (const struct sockaddr *)&results[i].broadcast : NULL,
409 results[i].flags & ENUMNICS3_MASK_OK ?
410 (const struct sockaddr *)&results[i].mask : NULL,
411 results[i].addr_size))
412 break;
413 }
414 EnumNICs3_free(results);
415 return;
416#elif HAVE_GETIFADDRS && HAVE_FREEIFADDRS
417 struct ifaddrs *ifa_first; 392 struct ifaddrs *ifa_first;
418 struct ifaddrs *ifa_ptr; 393 struct ifaddrs *ifa_ptr;
419 socklen_t alen; 394 socklen_t alen;
diff --git a/src/util/os_priority.c b/src/util/os_priority.c
index ebe469b3b..e25623af5 100644
--- a/src/util/os_priority.c
+++ b/src/util/os_priority.c
@@ -350,7 +350,6 @@ start_process(int pipe_control,
350 const char *filename, 350 const char *filename,
351 char *const argv[]) 351 char *const argv[])
352{ 352{
353#ifndef MINGW
354 pid_t ret; 353 pid_t ret;
355 char fds[16]; 354 char fds[16];
356 struct GNUNET_OS_Process *gnunet_proc; 355 struct GNUNET_OS_Process *gnunet_proc;
@@ -464,7 +463,7 @@ start_process(int pipe_control,
464 GNUNET_array_append(lscp, ls, -1); 463 GNUNET_array_append(lscp, ls, -1);
465 } 464 }
466#if DARWIN 465#if DARWIN
467 /* see https://gnunet.org/vfork */ 466 /* see https://web.archive.org/web/20150924082249/gnunet.org/vfork */
468 ret = vfork(); 467 ret = vfork();
469#else 468#else
470 ret = fork(); 469 ret = fork();
@@ -589,547 +588,6 @@ start_process(int pipe_control,
589 execvp(filename, argv); 588 execvp(filename, argv);
590 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_ERROR, "execvp", filename); 589 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_ERROR, "execvp", filename);
591 _exit(1); 590 _exit(1);
592#else
593 struct GNUNET_DISK_FileHandle *childpipe_read;
594 struct GNUNET_DISK_FileHandle *childpipe_write;
595 HANDLE childpipe_read_handle;
596 char **arg;
597 char **non_const_argv;
598 unsigned int cmdlen;
599 char *cmd;
600 char *idx;
601 STARTUPINFOW start;
602 PROCESS_INFORMATION proc;
603 int argcount = 0;
604 struct GNUNET_OS_Process *gnunet_proc;
605 char path[MAX_PATH + 1];
606 char *our_env[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
607 char *env_block = NULL;
608 char *pathbuf;
609 DWORD pathbuf_len;
610 DWORD alloc_len;
611 char *self_prefix;
612 char *bindir;
613 char *libdir;
614 char *ptr;
615 char *non_const_filename;
616 char win_path[MAX_PATH + 1];
617 struct GNUNET_DISK_PipeHandle *lsocks_pipe;
618 const struct GNUNET_DISK_FileHandle *lsocks_write_fd;
619 HANDLE lsocks_read;
620 HANDLE lsocks_write;
621 wchar_t *wpath;
622 wchar_t *wcmd;
623 size_t wpath_len;
624 size_t wcmd_len;
625 int env_off;
626 int fail;
627 long lRet;
628 HANDLE stdin_handle;
629 HANDLE stdout_handle;
630 HANDLE stdih, stdoh, stdeh;
631 DWORD stdif, stdof, stdef;
632 BOOL bresult;
633 DWORD error_code;
634 DWORD create_no_window;
635
636 if (GNUNET_SYSERR ==
637 GNUNET_OS_check_helper_binary(filename, GNUNET_NO, NULL))
638 return NULL; /* not executable */
639
640 /* Search in prefix dir (hopefully - the directory from which
641 * the current module was loaded), bindir and libdir, then in PATH
642 */
643 self_prefix = GNUNET_OS_installation_get_path(GNUNET_OS_IPK_SELF_PREFIX);
644 bindir = GNUNET_OS_installation_get_path(GNUNET_OS_IPK_BINDIR);
645 libdir = GNUNET_OS_installation_get_path(GNUNET_OS_IPK_LIBDIR);
646
647 pathbuf_len = GetEnvironmentVariableA("PATH", (char *)&pathbuf, 0);
648
649 alloc_len = pathbuf_len + 1 + strlen(self_prefix) + 1 + strlen(bindir) + 1 +
650 strlen(libdir);
651
652 pathbuf = GNUNET_malloc(alloc_len * sizeof(char));
653
654 ptr = pathbuf;
655 ptr += sprintf(pathbuf, "%s;%s;%s;", self_prefix, bindir, libdir);
656 GNUNET_free(self_prefix);
657 GNUNET_free(bindir);
658 GNUNET_free(libdir);
659
660 alloc_len = GetEnvironmentVariableA("PATH", ptr, pathbuf_len);
661 if (alloc_len != pathbuf_len - 1)
662 {
663 GNUNET_free(pathbuf);
664 errno = ENOSYS; /* PATH changed on the fly. What kind of error is that? */
665 return NULL;
666 }
667
668 cmdlen = strlen(filename);
669 if ((cmdlen < 5) || (0 != strcmp(&filename[cmdlen - 4], ".exe")))
670 GNUNET_asprintf(&non_const_filename, "%s.exe", filename);
671 else
672 GNUNET_asprintf(&non_const_filename, "%s", filename);
673
674 /* It could be in POSIX form, convert it to a DOS path early on */
675 if (ERROR_SUCCESS !=
676 (lRet = plibc_conv_to_win_path(non_const_filename, win_path)))
677 {
678 SetErrnoFromWinError(lRet);
679 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_ERROR,
680 "plibc_conv_to_win_path",
681 non_const_filename);
682 GNUNET_free(non_const_filename);
683 GNUNET_free(pathbuf);
684 return NULL;
685 }
686 GNUNET_free(non_const_filename);
687 non_const_filename = GNUNET_strdup(win_path);
688 /* Check that this is the full path. If it isn't, search. */
689 /* FIXME: convert it to wchar_t and use SearchPathW?
690 * Remember: arguments to _start_process() are technically in UTF-8...
691 */
692 if (non_const_filename[1] == ':')
693 {
694 snprintf(path, sizeof(path) / sizeof(char), "%s", non_const_filename);
695 LOG(GNUNET_ERROR_TYPE_DEBUG,
696 "Using path `%s' as-is. PATH is %s\n",
697 path,
698 ptr);
699 }
700 else if (!SearchPathA(pathbuf,
701 non_const_filename,
702 NULL,
703 sizeof(path) / sizeof(char),
704 path,
705 NULL))
706 {
707 SetErrnoFromWinError(GetLastError());
708 LOG_STRERROR_FILE(GNUNET_ERROR_TYPE_ERROR,
709 "SearchPath",
710 non_const_filename);
711 GNUNET_free(non_const_filename);
712 GNUNET_free(pathbuf);
713 return NULL;
714 }
715 else
716 LOG(GNUNET_ERROR_TYPE_DEBUG, "Found `%s' in PATH `%s'\n", path, pathbuf);
717 GNUNET_free(pathbuf);
718 GNUNET_free(non_const_filename);
719
720 /* Count the number of arguments */
721 arg = (char **)argv;
722 while (*arg)
723 {
724 arg++;
725 argcount++;
726 }
727
728 /* Allocate a copy argv */
729 non_const_argv = GNUNET_malloc(sizeof(char *) * (argcount + 1));
730
731 /* Copy all argv strings */
732 argcount = 0;
733 arg = (char **)argv;
734 while (*arg)
735 {
736 if (arg == argv)
737 non_const_argv[argcount] = GNUNET_strdup(path);
738 else
739 non_const_argv[argcount] = GNUNET_strdup(*arg);
740 arg++;
741 argcount++;
742 }
743 non_const_argv[argcount] = NULL;
744
745 /* Count cmd len */
746 cmdlen = 1;
747 arg = non_const_argv;
748 while (*arg)
749 {
750 cmdlen = cmdlen + strlen(*arg) + 4;
751 arg++;
752 }
753
754 /* Allocate and create cmd */
755 cmd = idx = GNUNET_malloc(sizeof(char) * cmdlen);
756 arg = non_const_argv;
757 while (*arg)
758 {
759 char arg_last_char = (*arg)[strlen(*arg) - 1];
760 idx += sprintf(idx,
761 "\"%s%s\"%s",
762 *arg,
763 arg_last_char == '\\' ? "\\" : "",
764 *(arg + 1) ? " " : "");
765 arg++;
766 }
767
768 while (argcount > 0)
769 GNUNET_free(non_const_argv[--argcount]);
770 GNUNET_free(non_const_argv);
771
772 memset(&start, 0, sizeof(start));
773 start.cb = sizeof(start);
774 if ((pipe_stdin != NULL) || (pipe_stdout != NULL) || (std_inheritance != 0))
775 start.dwFlags |= STARTF_USESTDHANDLES;
776
777 stdih = GetStdHandle(STD_INPUT_HANDLE);
778 GetHandleInformation(stdih, &stdif);
779 if (pipe_stdin != NULL)
780 {
781 GNUNET_DISK_internal_file_handle_(
782 GNUNET_DISK_pipe_handle(pipe_stdin, GNUNET_DISK_PIPE_END_READ),
783 &stdin_handle,
784 sizeof(HANDLE));
785 start.hStdInput = stdin_handle;
786 }
787 else if (stdih)
788 {
789 if (std_inheritance & GNUNET_OS_INHERIT_STD_IN)
790 {
791 SetHandleInformation(stdih, HANDLE_FLAG_INHERIT, 1);
792 if (pipe_stdin == NULL)
793 start.hStdInput = stdih;
794 }
795 else
796 SetHandleInformation(stdih, HANDLE_FLAG_INHERIT, 0);
797 }
798
799
800 stdoh = GetStdHandle(STD_OUTPUT_HANDLE);
801 GetHandleInformation(stdoh, &stdof);
802 if (NULL != pipe_stdout)
803 {
804 GNUNET_DISK_internal_file_handle_(
805 GNUNET_DISK_pipe_handle(pipe_stdout, GNUNET_DISK_PIPE_END_WRITE),
806 &stdout_handle,
807 sizeof(HANDLE));
808 start.hStdOutput = stdout_handle;
809 }
810 else if (stdoh)
811 {
812 if (std_inheritance & GNUNET_OS_INHERIT_STD_OUT)
813 {
814 SetHandleInformation(stdoh, HANDLE_FLAG_INHERIT, 1);
815 if (pipe_stdout == NULL)
816 start.hStdOutput = stdoh;
817 }
818 else
819 SetHandleInformation(stdoh, HANDLE_FLAG_INHERIT, 0);
820 }
821
822 stdeh = GetStdHandle(STD_ERROR_HANDLE);
823 GetHandleInformation(stdeh, &stdef);
824 if (stdeh)
825 {
826 if (std_inheritance & GNUNET_OS_INHERIT_STD_ERR)
827 {
828 SetHandleInformation(stdeh, HANDLE_FLAG_INHERIT, 1);
829 start.hStdError = stdeh;
830 }
831 else
832 SetHandleInformation(stdeh, HANDLE_FLAG_INHERIT, 0);
833 }
834
835 if (GNUNET_YES == pipe_control)
836 {
837 struct GNUNET_DISK_PipeHandle *childpipe;
838 childpipe = GNUNET_DISK_pipe(GNUNET_NO, GNUNET_NO, GNUNET_YES, GNUNET_NO);
839 if (NULL == childpipe)
840 return NULL;
841 childpipe_read =
842 GNUNET_DISK_pipe_detach_end(childpipe, GNUNET_DISK_PIPE_END_READ);
843 childpipe_write =
844 GNUNET_DISK_pipe_detach_end(childpipe, GNUNET_DISK_PIPE_END_WRITE);
845 GNUNET_DISK_pipe_close(childpipe);
846 if ((NULL == childpipe_read) || (NULL == childpipe_write) ||
847 (GNUNET_OK != GNUNET_DISK_internal_file_handle_(childpipe_read,
848 &childpipe_read_handle,
849 sizeof(HANDLE))))
850 {
851 if (childpipe_read)
852 GNUNET_DISK_file_close(childpipe_read);
853 if (childpipe_write)
854 GNUNET_DISK_file_close(childpipe_write);
855 GNUNET_free(cmd);
856 return NULL;
857 }
858 /* Unlike *nix variant, we don't dup the handle, so can't close
859 * filehandle right now.
860 */
861 SetHandleInformation(childpipe_read_handle, HANDLE_FLAG_INHERIT, 1);
862 }
863 else
864 {
865 childpipe_read = NULL;
866 childpipe_write = NULL;
867 }
868
869 if (lsocks != NULL && lsocks[0] != INVALID_SOCKET)
870 {
871 lsocks_pipe =
872 GNUNET_DISK_pipe(GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO);
873
874 if (lsocks_pipe == NULL)
875 {
876 GNUNET_free(cmd);
877 GNUNET_DISK_pipe_close(lsocks_pipe);
878 if (GNUNET_YES == pipe_control)
879 {
880 GNUNET_DISK_file_close(childpipe_write);
881 GNUNET_DISK_file_close(childpipe_read);
882 }
883 return NULL;
884 }
885 lsocks_write_fd =
886 GNUNET_DISK_pipe_handle(lsocks_pipe, GNUNET_DISK_PIPE_END_WRITE);
887 GNUNET_DISK_internal_file_handle_(lsocks_write_fd,
888 &lsocks_write,
889 sizeof(HANDLE));
890 GNUNET_DISK_internal_file_handle_(
891 GNUNET_DISK_pipe_handle(lsocks_pipe, GNUNET_DISK_PIPE_END_READ),
892 &lsocks_read,
893 sizeof(HANDLE));
894 }
895 else
896 {
897 lsocks_pipe = NULL;
898 lsocks_write_fd = NULL;
899 }
900
901 env_off = 0;
902 if (GNUNET_YES == pipe_control)
903 {
904 GNUNET_asprintf(&our_env[env_off++], "%s=", GNUNET_OS_CONTROL_PIPE);
905 GNUNET_asprintf(&our_env[env_off++], "%p", childpipe_read_handle);
906 }
907 if ((lsocks != NULL) && (lsocks[0] != INVALID_SOCKET))
908 {
909 /*This will tell the child that we're going to send lsocks over the pipe*/
910 GNUNET_asprintf(&our_env[env_off++], "%s=", "GNUNET_OS_READ_LSOCKS");
911 GNUNET_asprintf(&our_env[env_off++], "%lu", lsocks_read);
912 }
913 our_env[env_off++] = NULL;
914 env_block = CreateCustomEnvTable(our_env);
915 while (0 > env_off)
916 GNUNET_free_non_null(our_env[--env_off]);
917
918 wpath_len = 0;
919 if (NULL ==
920 (wpath =
921 u8_to_u16((uint8_t *)path, 1 + strlen(path), NULL, &wpath_len)))
922 {
923 LOG(GNUNET_ERROR_TYPE_DEBUG,
924 "Failed to convert `%s' from UTF-8 to UTF-16: %d\n",
925 path,
926 errno);
927 GNUNET_free(env_block);
928 GNUNET_free(cmd);
929 if (lsocks_pipe)
930 GNUNET_DISK_pipe_close(lsocks_pipe);
931 if (GNUNET_YES == pipe_control)
932 {
933 GNUNET_DISK_file_close(childpipe_write);
934 GNUNET_DISK_file_close(childpipe_read);
935 }
936 return NULL;
937 }
938
939 wcmd_len = 0;
940 if (NULL ==
941 (wcmd = u8_to_u16((uint8_t *)cmd, 1 + strlen(cmd), NULL, &wcmd_len)))
942 {
943 LOG(GNUNET_ERROR_TYPE_DEBUG,
944 "Failed to convert `%s' from UTF-8 to UTF-16: %d\n",
945 cmd,
946 errno);
947 GNUNET_free(env_block);
948 GNUNET_free(cmd);
949 free(wpath);
950 if (lsocks_pipe)
951 GNUNET_DISK_pipe_close(lsocks_pipe);
952 if (GNUNET_YES == pipe_control)
953 {
954 GNUNET_DISK_file_close(childpipe_write);
955 GNUNET_DISK_file_close(childpipe_read);
956 }
957 return NULL;
958 }
959
960 create_no_window = 0;
961 {
962 HANDLE console_input = CreateFile("CONIN$",
963 GENERIC_READ,
964 FILE_SHARE_READ | FILE_SHARE_WRITE,
965 NULL,
966 OPEN_EXISTING,
967 0,
968 NULL);
969 if (INVALID_HANDLE_VALUE == console_input)
970 create_no_window = CREATE_NO_WINDOW;
971 else
972 CloseHandle(console_input);
973 }
974
975 bresult = CreateProcessW(wpath,
976 wcmd,
977 NULL,
978 NULL,
979 GNUNET_YES,
980 create_no_window | CREATE_SUSPENDED,
981 env_block,
982 NULL,
983 &start,
984 &proc);
985 error_code = GetLastError();
986
987 if ((NULL == pipe_stdin) && (stdih))
988 SetHandleInformation(stdih, HANDLE_FLAG_INHERIT, stdif);
989
990
991 if ((NULL == pipe_stdout) && (stdoh))
992 SetHandleInformation(stdoh, HANDLE_FLAG_INHERIT, stdof);
993
994 if (stdeh)
995 SetHandleInformation(stdeh, HANDLE_FLAG_INHERIT, stdef);
996
997 if (!bresult)
998 LOG(GNUNET_ERROR_TYPE_ERROR,
999 "CreateProcess(%s, %s) failed: %lu\n",
1000 path,
1001 cmd,
1002 error_code);
1003
1004 GNUNET_free(env_block);
1005 GNUNET_free(cmd);
1006 free(wpath);
1007 free(wcmd);
1008 if (GNUNET_YES == pipe_control)
1009 {
1010 GNUNET_DISK_file_close(childpipe_read);
1011 }
1012
1013 if (!bresult)
1014 {
1015 if (GNUNET_YES == pipe_control)
1016 {
1017 GNUNET_DISK_file_close(childpipe_write);
1018 }
1019 if (NULL != lsocks)
1020 GNUNET_DISK_pipe_close(lsocks_pipe);
1021 SetErrnoFromWinError(error_code);
1022 return NULL;
1023 }
1024
1025 gnunet_proc = GNUNET_new(struct GNUNET_OS_Process);
1026 gnunet_proc->pid = proc.dwProcessId;
1027 gnunet_proc->handle = proc.hProcess;
1028 gnunet_proc->control_pipe = childpipe_write;
1029
1030 CreateThread(NULL, 64000, &child_wait_thread, (void *)gnunet_proc, 0, NULL);
1031
1032 ResumeThread(proc.hThread);
1033 CloseHandle(proc.hThread);
1034
1035 if ((NULL == lsocks) || (INVALID_SOCKET == lsocks[0]))
1036 return gnunet_proc;
1037
1038 GNUNET_DISK_pipe_close_end(lsocks_pipe, GNUNET_DISK_PIPE_END_READ);
1039
1040 /* This is a replacement for "goto error" that doesn't use goto */
1041 fail = 1;
1042 do
1043 {
1044 ssize_t wrote;
1045 uint64_t size;
1046 uint64_t count;
1047 unsigned int i;
1048
1049 /* Tell the number of sockets */
1050 for (count = 0; lsocks && lsocks[count] != INVALID_SOCKET; count++)
1051 ;
1052
1053 wrote = GNUNET_DISK_file_write(lsocks_write_fd, &count, sizeof(count));
1054 if (sizeof(count) != wrote)
1055 {
1056 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1057 "Failed to write %u count bytes to the child: %lu\n",
1058 sizeof(count),
1059 GetLastError());
1060 break;
1061 }
1062 for (i = 0; lsocks && lsocks[i] != INVALID_SOCKET; i++)
1063 {
1064 WSAPROTOCOL_INFOA pi;
1065 /* Get a socket duplication info */
1066 if (SOCKET_ERROR ==
1067 WSADuplicateSocketA(lsocks[i], gnunet_proc->pid, &pi))
1068 {
1069 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1070 "Failed to duplicate an socket[%u]: %lu\n",
1071 i,
1072 GetLastError());
1073 break;
1074 }
1075 /* Synchronous I/O is not nice, but we can't schedule this:
1076 * lsocks will be closed/freed by the caller soon, and until
1077 * the child creates a duplicate, closing a socket here will
1078 * close it for good.
1079 */
1080 /* Send the size of the structure
1081 * (the child might be built with different headers...)
1082 */
1083 size = sizeof(pi);
1084 wrote = GNUNET_DISK_file_write(lsocks_write_fd, &size, sizeof(size));
1085 if (sizeof(size) != wrote)
1086 {
1087 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1088 "Failed to write %u size[%u] bytes to the child: %lu\n",
1089 sizeof(size),
1090 i,
1091 GetLastError());
1092 break;
1093 }
1094 /* Finally! Send the data */
1095 wrote = GNUNET_DISK_file_write(lsocks_write_fd, &pi, sizeof(pi));
1096 if (sizeof(pi) != wrote)
1097 {
1098 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1099 "Failed to write %u socket[%u] bytes to the child: %lu\n",
1100 sizeof(pi),
1101 i,
1102 GetLastError());
1103 break;
1104 }
1105 }
1106 /* This will block us until the child makes a final read or closes
1107 * the pipe (hence no 'wrote' check), since we have to wait for it
1108 * to duplicate the last socket, before we return and start closing
1109 * our own copies)
1110 */
1111 wrote = GNUNET_DISK_file_write(lsocks_write_fd, &count, sizeof(count));
1112 fail = 0;
1113 }
1114 while (fail);
1115
1116 GNUNET_DISK_file_sync(lsocks_write_fd);
1117 GNUNET_DISK_pipe_close(lsocks_pipe);
1118
1119 if (fail)
1120 {
1121 /* If we can't pass on the socket(s), the child will block forever,
1122 * better put it out of its misery.
1123 */
1124 SafeTerminateProcess(gnunet_proc->handle, 0, 0);
1125 CloseHandle(gnunet_proc->handle);
1126 if (NULL != gnunet_proc->control_pipe)
1127 GNUNET_DISK_file_close(gnunet_proc->control_pipe);
1128 GNUNET_free(gnunet_proc);
1129 return NULL;
1130 }
1131 return gnunet_proc;
1132#endif
1133} 591}
1134 592
1135 593
@@ -1439,7 +897,6 @@ process_status(struct GNUNET_OS_Process *proc,
1439 unsigned long *code, 897 unsigned long *code,
1440 int options) 898 int options)
1441{ 899{
1442#ifndef MINGW
1443 int status; 900 int status;
1444 int ret; 901 int ret;
1445 902
@@ -1488,53 +945,6 @@ process_status(struct GNUNET_OS_Process *proc,
1488 *type = GNUNET_OS_PROCESS_UNKNOWN; 945 *type = GNUNET_OS_PROCESS_UNKNOWN;
1489 *code = 0; 946 *code = 0;
1490 } 947 }
1491#else
1492#ifndef WNOHANG
1493#define WNOHANG 42 /* just a flag for W32, purely internal at this point */
1494#endif
1495
1496 HANDLE h;
1497 DWORD c, error_code, ret;
1498
1499 h = proc->handle;
1500 ret = proc->pid;
1501 if (h == NULL || ret == 0)
1502 {
1503 LOG(GNUNET_ERROR_TYPE_WARNING,
1504 "Invalid process information {%d, %08X}\n",
1505 ret,
1506 h);
1507 return GNUNET_SYSERR;
1508 }
1509 if (h == NULL)
1510 h = GetCurrentProcess();
1511
1512 if (WNOHANG != options)
1513 {
1514 if (WAIT_OBJECT_0 != WaitForSingleObject(h, INFINITE))
1515 {
1516 SetErrnoFromWinError(GetLastError());
1517 return GNUNET_SYSERR;
1518 }
1519 }
1520 SetLastError(0);
1521 ret = GetExitCodeProcess(h, &c);
1522 error_code = GetLastError();
1523 if (ret == 0 || error_code != NO_ERROR)
1524 {
1525 SetErrnoFromWinError(error_code);
1526 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING, "GetExitCodeProcess");
1527 return GNUNET_SYSERR;
1528 }
1529 if (STILL_ACTIVE == c)
1530 {
1531 *type = GNUNET_OS_PROCESS_RUNNING;
1532 *code = 0;
1533 return GNUNET_NO;
1534 }
1535 *type = GNUNET_OS_PROCESS_EXITED;
1536 *code = c;
1537#endif
1538 948
1539 return GNUNET_OK; 949 return GNUNET_OK;
1540} 950}
@@ -1589,7 +999,6 @@ GNUNET_OS_process_wait_status(struct GNUNET_OS_Process *proc,
1589int 999int
1590GNUNET_OS_process_wait(struct GNUNET_OS_Process *proc) 1000GNUNET_OS_process_wait(struct GNUNET_OS_Process *proc)
1591{ 1001{
1592#ifndef MINGW
1593 pid_t pid = proc->pid; 1002 pid_t pid = proc->pid;
1594 pid_t ret; 1003 pid_t ret;
1595 1004
@@ -1601,28 +1010,6 @@ GNUNET_OS_process_wait(struct GNUNET_OS_Process *proc)
1601 return GNUNET_SYSERR; 1010 return GNUNET_SYSERR;
1602 } 1011 }
1603 return GNUNET_OK; 1012 return GNUNET_OK;
1604#else
1605 HANDLE h;
1606
1607 h = proc->handle;
1608 if (NULL == h)
1609 {
1610 LOG(GNUNET_ERROR_TYPE_WARNING,
1611 "Invalid process information {%d, %08X}\n",
1612 proc->pid,
1613 h);
1614 return GNUNET_SYSERR;
1615 }
1616 if (NULL == h)
1617 h = GetCurrentProcess();
1618
1619 if (WAIT_OBJECT_0 != WaitForSingleObject(h, INFINITE))
1620 {
1621 SetErrnoFromWinError(GetLastError());
1622 return GNUNET_SYSERR;
1623 }
1624 return GNUNET_OK;
1625#endif
1626} 1013}
1627 1014
1628 1015
diff --git a/src/util/scheduler.c b/src/util/scheduler.c
index 4bea5bd5d..f379bce42 100644
--- a/src/util/scheduler.c
+++ b/src/util/scheduler.c
@@ -108,7 +108,6 @@ struct GNUNET_SCHEDULER_Handle {
108 struct GNUNET_SIGNAL_Context *shc_gterm; 108 struct GNUNET_SIGNAL_Context *shc_gterm;
109#endif 109#endif
110 110
111#ifndef MINGW
112 /** 111 /**
113 * context of the SIGQUIT handler 112 * context of the SIGQUIT handler
114 */ 113 */
@@ -123,7 +122,6 @@ struct GNUNET_SCHEDULER_Handle {
123 * context of hte SIGPIPE handler 122 * context of hte SIGPIPE handler
124 */ 123 */
125 struct GNUNET_SIGNAL_Context *shc_pipe; 124 struct GNUNET_SIGNAL_Context *shc_pipe;
126#endif
127}; 125};
128 126
129 127
@@ -621,13 +619,11 @@ static pid_t my_pid;
621/** 619/**
622 * Signal handler called for SIGPIPE. 620 * Signal handler called for SIGPIPE.
623 */ 621 */
624#ifndef MINGW
625static void 622static void
626sighandler_pipe() 623sighandler_pipe()
627{ 624{
628 return; 625 return;
629} 626}
630#endif
631 627
632 628
633///** 629///**
@@ -1396,7 +1392,6 @@ check_fd(struct GNUNET_SCHEDULER_Task *t, int raw_fd)
1396 * @return unique task identifier for the job 1392 * @return unique task identifier for the job
1397 * only valid until @a task is started! 1393 * only valid until @a task is started!
1398 */ 1394 */
1399#ifndef MINGW
1400static struct GNUNET_SCHEDULER_Task * 1395static struct GNUNET_SCHEDULER_Task *
1401add_without_sets(struct GNUNET_TIME_Relative delay, 1396add_without_sets(struct GNUNET_TIME_Relative delay,
1402 enum GNUNET_SCHEDULER_Priority priority, 1397 enum GNUNET_SCHEDULER_Priority priority,
@@ -1446,7 +1441,6 @@ add_without_sets(struct GNUNET_TIME_Relative delay,
1446 init_backtrace(t); 1441 init_backtrace(t);
1447 return t; 1442 return t;
1448} 1443}
1449#endif
1450 1444
1451 1445
1452/** 1446/**
@@ -1586,22 +1580,6 @@ GNUNET_SCHEDULER_add_net_with_priority(struct GNUNET_TIME_Relative delay,
1586{ 1580{
1587 /* scheduler must be running */ 1581 /* scheduler must be running */
1588 GNUNET_assert(NULL != scheduler_driver); 1582 GNUNET_assert(NULL != scheduler_driver);
1589
1590#if MINGW
1591 struct GNUNET_NETWORK_FDSet *s;
1592 struct GNUNET_SCHEDULER_Task * ret;
1593
1594 GNUNET_assert(NULL != fd);
1595 s = GNUNET_NETWORK_fdset_create();
1596 GNUNET_NETWORK_fdset_set(s, fd);
1597 ret = GNUNET_SCHEDULER_add_select(
1598 priority, delay,
1599 on_read ? s : NULL,
1600 on_write ? s : NULL,
1601 task, task_cls);
1602 GNUNET_NETWORK_fdset_destroy(s);
1603 return ret;
1604#else
1605 GNUNET_assert(on_read || on_write); 1583 GNUNET_assert(on_read || on_write);
1606 GNUNET_assert(GNUNET_NETWORK_get_fd(fd) >= 0); 1584 GNUNET_assert(GNUNET_NETWORK_get_fd(fd) >= 0);
1607 return add_without_sets(delay, priority, 1585 return add_without_sets(delay, priority,
@@ -1610,7 +1588,6 @@ GNUNET_SCHEDULER_add_net_with_priority(struct GNUNET_TIME_Relative delay,
1610 NULL, 1588 NULL,
1611 NULL, 1589 NULL,
1612 task, task_cls); 1590 task, task_cls);
1613#endif
1614} 1591}
1615 1592
1616 1593
@@ -1710,22 +1687,6 @@ GNUNET_SCHEDULER_add_file_with_priority(struct GNUNET_TIME_Relative delay,
1710{ 1687{
1711 /* scheduler must be running */ 1688 /* scheduler must be running */
1712 GNUNET_assert(NULL != scheduler_driver); 1689 GNUNET_assert(NULL != scheduler_driver);
1713
1714#if MINGW
1715 struct GNUNET_NETWORK_FDSet *s;
1716 struct GNUNET_SCHEDULER_Task * ret;
1717
1718 GNUNET_assert(NULL != fd);
1719 s = GNUNET_NETWORK_fdset_create();
1720 GNUNET_NETWORK_fdset_handle_set(s, fd);
1721 ret = GNUNET_SCHEDULER_add_select(
1722 priority, delay,
1723 on_read ? s : NULL,
1724 on_write ? s : NULL,
1725 task, task_cls);
1726 GNUNET_NETWORK_fdset_destroy(s);
1727 return ret;
1728#else
1729 GNUNET_assert(on_read || on_write); 1690 GNUNET_assert(on_read || on_write);
1730 GNUNET_assert(fd->fd >= 0); 1691 GNUNET_assert(fd->fd >= 0);
1731 return add_without_sets(delay, priority, 1692 return add_without_sets(delay, priority,
@@ -1734,7 +1695,6 @@ GNUNET_SCHEDULER_add_file_with_priority(struct GNUNET_TIME_Relative delay,
1734 on_read ? fd : NULL, 1695 on_read ? fd : NULL,
1735 on_write ? fd : NULL, 1696 on_write ? fd : NULL,
1736 task, task_cls); 1697 task, task_cls);
1737#endif
1738} 1698}
1739 1699
1740 1700
@@ -2218,14 +2178,12 @@ GNUNET_SCHEDULER_driver_init(const struct GNUNET_SCHEDULER_Driver *driver)
2218 sh->shc_gterm = GNUNET_SIGNAL_handler_install(GNUNET_TERM_SIG, 2178 sh->shc_gterm = GNUNET_SIGNAL_handler_install(GNUNET_TERM_SIG,
2219 &sighandler_shutdown); 2179 &sighandler_shutdown);
2220#endif 2180#endif
2221#ifndef MINGW
2222 sh->shc_pipe = GNUNET_SIGNAL_handler_install(SIGPIPE, 2181 sh->shc_pipe = GNUNET_SIGNAL_handler_install(SIGPIPE,
2223 &sighandler_pipe); 2182 &sighandler_pipe);
2224 sh->shc_quit = GNUNET_SIGNAL_handler_install(SIGQUIT, 2183 sh->shc_quit = GNUNET_SIGNAL_handler_install(SIGQUIT,
2225 &sighandler_shutdown); 2184 &sighandler_shutdown);
2226 sh->shc_hup = GNUNET_SIGNAL_handler_install(SIGHUP, 2185 sh->shc_hup = GNUNET_SIGNAL_handler_install(SIGHUP,
2227 &sighandler_shutdown); 2186 &sighandler_shutdown);
2228#endif
2229 2187
2230 /* Setup initial tasks */ 2188 /* Setup initial tasks */
2231 current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT; 2189 current_priority = GNUNET_SCHEDULER_PRIORITY_DEFAULT;
@@ -2282,11 +2240,9 @@ GNUNET_SCHEDULER_driver_done(struct GNUNET_SCHEDULER_Handle *sh)
2282#if (SIGTERM != GNUNET_TERM_SIG) 2240#if (SIGTERM != GNUNET_TERM_SIG)
2283 GNUNET_SIGNAL_handler_uninstall(sh->shc_gterm); 2241 GNUNET_SIGNAL_handler_uninstall(sh->shc_gterm);
2284#endif 2242#endif
2285#ifndef MINGW
2286 GNUNET_SIGNAL_handler_uninstall(sh->shc_pipe); 2243 GNUNET_SIGNAL_handler_uninstall(sh->shc_pipe);
2287 GNUNET_SIGNAL_handler_uninstall(sh->shc_quit); 2244 GNUNET_SIGNAL_handler_uninstall(sh->shc_quit);
2288 GNUNET_SIGNAL_handler_uninstall(sh->shc_hup); 2245 GNUNET_SIGNAL_handler_uninstall(sh->shc_hup);
2289#endif
2290 GNUNET_DISK_pipe_close(shutdown_pipe_handle); 2246 GNUNET_DISK_pipe_close(shutdown_pipe_handle);
2291 shutdown_pipe_handle = NULL; 2247 shutdown_pipe_handle = NULL;
2292 scheduler_driver = NULL; 2248 scheduler_driver = NULL;
@@ -2352,7 +2308,6 @@ select_loop(struct GNUNET_SCHEDULER_Handle *sh,
2352 2308
2353 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, 2309 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR,
2354 "select"); 2310 "select");
2355#ifndef MINGW
2356#if USE_LSOF 2311#if USE_LSOF
2357 char lsof[512]; 2312 char lsof[512];
2358 2313
@@ -2366,7 +2321,6 @@ select_loop(struct GNUNET_SCHEDULER_Handle *sh,
2366 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING, 2321 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING,
2367 "system"); 2322 "system");
2368#endif 2323#endif
2369#endif
2370#if DEBUG_FDS 2324#if DEBUG_FDS
2371 for (struct Scheduled *s = context->scheduled_head; 2325 for (struct Scheduled *s = context->scheduled_head;
2372 NULL != s; 2326 NULL != s;
diff --git a/src/util/service.c b/src/util/service.c
index 880047a42..b0f4ea289 100644
--- a/src/util/service.c
+++ b/src/util/service.c
@@ -1354,93 +1354,6 @@ get_server_addresses(const char *service_name,
1354} 1354}
1355 1355
1356 1356
1357#ifdef MINGW
1358/**
1359 * Read listen sockets from the parent process (ARM).
1360 *
1361 * @param sh service context to initialize
1362 * @return NULL-terminated array of sockets on success,
1363 * NULL if not ok (must bind yourself)
1364 */
1365static struct GNUNET_NETWORK_Handle **
1366receive_sockets_from_parent(struct GNUNET_SERVICE_Handle *sh)
1367{
1368 static struct GNUNET_NETWORK_Handle **lsocks;
1369 const char *env_buf;
1370 int fail;
1371 uint64_t count;
1372 uint64_t i;
1373 HANDLE lsocks_pipe;
1374
1375 env_buf = getenv("GNUNET_OS_READ_LSOCKS");
1376 if ((NULL == env_buf) || (strlen(env_buf) <= 0))
1377 return NULL;
1378 /* Using W32 API directly here, because this pipe will
1379 * never be used outside of this function, and it's just too much of a bother
1380 * to create a GNUnet API that boxes a HANDLE (the way it is done with socks)
1381 */
1382 lsocks_pipe = (HANDLE)strtoul(env_buf, NULL, 10);
1383 if ((0 == lsocks_pipe) || (INVALID_HANDLE_VALUE == lsocks_pipe))
1384 return NULL;
1385 fail = 1;
1386 do
1387 {
1388 int ret;
1389 int fail2;
1390 DWORD rd;
1391
1392 ret = ReadFile(lsocks_pipe, &count, sizeof(count), &rd, NULL);
1393 if ((0 == ret) || (sizeof(count) != rd) || (0 == count))
1394 break;
1395 lsocks = GNUNET_new_array(count + 1, struct GNUNET_NETWORK_Handle *);
1396
1397 fail2 = 1;
1398 for (i = 0; i < count; i++)
1399 {
1400 WSAPROTOCOL_INFOA pi;
1401 uint64_t size;
1402 _win_socket s;
1403
1404 ret = ReadFile(lsocks_pipe, &size, sizeof(size), &rd, NULL);
1405 if ((0 == ret) || (sizeof(size) != rd) || (sizeof(pi) != size))
1406 break;
1407 ret = ReadFile(lsocks_pipe, &pi, sizeof(pi), &rd, NULL);
1408 if ((0 == ret) || (sizeof(pi) != rd))
1409 break;
1410 s = WSASocketA(pi.iAddressFamily,
1411 pi.iSocketType,
1412 pi.iProtocol,
1413 &pi,
1414 0,
1415 WSA_FLAG_OVERLAPPED);
1416 lsocks[i] = GNUNET_NETWORK_socket_box_native(s);
1417 if (NULL == lsocks[i])
1418 break;
1419 else if (i == count - 1)
1420 fail2 = 0;
1421 }
1422 if (fail2)
1423 break;
1424 lsocks[count] = NULL;
1425 fail = 0;
1426 }
1427 while (fail);
1428 CloseHandle(lsocks_pipe);
1429
1430 if (fail)
1431 {
1432 LOG(GNUNET_ERROR_TYPE_ERROR,
1433 _("Could not access a pre-bound socket, will try to bind myself\n"));
1434 for (i = 0; (i < count) && (NULL != lsocks[i]); i++)
1435 GNUNET_break(GNUNET_OK == GNUNET_NETWORK_socket_close(lsocks[i]));
1436 GNUNET_free(lsocks);
1437 return NULL;
1438 }
1439 return lsocks;
1440}
1441#endif
1442
1443
1444/** 1357/**
1445 * Create and initialize a listen socket for the server. 1358 * Create and initialize a listen socket for the server.
1446 * 1359 *
@@ -1557,13 +1470,10 @@ setup_service(struct GNUNET_SERVICE_Handle *sh)
1557{ 1470{
1558 int tolerant; 1471 int tolerant;
1559 struct GNUNET_NETWORK_Handle **lsocks; 1472 struct GNUNET_NETWORK_Handle **lsocks;
1560
1561#ifndef MINGW
1562 const char *nfds; 1473 const char *nfds;
1563 unsigned int cnt; 1474 unsigned int cnt;
1564 int flags; 1475 int flags;
1565 char dummy[2]; 1476 char dummy[2];
1566#endif
1567 1477
1568 if (GNUNET_CONFIGURATION_have_value(sh->cfg, sh->service_name, "TOLERANT")) 1478 if (GNUNET_CONFIGURATION_have_value(sh->cfg, sh->service_name, "TOLERANT"))
1569 { 1479 {
@@ -1583,7 +1493,7 @@ setup_service(struct GNUNET_SERVICE_Handle *sh)
1583 tolerant = GNUNET_NO; 1493 tolerant = GNUNET_NO;
1584 1494
1585 lsocks = NULL; 1495 lsocks = NULL;
1586#ifndef MINGW 1496
1587 errno = 0; 1497 errno = 0;
1588 if ((NULL != (nfds = getenv("LISTEN_FDS"))) && 1498 if ((NULL != (nfds = getenv("LISTEN_FDS"))) &&
1589 (1 == sscanf(nfds, "%u%1s", &cnt, dummy)) && (cnt > 0) && 1499 (1 == sscanf(nfds, "%u%1s", &cnt, dummy)) && (cnt > 0) &&
@@ -1611,13 +1521,6 @@ setup_service(struct GNUNET_SERVICE_Handle *sh)
1611 } 1521 }
1612 unsetenv("LISTEN_FDS"); 1522 unsetenv("LISTEN_FDS");
1613 } 1523 }
1614#else
1615 if (NULL != getenv("GNUNET_OS_READ_LSOCKS"))
1616 {
1617 lsocks = receive_sockets_from_parent(sh);
1618 putenv("GNUNET_OS_READ_LSOCKS=");
1619 }
1620#endif
1621 1524
1622 if (NULL != lsocks) 1525 if (NULL != lsocks)
1623 { 1526 {
@@ -1723,7 +1626,7 @@ set_user_id(struct GNUNET_SERVICE_Handle *sh)
1723 1626
1724 if (NULL == (user = get_user_name(sh))) 1627 if (NULL == (user = get_user_name(sh)))
1725 return GNUNET_OK; /* keep */ 1628 return GNUNET_OK; /* keep */
1726#ifndef MINGW 1629
1727 struct passwd *pws; 1630 struct passwd *pws;
1728 1631
1729 errno = 0; 1632 errno = 0;
@@ -1754,7 +1657,7 @@ set_user_id(struct GNUNET_SERVICE_Handle *sh)
1754 return GNUNET_SYSERR; 1657 return GNUNET_SYSERR;
1755 } 1658 }
1756 } 1659 }
1757#endif 1660
1758 GNUNET_free(user); 1661 GNUNET_free(user);
1759 return GNUNET_OK; 1662 return GNUNET_OK;
1760} 1663}
@@ -1808,7 +1711,6 @@ pid_file_delete(struct GNUNET_SERVICE_Handle *sh)
1808static int 1711static int
1809detach_terminal(struct GNUNET_SERVICE_Handle *sh) 1712detach_terminal(struct GNUNET_SERVICE_Handle *sh)
1810{ 1713{
1811#ifndef MINGW
1812 pid_t pid; 1714 pid_t pid;
1813 int nullfd; 1715 int nullfd;
1814 int filedes[2]; 1716 int filedes[2];
@@ -1875,11 +1777,7 @@ detach_terminal(struct GNUNET_SERVICE_Handle *sh)
1875 if (-1 == pid) 1777 if (-1 == pid)
1876 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, "setsid"); 1778 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, "setsid");
1877 sh->ready_confirm_fd = filedes[1]; 1779 sh->ready_confirm_fd = filedes[1];
1878#else 1780
1879 /* FIXME: we probably need to do something else
1880 * elsewhere in order to fork the process itself... */
1881 FreeConsole();
1882#endif
1883 return GNUNET_OK; 1781 return GNUNET_OK;
1884} 1782}
1885 1783
diff --git a/src/util/strings.c b/src/util/strings.c
index dc46ad33a..25b09f8e2 100644
--- a/src/util/strings.c
+++ b/src/util/strings.c
@@ -602,20 +602,13 @@ char *
602GNUNET_STRINGS_filename_expand(const char *fil) 602GNUNET_STRINGS_filename_expand(const char *fil)
603{ 603{
604 char *buffer; 604 char *buffer;
605
606#ifndef MINGW
607 size_t len; 605 size_t len;
608 char *fm; 606 char *fm;
609 const char *fil_ptr; 607 const char *fil_ptr;
610#else
611 char *fn;
612 long lRet;
613#endif
614 608
615 if (fil == NULL) 609 if (fil == NULL)
616 return NULL; 610 return NULL;
617 611
618#ifndef MINGW
619 if (fil[0] == DIR_SEPARATOR) 612 if (fil[0] == DIR_SEPARATOR)
620 /* absolute path, just copy */ 613 /* absolute path, just copy */
621 return GNUNET_strdup(fil); 614 return GNUNET_strdup(fil);
@@ -677,34 +670,6 @@ GNUNET_STRINGS_filename_expand(const char *fil)
677 fil_ptr); 670 fil_ptr);
678 GNUNET_free(fm); 671 GNUNET_free(fm);
679 return buffer; 672 return buffer;
680#else
681 fn = GNUNET_malloc(MAX_PATH + 1);
682
683 if ((lRet = plibc_conv_to_win_path(fil, fn)) != ERROR_SUCCESS)
684 {
685 SetErrnoFromWinError(lRet);
686 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING, "plibc_conv_to_win_path");
687 return NULL;
688 }
689 /* is the path relative? */
690 if ((0 != strncmp(fn + 1, ":\\", 2)) && (0 != strncmp(fn, "\\\\", 2)))
691 {
692 char szCurDir[MAX_PATH + 1];
693
694 lRet = GetCurrentDirectory(MAX_PATH + 1, szCurDir);
695 if (lRet + strlen(fn) + 1 > (MAX_PATH + 1))
696 {
697 SetErrnoFromWinError(ERROR_BUFFER_OVERFLOW);
698 LOG_STRERROR(GNUNET_ERROR_TYPE_WARNING, "GetCurrentDirectory");
699 return NULL;
700 }
701 GNUNET_asprintf(&buffer, "%s\\%s", szCurDir, fn);
702 GNUNET_free(fn);
703 fn = buffer;
704 }
705
706 return fn;
707#endif
708} 673}
709 674
710 675
diff --git a/src/util/test_common_logging_runtime_loglevels.c b/src/util/test_common_logging_runtime_loglevels.c
index 07e2327c9..4ba7b544c 100644
--- a/src/util/test_common_logging_runtime_loglevels.c
+++ b/src/util/test_common_logging_runtime_loglevels.c
@@ -401,11 +401,7 @@ runone()
401 401
402 proc = GNUNET_OS_start_process(GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, 402 proc = GNUNET_OS_start_process(GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
403 NULL, pipe_stdout, NULL, 403 NULL, pipe_stdout, NULL,
404#if MINGW
405 "test_common_logging_dummy",
406#else
407 "./test_common_logging_dummy", 404 "./test_common_logging_dummy",
408#endif
409 "test_common_logging_dummy", NULL); 405 "test_common_logging_dummy", NULL);
410 GNUNET_assert(NULL != proc); 406 GNUNET_assert(NULL != proc);
411 putenv("GNUNET_FORCE_LOG="); 407 putenv("GNUNET_FORCE_LOG=");
diff --git a/src/util/test_configuration.c b/src/util/test_configuration.c
index 71a1ae5bd..b5b1e238c 100644
--- a/src/util/test_configuration.c
+++ b/src/util/test_configuration.c
@@ -323,12 +323,8 @@ testConfig()
323 GNUNET_break(0); 323 GNUNET_break(0);
324 return 8; 324 return 8;
325 } 325 }
326#ifndef MINGW 326
327 if (0 != strcmp(c, "/hello/world")) 327 if (0 != strcmp(c, "/hello/world"))
328#else
329#define HI "\\hello\\world"
330 if (strstr(c, HI) != c + strlen(c) - strlen(HI))
331#endif
332 { 328 {
333 GNUNET_break(0); 329 GNUNET_break(0);
334 GNUNET_free(c); 330 GNUNET_free(c);
diff --git a/src/util/test_getopt.c b/src/util/test_getopt.c
index 620605f96..77b8c8b2f 100644
--- a/src/util/test_getopt.c
+++ b/src/util/test_getopt.c
@@ -163,9 +163,9 @@ main(int argc, char *argv[])
163 163
164 GNUNET_log_setup("test_getopt", "WARNING", NULL); 164 GNUNET_log_setup("test_getopt", "WARNING", NULL);
165 /* suppress output from -h, -v options */ 165 /* suppress output from -h, -v options */
166#ifndef MINGW 166
167 GNUNET_break(0 == close(1)); 167 GNUNET_break(0 == close(1));
168#endif 168
169 if (0 != testMinimal()) 169 if (0 != testMinimal())
170 errCnt++; 170 errCnt++;
171 if (0 != testVerbose()) 171 if (0 != testVerbose())
diff --git a/src/util/test_resolver_api.c b/src/util/test_resolver_api.c
index ea26c4ee6..0b27a2eff 100644
--- a/src/util/test_resolver_api.c
+++ b/src/util/test_resolver_api.c
@@ -307,11 +307,8 @@ run(void *cls, char *const *args, const char *cfgfile,
307#if HAVE_SOCKADDR_IN_SIN_LEN 307#if HAVE_SOCKADDR_IN_SIN_LEN
308 sa.sin_len = (u_char)sizeof(sa); 308 sa.sin_len = (u_char)sizeof(sa);
309#endif 309#endif
310#ifndef MINGW
311 inet_aton(ROOTSERVER_IP, &sa.sin_addr); 310 inet_aton(ROOTSERVER_IP, &sa.sin_addr);
312#else 311
313 sa.sin_addr.S_un.S_addr = inet_addr(ROOTSERVER_IP);
314#endif
315 GNUNET_RESOLVER_hostname_get((const struct sockaddr *)&sa, 312 GNUNET_RESOLVER_hostname_get((const struct sockaddr *)&sa,
316 sizeof(struct sockaddr), GNUNET_YES, timeout, 313 sizeof(struct sockaddr), GNUNET_YES, timeout,
317 &check_rootserver_name, cls); 314 &check_rootserver_name, cls);
diff --git a/src/util/test_scheduler.c b/src/util/test_scheduler.c
index 236bb4e76..8952225c2 100644
--- a/src/util/test_scheduler.c
+++ b/src/util/test_scheduler.c
@@ -211,7 +211,6 @@ checkShutdown()
211} 211}
212 212
213 213
214#ifndef MINGW
215static void 214static void
216taskSig(void *cls) 215taskSig(void *cls)
217{ 216{
@@ -244,7 +243,6 @@ checkSignal()
244 GNUNET_SCHEDULER_run(&taskSig, &ok); 243 GNUNET_SCHEDULER_run(&taskSig, &ok);
245 return ok; 244 return ok;
246} 245}
247#endif
248 246
249 247
250static void 248static void
@@ -283,9 +281,7 @@ main(int argc, char *argv[])
283 GNUNET_log_setup("test_scheduler", "WARNING", NULL); 281 GNUNET_log_setup("test_scheduler", "WARNING", NULL);
284 ret += check(); 282 ret += check();
285 ret += checkCancel(); 283 ret += checkCancel();
286#ifndef MINGW
287 ret += checkSignal(); 284 ret += checkSignal();
288#endif
289 ret += checkShutdown(); 285 ret += checkShutdown();
290 GNUNET_DISK_pipe_close(p); 286 GNUNET_DISK_pipe_close(p);
291 287
diff --git a/src/util/test_service.c b/src/util/test_service.c
index c0b02872f..4edc38a0d 100644
--- a/src/util/test_service.c
+++ b/src/util/test_service.c
@@ -206,11 +206,10 @@ main(int argc,
206 NULL); 206 NULL);
207 ret += check("test_service"); 207 ret += check("test_service");
208 ret += check("test_service"); 208 ret += check("test_service");
209#ifndef MINGW
210 s = GNUNET_NETWORK_socket_create(PF_INET6, 209 s = GNUNET_NETWORK_socket_create(PF_INET6,
211 SOCK_STREAM, 210 SOCK_STREAM,
212 0); 211 0);
213#endif 212
214 if (NULL == s) 213 if (NULL == s)
215 { 214 {
216 if ((errno == ENOBUFS) || 215 if ((errno == ENOBUFS) ||
diff --git a/src/util/test_strings.c b/src/util/test_strings.c
index a4e548e31..60887c587 100644
--- a/src/util/test_strings.c
+++ b/src/util/test_strings.c
@@ -67,11 +67,9 @@ main(int argc, char *argv[])
67 (GNUNET_TIME_UNIT_MILLISECONDS, 67 (GNUNET_TIME_UNIT_MILLISECONDS,
68 7 * 60 * 60 * 1000), GNUNET_YES); 68 7 * 60 * 60 * 1000), GNUNET_YES);
69 WANTNF(buf, bc); 69 WANTNF(buf, bc);
70#ifndef MINGW 70
71 hdir = getenv("HOME"); 71 hdir = getenv("HOME");
72#else 72
73 hdir = getenv("USERPROFILE");
74#endif
75 GNUNET_snprintf(buf, sizeof(buf), "%s%s", hdir, DIR_SEPARATOR_STR); 73 GNUNET_snprintf(buf, sizeof(buf), "%s%s", hdir, DIR_SEPARATOR_STR);
76 b = GNUNET_STRINGS_filename_expand("~"); 74 b = GNUNET_STRINGS_filename_expand("~");
77 GNUNET_assert(b != NULL); 75 GNUNET_assert(b != NULL);
diff --git a/src/util/w32cat.c b/src/util/w32cat.c
deleted file mode 100644
index fa7637d38..000000000
--- a/src/util/w32cat.c
+++ /dev/null
@@ -1,154 +0,0 @@
1/*
2 W32 version of 'cat' program
3 Copyright (C) 2012 LRN
4
5 cat is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 cat is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with cat; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19
20 SPDX-License-Identifier: AGPL3.0-or-later
21 */
22
23#include <stdio.h>
24#include <windows.h>
25#include <stdint.h>
26#include <signal.h>
27
28DWORD WINAPI
29parent_control_thread(LPVOID lpParameter)
30{
31 HANDLE h = (HANDLE)lpParameter;
32
33 while (TRUE)
34 {
35 DWORD dw;
36 BOOL b;
37 unsigned char c;
38 b = ReadFile(h, &c, 1, &dw, NULL);
39 if (!b)
40 {
41 ExitProcess(0);
42 }
43 raise((int)c);
44 }
45}
46
47void
48install_parent_control_handler()
49{
50 const char *env_buf;
51 char *env_buf_end;
52 uint64_t pipe_fd;
53 HANDLE pipe_handle;
54
55 env_buf = getenv("GNUNET_OS_CONTROL_PIPE");
56 if ((NULL == env_buf) || (strlen(env_buf) <= 0))
57 return;
58 errno = 0;
59 pipe_fd = strtoull(env_buf, &env_buf_end, 16);
60 if ((0 != errno) || (env_buf == env_buf_end))
61 return;
62 /* Gcc will issue a warning here. What to do with it? */
63 pipe_handle = (HANDLE)(uintptr_t)pipe_fd;
64 CreateThread(NULL, 0, parent_control_thread, (LPVOID)pipe_handle, 0, NULL);
65}
66
67int
68main(int argc, char **argv)
69{
70 HANDLE stdi, stdo;
71 BOOL b;
72 wchar_t *commandlinew, **argvw;
73 int argcw;
74 int i;
75
76 stdo = GetStdHandle(STD_OUTPUT_HANDLE);
77 if (stdo == INVALID_HANDLE_VALUE || stdo == NULL)
78 return 1;
79
80 commandlinew = GetCommandLineW();
81 argvw = CommandLineToArgvW(commandlinew, &argcw);
82 if (argvw == NULL)
83 return 1;
84
85 install_parent_control_handler();
86
87 for (i = 1; i < argcw || argcw == 1; i++)
88 {
89 DWORD r, w;
90 int is_dash = wcscmp(NULL == argvw[i] ? L"-" : argvw[i], L"-") == 0;
91 if (argcw == 1 || is_dash)
92 {
93 stdi = GetStdHandle(STD_INPUT_HANDLE);
94 if (stdi == INVALID_HANDLE_VALUE)
95 {
96 fprintf(stderr, "cat: Failed to obtain stdin handle.\n");
97 return 4;
98 }
99 if (stdi == NULL)
100 {
101 fprintf(stderr, "cat: Have no stdin.\n");
102 return 5;
103 }
104 }
105 else
106 {
107 stdi = CreateFileW(argvw[i], GENERIC_READ, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
108 if (stdi == INVALID_HANDLE_VALUE)
109 {
110 wchar_t *msgbuf;
111 DWORD le = GetLastError();
112 if (0 < FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, le, 0, (wchar_t *)&msgbuf, 0, NULL))
113 {
114 fprintf(stderr, "cat: Failed to open file `%S'. Error %lu.\n", argvw[i], le);
115 return 3;
116 }
117 fprintf(stderr, "cat: Failed to open file `%S'. Error %lu: %S\n", argvw[i], le, msgbuf);
118 if (msgbuf != NULL)
119 LocalFree(msgbuf);
120 return 2;
121 }
122 }
123 do
124 {
125 unsigned char c;
126 b = ReadFile(stdi, &c, 1, &r, NULL);
127 if (b && r > 0)
128 {
129 b = WriteFile(stdo, &c, 1, &w, NULL);
130 if (b == 0)
131 {
132 wchar_t *msgbuf;
133 DWORD le = GetLastError();
134 if (0 < FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, le, 0, (wchar_t *)&msgbuf, 0, NULL))
135 {
136 fprintf(stderr, "cat: Failed to write into stdout. Error %lu.\n", le);
137 return 3;
138 }
139 fprintf(stderr, "cat: Failed to write into stdout. Error %lu: %S\n", le, msgbuf);
140 if (msgbuf != NULL)
141 LocalFree(msgbuf);
142 return 6;
143 }
144 }
145 }
146 while (b && r > 0);
147 if (argcw == 1)
148 break;
149 if (!is_dash)
150 CloseHandle(stdi);
151 }
152 LocalFree(argvw);
153 return 0;
154}
diff --git a/src/util/win.c b/src/util/win.c
deleted file mode 100644
index a2b0d08da..000000000
--- a/src/util/win.c
+++ /dev/null
@@ -1,1365 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file util/win.c
23 * @brief Helper functions for MS Windows in C++
24 * @author Nils Durner
25 */
26
27#ifndef _WIN_C
28#define _WIN_C
29
30#include "winproc.h"
31#include "platform.h"
32#include "gnunet_crypto_lib.h"
33#include "gnunet_common.h"
34#include "gnunet_connection_lib.h"
35
36#include <ntdef.h>
37#ifndef INHERITED_ACE
38#define INHERITED_ACE 0x10
39#endif
40
41int plibc_conv_to_win_path(const char *pszUnix, char *pszWindows);
42
43#define _IP_ADAPTER_UNICAST_ADDRESS_HEAD \
44 union { \
45 struct { \
46 ULONG Length; \
47 DWORD Flags; \
48 }; \
49 };
50
51#define _IP_ADAPTER_UNICAST_ADDRESS_BASE \
52 SOCKET_ADDRESS Address; \
53 IP_PREFIX_ORIGIN PrefixOrigin; \
54 IP_SUFFIX_ORIGIN SuffixOrigin; \
55 IP_DAD_STATE DadState; \
56 ULONG ValidLifetime; \
57 ULONG PreferredLifetime; \
58 ULONG LeaseLifetime;
59
60#define _IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA \
61 UINT8 OnLinkPrefixLength;
62
63
64#define _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(suffix, addition) \
65 typedef struct _IP_ADAPTER_UNICAST_ADDRESS ## suffix { \
66 _IP_ADAPTER_UNICAST_ADDRESS_HEAD \
67 struct _IP_ADAPTER_UNICAST_ADDRESS ## suffix *Next; \
68 _IP_ADAPTER_UNICAST_ADDRESS_BASE \
69 addition \
70 } IP_ADAPTER_UNICAST_ADDRESS ## suffix, *PIP_ADAPTER_UNICAST_ADDRESS ## suffix;
71
72/* _IP_ADAPTER_UNICAST_ADDRESS_DEFINE(,) defined in w32api headers */
73_IP_ADAPTER_UNICAST_ADDRESS_DEFINE(_VISTA, _IP_ADAPTER_UNICAST_ADDRESS_ADD_VISTA)
74
75
76#ifndef __MINGW64_VERSION_MAJOR
77typedef struct _IP_ADAPTER_WINS_SERVER_ADDRESS {
78 union {
79 ULONGLONG Alignment;
80 struct {
81 ULONG Length;
82 DWORD Reserved;
83 };
84 };
85 struct _IP_ADAPTER_WINS_SERVER_ADDRESS *Next;
86 SOCKET_ADDRESS Address;
87} IP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS, *PIP_ADAPTER_WINS_SERVER_ADDRESS_LH;
88
89typedef struct _IP_ADAPTER_GATEWAY_ADDRESS {
90 union {
91 ULONGLONG Alignment;
92 struct {
93 ULONG Length;
94 DWORD Reserved;
95 };
96 };
97 struct _IP_ADAPTER_GATEWAY_ADDRESS *Next;
98 SOCKET_ADDRESS Address;
99} IP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS, *PIP_ADAPTER_GATEWAY_ADDRESS_LH;
100#endif
101
102typedef UINT32 NET_IF_COMPARTMENT_ID;
103typedef GUID NET_IF_NETWORK_GUID;
104
105#ifndef __MINGW64_VERSION_MAJOR
106typedef enum _NET_IF_CONNECTION_TYPE {
107 NET_IF_CONNECTION_DEDICATED = 1,
108 NET_IF_CONNECTION_PASSIVE,
109 NET_IF_CONNECTION_DEMAND,
110 NET_IF_CONNECTION_MAXIMUM
111} NET_IF_CONNECTION_TYPE, *PNET_IF_CONNECTION_TYPE;
112
113typedef enum {
114 TUNNEL_TYPE_NONE = 0,
115 TUNNEL_TYPE_OTHER,
116 TUNNEL_TYPE_DIRECT,
117 TUNNEL_TYPE_6TO4,
118 TUNNEL_TYPE_ISATAP,
119 TUNNEL_TYPE_TEREDO,
120 TUNNEL_TYPE_IPHTTPS
121} TUNNEL_TYPE, *PTUNNEL_TYPE;
122#endif
123
124/*
125 A DUID consists of a two-octet type code represented in network byte
126 order, followed by a variable number of octets that make up the
127 actual identifier. A DUID can be no more than 128 octets long (not
128 including the type code).
129 */
130#define MAX_DHCPV6_DUID_LENGTH 130
131
132#ifndef __MINGW64_VERSION_MAJOR
133typedef union _NET_LUID {
134 ULONG64 Value;
135 struct {
136 ULONG64 Reserved : 24;
137 ULONG64 NetLuidIndex : 24;
138 ULONG64 IfType : 16;
139 } Info;
140} NET_LUID, *PNET_LUID, IF_LUID;
141
142#define MAX_DNS_SUFFIX_STRING_LENGTH 246
143
144typedef struct _IP_ADAPTER_DNS_SUFFIX {
145 struct _IP_ADAPTER_DNS_SUFFIX *Next;
146 WCHAR String[MAX_DNS_SUFFIX_STRING_LENGTH];
147} IP_ADAPTER_DNS_SUFFIX, *PIP_ADAPTER_DNS_SUFFIX;
148#endif
149
150
151
152#define _IP_ADAPTER_ADDRESSES_HEAD \
153 union { \
154 ULONGLONG Alignment; \
155 struct { \
156 ULONG Length; \
157 DWORD IfIndex; \
158 }; \
159 };
160
161#define _IP_ADAPTER_ADDRESSES_BASE \
162 PCHAR AdapterName; \
163 PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress; \
164 PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress; \
165 PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress; \
166 PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress; \
167 PWCHAR DnsSuffix; \
168 PWCHAR Description; \
169 PWCHAR FriendlyName; \
170 BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH]; \
171 DWORD PhysicalAddressLength; \
172 DWORD Flags; \
173 DWORD Mtu; \
174 DWORD IfType; \
175 IF_OPER_STATUS OperStatus;
176
177#define _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \
178 DWORD Ipv6IfIndex; \
179 DWORD ZoneIndices[16]; \
180 PIP_ADAPTER_PREFIX FirstPrefix; \
181
182
183#define _IP_ADAPTER_ADDRESSES_ADD_VISTA \
184 _IP_ADAPTER_ADDRESSES_ADD_XPSP1 \
185 ULONG64 TransmitLinkSpeed; \
186 ULONG64 ReceiveLinkSpeed; \
187 PIP_ADAPTER_WINS_SERVER_ADDRESS_LH FirstWinsServerAddress; \
188 PIP_ADAPTER_GATEWAY_ADDRESS_LH FirstGatewayAddress; \
189 ULONG Ipv4Metric; \
190 ULONG Ipv6Metric; \
191 IF_LUID Luid; \
192 SOCKET_ADDRESS Dhcpv4Server; \
193 NET_IF_COMPARTMENT_ID CompartmentId; \
194 NET_IF_NETWORK_GUID NetworkGuid; \
195 NET_IF_CONNECTION_TYPE ConnectionType; \
196 TUNNEL_TYPE TunnelType; \
197 SOCKET_ADDRESS Dhcpv6Server; \
198 BYTE Dhcpv6ClientDuid[MAX_DHCPV6_DUID_LENGTH]; \
199 ULONG Dhcpv6ClientDuidLength; \
200 ULONG Dhcpv6Iaid;
201
202#define _IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1 \
203 _IP_ADAPTER_ADDRESSES_ADD_VISTA \
204 PIP_ADAPTER_DNS_SUFFIX FirstDnsSuffix;
205
206#define _IP_ADAPTER_ADDRESSES_DEFINE(suffix, addition) \
207 typedef struct _IP_ADAPTER_ADDRESSES ## suffix { \
208 _IP_ADAPTER_ADDRESSES_HEAD \
209 struct _IP_ADAPTER_ADDRESSES ## suffix *Next; \
210 _IP_ADAPTER_ADDRESSES_BASE \
211 addition \
212 } IP_ADAPTER_ADDRESSES ## suffix, *PIP_ADAPTER_ADDRESSES ## suffix;
213
214
215/* _IP_ADAPTER_ADDRESSES_DEFINE(,) defined in w32api headers */
216_IP_ADAPTER_ADDRESSES_DEFINE(_XPSP1, _IP_ADAPTER_ADDRESSES_ADD_XPSP1)
217_IP_ADAPTER_ADDRESSES_DEFINE(_VISTA, _IP_ADAPTER_ADDRESSES_ADD_VISTA)
218_IP_ADAPTER_ADDRESSES_DEFINE(_2008_OR_VISTASP1, _IP_ADAPTER_ADDRESSES_ADD_2008_OR_VISTASP1)
219
220static int
221EnumNICs_IPv6_get_ifs_count(_win_socket s)
222{
223 DWORD dwret = 0, err;
224 int iret;
225
226 iret = WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL, 0, NULL, 0,
227 &dwret, NULL, NULL);
228 err = GetLastError();
229 if (iret == SOCKET_ERROR && err == WSAEFAULT)
230 return dwret;
231 else if (iret == 0)
232 return 0;
233 return GNUNET_SYSERR;
234}
235
236static int
237EnumNICs_IPv6_get_ifs(_win_socket s, SOCKET_ADDRESS_LIST *inf, int size)
238{
239 int iret;
240 DWORD dwret = 0;
241
242 iret = WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL, 0, inf, size,
243 &dwret, NULL, NULL);
244
245 if (iret != 0 || dwret != size)
246 {
247 /* It's supposed to succeed! And size should be the same */
248 return GNUNET_SYSERR;
249 }
250 return GNUNET_OK;
251}
252
253#undef GNUNET_malloc
254#define GNUNET_malloc(a) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY | \
255 HEAP_GENERATE_EXCEPTIONS, a)
256
257#undef GNUNET_free
258#define GNUNET_free(a) HeapFree(GetProcessHeap(), 0, a)
259
260#undef GNUNET_free_non_null
261#define GNUNET_free_non_null(a) do { if ((a) != NULL) GNUNET_free (a); } while (0)
262
263static int
264EnumNICs_IPv4_get_ifs(SOCKET s, INTERFACE_INFO **inf, int *size)
265{
266 int iret;
267 DWORD dwret = 0;
268 DWORD error;
269 INTERFACE_INFO *ii = NULL;
270 DWORD ii_size = sizeof(INTERFACE_INFO) * 15;
271
272 while (TRUE)
273 {
274 if (ii_size >= sizeof(INTERFACE_INFO) * 1000)
275 return GNUNET_SYSERR;
276 ii = (INTERFACE_INFO *)GNUNET_malloc(ii_size);
277 dwret = 0;
278 iret = WSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, 0, ii, ii_size,
279 &dwret, NULL, NULL);
280 error = GetLastError();
281 if (iret == SOCKET_ERROR)
282 {
283 if (error == WSAEFAULT)
284 {
285 GNUNET_free(ii);
286 ii_size *= 2;
287 continue;
288 }
289 GNUNET_free(ii);
290 return GNUNET_SYSERR;
291 }
292 else
293 {
294 *inf = ii;
295 *size = dwret;
296 return GNUNET_OK;
297 }
298 }
299 return GNUNET_SYSERR;
300}
301
302int
303EnumNICs2(INTERFACE_INFO **ifs4, int *ifs4_len, SOCKET_ADDRESS_LIST **ifs6)
304{
305 int result = 0;
306 _win_socket s4;
307 _win_socket s6;
308 int ifs4len = 0;
309 int ifs6len = 0;
310 INTERFACE_INFO *interfaces4 = NULL;
311 SOCKET_ADDRESS_LIST *interfaces6 = NULL;
312
313 SetLastError(0);
314 s4 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
315 (void)GetLastError();
316 SetLastError(0);
317 s6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
318 (void)GetLastError();
319 if (s6 != INVALID_SOCKET)
320 {
321 ifs6len = EnumNICs_IPv6_get_ifs_count(s6);
322 if (ifs6len > 0)
323 {
324 interfaces6 = (SOCKET_ADDRESS_LIST *)GNUNET_malloc(ifs6len);
325 result = EnumNICs_IPv6_get_ifs(s6, interfaces6, ifs6len) || result;
326 }
327 closesocket(s6);
328 s6 = INVALID_SOCKET;
329 }
330
331 if (s4 != INVALID_SOCKET)
332 {
333 result = EnumNICs_IPv4_get_ifs(s4, &interfaces4, &ifs4len) || result;
334 closesocket(s4);
335 s4 = INVALID_SOCKET;
336 }
337 if (ifs6len + ifs4len == 0)
338 goto error;
339
340 if (!result)
341 {
342 *ifs4 = interfaces4;
343 *ifs4_len = ifs4len;
344 *ifs6 = interfaces6;
345 return GNUNET_OK;
346 }
347error:
348 if (interfaces4 != NULL)
349 GNUNET_free(interfaces4);
350 if (interfaces6 != NULL)
351 GNUNET_free(interfaces6);
352 if (s4 != INVALID_SOCKET)
353 closesocket(s4);
354 if (s6 != INVALID_SOCKET)
355 closesocket(s6);
356 return GNUNET_SYSERR;
357}
358
359
360/**
361 * @returns #GNUNET_OK on success, #GNUNET_SYSERR on error
362 */
363int
364EnumNICs3(struct EnumNICs3_results **results, int *results_count)
365{
366 DWORD dwRetVal = 0;
367 int count = 0;
368 ULONG flags = /*GAA_FLAG_INCLUDE_PREFIX |*/ GAA_FLAG_SKIP_ANYCAST |
369 GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
370 struct sockaddr_in6 examplecom6;
371 IPAddr examplecom;
372 DWORD best_interface = 0;
373 DWORD best_interface6 = 0;
374
375 int use_enum2 = 0;
376 INTERFACE_INFO *interfaces4 = NULL;
377 int interfaces4_len = 0;
378 SOCKET_ADDRESS_LIST *interfaces6 = NULL;
379
380 unsigned long outBufLen = sizeof(IP_ADAPTER_ADDRESSES);
381 IP_ADAPTER_ADDRESSES *pCurrentAddress = NULL;
382 IP_ADAPTER_ADDRESSES *pAddresses = (IP_ADAPTER_ADDRESSES *)GNUNET_malloc(outBufLen);
383
384 if (GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAddresses, &outBufLen)
385 == ERROR_BUFFER_OVERFLOW)
386 {
387 GNUNET_free(pAddresses);
388 pAddresses = (IP_ADAPTER_ADDRESSES *)GNUNET_malloc(outBufLen);
389 }
390
391 dwRetVal = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAddresses, &outBufLen);
392
393 if (dwRetVal != NO_ERROR)
394 {
395 GNUNET_free(pAddresses);
396 return GNUNET_SYSERR;
397 }
398
399 if (pAddresses->Length < sizeof(IP_ADAPTER_ADDRESSES_VISTA))
400 {
401 use_enum2 = 1;
402
403 /* Enumerate NICs using WSAIoctl() */
404 if (GNUNET_OK != EnumNICs2(&interfaces4, &interfaces4_len, &interfaces6))
405 {
406 GNUNET_free(pAddresses);
407 return GNUNET_SYSERR;
408 }
409 }
410
411 examplecom = inet_addr("192.0.34.166"); /* www.example.com */
412 if (GetBestInterface(examplecom, &best_interface) != NO_ERROR)
413 best_interface = 0;
414
415 if (GNGetBestInterfaceEx != NULL)
416 {
417 examplecom6.sin6_family = AF_INET6;
418 examplecom6.sin6_port = 0;
419 examplecom6.sin6_flowinfo = 0;
420 examplecom6.sin6_scope_id = 0;
421 inet_pton(AF_INET6, "2001:500:88:200:0:0:0:10",
422 (struct sockaddr *)&examplecom6.sin6_addr);
423 dwRetVal = GNGetBestInterfaceEx((struct sockaddr *)&examplecom6,
424 &best_interface6);
425 if (dwRetVal != NO_ERROR)
426 best_interface6 = 0;
427 }
428
429 /* Give IPv6 a priority */
430 if (best_interface6 != 0)
431 best_interface = best_interface6;
432
433 count = 0;
434 for (pCurrentAddress = pAddresses;
435 pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)
436 {
437 if (pCurrentAddress->OperStatus == IfOperStatusUp)
438 {
439 IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;
440 for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;
441 unicast = unicast->Next)
442 {
443 if ((unicast->Address.lpSockaddr->sa_family == AF_INET ||
444 unicast->Address.lpSockaddr->sa_family == AF_INET6) &&
445 (unicast->DadState == IpDadStateDeprecated ||
446 unicast->DadState == IpDadStatePreferred))
447 count += 1;
448 }
449 }
450 }
451
452 if (count == 0)
453 {
454 *results = NULL;
455 *results_count = 0;
456 GNUNET_free(pAddresses);
457 GNUNET_free_non_null(interfaces4);
458 GNUNET_free_non_null(interfaces6);
459 return GNUNET_OK;
460 }
461
462 *results = (struct EnumNICs3_results *)GNUNET_malloc(
463 sizeof(struct EnumNICs3_results) * count);
464 *results_count = count;
465
466 count = 0;
467 for (pCurrentAddress = pAddresses;
468 pCurrentAddress != NULL; pCurrentAddress = pCurrentAddress->Next)
469 {
470 struct EnumNICs3_results *r;
471 IP_ADAPTER_UNICAST_ADDRESS *unicast = NULL;
472 if (pCurrentAddress->OperStatus != IfOperStatusUp)
473 continue;
474 for (unicast = pCurrentAddress->FirstUnicastAddress; unicast != NULL;
475 unicast = unicast->Next)
476 {
477 int i, j;
478 int mask_length = -1;
479 char dst[INET6_ADDRSTRLEN + 1];
480
481 if ((unicast->Address.lpSockaddr->sa_family != AF_INET &&
482 unicast->Address.lpSockaddr->sa_family != AF_INET6) ||
483 (unicast->DadState != IpDadStateDeprecated &&
484 unicast->DadState != IpDadStatePreferred))
485 continue;
486
487 r = &(*results)[count];
488 r->flags = 0;
489 if (pCurrentAddress->IfIndex > 0 &&
490 pCurrentAddress->IfIndex == best_interface &&
491 unicast->Address.lpSockaddr->sa_family == AF_INET)
492 r->is_default = 1;
493 else if (pCurrentAddress->Ipv6IfIndex > 0 &&
494 pCurrentAddress->Ipv6IfIndex == best_interface6 &&
495 unicast->Address.lpSockaddr->sa_family == AF_INET6)
496 r->is_default = 1;
497 else
498 r->is_default = 0;
499
500 /* Don't choose default interface twice */
501 if (r->is_default)
502 best_interface = best_interface6 = 0;
503
504 if (!use_enum2)
505 {
506 GNUNET_memcpy(&r->address, unicast->Address.lpSockaddr,
507 unicast->Address.iSockaddrLength);
508 memset(&r->mask, 0, sizeof(struct sockaddr));
509 mask_length = ((IP_ADAPTER_UNICAST_ADDRESS_VISTA *)unicast)->
510 OnLinkPrefixLength;
511 /* OnLinkPrefixLength is the number of leading 1s in the mask.
512 * OnLinkPrefixLength is available on Vista and later (hence use_enum2).
513 */
514 if (unicast->Address.lpSockaddr->sa_family == AF_INET)
515 {
516 struct sockaddr_in *m = (struct sockaddr_in *)&r->mask;
517 for (i = 0; i < mask_length; i++)
518 ((unsigned char *)&m->sin_addr)[i / 8] |= 0x80 >> (i % 8);
519 }
520 else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
521 {
522 struct sockaddr_in6 *m = (struct sockaddr_in6 *)&r->mask;
523 struct sockaddr_in6 *b = (struct sockaddr_in6 *)&r->broadcast;
524 for (i = 0; i < mask_length; i++)
525 ((unsigned char *)&m->sin6_addr)[i / 8] |= 0x80 >> (i % 8);
526 GNUNET_memcpy(&r->broadcast, &r->address, unicast->Address.iSockaddrLength);
527 for (i = mask_length; i < 128; i++)
528 ((unsigned char *)&b->sin6_addr)[i / 8] |= 0x80 >> (i % 8);
529 }
530 r->flags |= ENUMNICS3_MASK_OK;
531 }
532 else
533 {
534 int found = 0;
535 if (unicast->Address.lpSockaddr->sa_family == AF_INET)
536 {
537 for (i = 0; !found && i < interfaces4_len / sizeof(INTERFACE_INFO); i++)
538 {
539 struct sockaddr_in *m = (struct sockaddr_in *)&r->mask;
540 GNUNET_memcpy(&interfaces4[i].iiAddress.Address,
541 unicast->Address.lpSockaddr,
542 unicast->Address.iSockaddrLength);
543 found = 1;
544 GNUNET_memcpy(&r->address, &interfaces4[i].iiAddress.Address,
545 sizeof(struct sockaddr_in));
546 GNUNET_memcpy(&r->mask, &interfaces4[i].iiNetmask.Address,
547 sizeof(struct sockaddr_in));
548 for (mask_length = 0;
549 ((unsigned char *)&m->sin_addr)[mask_length / 8] &
550 0x80 >> (mask_length % 8); mask_length++)
551 {
552 }
553 r->flags |= ENUMNICS3_MASK_OK;
554 }
555 }
556 else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
557 {
558 for (i = 0;
559 interfaces6 != NULL && !found && i < interfaces6->iAddressCount;
560 i++)
561 {
562 GNUNET_memcpy(interfaces6->Address[i].lpSockaddr,
563 unicast->Address.lpSockaddr,
564 unicast->Address.iSockaddrLength);
565 found = 1;
566 GNUNET_memcpy(&r->address, interfaces6->Address[i].lpSockaddr,
567 sizeof(struct sockaddr_in6));
568 /* TODO: Find a way to reliably get network mask for IPv6 on XP */
569 memset(&r->mask, 0, sizeof(struct sockaddr));
570 r->flags &= ~ENUMNICS3_MASK_OK;
571 }
572 }
573 if (!found)
574 {
575 DebugBreak();
576 }
577 }
578 if (unicast->Address.lpSockaddr->sa_family == AF_INET)
579 {
580 struct sockaddr_in *m = (struct sockaddr_in *)&r->mask;
581 struct sockaddr_in *a = (struct sockaddr_in *)&r->address;
582 /* copy address to broadcast, then flip all the trailing bits not
583 * falling under netmask to 1,
584 * so we get, 192.168.0.255 from, say, 192.168.0.43 with mask == 24.
585 */
586 GNUNET_memcpy(&r->broadcast, &r->address, unicast->Address.iSockaddrLength);
587 for (i = mask_length; i < 32; i++)
588 ((unsigned char *)&m->sin_addr)[i / 8] |= 0x80 >> (i % 8);
589 r->flags |= ENUMNICS3_BCAST_OK;
590 r->addr_size = sizeof(struct sockaddr_in);
591 inet_ntop(AF_INET, &a->sin_addr, dst, INET_ADDRSTRLEN);
592 }
593 else if (unicast->Address.lpSockaddr->sa_family == AF_INET6)
594 {
595 struct sockaddr_in6 *a = (struct sockaddr_in6 *)&r->address;
596 /* for IPv6 broadcast is not defined, zero it down */
597 memset(&r->broadcast, 0, sizeof(struct sockaddr));
598 r->flags &= ~ENUMNICS3_BCAST_OK;
599 r->addr_size = sizeof(struct sockaddr_in6);
600 inet_ntop(AF_INET6, &a->sin6_addr, dst, INET6_ADDRSTRLEN);
601 }
602
603 i = 0;
604 i += snprintf(&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,
605 "%S (%s", pCurrentAddress->FriendlyName, dst);
606 for (j = 0; j < pCurrentAddress->PhysicalAddressLength; j++)
607 i += snprintf(&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0,
608 "%s%02X", j > 0 ? ":" : " - ", pCurrentAddress->PhysicalAddress[j]);
609 i += snprintf(&r->pretty_name[i], 1000 - i > 0 ? 1000 - i : 0, ")");
610 r->pretty_name[1000] = '\0';
611 count += 1;
612 }
613 }
614
615 if (use_enum2)
616 {
617 GNUNET_free_non_null(interfaces4);
618 GNUNET_free_non_null(interfaces6);
619 }
620
621 GNUNET_free(pAddresses);
622 return GNUNET_OK;
623}
624
625void
626EnumNICs3_free(struct EnumNICs3_results *r)
627{
628 GNUNET_free_non_null(r);
629}
630
631
632/**
633 * Lists all network interfaces in a combo box
634 * Used by the basic GTK configurator
635 *
636 * @param callback function to call for each NIC
637 * @param callback_cls closure for callback
638 */
639int
640ListNICs(void (*callback)(void *, const char *, int), void * callback_cls)
641{
642 int r;
643 int i;
644 struct EnumNICs3_results *results = NULL;
645 int results_count;
646
647 r = EnumNICs3(&results, &results_count);
648 if (r != GNUNET_OK)
649 return GNUNET_NO;
650
651 for (i = 0; i < results_count; i++)
652 callback(callback_cls, results[i].pretty_name, results[i].is_default);
653 GNUNET_free_non_null(results);
654 return GNUNET_YES;
655}
656
657/**
658 * @brief Installs the Windows service
659 * @param servicename name of the service as diplayed by the SCM
660 * @param application path to the application binary
661 * @param username the name of the service's user account
662 * @returns 0 on success
663 * 1 if the Windows version doesn't support services
664 * 2 if the SCM could not be opened
665 * 3 if the service could not be created
666 */
667int InstallAsService(char *servicename, char *application, char *username)
668{
669 SC_HANDLE hManager, hService;
670 char szEXE[_MAX_PATH + 17] = "\"";
671 char *user = NULL;
672
673 if (!GNOpenSCManager)
674 return 1;
675
676 plibc_conv_to_win_path(application, szEXE + 1);
677 strcat(szEXE, "\" --win-service");
678 hManager = GNOpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
679 if (!hManager)
680 return 2;
681
682 if (username)
683 {
684 user = (char *)malloc(strlen(username) + 3);
685 sprintf(user, ".\\%s", username);
686 }
687
688 hService = GNCreateService(hManager, (LPCTSTR)servicename, (LPCTSTR)servicename, 0,
689 SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, (LPCTSTR)szEXE,
690 NULL, NULL, NULL, (LPCTSTR)user, (LPCTSTR)username);
691
692 if (user)
693 free(user);
694
695 if (!hService)
696 return 3;
697
698 GNCloseServiceHandle(hService);
699
700 return 0;
701}
702
703
704/**
705 * @brief Uninstall Windows service
706 * @param servicename name of the service to delete
707 * @returns 0 on success
708 * 1 if the Windows version doesn't support services
709 * 2 if the SCM could not be openend
710 * 3 if the service cannot be accessed
711 * 4 if the service cannot be deleted
712 */
713int
714UninstallService(char *servicename)
715{
716 SC_HANDLE hManager, hService;
717
718 if (!GNOpenSCManager)
719 return 1;
720
721 hManager = GNOpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
722 if (!hManager)
723 return 2;
724
725 if (!(hService = GNOpenService(hManager, (LPCTSTR)servicename, DELETE)))
726 {
727 if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)
728 return 3;
729 else
730 goto closeSCM;
731 }
732
733 if (!GNDeleteService(hService))
734 if (GetLastError() != ERROR_SERVICE_MARKED_FOR_DELETE)
735 return 4;
736
737closeSCM:
738 GNCloseServiceHandle(hService);
739
740 return 0;
741}
742
743/**
744 * @author Scott Field, Microsoft
745 * @see http://support.microsoft.com/?scid=kb;en-us;132958
746 * @date 12-Jul-95
747 */
748void
749_InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String)
750{
751 DWORD StringLength;
752
753 if (String == NULL)
754 {
755 LsaString->Buffer = NULL;
756 LsaString->Length = 0;
757 LsaString->MaximumLength = 0;
758 return;
759 }
760
761 StringLength = wcslen(String);
762 LsaString->Buffer = String;
763 LsaString->Length = (USHORT)StringLength * sizeof(WCHAR);
764 LsaString->MaximumLength = (USHORT)(StringLength + 1) * sizeof(WCHAR);
765}
766
767
768/**
769 * @author Scott Field, Microsoft
770 * @see http://support.microsoft.com/?scid=kb;en-us;132958
771 * @date 12-Jul-95
772 */
773NTSTATUS
774_OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle)
775{
776 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
777 LSA_UNICODE_STRING ServerString;
778 PLSA_UNICODE_STRING Server = NULL;
779
780 /* Always initialize the object attributes to all zeroes. */
781 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
782
783 if (ServerName != NULL)
784 {
785 /* Make a LSA_UNICODE_STRING out of the LPWSTR passed in */
786 _InitLsaString(&ServerString, ServerName);
787 Server = &ServerString;
788 }
789
790 /* Attempt to open the policy. */
791 return GNLsaOpenPolicy(Server,
792 &ObjectAttributes, DesiredAccess, PolicyHandle);
793}
794
795/**
796 * @brief Obtain a SID representing the supplied account on the supplied system
797 * @return TRUE on success, FALSE on failure
798 * @author Scott Field, Microsoft
799 * @date 12-Jul-95
800 * @remarks A buffer is allocated which contains the SID representing the
801 * supplied account. This buffer should be freed when it is no longer
802 * needed by calling\n
803 * HeapFree(GetProcessHeap(), 0, buffer)
804 * @remarks Call GetLastError() to obtain extended error information.
805 * @see http://support.microsoft.com/?scid=kb;en-us;132958
806 */
807BOOL
808_GetAccountSid(LPCTSTR SystemName, LPCTSTR AccountName, PSID * Sid)
809{
810 LPTSTR ReferencedDomain = NULL;
811 DWORD cbSid = 128; /* initial allocation attempt */
812 DWORD cchReferencedDomain = 16; /* initial allocation size */
813 SID_NAME_USE peUse;
814 BOOL bSuccess = FALSE; /* assume this function will fail */
815
816 /* initial memory allocations */
817 if ((*Sid = HeapAlloc(GetProcessHeap(), 0, cbSid)) == NULL)
818 return FALSE;
819
820 if ((ReferencedDomain = (LPTSTR)HeapAlloc(GetProcessHeap(),
821 0,
822 cchReferencedDomain *
823 sizeof(TCHAR))) == NULL)
824 return FALSE;
825
826 /* Obtain the SID of the specified account on the specified system. */
827 while (!GNLookupAccountName(SystemName, /* machine to lookup account on */
828 AccountName, /* account to lookup */
829 *Sid, /* SID of interest */
830 &cbSid, /* size of SID */
831 ReferencedDomain, /* domain account was found on */
832 &cchReferencedDomain, &peUse))
833 {
834 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
835 {
836 /* reallocate memory */
837 if ((*Sid = HeapReAlloc(GetProcessHeap(), 0, *Sid, cbSid)) == NULL)
838 return FALSE;
839
840 if ((ReferencedDomain = (LPTSTR)HeapReAlloc(GetProcessHeap(),
841 0,
842 ReferencedDomain,
843 cchReferencedDomain
844 * sizeof(TCHAR))) == NULL)
845 return FALSE;
846 }
847 else
848 goto end;
849 }
850
851 /* Indicate success. */
852 bSuccess = TRUE;
853
854end:
855 /* Cleanup and indicate failure, if appropriate. */
856 HeapFree(GetProcessHeap(), 0, ReferencedDomain);
857
858 if (!bSuccess)
859 {
860 if (*Sid != NULL)
861 {
862 HeapFree(GetProcessHeap(), 0, *Sid);
863 *Sid = NULL;
864 }
865 }
866
867 return bSuccess;
868}
869
870/**
871 * @author Scott Field, Microsoft
872 * @see http://support.microsoft.com/?scid=kb;en-us;132958
873 * @date 12-Jul-95
874 */
875NTSTATUS
876_SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle,/* open policy handle */
877 PSID AccountSid, /* SID to grant privilege to */
878 LPWSTR PrivilegeName, /* privilege to grant (Unicode) */
879 BOOL bEnable /* enable or disable */
880 )
881{
882 LSA_UNICODE_STRING PrivilegeString;
883
884 /* Create a LSA_UNICODE_STRING for the privilege name. */
885 _InitLsaString(&PrivilegeString, PrivilegeName);
886
887 /* grant or revoke the privilege, accordingly */
888 if (bEnable)
889 {
890 NTSTATUS i;
891
892 i = GNLsaAddAccountRights(PolicyHandle, /* open policy handle */
893 AccountSid, /* target SID */
894 &PrivilegeString, /* privileges */
895 1 /* privilege count */
896 );
897 return i;
898 }
899 else
900 {
901 return GNLsaRemoveAccountRights(PolicyHandle, /* open policy handle */
902 AccountSid, /* target SID */
903 FALSE, /* do not disable all rights */
904 &PrivilegeString, /* privileges */
905 1 /* privilege count */
906 );
907 }
908}
909
910/**
911 * @brief Create a Windows service account
912 * @return 0 on success, > 0 otherwise
913 * @param pszName the name of the account
914 * @param pszDesc description of the account
915 */
916int
917CreateServiceAccount(const char *pszName,
918 const char *pszDesc)
919{
920 USER_INFO_1 ui;
921 USER_INFO_1008 ui2;
922 NET_API_STATUS nStatus;
923 wchar_t wszName[MAX_NAME_LENGTH], wszDesc[MAX_NAME_LENGTH];
924 LSA_HANDLE hPolicy;
925 PSID pSID;
926
927 if (!GNNetUserAdd)
928 return 1;
929 mbstowcs(wszName, pszName, strlen(pszName) + 1);
930 mbstowcs(wszDesc, pszDesc, strlen(pszDesc) + 1);
931
932 memset(&ui, 0, sizeof(ui));
933 ui.usri1_name = wszName;
934 ui.usri1_password = wszName; /* account is locked anyway */
935 ui.usri1_priv = USER_PRIV_USER;
936 ui.usri1_comment = wszDesc;
937 ui.usri1_flags = UF_SCRIPT;
938
939 nStatus = GNNetUserAdd(NULL, 1, (LPBYTE)&ui, NULL);
940
941 if (nStatus != NERR_Success && nStatus != NERR_UserExists)
942 return 2;
943
944 ui2.usri1008_flags = UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD;
945 GNNetUserSetInfo(NULL, wszName, 1008, (LPBYTE)&ui2, NULL);
946
947 if (!NT_SUCCESS(_OpenPolicy(NULL, POLICY_ALL_ACCESS, &hPolicy)))
948 return 3;
949
950 _GetAccountSid(NULL, (LPCTSTR)pszName, &pSID);
951
952 if (!NT_SUCCESS(_SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR)L"SeServiceLogonRight", TRUE)))
953 return 4;
954
955 _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR)L"SeDenyInteractiveLogonRight", TRUE);
956 _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR)L"SeDenyBatchLogonRight", TRUE);
957 _SetPrivilegeOnAccount(hPolicy, pSID, (LPWSTR)L"SeDenyNetworkLogonRight", TRUE);
958
959 GNLsaClose(hPolicy);
960
961 return 0;
962}
963
964/**
965 * @brief Grant permission to a file
966 * @param lpszFileName the name of the file or directory
967 * @param lpszAccountName the user account
968 * @param dwAccessMask the desired access (e.g. GENERIC_ALL)
969 * @return TRUE on success
970 * @remark based on http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q102102&
971 */
972BOOL AddPathAccessRights(char *lpszFileName, char *lpszAccountName,
973 DWORD dwAccessMask)
974{
975 /* SID variables. */
976 SID_NAME_USE snuType;
977 TCHAR * szDomain = NULL;
978 DWORD cbDomain = 0;
979 LPVOID pUserSID = NULL;
980 DWORD cbUserSID = 0;
981
982 /* File SD variables. */
983 PSECURITY_DESCRIPTOR pFileSD = NULL;
984 DWORD cbFileSD = 0;
985
986 /* New SD variables. */
987 SECURITY_DESCRIPTOR newSD;
988
989 /* ACL variables. */
990 PACL pACL = NULL;
991 BOOL fDaclPresent;
992 BOOL fDaclDefaulted;
993 ACL_SIZE_INFORMATION AclInfo;
994
995 /* New ACL variables. */
996 PACL pNewACL = NULL;
997 DWORD cbNewACL = 0;
998
999 /* Temporary ACE. */
1000 LPVOID pTempAce = NULL;
1001 UINT CurrentAceIndex = 0;
1002
1003 UINT newAceIndex = 0;
1004
1005 /* Assume function will fail. */
1006 BOOL fResult = FALSE;
1007 BOOL fAPISuccess;
1008
1009 SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION;
1010
1011 /**
1012 * STEP 1: Get SID of the account name specified.
1013 */
1014 fAPISuccess = GNLookupAccountName(NULL, (LPCTSTR)lpszAccountName,
1015 pUserSID, &cbUserSID, (LPTSTR)szDomain, &cbDomain, &snuType);
1016
1017 /* API should have failed with insufficient buffer. */
1018 if (fAPISuccess)
1019 goto end;
1020 else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1021 {
1022 goto end;
1023 }
1024
1025 pUserSID = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbUserSID);
1026 if (!pUserSID)
1027 {
1028 goto end;
1029 }
1030
1031 szDomain = (TCHAR *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbDomain * sizeof(TCHAR));
1032 if (!szDomain)
1033 {
1034 goto end;
1035 }
1036
1037 fAPISuccess = GNLookupAccountName(NULL, (LPCTSTR)lpszAccountName,
1038 pUserSID, &cbUserSID, (LPTSTR)szDomain, &cbDomain, &snuType);
1039 if (!fAPISuccess)
1040 {
1041 goto end;
1042 }
1043
1044 /**
1045 * STEP 2: Get security descriptor (SD) of the file specified.
1046 */
1047 fAPISuccess = GNGetFileSecurity((LPCTSTR)lpszFileName,
1048 secInfo, pFileSD, 0, &cbFileSD);
1049
1050 /* API should have failed with insufficient buffer. */
1051 if (fAPISuccess)
1052 goto end;
1053 else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1054 {
1055 goto end;
1056 }
1057
1058 pFileSD = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1059 cbFileSD);
1060 if (!pFileSD)
1061 {
1062 goto end;
1063 }
1064
1065 fAPISuccess = GNGetFileSecurity((LPCTSTR)lpszFileName,
1066 secInfo, pFileSD, cbFileSD, &cbFileSD);
1067 if (!fAPISuccess)
1068 {
1069 goto end;
1070 }
1071
1072 /**
1073 * STEP 3: Initialize new SD.
1074 */
1075 if (!GNInitializeSecurityDescriptor(&newSD,
1076 SECURITY_DESCRIPTOR_REVISION))
1077 {
1078 goto end;
1079 }
1080
1081 /**
1082 * STEP 4: Get DACL from the old SD.
1083 */
1084 if (!GNGetSecurityDescriptorDacl(pFileSD, &fDaclPresent, &pACL,
1085 &fDaclDefaulted))
1086 {
1087 goto end;
1088 }
1089
1090 /**
1091 * STEP 5: Get size information for DACL.
1092 */
1093 AclInfo.AceCount = 0; // Assume NULL DACL.
1094 AclInfo.AclBytesFree = 0;
1095 AclInfo.AclBytesInUse = sizeof(ACL);
1096
1097 if (pACL == NULL)
1098 fDaclPresent = FALSE;
1099
1100 /* If not NULL DACL, gather size information from DACL. */
1101 if (fDaclPresent)
1102 {
1103 if (!GNGetAclInformation(pACL, &AclInfo,
1104 sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
1105 {
1106 goto end;
1107 }
1108 }
1109
1110 /**
1111 * STEP 6: Compute size needed for the new ACL.
1112 */
1113 cbNewACL = AclInfo.AclBytesInUse + sizeof(ACCESS_ALLOWED_ACE)
1114 + GetLengthSid(pUserSID) - sizeof(DWORD);
1115
1116 /**
1117 * STEP 7: Allocate memory for new ACL.
1118 */
1119 pNewACL = (PACL)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbNewACL);
1120 if (!pNewACL)
1121 {
1122 goto end;
1123 }
1124
1125 /**
1126 * STEP 8: Initialize the new ACL.
1127 */
1128 if (!GNInitializeAcl(pNewACL, cbNewACL, ACL_REVISION2))
1129 {
1130 goto end;
1131 }
1132
1133 /**
1134 * STEP 9 If DACL is present, copy all the ACEs from the old DACL
1135 * to the new DACL.
1136 *
1137 * The following code assumes that the old DACL is
1138 * already in Windows 2000 preferred order. To conform
1139 * to the new Windows 2000 preferred order, first we will
1140 * copy all non-inherited ACEs from the old DACL to the
1141 * new DACL, irrespective of the ACE type.
1142 */
1143
1144 newAceIndex = 0;
1145
1146 if (fDaclPresent && AclInfo.AceCount)
1147 {
1148 for (CurrentAceIndex = 0;
1149 CurrentAceIndex < AclInfo.AceCount;
1150 CurrentAceIndex++)
1151 {
1152 /**
1153 * TEP 10: Get an ACE.
1154 */
1155 if (!GNGetAce(pACL, CurrentAceIndex, &pTempAce))
1156 {
1157 goto end;
1158 }
1159
1160 /**
1161 * STEP 11: Check if it is a non-inherited ACE.
1162 * If it is an inherited ACE, break from the loop so
1163 * that the new access allowed non-inherited ACE can
1164 * be added in the correct position, immediately after
1165 * all non-inherited ACEs.
1166 */
1167 if (((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags
1168 & INHERITED_ACE)
1169 break;
1170
1171 /**
1172 * STEP 12: Skip adding the ACE, if the SID matches
1173 * with the account specified, as we are going to
1174 * add an access allowed ACE with a different access
1175 * mask.
1176 */
1177 if (GNEqualSid(pUserSID,
1178 &(((ACCESS_ALLOWED_ACE *)pTempAce)->SidStart)))
1179 continue;
1180
1181 /**
1182 * STEP 13: Add the ACE to the new ACL.
1183 */
1184 if (!GNAddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
1185 ((PACE_HEADER)pTempAce)->AceSize))
1186 {
1187 goto end;
1188 }
1189
1190 newAceIndex++;
1191 }
1192 }
1193
1194 /**
1195 * STEP 14: Add the access-allowed ACE to the new DACL.
1196 * The new ACE added here will be in the correct position,
1197 * immediately after all existing non-inherited ACEs.
1198 */
1199 if (!GNAddAccessAllowedAce(pNewACL, ACL_REVISION2, dwAccessMask,
1200 pUserSID))
1201 {
1202 goto end;
1203 }
1204
1205 /**
1206 * STEP 14.5: Make new ACE inheritable
1207 */
1208 if (!GetAce(pNewACL, newAceIndex, &pTempAce))
1209 goto end;
1210 ((ACCESS_ALLOWED_ACE *)pTempAce)->Header.AceFlags |=
1211 (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE);
1212
1213 /**
1214 * STEP 15: To conform to the new Windows 2000 preferred order,
1215 * we will now copy the rest of inherited ACEs from the
1216 * old DACL to the new DACL.
1217 */
1218 if (fDaclPresent && AclInfo.AceCount)
1219 {
1220 for (;
1221 CurrentAceIndex < AclInfo.AceCount;
1222 CurrentAceIndex++)
1223 {
1224 /**
1225 * STEP 16: Get an ACE.
1226 */
1227 if (!GNGetAce(pACL, CurrentAceIndex, &pTempAce))
1228 {
1229 goto end;
1230 }
1231
1232 /**
1233 * STEP 17: Add the ACE to the new ACL.
1234 */
1235 if (!GNAddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,
1236 ((PACE_HEADER)pTempAce)->AceSize))
1237 {
1238 goto end;
1239 }
1240 }
1241 }
1242
1243 /**
1244 * STEP 18: Set permissions
1245 */
1246 if (GNSetNamedSecurityInfo((LPTSTR)lpszFileName, SE_FILE_OBJECT,
1247 DACL_SECURITY_INFORMATION, NULL, NULL, pNewACL, NULL) != ERROR_SUCCESS)
1248 {
1249 goto end;
1250 }
1251
1252 fResult = TRUE;
1253
1254end:
1255
1256 /**
1257 * STEP 19: Free allocated memory
1258 */
1259 if (pUserSID)
1260 HeapFree(GetProcessHeap(), 0, pUserSID);
1261
1262 if (szDomain)
1263 HeapFree(GetProcessHeap(), 0, szDomain);
1264
1265 if (pFileSD)
1266 HeapFree(GetProcessHeap(), 0, pFileSD);
1267
1268 if (pNewACL)
1269 HeapFree(GetProcessHeap(), 0, pNewACL);
1270
1271 return fResult;
1272}
1273
1274char *winErrorStr(const char *prefix, int dwErr)
1275{
1276 char *err, *ret;
1277 int mem;
1278
1279 if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
1280 NULL, (DWORD)dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&err,
1281 0, NULL))
1282 {
1283 err = (char *)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, 1);
1284 }
1285
1286 mem = strlen(err) + strlen(prefix) + 20;
1287 ret = (char *)malloc(mem);
1288
1289 snprintf(ret, mem, "%s: %s (#%u)", prefix, err, dwErr);
1290
1291 LocalFree(err);
1292
1293 return ret;
1294}
1295
1296/**
1297 * Terminate a process by creating a remote thread within it,
1298 * which proceeds to call ExitProcess() inside that process.
1299 * Safer than TerminateProcess ().
1300 *
1301 * Code is from From http://private-storm.de/2009/08/11/case-terminateprocess/
1302 *
1303 * @param hProcess handle of a process to terminate
1304 * @param uExitCode exit code to use for ExitProcess()
1305 * @param dwTimeout number of ms to wait for the process to terminate
1306 * @return TRUE on success, FALSE on failure (check last error for the code)
1307 */
1308BOOL
1309SafeTerminateProcess(HANDLE hProcess, UINT uExitCode, DWORD dwTimeout)
1310{
1311 DWORD dwTID, dwCode, dwErr = 0;
1312 HANDLE hProcessDup = INVALID_HANDLE_VALUE;
1313 HANDLE hRT = NULL;
1314 HINSTANCE hKernel = GetModuleHandle("Kernel32");
1315 BOOL bSuccess = FALSE;
1316
1317 BOOL bDup = DuplicateHandle(GetCurrentProcess(), hProcess,
1318 GetCurrentProcess(), &hProcessDup, PROCESS_ALL_ACCESS,
1319 FALSE, 0);
1320
1321 /* Detect the special case where the process is
1322 * already dead...
1323 */
1324 if (GetExitCodeProcess(bDup ? hProcessDup : hProcess, &dwCode) &&
1325 (STILL_ACTIVE == dwCode))
1326 {
1327 FARPROC pfnExitProc;
1328
1329 pfnExitProc = GetProcAddress(hKernel, "ExitProcess");
1330
1331 hRT = CreateRemoteThread((bDup) ? hProcessDup : hProcess, NULL, 0,
1332 (LPTHREAD_START_ROUTINE)pfnExitProc, (PVOID)uExitCode, 0, &dwTID);
1333
1334 dwErr = GetLastError();
1335 }
1336 else
1337 {
1338 dwErr = ERROR_PROCESS_ABORTED;
1339 }
1340
1341 if (hRT)
1342 {
1343 /* Must wait process to terminate to
1344 * guarantee that it has exited...
1345 */
1346 DWORD dwWaitResult = WaitForSingleObject((bDup) ? hProcessDup : hProcess,
1347 dwTimeout);
1348 if (dwWaitResult == WAIT_TIMEOUT)
1349 dwErr = WAIT_TIMEOUT;
1350 else
1351 dwErr = GetLastError();
1352
1353 CloseHandle(hRT);
1354 bSuccess = dwErr == NO_ERROR;
1355 }
1356
1357 if (bDup)
1358 CloseHandle(hProcessDup);
1359
1360 SetLastError(dwErr);
1361
1362 return bSuccess;
1363}
1364
1365#endif
diff --git a/src/util/winproc.c b/src/util/winproc.c
deleted file mode 100644
index f2e4de4df..000000000
--- a/src/util/winproc.c
+++ /dev/null
@@ -1,340 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file util/winproc.c
23 * @brief Functions for MS Windows
24 * @author Nils Durner
25 */
26
27#include "platform.h"
28#include "gnunet_crypto_lib.h"
29#include "gnunet_common.h"
30
31
32#ifdef MINGW
33
34static HINSTANCE hNTDLL, hIphlpapi, hAdvapi, hNetapi;
35#ifdef W32_VEH
36static void *GNWinVEH_handle = NULL;
37#endif
38
39TNtQuerySystemInformation GNNtQuerySystemInformation;
40TGetIfEntry GNGetIfEntry;
41TGetIpAddrTable GNGetIpAddrTable;
42TGetIfTable GNGetIfTable;
43TOpenSCManager GNOpenSCManager;
44TCreateService GNCreateService;
45TCloseServiceHandle GNCloseServiceHandle;
46TDeleteService GNDeleteService;
47TRegisterServiceCtrlHandler GNRegisterServiceCtrlHandler;
48TSetServiceStatus GNSetServiceStatus;
49TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher;
50TControlService GNControlService;
51TOpenService GNOpenService;
52TGetBestInterfaceEx GNGetBestInterfaceEx;
53TGetAdaptersInfo GNGetAdaptersInfo;
54TNetUserAdd GNNetUserAdd;
55TNetUserSetInfo GNNetUserSetInfo;
56TLsaOpenPolicy GNLsaOpenPolicy;
57TLsaAddAccountRights GNLsaAddAccountRights;
58TLsaRemoveAccountRights GNLsaRemoveAccountRights;
59TLsaClose GNLsaClose;
60TLookupAccountName GNLookupAccountName;
61TGetFileSecurity GNGetFileSecurity;
62TInitializeSecurityDescriptor GNInitializeSecurityDescriptor;
63TGetSecurityDescriptorDacl GNGetSecurityDescriptorDacl;
64TGetAclInformation GNGetAclInformation;
65TInitializeAcl GNInitializeAcl;
66TGetAce GNGetAce;
67TEqualSid GNEqualSid;
68TAddAce GNAddAce;
69TAddAccessAllowedAce GNAddAccessAllowedAce;
70TSetNamedSecurityInfo GNSetNamedSecurityInfo;
71
72#define LOG(kind, ...) GNUNET_log_from(kind, "util-winproc", __VA_ARGS__)
73/**
74 * Log (panic) messages from PlibC
75 */
76void
77plibc_panic(int err, char *msg)
78{
79 LOG(((err == INT_MAX) ? GNUNET_ERROR_TYPE_DEBUG : GNUNET_ERROR_TYPE_ERROR),
80 "%s", msg);
81}
82
83#ifdef W32_VEH
84/**
85 * Handles exceptions (useful for debugging).
86 * Issues a DebugBreak() call if the process is being debugged (not really
87 * useful - if the process is being debugged, this handler won't be invoked
88 * anyway). If it is not, runs a debugger from GNUNET_DEBUGGER env var,
89 * substituting first %u in it for PID, and the second one for the event,
90 * that should be set once the debugger attaches itself (otherwise the
91 * only way out of WaitForSingleObject() is to time out after 1 minute).
92 */
93LONG __stdcall
94GNWinVEH(PEXCEPTION_POINTERS ExceptionInfo)
95{
96 char debugger[MAX_PATH + 1];
97 char *debugger_env = NULL;
98
99 if (IsDebuggerPresent())
100 {
101 DebugBreak();
102 return EXCEPTION_CONTINUE_EXECUTION;
103 }
104 debugger_env = getenv("GNUNET_DEBUGGER");
105 if (debugger_env != NULL)
106 {
107 STARTUPINFO si;
108 PROCESS_INFORMATION pi;
109 HANDLE event;
110 SECURITY_ATTRIBUTES sa;
111 memset(&si, 0, sizeof(si));
112 si.cb = sizeof(si);
113 memset(&pi, 0, sizeof(pi));
114 memset(&sa, 0, sizeof(sa));
115 sa.nLength = sizeof(sa);
116 sa.bInheritHandle = TRUE;
117 event = CreateEvent(&sa, FALSE, FALSE, NULL);
118 snprintf(debugger, MAX_PATH + 1, debugger_env, GetCurrentProcessId(), (uintptr_t)event);
119 debugger[MAX_PATH] = '\0';
120 if (0 != CreateProcessA(NULL, debugger, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
121 {
122 CloseHandle(pi.hProcess);
123 CloseHandle(pi.hThread);
124 WaitForSingleObject(event, 60000);
125 CloseHandle(event);
126 if (IsDebuggerPresent())
127 {
128 return EXCEPTION_CONTINUE_EXECUTION;
129 }
130 }
131 else
132 CloseHandle(event);
133 }
134 return EXCEPTION_CONTINUE_SEARCH;
135}
136#endif
137
138/**
139 * @brief Initialize PlibC and set up Windows environment
140 * @param logging context, NULL means stderr
141 * @return Error code from winerror.h, ERROR_SUCCESS on success
142 */
143int
144GNInitWinEnv()
145{
146 int ret;
147
148 plibc_initialized();
149 plibc_set_panic_proc(plibc_panic);
150 ret = plibc_init_utf8("GNU", PACKAGE, 1);
151 plibc_set_stat_size_size(sizeof(((struct stat *)0)->st_size));
152 plibc_set_stat_time_size(sizeof(((struct stat *)0)->st_mtime));
153 /* don't load other DLLs twice */
154 if (hNTDLL)
155 return ret;
156
157#ifdef W32_VEH
158 if (GNWinVEH_handle == NULL)
159 {
160 GNWinVEH_handle = AddVectoredExceptionHandler(1, &GNWinVEH);
161 if (GNWinVEH_handle == NULL)
162 {
163 /* This is bad, but what can we do? */
164 printf("Failed to set up an exception handler!\n");
165 }
166 }
167#endif
168
169 hNTDLL = LoadLibrary("ntdll.dll");
170
171 /* Function to get CPU usage under Win NT */
172 if (hNTDLL)
173 {
174 GNNtQuerySystemInformation =
175 (TNtQuerySystemInformation)GetProcAddress(hNTDLL,
176 "NtQuerySystemInformation");
177 }
178 else
179 {
180 GNNtQuerySystemInformation = NULL;
181 }
182
183 /* Functions to get information about a network adapter */
184 hIphlpapi = LoadLibrary("iphlpapi.dll");
185 if (hIphlpapi)
186 {
187 GNGetIfEntry = (TGetIfEntry)GetProcAddress(hIphlpapi, "GetIfEntry");
188 GNGetIpAddrTable =
189 (TGetIpAddrTable)GetProcAddress(hIphlpapi, "GetIpAddrTable");
190 GNGetIfTable = (TGetIfTable)GetProcAddress(hIphlpapi, "GetIfTable");
191 GNGetBestInterfaceEx =
192 (TGetBestInterfaceEx)GetProcAddress(hIphlpapi, "GetBestInterfaceEx");
193 GNGetAdaptersInfo =
194 (TGetAdaptersInfo)GetProcAddress(hIphlpapi, "GetAdaptersInfo");
195 }
196 else
197 {
198 GNGetIfEntry = NULL;
199 GNGetIpAddrTable = NULL;
200 GNGetIfTable = NULL;
201 GNGetBestInterfaceEx = NULL;
202 GNGetAdaptersInfo = NULL;
203 }
204
205 /* Service & Account functions */
206 hAdvapi = LoadLibrary("advapi32.dll");
207 if (hAdvapi)
208 {
209 GNOpenSCManager =
210 (TOpenSCManager)GetProcAddress(hAdvapi, "OpenSCManagerA");
211 GNCreateService =
212 (TCreateService)GetProcAddress(hAdvapi, "CreateServiceA");
213 GNCloseServiceHandle =
214 (TCloseServiceHandle)GetProcAddress(hAdvapi, "CloseServiceHandle");
215 GNDeleteService =
216 (TDeleteService)GetProcAddress(hAdvapi, "DeleteService");
217 GNRegisterServiceCtrlHandler =
218 (TRegisterServiceCtrlHandler)GetProcAddress(hAdvapi,
219 "RegisterServiceCtrlHandlerA");
220 GNSetServiceStatus =
221 (TSetServiceStatus)GetProcAddress(hAdvapi, "SetServiceStatus");
222 GNStartServiceCtrlDispatcher =
223 (TStartServiceCtrlDispatcher)GetProcAddress(hAdvapi,
224 "StartServiceCtrlDispatcherA");
225 GNControlService =
226 (TControlService)GetProcAddress(hAdvapi, "ControlService");
227 GNOpenService = (TOpenService)GetProcAddress(hAdvapi, "OpenServiceA");
228
229 GNLsaOpenPolicy =
230 (TLsaOpenPolicy)GetProcAddress(hAdvapi, "LsaOpenPolicy");
231 GNLsaAddAccountRights =
232 (TLsaAddAccountRights)GetProcAddress(hAdvapi, "LsaAddAccountRights");
233 GNLsaRemoveAccountRights =
234 (TLsaRemoveAccountRights)GetProcAddress(hAdvapi,
235 "LsaRemoveAccountRights");
236 GNLsaClose = (TLsaClose)GetProcAddress(hAdvapi, "LsaClose");
237 GNLookupAccountName =
238 (TLookupAccountName)GetProcAddress(hAdvapi, "LookupAccountNameA");
239
240 GNGetFileSecurity =
241 (TGetFileSecurity)GetProcAddress(hAdvapi, "GetFileSecurityA");
242 GNInitializeSecurityDescriptor =
243 (TInitializeSecurityDescriptor)GetProcAddress(hAdvapi,
244 "InitializeSecurityDescriptor");
245 GNGetSecurityDescriptorDacl =
246 (TGetSecurityDescriptorDacl)GetProcAddress(hAdvapi,
247 "GetSecurityDescriptorDacl");
248 GNGetAclInformation =
249 (TGetAclInformation)GetProcAddress(hAdvapi, "GetAclInformation");
250 GNInitializeAcl =
251 (TInitializeAcl)GetProcAddress(hAdvapi, "InitializeAcl");
252 GNGetAce = (TGetAce)GetProcAddress(hAdvapi, "GetAce");
253 GNEqualSid = (TEqualSid)GetProcAddress(hAdvapi, "EqualSid");
254 GNAddAce = (TAddAce)GetProcAddress(hAdvapi, "AddAce");
255 GNAddAccessAllowedAce =
256 (TAddAccessAllowedAce)GetProcAddress(hAdvapi, "AddAccessAllowedAce");
257 GNSetNamedSecurityInfo =
258 (TSetNamedSecurityInfo)GetProcAddress(hAdvapi,
259 "SetNamedSecurityInfoA");
260 }
261 else
262 {
263 GNOpenSCManager = NULL;
264 GNCreateService = NULL;
265 GNCloseServiceHandle = NULL;
266 GNDeleteService = NULL;
267 GNRegisterServiceCtrlHandler = NULL;
268 GNSetServiceStatus = NULL;
269 GNStartServiceCtrlDispatcher = NULL;
270 GNControlService = NULL;
271 GNOpenService = NULL;
272
273 GNLsaOpenPolicy = NULL;
274 GNLsaAddAccountRights = NULL;
275 GNLsaRemoveAccountRights = NULL;
276 GNLsaClose = NULL;
277 GNLookupAccountName = NULL;
278
279 GNGetFileSecurity = NULL;
280 GNInitializeSecurityDescriptor = NULL;
281 GNGetSecurityDescriptorDacl = NULL;
282 GNGetAclInformation = NULL;
283 GNInitializeAcl = NULL;
284 GNGetAce = NULL;
285 GNEqualSid = NULL;
286 GNAddAce = NULL;
287 GNAddAccessAllowedAce = NULL;
288 GNSetNamedSecurityInfo = NULL;
289 }
290
291 /* Account function */
292 hNetapi = LoadLibrary("netapi32.dll");
293 if (hNetapi)
294 {
295 GNNetUserAdd = (TNetUserAdd)GetProcAddress(hNetapi, "NetUserAdd");
296 GNNetUserSetInfo =
297 (TNetUserSetInfo)GetProcAddress(hNetapi, "NetUserSetInfo");
298 }
299 else
300 {
301 GNNetUserAdd = NULL;
302 GNNetUserSetInfo = NULL;
303 }
304
305 return ret;
306}
307
308/**
309 * Clean up Windows environment
310 */
311void
312GNShutdownWinEnv()
313{
314 plibc_shutdown();
315
316#ifdef W32_VEH
317 if (GNWinVEH_handle != NULL)
318 {
319 RemoveVectoredExceptionHandler(GNWinVEH_handle);
320 GNWinVEH_handle = NULL;
321 }
322#endif
323
324 FreeLibrary(hNTDLL);
325 FreeLibrary(hIphlpapi);
326 FreeLibrary(hAdvapi);
327 FreeLibrary(hNetapi);
328
329 CoUninitialize();
330}
331
332#endif /* MINGW */
333
334#if !HAVE_ATOLL
335long long
336atoll(const char *nptr)
337{
338 return atol(nptr);
339}
340#endif