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