aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
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