diff options
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/Makefile.am | 43 | ||||
-rw-r--r-- | src/util/disk.c | 88 | ||||
-rw-r--r-- | src/util/dnsstub.c | 6 | ||||
-rw-r--r-- | src/util/gnunet-timeout-w32.c | 193 | ||||
-rw-r--r-- | src/util/network.c | 866 | ||||
-rw-r--r-- | src/util/os_installation.c | 78 | ||||
-rw-r--r-- | src/util/os_network.c | 29 | ||||
-rw-r--r-- | src/util/os_priority.c | 615 | ||||
-rw-r--r-- | src/util/scheduler.c | 46 | ||||
-rw-r--r-- | src/util/service.c | 110 | ||||
-rw-r--r-- | src/util/strings.c | 35 | ||||
-rw-r--r-- | src/util/test_common_logging_runtime_loglevels.c | 4 | ||||
-rw-r--r-- | src/util/test_configuration.c | 6 | ||||
-rw-r--r-- | src/util/test_getopt.c | 4 | ||||
-rw-r--r-- | src/util/test_resolver_api.c | 5 | ||||
-rw-r--r-- | src/util/test_scheduler.c | 4 | ||||
-rw-r--r-- | src/util/test_service.c | 3 | ||||
-rw-r--r-- | src/util/test_strings.c | 6 | ||||
-rw-r--r-- | src/util/w32cat.c | 154 | ||||
-rw-r--r-- | src/util/win.c | 1365 | ||||
-rw-r--r-- | src/util/winproc.c | 340 |
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 = \ | |||
13 | pkgcfg_DATA = \ | 13 | pkgcfg_DATA = \ |
14 | resolver.conf | 14 | resolver.conf |
15 | 15 | ||
16 | if MINGW | 16 | TEST_CLIENT_UNIX_NC = test_client_unix.nc |
17 | noinst_LTLIBRARIES = \ | ||
18 | libgnunetutilwin.la | ||
19 | libgnunetutilwin_la_SOURCES = \ | ||
20 | win.c \ | ||
21 | winproc.c | ||
22 | libgnunetutilwin_la_LDFLAGS = \ | ||
23 | -no-undefined -Wl,--export-all-symbols | ||
24 | libgnunetutilwin_la_LIBADD = \ | ||
25 | -lshell32 -liconv -lstdc++ \ | ||
26 | -lcomdlg32 -lgdi32 -liphlpapi | ||
27 | WINLIB = libgnunetutilwin.la | ||
28 | W32CAT = w32cat | ||
29 | W32CONSOLEHELPER = gnunet-helper-w32-console | ||
30 | endif | ||
31 | |||
32 | if !MINGW | ||
33 | TEST_CLIENT_UNIX_NC = test_client_unix.nc | ||
34 | else | ||
35 | TEST_CLIENT_UNIX_NC = | ||
36 | endif | ||
37 | 17 | ||
38 | if USE_COVERAGE | 18 | if 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 |
46 | endif | 26 | endif |
47 | 27 | ||
48 | w32cat_SOURCES = w32cat.c | ||
49 | |||
50 | gnunet_helper_w32_console_SOURCES = \ | ||
51 | gnunet-helper-w32-console.c \ | ||
52 | gnunet-helper-w32-console.h | ||
53 | gnunet_helper_w32_console_LDADD = \ | ||
54 | libgnunetutil.la | ||
55 | |||
56 | gnunet_config_diff_SOURCES = \ | 28 | gnunet_config_diff_SOURCES = \ |
57 | gnunet-config-diff.c | 29 | gnunet-config-diff.c |
58 | gnunet_config_diff_LDADD = \ | 30 | gnunet_config_diff_LDADD = \ |
@@ -202,8 +174,7 @@ lib_LTLIBRARIES = libgnunetutil.la | |||
202 | 174 | ||
203 | libexec_PROGRAMS = \ | 175 | libexec_PROGRAMS = \ |
204 | gnunet-service-resolver \ | 176 | gnunet-service-resolver \ |
205 | gnunet-timeout \ | 177 | gnunet-timeout |
206 | $(W32CONSOLEHELPER) | ||
207 | 178 | ||
208 | bin_PROGRAMS = \ | 179 | bin_PROGRAMS = \ |
209 | gnunet-resolver \ | 180 | gnunet-resolver \ |
@@ -217,7 +188,6 @@ endif | |||
217 | 188 | ||
218 | noinst_PROGRAMS = \ | 189 | noinst_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 | ||
229 | endif | 199 | endif |
230 | 200 | ||
231 | |||
232 | if !MINGW | ||
233 | gnunet_timeout_SOURCES = \ | 201 | gnunet_timeout_SOURCES = \ |
234 | gnunet-timeout.c | 202 | gnunet-timeout.c |
235 | else | ||
236 | gnunet_timeout_SOURCES = \ | ||
237 | gnunet-timeout-w32.c | ||
238 | endif | ||
239 | 203 | ||
240 | gnunet_service_resolver_SOURCES = \ | 204 | gnunet_service_resolver_SOURCES = \ |
241 | gnunet-service-resolver.c | 205 | gnunet-service-resolver.c |
@@ -393,8 +357,7 @@ test_os_start_process_SOURCES = \ | |||
393 | test_os_start_process_LDADD = \ | 357 | test_os_start_process_LDADD = \ |
394 | libgnunetutil.la | 358 | libgnunetutil.la |
395 | test_os_start_process_DEPENDENCIES = \ | 359 | test_os_start_process_DEPENDENCIES = \ |
396 | libgnunetutil.la \ | 360 | libgnunetutil.la |
397 | $(WINCAT) | ||
398 | 361 | ||
399 | test_client_nc_SOURCES = \ | 362 | test_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) | |||
191 | int | 189 | int |
192 | GNUNET_DISK_handle_invalid(const struct GNUNET_DISK_FileHandle *h) | 190 | GNUNET_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 | |||
31 | int | ||
32 | main(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 | |||
1054 | GNUNET_NETWORK_fdset_add(struct GNUNET_NETWORK_FDSet *dst, | 1032 | GNUNET_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 | |||
1217 | GNUNET_NETWORK_fdset_handle_set(struct GNUNET_NETWORK_FDSet *fds, | 1159 | GNUNET_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 | |||
1247 | GNUNET_NETWORK_fdset_handle_set_first(struct GNUNET_NETWORK_FDSet *fds, | 1181 | GNUNET_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 | |||
1277 | GNUNET_NETWORK_fdset_handle_isset(const struct GNUNET_NETWORK_FDSet *fds, | 1196 | GNUNET_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 | */ | ||
1303 | static int | ||
1304 | ptr_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 | |||
1324 | GNUNET_NETWORK_fdset_overlap(const struct GNUNET_NETWORK_FDSet *fds1, | 1212 | GNUNET_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() | |||
1413 | void | 1253 | void |
1414 | GNUNET_NETWORK_fdset_destroy(struct GNUNET_NETWORK_FDSet *fds) | 1254 | GNUNET_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 | */ | ||
1429 | struct _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 | */ | ||
1475 | static 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 | |||
1503 | static HANDLE hEventPipeWrite; | ||
1504 | |||
1505 | static HANDLE hEventReadReady; | ||
1506 | |||
1507 | static struct _select_params sp; | ||
1508 | |||
1509 | static HANDLE select_thread; | ||
1510 | |||
1511 | static HANDLE select_finished_event; | ||
1512 | |||
1513 | static HANDLE select_standby_event; | ||
1514 | |||
1515 | static _win_socket select_wakeup_socket = -1; | ||
1516 | |||
1517 | static _win_socket select_send_socket = -1; | ||
1518 | |||
1519 | static 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 | */ | ||
1527 | static void | ||
1528 | initialize_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 | */ | ||
1728 | static int | ||
1729 | pipe_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 | */ | ||
1760 | static int | ||
1761 | pipe_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 | */ | ||
1784 | static int | ||
1785 | check_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 | */ | ||
1831 | int | ||
1832 | GNUNET_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 | |||
388 | GNUNET_OS_network_interfaces_list(GNUNET_OS_NetworkInterfaceProcessor proc, | 388 | GNUNET_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, | |||
1589 | int | 999 | int |
1590 | GNUNET_OS_process_wait(struct GNUNET_OS_Process *proc) | 1000 | GNUNET_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 | ||
625 | static void | 622 | static void |
626 | sighandler_pipe() | 623 | sighandler_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 | ||
1400 | static struct GNUNET_SCHEDULER_Task * | 1395 | static struct GNUNET_SCHEDULER_Task * |
1401 | add_without_sets(struct GNUNET_TIME_Relative delay, | 1396 | add_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 | */ | ||
1365 | static struct GNUNET_NETWORK_Handle ** | ||
1366 | receive_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) | |||
1808 | static int | 1711 | static int |
1809 | detach_terminal(struct GNUNET_SERVICE_Handle *sh) | 1712 | detach_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 * | |||
602 | GNUNET_STRINGS_filename_expand(const char *fil) | 602 | GNUNET_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 | ||
215 | static void | 214 | static void |
216 | taskSig(void *cls) | 215 | taskSig(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 | ||
250 | static void | 248 | static 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 | |||
28 | DWORD WINAPI | ||
29 | parent_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 | |||
47 | void | ||
48 | install_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 | |||
67 | int | ||
68 | main(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 | |||
41 | int 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 | ||
77 | typedef 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 | |||
89 | typedef 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 | |||
102 | typedef UINT32 NET_IF_COMPARTMENT_ID; | ||
103 | typedef GUID NET_IF_NETWORK_GUID; | ||
104 | |||
105 | #ifndef __MINGW64_VERSION_MAJOR | ||
106 | typedef 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 | |||
113 | typedef 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 | ||
133 | typedef 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 | |||
144 | typedef 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 | |||
220 | static int | ||
221 | EnumNICs_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 | |||
236 | static int | ||
237 | EnumNICs_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 | |||
263 | static int | ||
264 | EnumNICs_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 | |||
302 | int | ||
303 | EnumNICs2(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 | } | ||
347 | error: | ||
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 | */ | ||
363 | int | ||
364 | EnumNICs3(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 | |||
625 | void | ||
626 | EnumNICs3_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 | */ | ||
639 | int | ||
640 | ListNICs(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 | */ | ||
667 | int 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 | */ | ||
713 | int | ||
714 | UninstallService(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 | |||
737 | closeSCM: | ||
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 | */ | ||
748 | void | ||
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 | */ | ||
773 | NTSTATUS | ||
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 | */ | ||
807 | BOOL | ||
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 | |||
854 | end: | ||
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 | */ | ||
875 | NTSTATUS | ||
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 | */ | ||
916 | int | ||
917 | CreateServiceAccount(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 | */ | ||
972 | BOOL 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 | |||
1254 | end: | ||
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 | |||
1274 | char *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 | */ | ||
1308 | BOOL | ||
1309 | SafeTerminateProcess(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 | |||
34 | static HINSTANCE hNTDLL, hIphlpapi, hAdvapi, hNetapi; | ||
35 | #ifdef W32_VEH | ||
36 | static void *GNWinVEH_handle = NULL; | ||
37 | #endif | ||
38 | |||
39 | TNtQuerySystemInformation GNNtQuerySystemInformation; | ||
40 | TGetIfEntry GNGetIfEntry; | ||
41 | TGetIpAddrTable GNGetIpAddrTable; | ||
42 | TGetIfTable GNGetIfTable; | ||
43 | TOpenSCManager GNOpenSCManager; | ||
44 | TCreateService GNCreateService; | ||
45 | TCloseServiceHandle GNCloseServiceHandle; | ||
46 | TDeleteService GNDeleteService; | ||
47 | TRegisterServiceCtrlHandler GNRegisterServiceCtrlHandler; | ||
48 | TSetServiceStatus GNSetServiceStatus; | ||
49 | TStartServiceCtrlDispatcher GNStartServiceCtrlDispatcher; | ||
50 | TControlService GNControlService; | ||
51 | TOpenService GNOpenService; | ||
52 | TGetBestInterfaceEx GNGetBestInterfaceEx; | ||
53 | TGetAdaptersInfo GNGetAdaptersInfo; | ||
54 | TNetUserAdd GNNetUserAdd; | ||
55 | TNetUserSetInfo GNNetUserSetInfo; | ||
56 | TLsaOpenPolicy GNLsaOpenPolicy; | ||
57 | TLsaAddAccountRights GNLsaAddAccountRights; | ||
58 | TLsaRemoveAccountRights GNLsaRemoveAccountRights; | ||
59 | TLsaClose GNLsaClose; | ||
60 | TLookupAccountName GNLookupAccountName; | ||
61 | TGetFileSecurity GNGetFileSecurity; | ||
62 | TInitializeSecurityDescriptor GNInitializeSecurityDescriptor; | ||
63 | TGetSecurityDescriptorDacl GNGetSecurityDescriptorDacl; | ||
64 | TGetAclInformation GNGetAclInformation; | ||
65 | TInitializeAcl GNInitializeAcl; | ||
66 | TGetAce GNGetAce; | ||
67 | TEqualSid GNEqualSid; | ||
68 | TAddAce GNAddAce; | ||
69 | TAddAccessAllowedAce GNAddAccessAllowedAce; | ||
70 | TSetNamedSecurityInfo GNSetNamedSecurityInfo; | ||
71 | |||
72 | #define LOG(kind, ...) GNUNET_log_from(kind, "util-winproc", __VA_ARGS__) | ||
73 | /** | ||
74 | * Log (panic) messages from PlibC | ||
75 | */ | ||
76 | void | ||
77 | plibc_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 | */ | ||
93 | LONG __stdcall | ||
94 | GNWinVEH(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 | */ | ||
143 | int | ||
144 | GNInitWinEnv() | ||
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 | */ | ||
311 | void | ||
312 | GNShutdownWinEnv() | ||
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 | ||
335 | long long | ||
336 | atoll(const char *nptr) | ||
337 | { | ||
338 | return atol(nptr); | ||
339 | } | ||
340 | #endif | ||