[WINHTTP_WINETEST] Sync with Wine Staging 1.9.23. CORE-12409
[reactos.git] / rostests / winetests / winhttp / winhttp.c
1 /*
2 * WinHTTP - tests
3 *
4 * Copyright 2008 Google (Zac Brown)
5 * Copyright 2015 Dmitry Timoshkov
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #define WIN32_NO_STATUS
23 #define _INC_WINDOWS
24 #define COM_NO_WINDOWS_H
25
26 #define COBJMACROS
27 #include <stdarg.h>
28 #include <windef.h>
29 #include <winbase.h>
30 #include <winnls.h>
31 #include <ole2.h>
32 #include <winsock2.h>
33 //#include <ws2tcpip.h>
34 #include <winhttp.h>
35 #include <wincrypt.h>
36 #include <winreg.h>
37 #include <stdio.h>
38 //#include "initguid.h"
39 #include <httprequest.h>
40 #include <httprequestid.h>
41
42 #include <wine/test.h>
43
44 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
45
46 static const WCHAR test_useragent[] =
47 {'W','i','n','e',' ','R','e','g','r','e','s','s','i','o','n',' ','T','e','s','t',0};
48 static const WCHAR test_winehq[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
49 static const WCHAR test_winehq_https[] = {'h','t','t','p','s',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','4','4','3',0};
50 static const WCHAR localhostW[] = {'l','o','c','a','l','h','o','s','t',0};
51
52 static BOOL proxy_active(void)
53 {
54 WINHTTP_PROXY_INFO proxy_info;
55 BOOL active = FALSE;
56
57 SetLastError(0xdeadbeef);
58 if (WinHttpGetDefaultProxyConfiguration(&proxy_info))
59 {
60 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
61 "got %u\n", GetLastError());
62 active = (proxy_info.lpszProxy != NULL);
63 if (active)
64 GlobalFree(proxy_info.lpszProxy);
65 if (proxy_info.lpszProxyBypass != NULL)
66 GlobalFree(proxy_info.lpszProxyBypass);
67 }
68 else
69 active = FALSE;
70
71 return active;
72 }
73
74 static void test_QueryOption(void)
75 {
76 BOOL ret;
77 HINTERNET session, request, connection;
78 DWORD feature, size;
79
80 SetLastError(0xdeadbeef);
81 session = WinHttpOpen(test_useragent, 0, 0, 0, 0);
82 ok(session != NULL, "WinHttpOpen failed to open session, error %u\n", GetLastError());
83
84 SetLastError(0xdeadbeef);
85 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, NULL);
86 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
87 ok(GetLastError() == ERROR_INVALID_PARAMETER,
88 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
89
90 size = 0xdeadbeef;
91 SetLastError(0xdeadbeef);
92 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, &size);
93 ok(!ret, "should fail to query option\n");
94 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
95 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
96 ok(size == 4, "expected 4, got %u\n", size);
97
98 feature = 0xdeadbeef;
99 size = sizeof(feature) - 1;
100 SetLastError(0xdeadbeef);
101 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
102 ok(!ret, "should fail to query option\n");
103 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
104 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
105 ok(size == 4, "expected 4, got %u\n", size);
106
107 feature = 0xdeadbeef;
108 size = sizeof(feature) + 1;
109 SetLastError(0xdeadbeef);
110 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
111 ok(ret, "failed to query option %u\n", GetLastError());
112 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
113 "got %u\n", GetLastError());
114 ok(size == sizeof(feature), "WinHttpQueryOption should set the size: %u\n", size);
115 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP,
116 "expected WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP, got %#x\n", feature);
117
118 SetLastError(0xdeadbeef);
119 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, sizeof(feature));
120 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
121 ok(GetLastError() == ERROR_INVALID_PARAMETER,
122 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
123
124 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
125 SetLastError(0xdeadbeef);
126 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) - 1);
127 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
128 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
129 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
130
131 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
132 SetLastError(0xdeadbeef);
133 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) + 1);
134 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
135 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
136 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
137
138 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
139 SetLastError(0xdeadbeef);
140 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature));
141 ok(ret, "failed to set redirect policy %u\n", GetLastError());
142
143 feature = 0xdeadbeef;
144 size = sizeof(feature);
145 SetLastError(0xdeadbeef);
146 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
147 ok(ret, "failed to query option %u\n", GetLastError());
148 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS,
149 "expected WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS, got %#x\n", feature);
150
151 feature = WINHTTP_DISABLE_COOKIES;
152 SetLastError(0xdeadbeef);
153 ret = WinHttpSetOption(session, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
154 ok(!ret, "should fail to set disable feature for a session\n");
155 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
156 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
157
158 SetLastError(0xdeadbeef);
159 connection = WinHttpConnect(session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
160 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u\n", GetLastError());
161
162 feature = WINHTTP_DISABLE_COOKIES;
163 SetLastError(0xdeadbeef);
164 ret = WinHttpSetOption(connection, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
165 ok(!ret, "should fail to set disable feature for a connection\n");
166 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
167 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
168
169 SetLastError(0xdeadbeef);
170 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
171 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
172 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
173 {
174 skip("Network unreachable, skipping the test\n");
175 goto done;
176 }
177
178 feature = 0xdeadbeef;
179 size = sizeof(feature);
180 SetLastError(0xdeadbeef);
181 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, &size);
182 ok(!ret, "should fail to query disable feature for a request\n");
183 ok(GetLastError() == ERROR_INVALID_PARAMETER,
184 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
185
186 feature = 0;
187 size = sizeof(feature);
188 SetLastError(0xdeadbeef);
189 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
190 ok(ret, "failed to set feature %u\n", GetLastError());
191
192 feature = 0xffffffff;
193 size = sizeof(feature);
194 SetLastError(0xdeadbeef);
195 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
196 ok(ret, "failed to set feature %u\n", GetLastError());
197
198 feature = WINHTTP_DISABLE_COOKIES;
199 size = sizeof(feature);
200 SetLastError(0xdeadbeef);
201 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
202 ok(ret, "failed to set feature %u\n", GetLastError());
203
204 size = 0;
205 SetLastError(0xdeadbeef);
206 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, NULL, &size);
207 ok(!ret, "should fail to query disable feature for a request\n");
208 ok(GetLastError() == ERROR_INVALID_PARAMETER,
209 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
210
211 SetLastError(0xdeadbeef);
212 ret = WinHttpCloseHandle(request);
213 ok(ret, "WinHttpCloseHandle failed on closing request: %u\n", GetLastError());
214
215 done:
216 SetLastError(0xdeadbeef);
217 ret = WinHttpCloseHandle(connection);
218 ok(ret, "WinHttpCloseHandle failed on closing connection: %u\n", GetLastError());
219 SetLastError(0xdeadbeef);
220 ret = WinHttpCloseHandle(session);
221 ok(ret, "WinHttpCloseHandle failed on closing session: %u\n", GetLastError());
222 }
223
224 static void test_OpenRequest (void)
225 {
226 BOOL ret;
227 HINTERNET session, request, connection;
228 DWORD err;
229
230 SetLastError(0xdeadbeef);
231 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
232 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
233 err = GetLastError();
234 ok(session != NULL, "WinHttpOpen failed to open session.\n");
235 ok(err == ERROR_SUCCESS, "got %u\n", err);
236
237 /* Test with a bad server name */
238 SetLastError(0xdeadbeef);
239 connection = WinHttpConnect(session, NULL, INTERNET_DEFAULT_HTTP_PORT, 0);
240 err = GetLastError();
241 ok (connection == NULL, "WinHttpConnect succeeded in opening connection to NULL server argument.\n");
242 ok(err == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u.\n", err);
243
244 /* Test with a valid server name */
245 SetLastError(0xdeadbeef);
246 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
247 err = GetLastError();
248 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", err);
249 ok(err == ERROR_SUCCESS || broken(err == WSAEINVAL) /* < win7 */, "got %u\n", err);
250
251 SetLastError(0xdeadbeef);
252 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
253 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
254 err = GetLastError();
255 if (request == NULL && err == ERROR_WINHTTP_NAME_NOT_RESOLVED)
256 {
257 skip("Network unreachable, skipping.\n");
258 goto done;
259 }
260 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", err);
261 ok(err == ERROR_SUCCESS, "got %u\n", err);
262
263 SetLastError(0xdeadbeef);
264 ret = WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0);
265 err = GetLastError();
266 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
267 {
268 skip("Connection failed, skipping.\n");
269 goto done;
270 }
271 ok(ret, "WinHttpSendRequest failed: %u\n", err);
272 ok(err == ERROR_SUCCESS, "got %u\n", err);
273
274 SetLastError(0xdeadbeef);
275 ret = WinHttpCloseHandle(request);
276 err = GetLastError();
277 ok(ret, "WinHttpCloseHandle failed on closing request, got %u.\n", err);
278 ok(err == ERROR_SUCCESS, "got %u\n", err);
279
280 done:
281 ret = WinHttpCloseHandle(connection);
282 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
283 ret = WinHttpCloseHandle(session);
284 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
285
286 }
287
288 static void test_empty_headers_param(void)
289 {
290 static const WCHAR empty[] = {0};
291 HINTERNET ses, con, req;
292 DWORD err;
293 BOOL ret;
294
295 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
296 ok(ses != NULL, "failed to open session %u\n", GetLastError());
297
298 con = WinHttpConnect(ses, test_winehq, 80, 0);
299 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
300
301 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
302 ok(req != NULL, "failed to open a request %u\n", GetLastError());
303
304 ret = WinHttpSendRequest(req, empty, 0, NULL, 0, 0, 0);
305 err = GetLastError();
306 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
307 {
308 skip("connection failed, skipping\n");
309 goto done;
310 }
311 ok(ret, "failed to send request %u\n", GetLastError());
312
313 done:
314 WinHttpCloseHandle(req);
315 WinHttpCloseHandle(con);
316 WinHttpCloseHandle(ses);
317 }
318
319 static void test_SendRequest (void)
320 {
321 static const WCHAR content_type[] =
322 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t','i','o','n',
323 '/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o','d','e','d',0};
324 static const WCHAR test_file[] = {'t','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
325 static const WCHAR test_verb[] = {'P','O','S','T',0};
326 static CHAR post_data[] = "mode=Test";
327 static const char test_post[] = "mode => Test\0\n";
328 HINTERNET session, request, connection;
329 DWORD header_len, optional_len, total_len, bytes_rw, size, err;
330 DWORD_PTR context;
331 BOOL ret;
332 CHAR buffer[256];
333 int i;
334
335 header_len = -1L;
336 total_len = optional_len = sizeof(post_data);
337 memset(buffer, 0xff, sizeof(buffer));
338
339 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
340 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
341 ok(session != NULL, "WinHttpOpen failed to open session.\n");
342
343 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
344 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
345
346 request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
347 WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
348 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
349 {
350 skip("Network unreachable, skipping.\n");
351 goto done;
352 }
353 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
354 if (!request) goto done;
355
356 context = 0xdeadbeef;
357 ret = WinHttpSetOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(context));
358 ok(ret, "WinHttpSetOption failed: %u\n", GetLastError());
359
360 context++;
361 ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, context);
362 err = GetLastError();
363 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
364 {
365 skip("connection failed, skipping\n");
366 goto done;
367 }
368 ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
369
370 context = 0;
371 size = sizeof(context);
372 ret = WinHttpQueryOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, &size);
373 ok(ret, "WinHttpQueryOption failed: %u\n", GetLastError());
374 ok(context == 0xdeadbef0, "expected 0xdeadbef0, got %lx\n", context);
375
376 for (i = 3; post_data[i]; i++)
377 {
378 bytes_rw = -1;
379 SetLastError(0xdeadbeef);
380 ret = WinHttpWriteData(request, &post_data[i], 1, &bytes_rw);
381 if (ret)
382 {
383 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %u.\n", GetLastError());
384 ok(bytes_rw == 1, "WinHttpWriteData failed, wrote %u bytes instead of 1 byte.\n", bytes_rw);
385 }
386 else /* Since we already passed all optional data in WinHttpSendRequest Win7 fails our WinHttpWriteData call */
387 {
388 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER got %u.\n", GetLastError());
389 ok(bytes_rw == -1, "Expected bytes_rw to remain unchanged.\n");
390 }
391 }
392
393 SetLastError(0xdeadbeef);
394 ret = WinHttpReceiveResponse(request, NULL);
395 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == ERROR_NO_TOKEN) /* < win7 */,
396 "Expected ERROR_SUCCESS got %u.\n", GetLastError());
397 ok(ret == TRUE, "WinHttpReceiveResponse failed: %u.\n", GetLastError());
398
399 bytes_rw = -1;
400 ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw);
401 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
402
403 ok(bytes_rw == sizeof(test_post) - 1, "Read %u bytes\n", bytes_rw);
404 ok(!memcmp(buffer, test_post, sizeof(test_post) - 1), "Data read did not match.\n");
405
406 done:
407 ret = WinHttpCloseHandle(request);
408 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
409 ret = WinHttpCloseHandle(connection);
410 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
411 ret = WinHttpCloseHandle(session);
412 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
413 }
414
415 static void test_WinHttpTimeFromSystemTime(void)
416 {
417 BOOL ret;
418 static const SYSTEMTIME time = {2008, 7, 1, 28, 10, 5, 52, 0};
419 static const WCHAR expected_string[] =
420 {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
421 '1','0',':','0','5',':','5','2',' ','G','M','T',0};
422 WCHAR time_string[WINHTTP_TIME_FORMAT_BUFSIZE+1];
423 DWORD err;
424
425 SetLastError(0xdeadbeef);
426 ret = WinHttpTimeFromSystemTime(&time, NULL);
427 err = GetLastError();
428 ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
429 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
430
431 SetLastError(0xdeadbeef);
432 ret = WinHttpTimeFromSystemTime(NULL, time_string);
433 err = GetLastError();
434 ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
435 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
436
437 SetLastError(0xdeadbeef);
438 ret = WinHttpTimeFromSystemTime(&time, time_string);
439 err = GetLastError();
440 ok(ret, "WinHttpTimeFromSystemTime failed: %u\n", err);
441 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
442 ok(memcmp(time_string, expected_string, sizeof(expected_string)) == 0,
443 "Time string returned did not match expected time string.\n");
444 }
445
446 static void test_WinHttpTimeToSystemTime(void)
447 {
448 BOOL ret;
449 SYSTEMTIME time;
450 static const SYSTEMTIME expected_time = {2008, 7, 1, 28, 10, 5, 52, 0};
451 static const WCHAR time_string1[] =
452 {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
453 + '1','0',':','0','5',':','5','2',' ','G','M','T','\n',0};
454 static const WCHAR time_string2[] =
455 {' ','m','o','n',' ','2','8',' ','j','u','l',' ','2','0','0','8',' ',
456 '1','0',' ','0','5',' ','5','2','\n',0};
457 DWORD err;
458
459 SetLastError(0xdeadbeef);
460 ret = WinHttpTimeToSystemTime(time_string1, NULL);
461 err = GetLastError();
462 ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
463 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
464
465 SetLastError(0xdeadbeef);
466 ret = WinHttpTimeToSystemTime(NULL, &time);
467 err = GetLastError();
468 ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
469 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
470
471 SetLastError(0xdeadbeef);
472 ret = WinHttpTimeToSystemTime(time_string1, &time);
473 err = GetLastError();
474 ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
475 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
476 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
477 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
478
479 SetLastError(0xdeadbeef);
480 ret = WinHttpTimeToSystemTime(time_string2, &time);
481 err = GetLastError();
482 ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
483 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
484 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
485 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
486 }
487
488 static void test_WinHttpAddHeaders(void)
489 {
490 HINTERNET session, request, connection;
491 BOOL ret, reverse;
492 WCHAR buffer[MAX_PATH];
493 WCHAR check_buffer[MAX_PATH];
494 DWORD err, index, len, oldlen;
495
496 static const WCHAR test_file[] = {'/','p','o','s','t','t','e','s','t','.','p','h','p',0};
497 static const WCHAR test_verb[] = {'P','O','S','T',0};
498 static const WCHAR test_header_begin[] =
499 {'P','O','S','T',' ','/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
500 static const WCHAR full_path_test_header_begin[] =
501 {'P','O','S','T',' ','h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','8','0',
502 '/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
503 static const WCHAR test_header_end[] = {'\r','\n','\r','\n',0};
504 static const WCHAR test_header_name[] = {'W','a','r','n','i','n','g',0};
505 static const WCHAR test_header_name2[] = {'n','a','m','e',0};
506 static const WCHAR test_header_name3[] = {'a',0};
507 static const WCHAR test_header_range[] = {'R','a','n','g','e',0};
508 static const WCHAR test_header_range_bytes[] = {'R','a','n','g','e',':',' ','b','y','t','e','s','=','0','-','7','7','3','\r','\n',0};
509 static const WCHAR test_header_bytes[] = {'b','y','t','e','s','=','0','-','7','7','3',0};
510
511 static const WCHAR test_flag_coalesce[] = {'t','e','s','t','2',',',' ','t','e','s','t','4',0};
512 static const WCHAR test_flag_coalesce_reverse[] = {'t','e','s','t','3',',',' ','t','e','s','t','4',0};
513 static const WCHAR test_flag_coalesce_comma[] =
514 {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
515 static const WCHAR test_flag_coalesce_comma_reverse[] =
516 {'t','e','s','t','3',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
517 static const WCHAR test_flag_coalesce_semicolon[] =
518 {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
519 static const WCHAR test_flag_coalesce_semicolon_reverse[] =
520 {'t','e','s','t','3',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
521
522 static const WCHAR field[] = {'f','i','e','l','d',0};
523 static const WCHAR value[] = {'v','a','l','u','e',' ',0};
524 static const WCHAR value_nospace[] = {'v','a','l','u','e',0};
525 static const WCHAR empty[] = {0};
526
527 static const WCHAR test_headers[][14] =
528 {
529 {'W','a','r','n','i','n','g',':','t','e','s','t','1',0},
530 {'W','a','r','n','i','n','g',':','t','e','s','t','2',0},
531 {'W','a','r','n','i','n','g',':','t','e','s','t','3',0},
532 {'W','a','r','n','i','n','g',':','t','e','s','t','4',0},
533 {'W','a','r','n','i','n','g',':','t','e','s','t','5',0},
534 {'W','a','r','n','i','n','g',':','t','e','s','t','6',0},
535 {'W','a','r','n','i','n','g',':','t','e','s','t','7',0},
536 {0},
537 {':',0},
538 {'a',':',0},
539 {':','b',0},
540 {'c','d',0},
541 {' ','e',' ',':','f',0},
542 {'f','i','e','l','d',':',' ','v','a','l','u','e',' ',0},
543 {'n','a','m','e',':',' ','v','a','l','u','e',0},
544 {'n','a','m','e',':',0}
545 };
546 static const WCHAR test_indices[][6] =
547 {
548 {'t','e','s','t','1',0},
549 {'t','e','s','t','2',0},
550 {'t','e','s','t','3',0},
551 {'t','e','s','t','4',0}
552 };
553
554 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
555 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
556 ok(session != NULL, "WinHttpOpen failed to open session.\n");
557
558 connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
559 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
560
561 request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
562 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
563 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
564 {
565 skip("Network unreachable, skipping.\n");
566 goto done;
567 }
568 ok(request != NULL, "WinHttpOpenRequest failed to open a request, error: %u.\n", GetLastError());
569
570 index = 0;
571 len = sizeof(buffer);
572 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
573 test_header_name, buffer, &len, &index);
574 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, found 'Warning' header.\n");
575 SetLastError(0xdeadbeef);
576 ret = WinHttpAddRequestHeaders(request, test_headers[0], -1L, WINHTTP_ADDREQ_FLAG_ADD);
577 err = GetLastError();
578 ok(ret, "WinHttpAddRequestHeader failed to add new header, got %d with error %u.\n", ret, err);
579 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
580
581 index = 0;
582 len = sizeof(buffer);
583 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
584 test_header_name, buffer, &len, &index);
585 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
586 ok(index == 1, "WinHttpQueryHeaders failed: header index not incremented\n");
587 ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders failed: incorrect string returned\n");
588 ok(len == 5*sizeof(WCHAR), "WinHttpQueryHeaders failed: invalid length returned, expected 5, got %d\n", len);
589
590 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
591 test_header_name, buffer, &len, &index);
592 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, second index should not exist.\n");
593
594 /* Try to fetch the header info with a buffer that's big enough to fit the
595 * string but not the NULL terminator.
596 */
597 index = 0;
598 len = 5*sizeof(WCHAR);
599 memset(check_buffer, 0xab, sizeof(check_buffer));
600 memcpy(buffer, check_buffer, sizeof(buffer));
601 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
602 test_header_name, buffer, &len, &index);
603 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded with a buffer that's too small.\n");
604 ok(memcmp(buffer, check_buffer, sizeof(buffer)) == 0,
605 "WinHttpQueryHeaders failed, modified the buffer when it should not have.\n");
606 ok(len == 6*sizeof(WCHAR), "WinHttpQueryHeaders returned invalid length, expected 12, got %d\n", len);
607
608 /* Try with a NULL buffer */
609 index = 0;
610 len = sizeof(buffer);
611 SetLastError(0xdeadbeef);
612 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
613 test_header_name, NULL, &len, &index);
614 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
615 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
616 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
617 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
618
619 /* Try with a NULL buffer and a length that's too small */
620 index = 0;
621 len = 10;
622 SetLastError(0xdeadbeef);
623 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
624 test_header_name, NULL, &len, &index);
625 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
626 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
627 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICENT_BUFFER, got %u\n", GetLastError());
628 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
629 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
630
631 index = 0;
632 len = 0;
633 SetLastError(0xdeadbeef);
634 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
635 test_header_name, NULL, &len, &index);
636 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
637 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
638 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
639 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
640 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
641
642 /* valid query */
643 oldlen = len;
644 index = 0;
645 len = sizeof(buffer);
646 memset(buffer, 0xff, sizeof(buffer));
647 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
648 test_header_name, buffer, &len, &index);
649 ok(ret == TRUE, "WinHttpQueryHeaders failed: got %d\n", ret);
650 ok(len + sizeof(WCHAR) <= oldlen, "WinHttpQueryHeaders resulting length longer than advertized.\n");
651 ok((len < sizeof(buffer) - sizeof(WCHAR)) && buffer[len / sizeof(WCHAR)] == 0, "WinHttpQueryHeaders did not append NULL terminator\n");
652 ok(len == lstrlenW(buffer) * sizeof(WCHAR), "WinHttpQueryHeaders returned incorrect length.\n");
653 ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
654 memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
655 "WinHttpQueryHeaders returned invalid beginning of header string.\n");
656 ok(memcmp(buffer + lstrlenW(buffer) - 4, test_header_end, sizeof(test_header_end)) == 0,
657 "WinHttpQueryHeaders returned invalid end of header string.\n");
658 ok(index == 0, "WinHttpQueryHeaders incremented header index.\n");
659
660 index = 0;
661 len = 0;
662 SetLastError(0xdeadbeef);
663 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
664 test_header_name, NULL, &len, &index);
665 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
666 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
667 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
668 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
669 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
670
671 oldlen = len;
672 index = 0;
673 len = sizeof(buffer);
674 memset(buffer, 0xff, sizeof(buffer));
675 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
676 test_header_name, buffer, &len, &index);
677 ok(ret == TRUE, "WinHttpQueryHeaders failed %u\n", GetLastError());
678 ok(len + sizeof(WCHAR) <= oldlen, "resulting length longer than advertized\n");
679 ok((len < sizeof(buffer) - sizeof(WCHAR)) && !buffer[len / sizeof(WCHAR)] && !buffer[len / sizeof(WCHAR) - 1],
680 "no double NULL terminator\n");
681 ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
682 memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
683 "invalid beginning of header string.\n");
684 ok(index == 0, "header index was incremented\n");
685
686 /* tests for more indices */
687 ret = WinHttpAddRequestHeaders(request, test_headers[1], -1L, WINHTTP_ADDREQ_FLAG_ADD);
688 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header: %d\n", ret);
689
690 index = 0;
691 len = sizeof(buffer);
692 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
693 test_header_name, buffer, &len, &index);
694 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
695 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
696 ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
697
698 len = sizeof(buffer);
699 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
700 test_header_name, buffer, &len, &index);
701 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
702 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
703 ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
704
705 ret = WinHttpAddRequestHeaders(request, test_headers[2], -1L, WINHTTP_ADDREQ_FLAG_REPLACE);
706 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header.\n");
707
708 index = 0;
709 len = sizeof(buffer);
710 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
711 test_header_name, buffer, &len, &index);
712 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
713 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
714 reverse = (memcmp(buffer, test_indices[1], sizeof(test_indices[1])) != 0); /* Win7 returns values in reverse order of adding */
715 ok(memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
716
717 len = sizeof(buffer);
718 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
719 test_header_name, buffer, &len, &index);
720 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
721 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
722 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
723
724 /* add if new flag */
725 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW);
726 ok(ret == FALSE, "WinHttpAddRequestHeaders incorrectly replaced existing header.\n");
727
728 index = 0;
729 len = sizeof(buffer);
730 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
731 test_header_name, buffer, &len, &index);
732 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
733 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
734 ok(memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
735
736 len = sizeof(buffer);
737 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
738 test_header_name, buffer, &len, &index);
739 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
740 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
741 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
742
743 len = sizeof(buffer);
744 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
745 test_header_name, buffer, &len, &index);
746 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
747
748 /* coalesce flag */
749 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_COALESCE);
750 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE.\n");
751
752 index = 0;
753 len = sizeof(buffer);
754 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
755 test_header_name, buffer, &len, &index);
756 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
757 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
758 ok(memcmp(buffer, reverse ? test_flag_coalesce_reverse : test_flag_coalesce,
759 reverse ? sizeof(test_flag_coalesce_reverse) : sizeof(test_flag_coalesce)) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
760
761 len = sizeof(buffer);
762 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
763 test_header_name, buffer, &len, &index);
764 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
765 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
766 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
767
768 len = sizeof(buffer);
769 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
770 test_header_name, buffer, &len, &index);
771 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
772
773 /* coalesce with comma flag */
774 ret = WinHttpAddRequestHeaders(request, test_headers[4], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA);
775 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA.\n");
776
777 index = 0;
778 len = sizeof(buffer);
779 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
780 test_header_name, buffer, &len, &index);
781 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
782 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
783 ok(memcmp(buffer, reverse ? test_flag_coalesce_comma_reverse : test_flag_coalesce_comma,
784 reverse ? sizeof(test_flag_coalesce_comma_reverse) : sizeof(test_flag_coalesce_comma)) == 0,
785 "WinHttpQueryHeaders returned incorrect string.\n");
786
787 len = sizeof(buffer);
788 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
789 test_header_name, buffer, &len, &index);
790 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
791 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
792 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
793
794 len = sizeof(buffer);
795 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
796 test_header_name, buffer, &len, &index);
797 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
798
799
800 /* coalesce with semicolon flag */
801 ret = WinHttpAddRequestHeaders(request, test_headers[5], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON);
802 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON.\n");
803
804 index = 0;
805 len = sizeof(buffer);
806 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
807 test_header_name, buffer, &len, &index);
808 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
809 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
810 ok(memcmp(buffer, reverse ? test_flag_coalesce_semicolon_reverse : test_flag_coalesce_semicolon,
811 reverse ? sizeof(test_flag_coalesce_semicolon_reverse) : sizeof(test_flag_coalesce_semicolon)) == 0,
812 "WinHttpQueryHeaders returned incorrect string.\n");
813
814 len = sizeof(buffer);
815 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
816 test_header_name, buffer, &len, &index);
817 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
818 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
819 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
820
821 len = sizeof(buffer);
822 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
823 test_header_name, buffer, &len, &index);
824 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
825
826 /* add and replace flags */
827 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
828 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE.\n");
829
830 index = 0;
831 len = sizeof(buffer);
832 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
833 test_header_name, buffer, &len, &index);
834 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
835 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
836 ok(memcmp(buffer, test_indices[reverse ? 3 : 2], sizeof(test_indices[reverse ? 3 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
837
838 len = sizeof(buffer);
839 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
840 test_header_name, buffer, &len, &index);
841 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
842 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
843 ok(memcmp(buffer, test_indices[reverse ? 1 : 3], sizeof(test_indices[reverse ? 1 : 3])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
844
845 len = sizeof(buffer);
846 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
847 test_header_name, buffer, &len, &index);
848 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
849
850 ret = WinHttpAddRequestHeaders(request, test_headers[8], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
851 ok(!ret, "WinHttpAddRequestHeaders failed\n");
852
853 ret = WinHttpAddRequestHeaders(request, test_headers[9], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
854 ok(ret, "WinHttpAddRequestHeaders failed\n");
855
856 index = 0;
857 memset(buffer, 0xff, sizeof(buffer));
858 len = sizeof(buffer);
859 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
860 test_header_name3, buffer, &len, &index);
861 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
862 ok(!memcmp(buffer, empty, sizeof(empty)), "unexpected result\n");
863
864 ret = WinHttpAddRequestHeaders(request, test_headers[10], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
865 ok(!ret, "WinHttpAddRequestHeaders failed\n");
866
867 ret = WinHttpAddRequestHeaders(request, test_headers[11], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
868 ok(!ret, "WinHttpAddRequestHeaders failed\n");
869
870 ret = WinHttpAddRequestHeaders(request, test_headers[12], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
871 ok(!ret, "WinHttpAddRequestHeaders failed\n");
872
873 ret = WinHttpAddRequestHeaders(request, test_headers[13], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
874 ok(ret, "WinHttpAddRequestHeaders failed\n");
875
876 index = 0;
877 buffer[0] = 0;
878 len = sizeof(buffer);
879 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
880 field, buffer, &len, &index);
881 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
882 ok(!memcmp(buffer, value, sizeof(value)) || ! memcmp(buffer, value_nospace, sizeof(value_nospace)), "unexpected result\n");
883
884 SetLastError(0xdeadbeef);
885 ret = WinHttpAddRequestHeaders(request, test_header_range_bytes, 0,
886 WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
887 err = GetLastError();
888 ok(!ret, "unexpected success\n");
889 ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
890
891 ret = WinHttpAddRequestHeaders(request, test_header_range_bytes, ~0u,
892 WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
893 ok(ret, "failed to add header: %u\n", GetLastError());
894
895 index = 0;
896 len = sizeof(buffer);
897 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
898 test_header_range, buffer, &len, &index);
899 ok(ret, "failed to get range header %u\n", GetLastError());
900 ok(!memcmp(buffer, test_header_bytes, sizeof(test_header_bytes)), "incorrect string returned\n");
901 ok(len == lstrlenW(test_header_bytes) * sizeof(WCHAR), "wrong length %u\n", len);
902 ok(index == 1, "wrong index %u\n", index);
903
904 index = 0;
905 len = sizeof(buffer);
906 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
907 test_header_name2, buffer, &len, &index);
908 ok(!ret, "unexpected success\n");
909
910 SetLastError(0xdeadbeef);
911 ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
912 err = GetLastError();
913 ok(!ret, "unexpected success\n");
914 ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
915
916 ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
917 ok(ret, "got %u\n", GetLastError());
918
919 index = 0;
920 len = sizeof(buffer);
921 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
922 test_header_name2, buffer, &len, &index);
923 ok(ret, "got %u\n", GetLastError());
924 ok(index == 1, "wrong index %u\n", index);
925 ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
926
927 ret = WinHttpAddRequestHeaders(request, test_headers[15], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
928 ok(ret, "got %u\n", GetLastError());
929
930 index = 0;
931 len = sizeof(buffer);
932 SetLastError(0xdeadbeef);
933 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
934 test_header_name2, buffer, &len, &index);
935 err = GetLastError();
936 ok(!ret, "unexpected success\n");
937 ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
938
939 ret = WinHttpAddRequestHeaders(request, test_headers[14], -1L, 0);
940 ok(ret, "got %u\n", GetLastError());
941
942 index = 0;
943 len = sizeof(buffer);
944 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
945 test_header_name2, buffer, &len, &index);
946 ok(ret, "got %u\n", GetLastError());
947 ok(index == 1, "wrong index %u\n", index);
948 ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
949
950 ret = WinHttpCloseHandle(request);
951 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
952 done:
953 ret = WinHttpCloseHandle(connection);
954 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
955 ret = WinHttpCloseHandle(session);
956 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
957
958 }
959
960 static void CALLBACK cert_error(HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID buf, DWORD len)
961 {
962 DWORD flags = *(DWORD *)buf;
963
964 if (!flags)
965 {
966 trace("WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR\n");
967 return;
968 }
969 #define X(x) if (flags & x) trace("%s\n", #x);
970 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED)
971 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT)
972 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED)
973 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA)
974 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID)
975 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)
976 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE)
977 #undef X
978 }
979
980 static void test_secure_connection(void)
981 {
982 static const char data_start[] = "<!DOCTYPE html PUBLIC";
983 HINTERNET ses, con, req;
984 DWORD size, status, policy, bitness, read_size, err, available_size;
985 BOOL ret;
986 CERT_CONTEXT *cert;
987 WINHTTP_CERTIFICATE_INFO info;
988 char buffer[32];
989
990 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
991 ok(ses != NULL, "failed to open session %u\n", GetLastError());
992
993 policy = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
994 ret = WinHttpSetOption(ses, WINHTTP_OPTION_REDIRECT_POLICY, &policy, sizeof(policy));
995 ok(ret, "failed to set redirect policy %u\n", GetLastError());
996
997 con = WinHttpConnect(ses, test_winehq, 443, 0);
998 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
999
1000 /* try without setting WINHTTP_FLAG_SECURE */
1001 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1002 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1003
1004 ret = WinHttpSetOption(req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
1005 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "setting client cert context returned %x (%u)\n", ret, GetLastError());
1006
1007 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1008 err = GetLastError();
1009 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
1010 {
1011 skip("Connection failed, skipping.\n");
1012 goto cleanup;
1013 }
1014 ok(ret, "failed to send request %u\n", GetLastError());
1015
1016 ret = WinHttpReceiveResponse(req, NULL);
1017 ok(ret, "failed to receive response %u\n", GetLastError());
1018
1019 status = 0xdeadbeef;
1020 size = sizeof(status);
1021 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1022 ok(ret, "header query failed %u\n", GetLastError());
1023 ok(status == HTTP_STATUS_BAD_REQUEST, "got %u\n", status);
1024
1025 WinHttpCloseHandle(req);
1026
1027 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, WINHTTP_FLAG_SECURE);
1028 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1029
1030 ret = WinHttpSetOption(req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
1031 ok(ret, "failed to set client cert context %u\n", GetLastError());
1032
1033 WinHttpSetStatusCallback(req, cert_error, WINHTTP_CALLBACK_STATUS_SECURE_FAILURE, 0);
1034
1035 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1036 err = GetLastError();
1037 if (!ret && (err == ERROR_WINHTTP_SECURE_FAILURE || err == ERROR_WINHTTP_CANNOT_CONNECT ||
1038 err == ERROR_WINHTTP_TIMEOUT))
1039 {
1040 skip("secure connection failed, skipping remaining secure tests\n");
1041 goto cleanup;
1042 }
1043 ok(ret, "failed to send request %u\n", GetLastError());
1044
1045 size = sizeof(cert);
1046 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size );
1047 ok(ret, "failed to retrieve certificate context %u\n", GetLastError());
1048 if (ret) CertFreeCertificateContext(cert);
1049
1050 size = sizeof(bitness);
1051 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_KEY_BITNESS, &bitness, &size );
1052 ok(ret, "failed to retrieve key bitness %u\n", GetLastError());
1053
1054 size = sizeof(info);
1055 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT, &info, &size );
1056 ok(ret, "failed to retrieve certificate info %u\n", GetLastError());
1057
1058 if (ret)
1059 {
1060 trace("lpszSubjectInfo %s\n", wine_dbgstr_w(info.lpszSubjectInfo));
1061 trace("lpszIssuerInfo %s\n", wine_dbgstr_w(info.lpszIssuerInfo));
1062 trace("lpszProtocolName %s\n", wine_dbgstr_w(info.lpszProtocolName));
1063 trace("lpszSignatureAlgName %s\n", wine_dbgstr_w(info.lpszSignatureAlgName));
1064 trace("lpszEncryptionAlgName %s\n", wine_dbgstr_w(info.lpszEncryptionAlgName));
1065 trace("dwKeySize %u\n", info.dwKeySize);
1066 }
1067
1068 ret = WinHttpReceiveResponse(req, NULL);
1069 ok(ret, "failed to receive response %u\n", GetLastError());
1070
1071 available_size = 0;
1072 ret = WinHttpQueryDataAvailable(req, &available_size);
1073 ok(ret, "failed to query available data %u\n", GetLastError());
1074 ok(available_size > 2014, "available_size = %u\n", available_size);
1075
1076 status = 0xdeadbeef;
1077 size = sizeof(status);
1078 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1079 ok(ret, "failed unexpectedly %u\n", GetLastError());
1080 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1081
1082 size = 0;
1083 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
1084 ok(!ret, "succeeded unexpectedly\n");
1085
1086 read_size = 0;
1087 for (;;)
1088 {
1089 size = 0;
1090 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
1091 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
1092 if (!size) break;
1093 read_size += size;
1094
1095 if (read_size <= 32)
1096 ok(!memcmp(buffer, data_start, sizeof(data_start)-1), "not expected: %.32s\n", buffer);
1097 }
1098 ok(read_size >= available_size, "read_size = %u, available_size = %u\n", read_size, available_size);
1099
1100 cleanup:
1101 WinHttpCloseHandle(req);
1102 WinHttpCloseHandle(con);
1103 WinHttpCloseHandle(ses);
1104 }
1105
1106 static void test_request_parameter_defaults(void)
1107 {
1108 static const WCHAR empty[] = {0};
1109 HINTERNET ses, con, req;
1110 DWORD size, status, error;
1111 WCHAR *version;
1112 BOOL ret;
1113
1114 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1115 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1116
1117 con = WinHttpConnect(ses, test_winehq, 0, 0);
1118 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1119
1120 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1121 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1122
1123 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1124 error = GetLastError();
1125 if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1126 {
1127 skip("connection failed, skipping\n");
1128 goto done;
1129 }
1130 ok(ret, "failed to send request %u\n", GetLastError());
1131
1132 ret = WinHttpReceiveResponse(req, NULL);
1133 if (!ret && GetLastError() == ERROR_WINHTTP_INVALID_SERVER_RESPONSE) /* win2k */
1134 {
1135 win_skip("invalid response\n");
1136 goto done;
1137 }
1138 ok(ret, "failed to receive response %u\n", GetLastError());
1139
1140 status = 0xdeadbeef;
1141 size = sizeof(status);
1142 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1143 ok(ret, "failed unexpectedly %u\n", GetLastError());
1144 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1145
1146 WinHttpCloseHandle(req);
1147
1148 req = WinHttpOpenRequest(con, empty, empty, empty, NULL, NULL, 0);
1149 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1150
1151 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1152 error = GetLastError();
1153 if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1154 {
1155 skip("connection failed, skipping\n");
1156 goto done;
1157 }
1158 ok(ret, "failed to send request %u\n", GetLastError());
1159
1160 ret = WinHttpReceiveResponse(req, NULL);
1161 ok(ret, "failed to receive response %u\n", GetLastError());
1162
1163 size = 0;
1164 SetLastError(0xdeadbeef);
1165 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, NULL, &size, NULL);
1166 error = GetLastError();
1167 ok(!ret, "succeeded unexpectedly\n");
1168 ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
1169
1170 version = HeapAlloc(GetProcessHeap(), 0, size);
1171 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, version, &size, NULL);
1172 ok(ret, "failed unexpectedly %u\n", GetLastError());
1173 ok(lstrlenW(version) == size / sizeof(WCHAR), "unexpected size %u\n", size);
1174 HeapFree(GetProcessHeap(), 0, version);
1175
1176 status = 0xdeadbeef;
1177 size = sizeof(status);
1178 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1179 ok(ret, "failed unexpectedly %u\n", GetLastError());
1180 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1181
1182 done:
1183 WinHttpCloseHandle(req);
1184 WinHttpCloseHandle(con);
1185 WinHttpCloseHandle(ses);
1186 }
1187
1188 static const WCHAR Connections[] = {
1189 'S','o','f','t','w','a','r','e','\\',
1190 'M','i','c','r','o','s','o','f','t','\\',
1191 'W','i','n','d','o','w','s','\\',
1192 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1193 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
1194 'C','o','n','n','e','c','t','i','o','n','s',0 };
1195 static const WCHAR WinHttpSettings[] = {
1196 'W','i','n','H','t','t','p','S','e','t','t','i','n','g','s',0 };
1197
1198 static DWORD get_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD *type )
1199 {
1200 LONG l;
1201 HKEY key;
1202 DWORD ret = 0;
1203
1204 l = RegOpenKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, KEY_READ, &key );
1205 if (!l)
1206 {
1207 DWORD size = 0;
1208
1209 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, NULL, &size );
1210 if (!l)
1211 {
1212 if (size <= len)
1213 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, buf,
1214 &size );
1215 if (!l)
1216 ret = size;
1217 }
1218 RegCloseKey( key );
1219 }
1220 return ret;
1221 }
1222
1223 static void set_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD type )
1224 {
1225 LONG l;
1226 HKEY key;
1227
1228 l = RegCreateKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, NULL, 0,
1229 KEY_WRITE, NULL, &key, NULL );
1230 if (!l)
1231 {
1232 if (len)
1233 RegSetValueExW( key, WinHttpSettings, 0, type, buf, len );
1234 else
1235 RegDeleteValueW( key, WinHttpSettings );
1236 RegCloseKey( key );
1237 }
1238 }
1239
1240 static void test_set_default_proxy_config(void)
1241 {
1242 static WCHAR wideString[] = { 0x226f, 0x575b, 0 };
1243 static WCHAR normalString[] = { 'f','o','o',0 };
1244 DWORD type, len;
1245 BYTE *saved_proxy_settings = NULL;
1246 WINHTTP_PROXY_INFO info;
1247 BOOL ret;
1248
1249 /* FIXME: it would be simpler to read the current settings using
1250 * WinHttpGetDefaultProxyConfiguration and save them using
1251 * WinHttpSetDefaultProxyConfiguration, but they appear to have a bug.
1252 *
1253 * If a proxy is configured in the registry, e.g. via 'proxcfg -p "foo"',
1254 * the access type reported by WinHttpGetDefaultProxyConfiguration is 1,
1255 * WINHTTP_ACCESS_TYPE_NO_PROXY, whereas it should be
1256 * WINHTTP_ACCESS_TYPE_NAMED_PROXY.
1257 * If WinHttpSetDefaultProxyConfiguration is called with dwAccessType = 1,
1258 * the lpszProxy and lpszProxyBypass values are ignored.
1259 * Thus, if a proxy is set with proxycfg, then calling
1260 * WinHttpGetDefaultProxyConfiguration followed by
1261 * WinHttpSetDefaultProxyConfiguration results in the proxy settings
1262 * getting deleted from the registry.
1263 *
1264 * Instead I read the current registry value and restore it directly.
1265 */
1266 len = get_default_proxy_reg_value( NULL, 0, &type );
1267 if (len)
1268 {
1269 saved_proxy_settings = HeapAlloc( GetProcessHeap(), 0, len );
1270 len = get_default_proxy_reg_value( saved_proxy_settings, len, &type );
1271 }
1272
1273 if (0)
1274 {
1275 /* Crashes on Vista and higher */
1276 SetLastError(0xdeadbeef);
1277 ret = WinHttpSetDefaultProxyConfiguration(NULL);
1278 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1279 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1280 }
1281
1282 /* test with invalid access type */
1283 info.dwAccessType = 0xdeadbeef;
1284 info.lpszProxy = info.lpszProxyBypass = NULL;
1285 SetLastError(0xdeadbeef);
1286 ret = WinHttpSetDefaultProxyConfiguration(&info);
1287 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1288 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1289
1290 /* at a minimum, the proxy server must be set */
1291 info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1292 info.lpszProxy = info.lpszProxyBypass = NULL;
1293 SetLastError(0xdeadbeef);
1294 ret = WinHttpSetDefaultProxyConfiguration(&info);
1295 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1296 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1297 info.lpszProxyBypass = normalString;
1298 SetLastError(0xdeadbeef);
1299 ret = WinHttpSetDefaultProxyConfiguration(&info);
1300 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1301 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1302
1303 /* the proxy server can't have wide characters */
1304 info.lpszProxy = wideString;
1305 SetLastError(0xdeadbeef);
1306 ret = WinHttpSetDefaultProxyConfiguration(&info);
1307 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1308 skip("couldn't set default proxy configuration: access denied\n");
1309 else
1310 ok((!ret && GetLastError() == ERROR_INVALID_PARAMETER) ||
1311 broken(ret), /* Earlier winhttp versions on W2K/XP */
1312 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1313
1314 info.lpszProxy = normalString;
1315 SetLastError(0xdeadbeef);
1316 ret = WinHttpSetDefaultProxyConfiguration(&info);
1317 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1318 skip("couldn't set default proxy configuration: access denied\n");
1319 else
1320 {
1321 ok(ret, "WinHttpSetDefaultProxyConfiguration failed: %u\n", GetLastError());
1322 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1323 "got %u\n", GetLastError());
1324 }
1325 set_default_proxy_reg_value( saved_proxy_settings, len, type );
1326 }
1327
1328 static void test_Timeouts (void)
1329 {
1330 BOOL ret;
1331 DWORD value, size;
1332 HINTERNET ses, req, con;
1333
1334 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1335 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1336
1337 SetLastError(0xdeadbeef);
1338 ret = WinHttpSetTimeouts(ses, -2, 0, 0, 0);
1339 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1340 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1341
1342 SetLastError(0xdeadbeef);
1343 ret = WinHttpSetTimeouts(ses, 0, -2, 0, 0);
1344 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1345 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1346
1347 SetLastError(0xdeadbeef);
1348 ret = WinHttpSetTimeouts(ses, 0, 0, -2, 0);
1349 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1350 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1351
1352 SetLastError(0xdeadbeef);
1353 ret = WinHttpSetTimeouts(ses, 0, 0, 0, -2);
1354 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1355 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1356
1357 SetLastError(0xdeadbeef);
1358 ret = WinHttpSetTimeouts(ses, -1, -1, -1, -1);
1359 ok(ret, "%u\n", GetLastError());
1360 ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1361 "expected ERROR_SUCCESS, got %u\n", GetLastError());
1362
1363 SetLastError(0xdeadbeef);
1364 ret = WinHttpSetTimeouts(ses, 0, 0, 0, 0);
1365 ok(ret, "%u\n", GetLastError());
1366
1367 SetLastError(0xdeadbeef);
1368 ret = WinHttpSetTimeouts(ses, 0x0123, 0x4567, 0x89ab, 0xcdef);
1369 ok(ret, "%u\n", GetLastError());
1370
1371 SetLastError(0xdeadbeef);
1372 value = 0xdeadbeef;
1373 size = sizeof(DWORD);
1374 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1375 ok(ret, "%u\n", GetLastError());
1376 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1377
1378 SetLastError(0xdeadbeef);
1379 value = 0xdeadbeef;
1380 size = sizeof(DWORD);
1381 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1382 ok(ret, "%u\n", GetLastError());
1383 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1384
1385 SetLastError(0xdeadbeef);
1386 value = 0xdeadbeef;
1387 size = sizeof(DWORD);
1388 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1389 ok(ret, "%u\n", GetLastError());
1390 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1391
1392 SetLastError(0xdeadbeef);
1393 value = 0xdeadbeef;
1394 size = sizeof(DWORD);
1395 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1396 ok(ret, "%u\n", GetLastError());
1397 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1398
1399 SetLastError(0xdeadbeef);
1400 value = 0;
1401 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1402 ok(ret, "%u\n", GetLastError());
1403
1404 SetLastError(0xdeadbeef);
1405 value = 0xdeadbeef;
1406 size = sizeof(DWORD);
1407 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1408 ok(ret, "%u\n", GetLastError());
1409 ok(value == 0, "Expected 0, got %u\n", value);
1410
1411 SetLastError(0xdeadbeef);
1412 value = 0;
1413 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1414 ok(ret, "%u\n", GetLastError());
1415
1416 SetLastError(0xdeadbeef);
1417 value = 0xdeadbeef;
1418 size = sizeof(DWORD);
1419 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1420 ok(ret, "%u\n", GetLastError());
1421 ok(value == 0, "Expected 0, got %u\n", value);
1422
1423 SetLastError(0xdeadbeef);
1424 value = 0;
1425 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1426 ok(ret, "%u\n", GetLastError());
1427
1428 SetLastError(0xdeadbeef);
1429 value = 0xdeadbeef;
1430 size = sizeof(DWORD);
1431 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1432 ok(ret, "%u\n", GetLastError());
1433 ok(value == 0, "Expected 0, got %u\n", value);
1434
1435 SetLastError(0xdeadbeef);
1436 value = 0;
1437 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1438 ok(ret, "%u\n", GetLastError());
1439
1440 SetLastError(0xdeadbeef);
1441 value = 0xdeadbeef;
1442 size = sizeof(DWORD);
1443 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1444 ok(ret, "%u\n", GetLastError());
1445 ok(value == 0, "Expected 0, got %u\n", value);
1446
1447 SetLastError(0xdeadbeef);
1448 value = 0xbeefdead;
1449 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1450 ok(ret, "%u\n", GetLastError());
1451
1452 SetLastError(0xdeadbeef);
1453 value = 0xdeadbeef;
1454 size = sizeof(DWORD);
1455 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1456 ok(ret, "%u\n", GetLastError());
1457 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1458
1459 SetLastError(0xdeadbeef);
1460 value = 0xbeefdead;
1461 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1462 ok(ret, "%u\n", GetLastError());
1463
1464 SetLastError(0xdeadbeef);
1465 value = 0xdeadbeef;
1466 size = sizeof(DWORD);
1467 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1468 ok(ret, "%u\n", GetLastError());
1469 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1470
1471 SetLastError(0xdeadbeef);
1472 value = 0xbeefdead;
1473 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1474 ok(ret, "%u\n", GetLastError());
1475
1476 SetLastError(0xdeadbeef);
1477 value = 0xdeadbeef;
1478 size = sizeof(DWORD);
1479 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1480 ok(ret, "%u\n", GetLastError());
1481 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1482
1483 SetLastError(0xdeadbeef);
1484 value = 0xbeefdead;
1485 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1486 ok(ret, "%u\n", GetLastError());
1487
1488 SetLastError(0xdeadbeef);
1489 value = 0xdeadbeef;
1490 size = sizeof(DWORD);
1491 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1492 ok(ret, "%u\n", GetLastError());
1493 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1494
1495 con = WinHttpConnect(ses, test_winehq, 0, 0);
1496 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1497
1498 /* Timeout values should match the last one set for session */
1499 SetLastError(0xdeadbeef);
1500 value = 0xdeadbeef;
1501 size = sizeof(DWORD);
1502 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1503 ok(ret, "%u\n", GetLastError());
1504 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1505
1506 SetLastError(0xdeadbeef);
1507 value = 0xdeadbeef;
1508 size = sizeof(DWORD);
1509 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1510 ok(ret, "%u\n", GetLastError());
1511 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1512
1513 SetLastError(0xdeadbeef);
1514 value = 0xdeadbeef;
1515 size = sizeof(DWORD);
1516 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1517 ok(ret, "%u\n", GetLastError());
1518 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1519
1520 SetLastError(0xdeadbeef);
1521 value = 0xdeadbeef;
1522 size = sizeof(DWORD);
1523 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1524 ok(ret, "%u\n", GetLastError());
1525 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1526
1527 SetLastError(0xdeadbeef);
1528 ret = WinHttpSetTimeouts(con, -2, 0, 0, 0);
1529 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1530 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1531
1532 SetLastError(0xdeadbeef);
1533 ret = WinHttpSetTimeouts(con, 0, -2, 0, 0);
1534 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1535 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1536
1537 SetLastError(0xdeadbeef);
1538 ret = WinHttpSetTimeouts(con, 0, 0, -2, 0);
1539 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1540 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1541
1542 SetLastError(0xdeadbeef);
1543 ret = WinHttpSetTimeouts(con, 0, 0, 0, -2);
1544 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1545 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1546
1547 SetLastError(0xdeadbeef);
1548 ret = WinHttpSetTimeouts(con, -1, -1, -1, -1);
1549 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1550 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1551
1552 SetLastError(0xdeadbeef);
1553 ret = WinHttpSetTimeouts(con, 0, 0, 0, 0);
1554 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1555 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1556
1557 SetLastError(0xdeadbeef);
1558 value = 0;
1559 ret = WinHttpSetOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1560 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1561 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1562
1563 SetLastError(0xdeadbeef);
1564 value = 0;
1565 ret = WinHttpSetOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1566 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1567 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1568
1569 SetLastError(0xdeadbeef);
1570 value = 0;
1571 ret = WinHttpSetOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1572 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1573 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1574
1575 SetLastError(0xdeadbeef);
1576 value = 0;
1577 ret = WinHttpSetOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1578 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1579 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1580
1581 /* Changing timeout values for session should affect the values for connection */
1582 SetLastError(0xdeadbeef);
1583 value = 0xdead;
1584 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1585 ok(ret, "%u\n", GetLastError());
1586
1587 SetLastError(0xdeadbeef);
1588 value = 0xdeadbeef;
1589 size = sizeof(DWORD);
1590 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1591 ok(ret, "%u\n", GetLastError());
1592 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1593
1594 SetLastError(0xdeadbeef);
1595 value = 0xdead;
1596 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1597 ok(ret, "%u\n", GetLastError());
1598
1599 SetLastError(0xdeadbeef);
1600 value = 0xdeadbeef;
1601 size = sizeof(DWORD);
1602 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1603 ok(ret, "%u\n", GetLastError());
1604 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1605
1606 SetLastError(0xdeadbeef);
1607 value = 0xdead;
1608 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1609 ok(ret, "%u\n", GetLastError());
1610
1611 SetLastError(0xdeadbeef);
1612 value = 0xdeadbeef;
1613 size = sizeof(DWORD);
1614 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1615 ok(ret, "%u\n", GetLastError());
1616 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1617
1618 SetLastError(0xdeadbeef);
1619 value = 0xdead;
1620 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1621 ok(ret, "%u\n", GetLastError());
1622
1623 SetLastError(0xdeadbeef);
1624 value = 0xdeadbeef;
1625 size = sizeof(DWORD);
1626 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1627 ok(ret, "%u\n", GetLastError());
1628 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1629
1630 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1631 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1632
1633 /* Timeout values should match the last one set for session */
1634 SetLastError(0xdeadbeef);
1635 value = 0xdeadbeef;
1636 size = sizeof(DWORD);
1637 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1638 ok(ret, "%u\n", GetLastError());
1639 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1640
1641 SetLastError(0xdeadbeef);
1642 value = 0xdeadbeef;
1643 size = sizeof(DWORD);
1644 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1645 ok(ret, "%u\n", GetLastError());
1646 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1647
1648 SetLastError(0xdeadbeef);
1649 value = 0xdeadbeef;
1650 size = sizeof(DWORD);
1651 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1652 ok(ret, "%u\n", GetLastError());
1653 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1654
1655 SetLastError(0xdeadbeef);
1656 value = 0xdeadbeef;
1657 size = sizeof(DWORD);
1658 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1659 ok(ret, "%u\n", GetLastError());
1660 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1661
1662 SetLastError(0xdeadbeef);
1663 ret = WinHttpSetTimeouts(req, -2, 0, 0, 0);
1664 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1665 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1666
1667 SetLastError(0xdeadbeef);
1668 ret = WinHttpSetTimeouts(req, 0, -2, 0, 0);
1669 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1670 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1671
1672 SetLastError(0xdeadbeef);
1673 ret = WinHttpSetTimeouts(req, 0, 0, -2, 0);
1674 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1675 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1676
1677 SetLastError(0xdeadbeef);
1678 ret = WinHttpSetTimeouts(req, 0, 0, 0, -2);
1679 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1680 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1681
1682 SetLastError(0xdeadbeef);
1683 ret = WinHttpSetTimeouts(req, -1, -1, -1, -1);
1684 ok(ret, "%u\n", GetLastError());
1685
1686 SetLastError(0xdeadbeef);
1687 ret = WinHttpSetTimeouts(req, 0, 0, 0, 0);
1688 ok(ret, "%u\n", GetLastError());
1689
1690 SetLastError(0xdeadbeef);
1691 ret = WinHttpSetTimeouts(req, 0xcdef, 0x89ab, 0x4567, 0x0123);
1692 ok(ret, "%u\n", GetLastError());
1693
1694 SetLastError(0xdeadbeef);
1695 value = 0xdeadbeef;
1696 size = sizeof(DWORD);
1697 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1698 ok(ret, "%u\n", GetLastError());
1699 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1700
1701 SetLastError(0xdeadbeef);
1702 value = 0xdeadbeef;
1703 size = sizeof(DWORD);
1704 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1705 ok(ret, "%u\n", GetLastError());
1706 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1707
1708 SetLastError(0xdeadbeef);
1709 value = 0xdeadbeef;
1710 size = sizeof(DWORD);
1711 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1712 ok(ret, "%u\n", GetLastError());
1713 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1714
1715 SetLastError(0xdeadbeef);
1716 value = 0xdeadbeef;
1717 size = sizeof(DWORD);
1718 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1719 ok(ret, "%u\n", GetLastError());
1720 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1721
1722 SetLastError(0xdeadbeef);
1723 value = 0;
1724 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1725 ok(ret, "%u\n", GetLastError());
1726
1727 SetLastError(0xdeadbeef);
1728 value = 0xdeadbeef;
1729 size = sizeof(DWORD);
1730 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1731 ok(ret, "%u\n", GetLastError());
1732 ok(value == 0, "Expected 0, got %u\n", value);
1733
1734 SetLastError(0xdeadbeef);
1735 value = 0;
1736 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1737 ok(ret, "%u\n", GetLastError());
1738
1739 SetLastError(0xdeadbeef);
1740 value = 0xdeadbeef;
1741 size = sizeof(DWORD);
1742 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1743 ok(ret, "%u\n", GetLastError());
1744 ok(value == 0, "Expected 0, got %u\n", value);
1745
1746 SetLastError(0xdeadbeef);
1747 value = 0;
1748 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1749 ok(ret, "%u\n", GetLastError());
1750
1751 SetLastError(0xdeadbeef);
1752 value = 0xdeadbeef;
1753 size = sizeof(DWORD);
1754 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1755 ok(ret, "%u\n", GetLastError());
1756 ok(value == 0, "Expected 0, got %u\n", value);
1757
1758 SetLastError(0xdeadbeef);
1759 value = 0;
1760 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1761 ok(ret, "%u\n", GetLastError());
1762
1763 SetLastError(0xdeadbeef);
1764 value = 0xdeadbeef;
1765 size = sizeof(DWORD);
1766 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1767 ok(ret, "%u\n", GetLastError());
1768 ok(value == 0, "Expected 0, got %u\n", value);
1769
1770 SetLastError(0xdeadbeef);
1771 value = 0xbeefdead;
1772 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1773 ok(ret, "%u\n", GetLastError());
1774
1775 SetLastError(0xdeadbeef);
1776 value = 0xdeadbeef;
1777 size = sizeof(DWORD);
1778 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1779 ok(ret, "%u\n", GetLastError());
1780 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1781
1782 SetLastError(0xdeadbeef);
1783 value = 0xbeefdead;
1784 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1785 ok(ret, "%u\n", GetLastError());
1786
1787 SetLastError(0xdeadbeef);
1788 value = 0xdeadbeef;
1789 size = sizeof(DWORD);
1790 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1791 ok(ret, "%u\n", GetLastError());
1792 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1793
1794 SetLastError(0xdeadbeef);
1795 value = 0xbeefdead;
1796 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1797 ok(ret, "%u\n", GetLastError());
1798
1799 SetLastError(0xdeadbeef);
1800 value = 0xdeadbeef;
1801 size = sizeof(DWORD);
1802 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1803 ok(ret, "%u\n", GetLastError());
1804 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1805
1806 SetLastError(0xdeadbeef);
1807 value = 0xbeefdead;
1808 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1809 ok(ret, "%u\n", GetLastError());
1810
1811 SetLastError(0xdeadbeef);
1812 value = 0xdeadbeef;
1813 size = sizeof(DWORD);
1814 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1815 ok(ret, "%u\n", GetLastError());
1816 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1817
1818 /* Changing timeout values for session should not affect the values for a request,
1819 * neither should the other way around.
1820 */
1821 SetLastError(0xdeadbeef);
1822 value = 0xbeefdead;
1823 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1824 ok(ret, "%u\n", GetLastError());
1825
1826 SetLastError(0xdeadbeef);
1827 value = 0xdeadbeef;
1828 size = sizeof(DWORD);
1829 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1830 ok(ret, "%u\n", GetLastError());
1831 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1832
1833 SetLastError(0xdeadbeef);
1834 value = 0xbeefdead;
1835 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1836 ok(ret, "%u\n", GetLastError());
1837
1838 SetLastError(0xdeadbeef);
1839 value = 0xdeadbeef;
1840 size = sizeof(DWORD);
1841 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1842 ok(ret, "%u\n", GetLastError());
1843 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1844
1845 SetLastError(0xdeadbeef);
1846 value = 0xbeefdead;
1847 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1848 ok(ret, "%u\n", GetLastError());
1849
1850 SetLastError(0xdeadbeef);
1851 value = 0xdeadbeef;
1852 size = sizeof(DWORD);
1853 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1854 ok(ret, "%u\n", GetLastError());
1855 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1856
1857 SetLastError(0xdeadbeef);
1858 value = 0xbeefdead;
1859 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1860 ok(ret, "%u\n", GetLastError());
1861
1862 SetLastError(0xdeadbeef);
1863 value = 0xdeadbeef;
1864 size = sizeof(DWORD);
1865 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1866 ok(ret, "%u\n", GetLastError());
1867 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1868
1869 SetLastError(0xdeadbeef);
1870 value = 0xbeef;
1871 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1872 ok(ret, "%u\n", GetLastError());
1873
1874 SetLastError(0xdeadbeef);
1875 value = 0xdeadbeef;
1876 size = sizeof(DWORD);
1877 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1878 ok(ret, "%u\n", GetLastError());
1879 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1880
1881 SetLastError(0xdeadbeef);
1882 value = 0xbeef;
1883 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1884 ok(ret, "%u\n", GetLastError());
1885
1886 SetLastError(0xdeadbeef);
1887 value = 0xdeadbeef;
1888 size = sizeof(DWORD);
1889 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1890 ok(ret, "%u\n", GetLastError());
1891 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1892
1893 SetLastError(0xdeadbeef);
1894 value = 0xbeef;
1895 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1896 ok(ret, "%u\n", GetLastError());
1897
1898 SetLastError(0xdeadbeef);
1899 value = 0xdeadbeef;
1900 size = sizeof(DWORD);
1901 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1902 ok(ret, "%u\n", GetLastError());
1903 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1904
1905 SetLastError(0xdeadbeef);
1906 value = 0xbeef;
1907 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1908 ok(ret, "%u\n", GetLastError());
1909
1910 SetLastError(0xdeadbeef);
1911 value = 0xdeadbeef;
1912 size = sizeof(DWORD);
1913 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1914 ok(ret, "%u\n", GetLastError());
1915 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1916
1917 WinHttpCloseHandle(req);
1918 WinHttpCloseHandle(con);
1919 WinHttpCloseHandle(ses);
1920 }
1921
1922 static void test_resolve_timeout(void)
1923 {
1924 static const WCHAR nxdomain[] =
1925 {'n','x','d','o','m','a','i','n','.','w','i','n','e','h','q','.','o','r','g',0};
1926 HINTERNET ses, con, req;
1927 DWORD timeout;
1928 BOOL ret;
1929
1930 if (! proxy_active())
1931 {
1932 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1933 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1934
1935 timeout = 10000;
1936 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1937 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1938
1939 con = WinHttpConnect(ses, nxdomain, 0, 0);
1940 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1941
1942 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1943 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1944
1945 SetLastError(0xdeadbeef);
1946 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1947 if (ret)
1948 {
1949 skip("nxdomain returned success. Broken ISP redirects?\n");
1950 goto done;
1951 }
1952 ok(GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED,
1953 "expected ERROR_WINHTTP_NAME_NOT_RESOLVED got %u\n", GetLastError());
1954
1955 WinHttpCloseHandle(req);
1956 WinHttpCloseHandle(con);
1957 WinHttpCloseHandle(ses);
1958 }
1959 else
1960 skip("Skipping host resolution tests, host resolution preformed by proxy\n");
1961
1962 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1963 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1964
1965 timeout = 10000;
1966 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1967 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1968
1969 con = WinHttpConnect(ses, test_winehq, 0, 0);
1970 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1971
1972 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1973 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1974
1975 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1976 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
1977 {
1978 skip("connection failed, skipping\n");
1979 goto done;
1980 }
1981 ok(ret, "failed to send request\n");
1982
1983 done:
1984 WinHttpCloseHandle(req);
1985 WinHttpCloseHandle(con);
1986 WinHttpCloseHandle(ses);
1987 }
1988
1989 static const char page1[] =
1990 "<HTML>\r\n"
1991 "<HEAD><TITLE>winhttp test page</TITLE></HEAD>\r\n"
1992 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
1993 "</HTML>\r\n\r\n";
1994
1995 static const char okmsg[] =
1996 "HTTP/1.1 200 OK\r\n"
1997 "Server: winetest\r\n"
1998 "\r\n";
1999
2000 static const char notokmsg[] =
2001 "HTTP/1.1 400 Bad Request\r\n"
2002 "\r\n";
2003
2004 static const char cookiemsg[] =
2005 "HTTP/1.1 200 OK\r\n"
2006 "Set-Cookie: name = value \r\n"
2007 "Set-Cookie: NAME = value \r\n"
2008 "\r\n";
2009
2010 static const char nocontentmsg[] =
2011 "HTTP/1.1 204 No Content\r\n"
2012 "Server: winetest\r\n"
2013 "\r\n";
2014
2015 static const char notmodified[] =
2016 "HTTP/1.1 304 Not Modified\r\n"
2017 "\r\n";
2018
2019 static const char noauthmsg[] =
2020 "HTTP/1.1 401 Unauthorized\r\n"
2021 "Server: winetest\r\n"
2022 "Connection: close\r\n"
2023 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2024 "Content-Length: 12\r\n"
2025 "Content-Type: text/plain\r\n"
2026 "\r\n";
2027
2028 static const char okauthmsg[] =
2029 "HTTP/1.1 200 OK\r\n"
2030 "Server: winetest\r\n"
2031 "Connection: close\r\n"
2032 "Content-Length: 11\r\n"
2033 "Content-Type: text/plain\r\n"
2034 "\r\n";
2035
2036 static const char headmsg[] =
2037 "HTTP/1.1 200 OK\r\n"
2038 "Content-Length: 100\r\n"
2039 "\r\n";
2040
2041 static const char unauthorized[] = "Unauthorized";
2042 static const char hello_world[] = "Hello World";
2043
2044 struct server_info
2045 {
2046 HANDLE event;
2047 int port;
2048 };
2049
2050 #define BIG_BUFFER_LEN 0x2250
2051
2052 static DWORD CALLBACK server_thread(LPVOID param)
2053 {
2054 struct server_info *si = param;
2055 int r, c = -1, i, on;
2056 SOCKET s;
2057 struct sockaddr_in sa;
2058 char buffer[0x100];
2059 WSADATA wsaData;
2060 int last_request = 0;
2061
2062 WSAStartup(MAKEWORD(1,1), &wsaData);
2063
2064 s = socket(AF_INET, SOCK_STREAM, 0);
2065 if (s == INVALID_SOCKET)
2066 return 1;
2067
2068 on = 1;
2069 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof on);
2070
2071 memset(&sa, 0, sizeof sa);
2072 sa.sin_family = AF_INET;
2073 sa.sin_port = htons(si->port);
2074 sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
2075
2076 r = bind(s, (struct sockaddr *)&sa, sizeof(sa));
2077 if (r < 0)
2078 return 1;
2079
2080 listen(s, 0);
2081 SetEvent(si->event);
2082 do
2083 {
2084 if (c == -1) c = accept(s, NULL, NULL);
2085
2086 memset(buffer, 0, sizeof buffer);
2087 for(i = 0; i < sizeof buffer - 1; i++)
2088 {
2089 r = recv(c, &buffer[i], 1, 0);
2090 if (r != 1)
2091 break;
2092 if (i < 4) continue;
2093 if (buffer[i - 2] == '\n' && buffer[i] == '\n' &&
2094 buffer[i - 3] == '\r' && buffer[i - 1] == '\r')
2095 break;
2096 }
2097 if (strstr(buffer, "GET /basic"))
2098 {
2099 send(c, okmsg, sizeof okmsg - 1, 0);
2100 send(c, page1, sizeof page1 - 1, 0);
2101 }
2102 if (strstr(buffer, "/auth"))
2103 {
2104 if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2105 {
2106 send(c, okauthmsg, sizeof okauthmsg - 1, 0);
2107 send(c, hello_world, sizeof hello_world - 1, 0);
2108 }
2109 else
2110 {
2111 send(c, noauthmsg, sizeof noauthmsg - 1, 0);
2112 send(c, unauthorized, sizeof unauthorized - 1, 0);
2113 }
2114 continue;
2115 }
2116 if (strstr(buffer, "/big"))
2117 {
2118 char msg[BIG_BUFFER_LEN];
2119 memset(msg, 'm', sizeof(msg));
2120 send(c, okmsg, sizeof(okmsg) - 1, 0);
2121 send(c, msg, sizeof(msg), 0);
2122 }
2123 if (strstr(buffer, "/no_headers"))
2124 {
2125 send(c, page1, sizeof page1 - 1, 0);
2126 }
2127 if (strstr(buffer, "GET /no_content"))
2128 {
2129 send(c, nocontentmsg, sizeof nocontentmsg - 1, 0);
2130 continue;
2131 }
2132 if (strstr(buffer, "GET /not_modified"))
2133 {
2134 if (strstr(buffer, "If-Modified-Since:")) send(c, notmodified, sizeof notmodified - 1, 0);
2135 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2136 continue;
2137 }
2138 if (strstr(buffer, "HEAD /head"))
2139 {
2140 send(c, headmsg, sizeof headmsg - 1, 0);
2141 continue;
2142 }
2143 if (strstr(buffer, "GET /cookie3"))
2144 {
2145 if (strstr(buffer, "Cookie: name=value2; NAME=value; name=value\r\n") ||
2146 broken(strstr(buffer, "Cookie: name=value2; name=value; NAME=value\r\n") != NULL))
2147 send(c, okmsg, sizeof(okmsg) - 1, 0);
2148 else
2149 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2150 }
2151 if (strstr(buffer, "GET /cookie2"))
2152 {
2153 if (strstr(buffer, "Cookie: NAME=value; name=value\r\n") ||
2154 broken(strstr(buffer, "Cookie: name=value; NAME=value\r\n") != NULL))
2155 send(c, okmsg, sizeof(okmsg) - 1, 0);
2156 else
2157 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2158 }
2159 else if (strstr(buffer, "GET /cookie"))
2160 {
2161 if (!strstr(buffer, "Cookie: name=value\r\n")) send(c, cookiemsg, sizeof(cookiemsg) - 1, 0);
2162 else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2163 }
2164 if (strstr(buffer, "GET /quit"))
2165 {
2166 send(c, okmsg, sizeof okmsg - 1, 0);
2167 send(c, page1, sizeof page1 - 1, 0);
2168 last_request = 1;
2169 }
2170 shutdown(c, 2);
2171 closesocket(c);
2172 c = -1;
2173
2174 } while (!last_request);
2175
2176 closesocket(s);
2177 return 0;
2178 }
2179
2180 static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
2181 {
2182 static const WCHAR test_header_end_clrf[] = {'\r','\n','\r','\n',0};
2183 static const WCHAR test_header_end_raw[] = {0,0};
2184 HINTERNET ses, con, req;
2185 char buffer[0x100];
2186 WCHAR buffer2[0x100];
2187 DWORD count, status, size, error, supported, first, target;
2188 BOOL ret;
2189
2190 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2191 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2192
2193 con = WinHttpConnect(ses, localhostW, port, 0);
2194 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2195
2196 req = WinHttpOpenRequest(con, verb, path, NULL, NULL, NULL, 0);
2197 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2198
2199 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2200 ok(ret, "failed to send request %u\n", GetLastError());
2201
2202 ret = WinHttpReceiveResponse(req, NULL);
2203 ok(ret, "failed to receive response %u\n", GetLastError());
2204
2205 status = 0xdeadbeef;
2206 size = sizeof(status);
2207 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2208 ok(ret, "failed to query status code %u\n", GetLastError());
2209 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2210
2211 supported = first = target = 0xdeadbeef;
2212 SetLastError(0xdeadbeef);
2213 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2214 error = GetLastError();
2215 ok(!ret, "unexpected success\n");
2216 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2217 ok(supported == 0xdeadbeef, "got %x\n", supported);
2218 ok(first == 0xdeadbeef, "got %x\n", first);
2219 ok(target == 0xdeadbeef, "got %x\n", target);
2220
2221 size = sizeof(buffer2);
2222 memset(buffer2, 0, sizeof(buffer2));
2223 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buffer2, &size, NULL);
2224 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2225 ok(!memcmp(buffer2 + lstrlenW(buffer2) - 4, test_header_end_clrf, sizeof(test_header_end_clrf)),
2226 "WinHttpQueryHeaders returned invalid end of header string\n");
2227
2228 size = sizeof(buffer2);
2229 memset(buffer2, 0, sizeof(buffer2));
2230 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS, NULL, buffer2, &size, NULL);
2231 ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2232 ok(!memcmp(buffer2 + (size / sizeof(WCHAR)) - 1, test_header_end_raw, sizeof(test_header_end_raw)),
2233 "WinHttpQueryHeaders returned invalid end of header string\n");
2234 ok(buffer2[(size / sizeof(WCHAR)) - 2] != 0, "returned string has too many NULL characters\n");
2235
2236 count = 0;
2237 memset(buffer, 0, sizeof(buffer));
2238 ret = WinHttpReadData(req, buffer, sizeof buffer, &count);
2239 ok(ret, "failed to read data %u\n", GetLastError());
2240 ok(count == sizeof page1 - 1, "count was wrong\n");
2241 ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
2242
2243 WinHttpCloseHandle(req);
2244 WinHttpCloseHandle(con);
2245 WinHttpCloseHandle(ses);
2246 }
2247
2248 static void test_basic_authentication(int port)
2249 {
2250 static const WCHAR authW[] = {'/','a','u','t','h',0};
2251 static WCHAR userW[] = {'u','s','e','r',0};
2252 static WCHAR passW[] = {'p','w','d',0};
2253 static WCHAR pass2W[] = {'p','w','d','2',0};
2254 HINTERNET ses, con, req;
2255 DWORD status, size, error, supported, first, target;
2256 char buffer[32];
2257 BOOL ret;
2258
2259 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2260 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2261
2262 con = WinHttpConnect(ses, localhostW, port, 0);
2263 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2264
2265 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2266 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2267
2268 SetLastError(0xdeadbeef);
2269 ret = WinHttpQueryAuthSchemes(NULL, NULL, NULL, NULL);
2270 error = GetLastError();
2271 ok(!ret, "expected failure\n");
2272 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2273
2274 SetLastError(0xdeadbeef);
2275 ret = WinHttpQueryAuthSchemes(req, NULL, NULL, NULL);
2276 error = GetLastError();
2277 ok(!ret, "expected failure\n");
2278 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2279
2280 supported = 0xdeadbeef;
2281 SetLastError(0xdeadbeef);
2282 ret = WinHttpQueryAuthSchemes(req, &supported, NULL, NULL);
2283 error = GetLastError();
2284 ok(!ret, "expected failure\n");
2285 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2286 ok(supported == 0xdeadbeef, "got %x\n", supported);
2287
2288 supported = first = 0xdeadbeef;
2289 SetLastError(0xdeadbeef);
2290 ret = WinHttpQueryAuthSchemes(req, &supported, &first, NULL);
2291 error = GetLastError();
2292 ok(!ret, "expected failure\n");
2293 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2294 ok(supported == 0xdeadbeef, "got %x\n", supported);
2295 ok(first == 0xdeadbeef, "got %x\n", first);
2296
2297 supported = first = target = 0xdeadbeef;
2298 SetLastError(0xdeadbeef);
2299 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2300 error = GetLastError();
2301 ok(!ret, "expected failure\n");
2302 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2303 ok(supported == 0xdeadbeef, "got %x\n", supported);
2304 ok(first == 0xdeadbeef, "got %x\n", first);
2305 ok(target == 0xdeadbeef, "got %x\n", target);
2306
2307 supported = first = target = 0xdeadbeef;
2308 SetLastError(0xdeadbeef);
2309 ret = WinHttpQueryAuthSchemes(NULL, &supported, &first, &target);
2310 error = GetLastError();
2311 ok(!ret, "expected failure\n");
2312 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2313 ok(supported == 0xdeadbeef, "got %x\n", supported);
2314 ok(first == 0xdeadbeef, "got %x\n", first);
2315 ok(target == 0xdeadbeef, "got %x\n", target);
2316
2317 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2318 ok(ret, "failed to send request %u\n", GetLastError());
2319
2320 ret = WinHttpReceiveResponse(req, NULL);
2321 ok(ret, "failed to receive response %u\n", GetLastError());
2322
2323 status = 0xdeadbeef;
2324 size = sizeof(status);
2325 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2326 ok(ret, "failed to query status code %u\n", GetLastError());
2327 ok(status == HTTP_STATUS_DENIED, "request failed unexpectedly %u\n", status);
2328
2329 size = 0;
2330 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2331 error = GetLastError();
2332 ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2333 if (ret)
2334 {
2335 ok(size == 12, "expected 12, got %u\n", size);
2336 ok(!memcmp(buffer, unauthorized, 12), "got %s\n", buffer);
2337 }
2338
2339 supported = first = target = 0xdeadbeef;
2340 SetLastError(0xdeadbeef);
2341 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2342 error = GetLastError();
2343 ok(ret, "failed to query authentication schemes %u\n", error);
2344 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2345 ok(supported == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", supported);
2346 ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
2347 ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
2348
2349 SetLastError(0xdeadbeef);
2350 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, NULL, NULL, NULL);
2351 error = GetLastError();
2352 ok(ret, "failed to set credentials %u\n", error);
2353 ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2354
2355 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_PASSPORT, NULL, NULL, NULL);
2356 ok(ret, "failed to set credentials %u\n", GetLastError());
2357
2358 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NEGOTIATE, NULL, NULL, NULL);
2359 ok(ret, "failed to set credentials %u\n", GetLastError());
2360
2361 SetLastError(0xdeadbeef);
2362 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_DIGEST, NULL, NULL, NULL);
2363 error = GetLastError();
2364 ok(!ret, "expected failure\n");
2365 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2366
2367 SetLastError(0xdeadbeef);
2368 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, NULL, NULL);
2369 error = GetLastError();
2370 ok(!ret, "expected failure\n");
2371 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2372
2373 SetLastError(0xdeadbeef);
2374 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
2375 error = GetLastError();
2376 ok(!ret, "expected failure\n");
2377 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2378
2379 SetLastError(0xdeadbeef);
2380 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
2381 error = GetLastError();
2382 ok(!ret, "expected failure\n");
2383 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2384
2385 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2386 ok(ret, "failed to set credentials %u\n", GetLastError());
2387
2388 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2389 ok(ret, "failed to send request %u\n", GetLastError());
2390
2391 ret = WinHttpReceiveResponse(req, NULL);
2392 ok(ret, "failed to receive response %u\n", GetLastError());
2393
2394 status = 0xdeadbeef;
2395 size = sizeof(status);
2396 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2397 ok(ret, "failed to query status code %u\n", GetLastError());
2398 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2399
2400 size = 0;
2401 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2402 error = GetLastError();
2403 ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2404 if (ret)
2405 {
2406 ok(size == 11, "expected 11, got %u\n", size);
2407 ok(!memcmp(buffer, hello_world, 11), "got %s\n", buffer);
2408 }
2409
2410 WinHttpCloseHandle(req);
2411 WinHttpCloseHandle(con);
2412 WinHttpCloseHandle(ses);
2413
2414 /* credentials set with WinHttpSetCredentials take precedence over those set through options */
2415
2416 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2417 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2418
2419 con = WinHttpConnect(ses, localhostW, port, 0);
2420 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2421
2422 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2423 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2424
2425 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2426 ok(ret, "failed to set credentials %u\n", GetLastError());
2427
2428 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2429 ok(ret, "failed to set username %u\n", GetLastError());
2430
2431 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, pass2W, lstrlenW(pass2W));
2432 ok(ret, "failed to set password %u\n", GetLastError());
2433
2434 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2435 ok(ret, "failed to send request %u\n", GetLastError());
2436
2437 ret = WinHttpReceiveResponse(req, NULL);
2438 ok(ret, "failed to receive response %u\n", GetLastError());
2439
2440 status = 0xdeadbeef;
2441 size = sizeof(status);
2442 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2443 ok(ret, "failed to query status code %u\n", GetLastError());
2444 ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2445
2446 WinHttpCloseHandle(req);
2447 WinHttpCloseHandle(con);
2448 WinHttpCloseHandle(ses);
2449
2450 ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2451 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2452
2453 con = WinHttpConnect(ses, localhostW, port, 0);
2454 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2455
2456 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2457 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2458
2459 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2460 ok(ret, "failed to set username %u</