d7e283c0b0cc6a557d50b5582bc4aab8a0b9e988
[reactos.git] / rostests / winetests / winhttp / winhttp.c
1 /*
2 * WinHTTP - tests
3 *
4 * Copyright 2008 Google (Zac Brown)
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 #define COBJMACROS
26 #include <stdarg.h>
27 //#include <stdlib.h>
28 #include <windef.h>
29 #include <winbase.h>
30 #include <ole2.h>
31 #include <winsock2.h>
32 //#include <ws2tcpip.h>
33 #include <winhttp.h>
34 #include <wincrypt.h>
35 #include <winreg.h>
36 //#include <winsock.h>
37 //#include "initguid.h"
38 #include <httprequest.h>
39
40 #include <wine/test.h>
41
42 static const WCHAR test_useragent[] =
43 {'W','i','n','e',' ','R','e','g','r','e','s','s','i','o','n',' ','T','e','s','t',0};
44 static const WCHAR test_server[] = {'w','i','n','e','h','q','.','o','r','g',0};
45 static const WCHAR localhostW[] = {'l','o','c','a','l','h','o','s','t',0};
46
47 static BOOL proxy_active(void)
48 {
49 WINHTTP_PROXY_INFO proxy_info;
50 BOOL active = FALSE;
51
52 if (WinHttpGetDefaultProxyConfiguration(&proxy_info))
53 {
54 active = (proxy_info.lpszProxy != NULL);
55 if (active)
56 GlobalFree(proxy_info.lpszProxy);
57 if (proxy_info.lpszProxyBypass != NULL)
58 GlobalFree(proxy_info.lpszProxyBypass);
59 }
60 else
61 active = FALSE;
62
63 return active;
64 }
65
66 static void test_QueryOption(void)
67 {
68 BOOL ret;
69 HINTERNET session, request, connection;
70 DWORD feature, size;
71
72 SetLastError(0xdeadbeef);
73 session = WinHttpOpen(test_useragent, 0, 0, 0, 0);
74 ok(session != NULL, "WinHttpOpen failed to open session, error %u\n", GetLastError());
75
76 SetLastError(0xdeadbeef);
77 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, NULL);
78 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
79 ok(GetLastError() == ERROR_INVALID_PARAMETER,
80 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
81
82 size = 0xdeadbeef;
83 SetLastError(0xdeadbeef);
84 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, &size);
85 ok(!ret, "should fail to query option\n");
86 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
87 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
88 ok(size == 4, "expected 4, got %u\n", size);
89
90 feature = 0xdeadbeef;
91 size = sizeof(feature) - 1;
92 SetLastError(0xdeadbeef);
93 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
94 ok(!ret, "should fail to query option\n");
95 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
96 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
97 ok(size == 4, "expected 4, got %u\n", size);
98
99 feature = 0xdeadbeef;
100 size = sizeof(feature) + 1;
101 SetLastError(0xdeadbeef);
102 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
103 ok(ret, "failed to query option %u\n", GetLastError());
104 ok(size == sizeof(feature), "WinHttpQueryOption should set the size: %u\n", size);
105 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP,
106 "expected WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP, got %#x\n", feature);
107
108 SetLastError(0xdeadbeef);
109 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, sizeof(feature));
110 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
111 ok(GetLastError() == ERROR_INVALID_PARAMETER,
112 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
113
114 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
115 SetLastError(0xdeadbeef);
116 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) - 1);
117 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
118 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
119 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
120
121 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
122 SetLastError(0xdeadbeef);
123 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) + 1);
124 ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
125 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
126 "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
127
128 feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
129 SetLastError(0xdeadbeef);
130 ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature));
131 ok(ret, "failed to set redirect policy %u\n", GetLastError());
132
133 feature = 0xdeadbeef;
134 size = sizeof(feature);
135 SetLastError(0xdeadbeef);
136 ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
137 ok(ret, "failed to query option %u\n", GetLastError());
138 ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS,
139 "expected WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS, got %#x\n", feature);
140
141 feature = WINHTTP_DISABLE_COOKIES;
142 SetLastError(0xdeadbeef);
143 ret = WinHttpSetOption(session, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
144 ok(!ret, "should fail to set disable feature for a session\n");
145 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
146 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
147
148 SetLastError(0xdeadbeef);
149 connection = WinHttpConnect(session, test_server, INTERNET_DEFAULT_HTTP_PORT, 0);
150 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u\n", GetLastError());
151
152 feature = WINHTTP_DISABLE_COOKIES;
153 SetLastError(0xdeadbeef);
154 ret = WinHttpSetOption(connection, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
155 ok(!ret, "should fail to set disable feature for a connection\n");
156 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
157 "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
158
159 SetLastError(0xdeadbeef);
160 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
161 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
162 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
163 {
164 skip("Network unreachable, skipping the test\n");
165 goto done;
166 }
167
168 feature = 0xdeadbeef;
169 size = sizeof(feature);
170 SetLastError(0xdeadbeef);
171 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, &size);
172 ok(!ret, "should fail to query disable feature for a request\n");
173 ok(GetLastError() == ERROR_INVALID_PARAMETER,
174 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
175
176 feature = 0;
177 size = sizeof(feature);
178 SetLastError(0xdeadbeef);
179 ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
180 ok(ret, "failed to set feature %u\n", GetLastError());
181
182 feature = 0xffffffff;
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 = WINHTTP_DISABLE_COOKIES;
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 size = 0;
195 SetLastError(0xdeadbeef);
196 ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, NULL, &size);
197 ok(!ret, "should fail to query disable feature for a request\n");
198 ok(GetLastError() == ERROR_INVALID_PARAMETER,
199 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
200
201 SetLastError(0xdeadbeef);
202 ret = WinHttpCloseHandle(request);
203 ok(ret, "WinHttpCloseHandle failed on closing request: %u\n", GetLastError());
204
205 done:
206 SetLastError(0xdeadbeef);
207 ret = WinHttpCloseHandle(connection);
208 ok(ret, "WinHttpCloseHandle failed on closing connection: %u\n", GetLastError());
209 SetLastError(0xdeadbeef);
210 ret = WinHttpCloseHandle(session);
211 ok(ret, "WinHttpCloseHandle failed on closing session: %u\n", GetLastError());
212 }
213
214 static void test_OpenRequest (void)
215 {
216 BOOL ret;
217 HINTERNET session, request, connection;
218
219 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
220 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
221 ok(session != NULL, "WinHttpOpen failed to open session.\n");
222
223 /* Test with a bad server name */
224 SetLastError(0xdeadbeef);
225 connection = WinHttpConnect(session, NULL, INTERNET_DEFAULT_HTTP_PORT, 0);
226 ok (connection == NULL, "WinHttpConnect succeeded in opening connection to NULL server argument.\n");
227 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u.\n", GetLastError());
228
229 /* Test with a valid server name */
230 connection = WinHttpConnect (session, test_server, INTERNET_DEFAULT_HTTP_PORT, 0);
231 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
232
233 request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
234 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
235 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
236 {
237 skip("Network unreachable, skipping.\n");
238 goto done;
239 }
240 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
241
242 ret = WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0);
243 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
244 {
245 skip("Connection failed, skipping.\n");
246 goto done;
247 }
248 ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
249 ret = WinHttpCloseHandle(request);
250 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
251
252 done:
253 ret = WinHttpCloseHandle(connection);
254 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
255 ret = WinHttpCloseHandle(session);
256 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
257
258 }
259
260 static void test_empty_headers_param(void)
261 {
262 static const WCHAR winehq[] = {'w','i','n','e','h','q','.','o','r','g',0};
263 static const WCHAR empty[] = {0};
264 HINTERNET ses, con, req;
265 BOOL ret;
266
267 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
268 ok(ses != NULL, "failed to open session %u\n", GetLastError());
269
270 con = WinHttpConnect(ses, winehq, 80, 0);
271 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
272
273 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
274 ok(req != NULL, "failed to open a request %u\n", GetLastError());
275
276 ret = WinHttpSendRequest(req, empty, 0, NULL, 0, 0, 0);
277 ok(ret, "failed to send request %u\n", GetLastError());
278
279 WinHttpCloseHandle(req);
280 WinHttpCloseHandle(con);
281 WinHttpCloseHandle(ses);
282 }
283
284 static void test_SendRequest (void)
285 {
286 HINTERNET session, request, connection;
287 DWORD header_len, optional_len, total_len, bytes_rw, size;
288 DWORD_PTR context;
289 BOOL ret;
290 CHAR buffer[256];
291 int i;
292
293 static const WCHAR test_site[] = {'c','r','o','s','s','o','v','e','r','.',
294 'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
295 static const WCHAR content_type[] =
296 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t','i','o','n',
297 '/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o','d','e','d',0};
298 static const WCHAR test_file[] = {'/','p','o','s','t','t','e','s','t','.','p','h','p',0};
299 static const WCHAR test_verb[] = {'P','O','S','T',0};
300 static CHAR post_data[] = "mode=Test";
301 static CHAR test_post[] = "mode => Test\\0\n";
302
303 header_len = -1L;
304 total_len = optional_len = sizeof(post_data);
305 memset(buffer, 0xff, sizeof(buffer));
306
307 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
308 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
309 ok(session != NULL, "WinHttpOpen failed to open session.\n");
310
311 connection = WinHttpConnect (session, test_site, INTERNET_DEFAULT_HTTP_PORT, 0);
312 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
313
314 request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
315 WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
316 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
317 {
318 skip("Network unreachable, skipping.\n");
319 goto done;
320 }
321 ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
322 if (!request) goto done;
323
324 context = 0xdeadbeef;
325 ret = WinHttpSetOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(context));
326 ok(ret, "WinHttpSetOption failed: %u\n", GetLastError());
327
328 context++;
329 ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, context);
330 ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
331
332 context = 0;
333 size = sizeof(context);
334 ret = WinHttpQueryOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, &size);
335 ok(ret, "WinHttpQueryOption failed: %u\n", GetLastError());
336 ok(context == 0xdeadbef0, "expected 0xdeadbef0, got %lx\n", context);
337
338 for (i = 3; post_data[i]; i++)
339 {
340 bytes_rw = -1;
341 ret = WinHttpWriteData(request, &post_data[i], 1, &bytes_rw);
342 if (ret)
343 ok(bytes_rw == 1, "WinHttpWriteData failed, wrote %u bytes instead of 1 byte.\n", bytes_rw);
344 else /* Since we already passed all optional data in WinHttpSendRequest Win7 fails our WinHttpWriteData call */
345 {
346 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER got %u.\n", GetLastError());
347 ok(bytes_rw == -1, "Expected bytes_rw to remain unchanged.\n");
348 }
349 }
350
351 ret = WinHttpReceiveResponse(request, NULL);
352 ok(ret == TRUE, "WinHttpReceiveResponse failed: %u.\n", GetLastError());
353
354 bytes_rw = -1;
355 ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw);
356 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
357
358 ok(bytes_rw == strlen(test_post), "Read %u bytes instead of %d.\n", bytes_rw, lstrlen(test_post));
359 ok(strncmp(buffer, test_post, bytes_rw) == 0, "Data read did not match, got '%s'.\n", buffer);
360
361 ret = WinHttpCloseHandle(request);
362 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
363 done:
364 ret = WinHttpCloseHandle(connection);
365 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
366 ret = WinHttpCloseHandle(session);
367 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
368 }
369
370 static void test_WinHttpTimeFromSystemTime(void)
371 {
372 BOOL ret;
373 static const SYSTEMTIME time = {2008, 7, 1, 28, 10, 5, 52, 0};
374 static const WCHAR expected_string[] =
375 {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
376 '1','0',':','0','5',':','5','2',' ','G','M','T',0};
377 WCHAR time_string[WINHTTP_TIME_FORMAT_BUFSIZE+1];
378
379 ret = WinHttpTimeFromSystemTime(&time, time_string);
380 ok(ret == TRUE, "WinHttpTimeFromSystemTime failed: %u\n", GetLastError());
381 ok(memcmp(time_string, expected_string, sizeof(expected_string)) == 0,
382 "Time string returned did not match expected time string.\n");
383 }
384
385 static void test_WinHttpTimeToSystemTime(void)
386 {
387 BOOL ret;
388 SYSTEMTIME time;
389 static const SYSTEMTIME expected_time = {2008, 7, 1, 28, 10, 5, 52, 0};
390 static const WCHAR time_string1[] =
391 {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
392 + '1','0',':','0','5',':','5','2',' ','G','M','T','\n',0};
393 static const WCHAR time_string2[] =
394 {' ','m','o','n',' ','2','8',' ','j','u','l',' ','2','0','0','8',' ',
395 '1','0',' ','0','5',' ','5','2','\n',0};
396
397 ret = WinHttpTimeToSystemTime(time_string1, &time);
398 ok(ret == TRUE, "WinHttpTimeToSystemTime failed: %u\n", GetLastError());
399 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
400 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
401
402 ret = WinHttpTimeToSystemTime(time_string2, &time);
403 ok(ret == TRUE, "WinHttpTimeToSystemTime failed: %u\n", GetLastError());
404 ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
405 "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
406 }
407
408 static void test_WinHttpAddHeaders(void)
409 {
410 HINTERNET session, request, connection;
411 BOOL ret, reverse;
412 WCHAR buffer[MAX_PATH];
413 WCHAR check_buffer[MAX_PATH];
414 DWORD index, len, oldlen;
415
416 static const WCHAR test_site[] = {'c','r','o','s','s','o','v','e','r','.',
417 'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
418 static const WCHAR test_file[] = {'/','p','o','s','t','t','e','s','t','.','p','h','p',0};
419 static const WCHAR test_verb[] = {'P','O','S','T',0};
420
421 static const WCHAR test_header_begin[] =
422 {'P','O','S','T',' ','/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
423 static const WCHAR full_path_test_header_begin[] =
424 {'P','O','S','T',' ','h','t','t','p',':','/','/','c','r','o','s','s','o','v','e','r','.','c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',':','8','0','/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
425 static const WCHAR test_header_end[] = {'\r','\n','\r','\n',0};
426 static const WCHAR test_header_name[] = {'W','a','r','n','i','n','g',0};
427
428 static const WCHAR test_flag_coalesce[] = {'t','e','s','t','2',',',' ','t','e','s','t','4',0};
429 static const WCHAR test_flag_coalesce_reverse[] = {'t','e','s','t','3',',',' ','t','e','s','t','4',0};
430 static const WCHAR test_flag_coalesce_comma[] =
431 {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
432 static const WCHAR test_flag_coalesce_comma_reverse[] =
433 {'t','e','s','t','3',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
434 static const WCHAR test_flag_coalesce_semicolon[] =
435 {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
436 static const WCHAR test_flag_coalesce_semicolon_reverse[] =
437 {'t','e','s','t','3',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
438
439 static const WCHAR field[] = {'f','i','e','l','d',0};
440 static const WCHAR value[] = {'v','a','l','u','e',' ',0};
441 static const WCHAR value_nospace[] = {'v','a','l','u','e',0};
442
443 static const WCHAR test_headers[][14] =
444 {
445 {'W','a','r','n','i','n','g',':','t','e','s','t','1',0},
446 {'W','a','r','n','i','n','g',':','t','e','s','t','2',0},
447 {'W','a','r','n','i','n','g',':','t','e','s','t','3',0},
448 {'W','a','r','n','i','n','g',':','t','e','s','t','4',0},
449 {'W','a','r','n','i','n','g',':','t','e','s','t','5',0},
450 {'W','a','r','n','i','n','g',':','t','e','s','t','6',0},
451 {'W','a','r','n','i','n','g',':','t','e','s','t','7',0},
452 {0},
453 {':',0},
454 {'a',':',0},
455 {':','b',0},
456 {'c','d',0},
457 {' ','e',' ',':','f',0},
458 {'f','i','e','l','d',':',' ','v','a','l','u','e',' ',0}
459 };
460 static const WCHAR test_indices[][6] =
461 {
462 {'t','e','s','t','1',0},
463 {'t','e','s','t','2',0},
464 {'t','e','s','t','3',0},
465 {'t','e','s','t','4',0}
466 };
467
468 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
469 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
470 ok(session != NULL, "WinHttpOpen failed to open session.\n");
471
472 connection = WinHttpConnect (session, test_site, INTERNET_DEFAULT_HTTP_PORT, 0);
473 ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
474
475 request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
476 WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
477 if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
478 {
479 skip("Network unreachable, skipping.\n");
480 goto done;
481 }
482 ok(request != NULL, "WinHttpOpenRequest failed to open a request, error: %u.\n", GetLastError());
483
484 index = 0;
485 len = sizeof(buffer);
486 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
487 test_header_name, buffer, &len, &index);
488 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, found 'Warning' header.\n");
489 ret = WinHttpAddRequestHeaders(request, test_headers[0], -1L, WINHTTP_ADDREQ_FLAG_ADD);
490 ok(ret == TRUE, "WinHttpAddRequestHeader failed to add new header, got %d with error %u.\n", ret, GetLastError());
491
492 index = 0;
493 len = sizeof(buffer);
494 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
495 test_header_name, buffer, &len, &index);
496 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
497 ok(index == 1, "WinHttpQueryHeaders failed: header index not incremented\n");
498 ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders failed: incorrect string returned\n");
499 ok(len == 5*sizeof(WCHAR), "WinHttpQueryHeaders failed: invalid length returned, expected 5, got %d\n", len);
500
501 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
502 test_header_name, buffer, &len, &index);
503 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, second index should not exist.\n");
504
505 /* Try to fetch the header info with a buffer that's big enough to fit the
506 * string but not the NULL terminator.
507 */
508 index = 0;
509 len = 5*sizeof(WCHAR);
510 memset(check_buffer, 0xab, sizeof(check_buffer));
511 memcpy(buffer, check_buffer, sizeof(buffer));
512 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
513 test_header_name, buffer, &len, &index);
514 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded with a buffer that's too small.\n");
515 ok(memcmp(buffer, check_buffer, sizeof(buffer)) == 0,
516 "WinHttpQueryHeaders failed, modified the buffer when it should not have.\n");
517 ok(len == 6*sizeof(WCHAR), "WinHttpQueryHeaders returned invalid length, expected 12, got %d\n", len);
518
519 /* Try with a NULL buffer */
520 index = 0;
521 len = sizeof(buffer);
522 SetLastError(0xdeadbeef);
523 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
524 test_header_name, NULL, &len, &index);
525 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
526 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
527 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
528 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
529
530 /* Try with a NULL buffer and a length that's too small */
531 index = 0;
532 len = 10;
533 SetLastError(0xdeadbeef);
534 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
535 test_header_name, NULL, &len, &index);
536 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
537 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
538 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICENT_BUFFER, go %u\n", GetLastError());
539 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
540 ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
541
542 index = 0;
543 len = 0;
544 SetLastError(0xdeadbeef);
545 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
546 test_header_name, NULL, &len, &index);
547 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
548 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
549 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
550 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
551 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
552
553 /* valid query */
554 oldlen = len;
555 index = 0;
556 len = sizeof(buffer);
557 memset(buffer, 0xff, sizeof(buffer));
558 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
559 test_header_name, buffer, &len, &index);
560 ok(ret == TRUE, "WinHttpQueryHeaders failed: got %d\n", ret);
561 ok(len + sizeof(WCHAR) <= oldlen, "WinHttpQueryHeaders resulting length longer than advertized.\n");
562 ok((len < sizeof(buffer) - sizeof(WCHAR)) && buffer[len / sizeof(WCHAR)] == 0, "WinHttpQueryHeaders did not append NULL terminator\n");
563 ok(len == lstrlenW(buffer) * sizeof(WCHAR), "WinHttpQueryHeaders returned incorrect length.\n");
564 ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
565 memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
566 "WinHttpQueryHeaders returned invalid beginning of header string.\n");
567 ok(memcmp(buffer + lstrlenW(buffer) - 4, test_header_end, sizeof(test_header_end)) == 0,
568 "WinHttpQueryHeaders returned invalid end of header string.\n");
569 ok(index == 0, "WinHttpQueryHeaders incremented header index.\n");
570
571 index = 0;
572 len = 0;
573 SetLastError(0xdeadbeef);
574 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
575 test_header_name, NULL, &len, &index);
576 ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
577 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
578 "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
579 ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
580 ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
581
582 oldlen = len;
583 index = 0;
584 len = sizeof(buffer);
585 memset(buffer, 0xff, sizeof(buffer));
586 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
587 test_header_name, buffer, &len, &index);
588 ok(ret == TRUE, "WinHttpQueryHeaders failed %u\n", GetLastError());
589 ok(len + sizeof(WCHAR) <= oldlen, "resulting length longer than advertized\n");
590 ok((len < sizeof(buffer) - sizeof(WCHAR)) && !buffer[len / sizeof(WCHAR)] && !buffer[len / sizeof(WCHAR) - 1],
591 "no double NULL terminator\n");
592 ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
593 memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
594 "invalid beginning of header string.\n");
595 ok(index == 0, "header index was incremented\n");
596
597 /* tests for more indices */
598 ret = WinHttpAddRequestHeaders(request, test_headers[1], -1L, WINHTTP_ADDREQ_FLAG_ADD);
599 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header: %d\n", ret);
600
601 index = 0;
602 len = sizeof(buffer);
603 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
604 test_header_name, buffer, &len, &index);
605 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
606 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
607 ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
608
609 len = sizeof(buffer);
610 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
611 test_header_name, buffer, &len, &index);
612 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
613 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
614 ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
615
616 ret = WinHttpAddRequestHeaders(request, test_headers[2], -1L, WINHTTP_ADDREQ_FLAG_REPLACE);
617 ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header.\n");
618
619 index = 0;
620 len = sizeof(buffer);
621 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
622 test_header_name, buffer, &len, &index);
623 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
624 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
625 reverse = (memcmp(buffer, test_indices[1], sizeof(test_indices[1])) != 0); /* Win7 returns values in reverse order of adding */
626 ok(memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
627
628 len = sizeof(buffer);
629 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
630 test_header_name, buffer, &len, &index);
631 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
632 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
633 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
634
635 /* add if new flag */
636 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW);
637 ok(ret == FALSE, "WinHttpAddRequestHeaders incorrectly replaced existing header.\n");
638
639 index = 0;
640 len = sizeof(buffer);
641 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
642 test_header_name, buffer, &len, &index);
643 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
644 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
645 ok(memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
646
647 len = sizeof(buffer);
648 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
649 test_header_name, buffer, &len, &index);
650 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
651 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
652 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
653
654 len = sizeof(buffer);
655 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
656 test_header_name, buffer, &len, &index);
657 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
658
659 /* coalesce flag */
660 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_COALESCE);
661 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE.\n");
662
663 index = 0;
664 len = sizeof(buffer);
665 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
666 test_header_name, buffer, &len, &index);
667 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
668 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
669 ok(memcmp(buffer, reverse ? test_flag_coalesce_reverse : test_flag_coalesce,
670 reverse ? sizeof(test_flag_coalesce_reverse) : sizeof(test_flag_coalesce)) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
671
672 len = sizeof(buffer);
673 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
674 test_header_name, buffer, &len, &index);
675 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
676 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
677 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
678
679 len = sizeof(buffer);
680 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
681 test_header_name, buffer, &len, &index);
682 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
683
684 /* coalesce with comma flag */
685 ret = WinHttpAddRequestHeaders(request, test_headers[4], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA);
686 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA.\n");
687
688 index = 0;
689 len = sizeof(buffer);
690 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
691 test_header_name, buffer, &len, &index);
692 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
693 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
694 ok(memcmp(buffer, reverse ? test_flag_coalesce_comma_reverse : test_flag_coalesce_comma,
695 reverse ? sizeof(test_flag_coalesce_comma_reverse) : sizeof(test_flag_coalesce_comma)) == 0,
696 "WinHttpQueryHeaders returned incorrect string.\n");
697
698 len = sizeof(buffer);
699 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
700 test_header_name, buffer, &len, &index);
701 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
702 ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
703 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
704
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 == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
709
710
711 /* coalesce with semicolon flag */
712 ret = WinHttpAddRequestHeaders(request, test_headers[5], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON);
713 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON.\n");
714
715 index = 0;
716 len = sizeof(buffer);
717 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
718 test_header_name, buffer, &len, &index);
719 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
720 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
721 ok(memcmp(buffer, reverse ? test_flag_coalesce_semicolon_reverse : test_flag_coalesce_semicolon,
722 reverse ? sizeof(test_flag_coalesce_semicolon_reverse) : sizeof(test_flag_coalesce_semicolon)) == 0,
723 "WinHttpQueryHeaders returned incorrect string.\n");
724
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 == 2, "WinHttpQueryHeaders failed to increment index.\n");
730 ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 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 == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
736
737 /* add and replace flags */
738 ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
739 ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE.\n");
740
741 index = 0;
742 len = sizeof(buffer);
743 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
744 test_header_name, buffer, &len, &index);
745 ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
746 ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
747 ok(memcmp(buffer, test_indices[reverse ? 3 : 2], sizeof(test_indices[reverse ? 3 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
748
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 == 2, "WinHttpQueryHeaders failed to increment index.\n");
754 ok(memcmp(buffer, test_indices[reverse ? 1 : 3], sizeof(test_indices[reverse ? 1 : 3])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
755
756 len = sizeof(buffer);
757 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
758 test_header_name, buffer, &len, &index);
759 ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
760
761 ret = WinHttpAddRequestHeaders(request, test_headers[8], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
762 ok(!ret, "WinHttpAddRequestHeaders failed\n");
763
764 ret = WinHttpAddRequestHeaders(request, test_headers[9], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
765 ok(ret, "WinHttpAddRequestHeaders failed\n");
766
767 ret = WinHttpAddRequestHeaders(request, test_headers[10], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
768 ok(!ret, "WinHttpAddRequestHeaders failed\n");
769
770 ret = WinHttpAddRequestHeaders(request, test_headers[11], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
771 ok(!ret, "WinHttpAddRequestHeaders failed\n");
772
773 ret = WinHttpAddRequestHeaders(request, test_headers[12], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
774 ok(!ret, "WinHttpAddRequestHeaders failed\n");
775
776 ret = WinHttpAddRequestHeaders(request, test_headers[13], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
777 ok(ret, "WinHttpAddRequestHeaders failed\n");
778
779 index = 0;
780 buffer[0] = 0;
781 len = sizeof(buffer);
782 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
783 field, buffer, &len, &index);
784 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
785 ok(!memcmp(buffer, value, sizeof(value)) || ! memcmp(buffer, value_nospace, sizeof(value_nospace)), "unexpected result\n");
786
787 ret = WinHttpCloseHandle(request);
788 ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
789 done:
790 ret = WinHttpCloseHandle(connection);
791 ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
792 ret = WinHttpCloseHandle(session);
793 ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
794
795 }
796
797 static void CALLBACK cert_error(HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID buf, DWORD len)
798 {
799 DWORD flags = *(DWORD *)buf;
800
801 if (!flags)
802 {
803 trace("WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR\n");
804 return;
805 }
806 #define X(x) if (flags & x) trace("%s\n", #x);
807 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED)
808 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT)
809 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED)
810 X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA)
811 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID)
812 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)
813 X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE)
814 #undef X
815 }
816
817 static void test_secure_connection(void)
818 {
819 static const WCHAR google[] = {'w','w','w','.','g','o','o','g','l','e','.','c','o','m',0};
820
821 HINTERNET ses, con, req;
822 DWORD size, status, policy, bitness, read_size;
823 BOOL ret;
824 CERT_CONTEXT *cert;
825 WINHTTP_CERTIFICATE_INFO info;
826 char buffer[32];
827
828 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
829 ok(ses != NULL, "failed to open session %u\n", GetLastError());
830
831 policy = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
832 ret = WinHttpSetOption(ses, WINHTTP_OPTION_REDIRECT_POLICY, &policy, sizeof(policy));
833 ok(ret, "failed to set redirect policy %u\n", GetLastError());
834
835 con = WinHttpConnect(ses, google, 443, 0);
836 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
837
838 /* try without setting WINHTTP_FLAG_SECURE */
839 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
840 ok(req != NULL, "failed to open a request %u\n", GetLastError());
841
842 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
843 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
844 {
845 skip("Connection failed, skipping.\n");
846 goto cleanup;
847 }
848 ok(ret, "failed to send request %u\n", GetLastError());
849
850 ret = WinHttpReceiveResponse(req, NULL);
851 ok(!ret || proxy_active(), "succeeded unexpectedly\n");
852
853 size = 0;
854 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
855 ok(!ret, "succeeded unexpectedly\n");
856
857 WinHttpCloseHandle(req);
858
859 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, WINHTTP_FLAG_SECURE);
860 ok(req != NULL, "failed to open a request %u\n", GetLastError());
861
862 WinHttpSetStatusCallback(req, cert_error, WINHTTP_CALLBACK_STATUS_SECURE_FAILURE, 0);
863
864 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
865 ok(ret, "failed to send request %u\n", GetLastError());
866 if (!ret)
867 {
868 skip("secure connection failed, skipping remaining secure tests\n");
869 goto cleanup;
870 }
871
872 size = sizeof(cert);
873 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size );
874 ok(ret, "failed to retrieve certificate context %u\n", GetLastError());
875 if (ret)
876 CertFreeCertificateContext(cert);
877
878 size = sizeof(bitness);
879 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_KEY_BITNESS, &bitness, &size );
880 ok(ret, "failed to retrieve key bitness %u\n", GetLastError());
881
882 size = sizeof(info);
883 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT, &info, &size );
884 ok(ret, "failed to retrieve certificate info %u\n", GetLastError());
885
886 trace("lpszSubjectInfo %s\n", wine_dbgstr_w(info.lpszSubjectInfo));
887 trace("lpszIssuerInfo %s\n", wine_dbgstr_w(info.lpszIssuerInfo));
888 trace("lpszProtocolName %s\n", wine_dbgstr_w(info.lpszProtocolName));
889 trace("lpszSignatureAlgName %s\n", wine_dbgstr_w(info.lpszSignatureAlgName));
890 trace("lpszEncryptionAlgName %s\n", wine_dbgstr_w(info.lpszEncryptionAlgName));
891 trace("dwKeySize %u\n", info.dwKeySize);
892
893 ret = WinHttpReceiveResponse(req, NULL);
894 ok(ret, "failed to receive response %u\n", GetLastError());
895
896 size = sizeof(status);
897 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
898 ok(ret, "failed unexpectedly %u\n", GetLastError());
899 ok(status == 200, "request failed unexpectedly %u\n", status);
900
901 size = 0;
902 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
903 ok(!ret, "succeeded unexpectedly\n");
904
905 read_size = 0;
906 for (;;)
907 {
908 size = 0;
909 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
910 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
911 if (!size) break;
912 read_size += size;
913 }
914 ok(read_size > 2014, "read_size = %u\n", read_size);
915
916 cleanup:
917 WinHttpCloseHandle(req);
918 WinHttpCloseHandle(con);
919 WinHttpCloseHandle(ses);
920 }
921
922 static void test_request_parameter_defaults(void)
923 {
924 static const WCHAR empty[] = {0};
925 static const WCHAR codeweavers[] = {'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
926
927 HINTERNET ses, con, req;
928 DWORD size, status, error;
929 WCHAR *version;
930 BOOL ret;
931
932 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
933 ok(ses != NULL, "failed to open session %u\n", GetLastError());
934
935 con = WinHttpConnect(ses, codeweavers, 0, 0);
936 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
937
938 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
939 ok(req != NULL, "failed to open a request %u\n", GetLastError());
940
941 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
942 ok(ret, "failed to send request %u\n", GetLastError());
943
944 ret = WinHttpReceiveResponse(req, NULL);
945 ok(ret, "failed to receive response %u\n", GetLastError());
946
947 size = sizeof(status);
948 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
949 ok(ret, "failed unexpectedly %u\n", GetLastError());
950 ok(status == 200, "request failed unexpectedly %u\n", status);
951
952 WinHttpCloseHandle(req);
953
954 req = WinHttpOpenRequest(con, empty, empty, empty, NULL, NULL, 0);
955 ok(req != NULL, "failed to open a request %u\n", GetLastError());
956
957 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
958 ok(ret, "failed to send request %u\n", GetLastError());
959
960 ret = WinHttpReceiveResponse(req, NULL);
961 ok(ret, "failed to receive response %u\n", GetLastError());
962
963 size = 0;
964 SetLastError(0xdeadbeef);
965 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, NULL, &size, NULL);
966 error = GetLastError();
967 ok(!ret, "succeeded unexpectedly\n");
968 ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
969
970 version = HeapAlloc(GetProcessHeap(), 0, size);
971 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, version, &size, NULL);
972 ok(ret, "failed unexpectedly %u\n", GetLastError());
973 ok(lstrlenW(version) == size / sizeof(WCHAR), "unexpected size %u\n", size);
974 HeapFree(GetProcessHeap(), 0, version);
975
976 size = sizeof(status);
977 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
978 ok(ret, "failed unexpectedly %u\n", GetLastError());
979 ok(status == 200, "request failed unexpectedly %u\n", status);
980
981 WinHttpCloseHandle(req);
982 WinHttpCloseHandle(con);
983 WinHttpCloseHandle(ses);
984 }
985
986 static const WCHAR Connections[] = {
987 'S','o','f','t','w','a','r','e','\\',
988 'M','i','c','r','o','s','o','f','t','\\',
989 'W','i','n','d','o','w','s','\\',
990 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
991 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
992 'C','o','n','n','e','c','t','i','o','n','s',0 };
993 static const WCHAR WinHttpSettings[] = {
994 'W','i','n','H','t','t','p','S','e','t','t','i','n','g','s',0 };
995
996 static DWORD get_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD *type )
997 {
998 LONG l;
999 HKEY key;
1000 DWORD ret = 0;
1001
1002 l = RegOpenKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, KEY_READ, &key );
1003 if (!l)
1004 {
1005 DWORD size = 0;
1006
1007 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, NULL, &size );
1008 if (!l)
1009 {
1010 if (size <= len)
1011 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, buf,
1012 &size );
1013 if (!l)
1014 ret = size;
1015 }
1016 RegCloseKey( key );
1017 }
1018 return ret;
1019 }
1020
1021 static void set_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD type )
1022 {
1023 LONG l;
1024 HKEY key;
1025
1026 l = RegCreateKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, NULL, 0,
1027 KEY_WRITE, NULL, &key, NULL );
1028 if (!l)
1029 {
1030 if (len)
1031 RegSetValueExW( key, WinHttpSettings, 0, type, buf, len );
1032 else
1033 RegDeleteValueW( key, WinHttpSettings );
1034 RegCloseKey( key );
1035 }
1036 }
1037
1038 static void test_set_default_proxy_config(void)
1039 {
1040 static WCHAR wideString[] = { 0x226f, 0x575b, 0 };
1041 static WCHAR normalString[] = { 'f','o','o',0 };
1042 DWORD type, len;
1043 BYTE *saved_proxy_settings = NULL;
1044 WINHTTP_PROXY_INFO info;
1045 BOOL ret;
1046
1047 /* FIXME: it would be simpler to read the current settings using
1048 * WinHttpGetDefaultProxyConfiguration and save them using
1049 * WinHttpSetDefaultProxyConfiguration, but they appear to have a bug.
1050 *
1051 * If a proxy is configured in the registry, e.g. via 'proxcfg -p "foo"',
1052 * the access type reported by WinHttpGetDefaultProxyConfiguration is 1,
1053 * WINHTTP_ACCESS_TYPE_NO_PROXY, whereas it should be
1054 * WINHTTP_ACCESS_TYPE_NAMED_PROXY.
1055 * If WinHttpSetDefaultProxyConfiguration is called with dwAccessType = 1,
1056 * the lpszProxy and lpszProxyBypass values are ignored.
1057 * Thus, if a proxy is set with proxycfg, then calling
1058 * WinHttpGetDefaultProxyConfiguration followed by
1059 * WinHttpSetDefaultProxyConfiguration results in the proxy settings
1060 * getting deleted from the registry.
1061 *
1062 * Instead I read the current registry value and restore it directly.
1063 */
1064 len = get_default_proxy_reg_value( NULL, 0, &type );
1065 if (len)
1066 {
1067 saved_proxy_settings = HeapAlloc( GetProcessHeap(), 0, len );
1068 len = get_default_proxy_reg_value( saved_proxy_settings, len, &type );
1069 }
1070
1071 if (0)
1072 {
1073 /* Crashes on Vista and higher */
1074 SetLastError(0xdeadbeef);
1075 ret = WinHttpSetDefaultProxyConfiguration(NULL);
1076 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1077 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1078 }
1079
1080 /* test with invalid access type */
1081 info.dwAccessType = 0xdeadbeef;
1082 info.lpszProxy = info.lpszProxyBypass = NULL;
1083 SetLastError(0xdeadbeef);
1084 ret = WinHttpSetDefaultProxyConfiguration(&info);
1085 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1086 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1087
1088 /* at a minimum, the proxy server must be set */
1089 info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1090 info.lpszProxy = info.lpszProxyBypass = NULL;
1091 SetLastError(0xdeadbeef);
1092 ret = WinHttpSetDefaultProxyConfiguration(&info);
1093 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1094 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1095 info.lpszProxyBypass = normalString;
1096 SetLastError(0xdeadbeef);
1097 ret = WinHttpSetDefaultProxyConfiguration(&info);
1098 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1099 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1100
1101 /* the proxy server can't have wide characters */
1102 info.lpszProxy = wideString;
1103 SetLastError(0xdeadbeef);
1104 ret = WinHttpSetDefaultProxyConfiguration(&info);
1105 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1106 skip("couldn't set default proxy configuration: access denied\n");
1107 else
1108 ok((!ret && GetLastError() == ERROR_INVALID_PARAMETER) ||
1109 broken(ret), /* Earlier winhttp versions on W2K/XP */
1110 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1111
1112 info.lpszProxy = normalString;
1113 SetLastError(0xdeadbeef);
1114 ret = WinHttpSetDefaultProxyConfiguration(&info);
1115 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1116 skip("couldn't set default proxy configuration: access denied\n");
1117 else
1118 ok(ret, "WinHttpSetDefaultProxyConfiguration failed: %d\n",
1119 GetLastError());
1120
1121 set_default_proxy_reg_value( saved_proxy_settings, len, type );
1122 }
1123
1124 static void test_Timeouts (void)
1125 {
1126 BOOL ret;
1127 DWORD value, size;
1128 HINTERNET ses, req, con;
1129 static const WCHAR codeweavers[] = {'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
1130
1131
1132 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1133 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1134
1135 SetLastError(0xdeadbeef);
1136 ret = WinHttpSetTimeouts(ses, -2, 0, 0, 0);
1137 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1138 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1139
1140 SetLastError(0xdeadbeef);
1141 ret = WinHttpSetTimeouts(ses, 0, -2, 0, 0);
1142 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1143 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1144
1145 SetLastError(0xdeadbeef);
1146 ret = WinHttpSetTimeouts(ses, 0, 0, -2, 0);
1147 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1148 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1149
1150 SetLastError(0xdeadbeef);
1151 ret = WinHttpSetTimeouts(ses, 0, 0, 0, -2);
1152 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1153 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1154
1155 SetLastError(0xdeadbeef);
1156 ret = WinHttpSetTimeouts(ses, -1, -1, -1, -1);
1157 ok(ret, "%u\n", GetLastError());
1158
1159 SetLastError(0xdeadbeef);
1160 ret = WinHttpSetTimeouts(ses, 0, 0, 0, 0);
1161 ok(ret, "%u\n", GetLastError());
1162
1163 SetLastError(0xdeadbeef);
1164 ret = WinHttpSetTimeouts(ses, 0x0123, 0x4567, 0x89ab, 0xcdef);
1165 ok(ret, "%u\n", GetLastError());
1166
1167 SetLastError(0xdeadbeef);
1168 value = 0xdeadbeef;
1169 size = sizeof(DWORD);
1170 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1171 ok(ret, "%u\n", GetLastError());
1172 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1173
1174 SetLastError(0xdeadbeef);
1175 value = 0xdeadbeef;
1176 size = sizeof(DWORD);
1177 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1178 ok(ret, "%u\n", GetLastError());
1179 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1180
1181 SetLastError(0xdeadbeef);
1182 value = 0xdeadbeef;
1183 size = sizeof(DWORD);
1184 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1185 ok(ret, "%u\n", GetLastError());
1186 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1187
1188 SetLastError(0xdeadbeef);
1189 value = 0xdeadbeef;
1190 size = sizeof(DWORD);
1191 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1192 ok(ret, "%u\n", GetLastError());
1193 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1194
1195 SetLastError(0xdeadbeef);
1196 value = 0;
1197 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1198 ok(ret, "%u\n", GetLastError());
1199
1200 SetLastError(0xdeadbeef);
1201 value = 0xdeadbeef;
1202 size = sizeof(DWORD);
1203 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1204 ok(ret, "%u\n", GetLastError());
1205 ok(value == 0, "Expected 0, got %u\n", value);
1206
1207 SetLastError(0xdeadbeef);
1208 value = 0;
1209 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1210 ok(ret, "%u\n", GetLastError());
1211
1212 SetLastError(0xdeadbeef);
1213 value = 0xdeadbeef;
1214 size = sizeof(DWORD);
1215 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1216 ok(ret, "%u\n", GetLastError());
1217 ok(value == 0, "Expected 0, got %u\n", value);
1218
1219 SetLastError(0xdeadbeef);
1220 value = 0;
1221 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1222 ok(ret, "%u\n", GetLastError());
1223
1224 SetLastError(0xdeadbeef);
1225 value = 0xdeadbeef;
1226 size = sizeof(DWORD);
1227 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1228 ok(ret, "%u\n", GetLastError());
1229 ok(value == 0, "Expected 0, got %u\n", value);
1230
1231 SetLastError(0xdeadbeef);
1232 value = 0;
1233 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1234 ok(ret, "%u\n", GetLastError());
1235
1236 SetLastError(0xdeadbeef);
1237 value = 0xdeadbeef;
1238 size = sizeof(DWORD);
1239 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1240 ok(ret, "%u\n", GetLastError());
1241 ok(value == 0, "Expected 0, got %u\n", value);
1242
1243 SetLastError(0xdeadbeef);
1244 value = 0xbeefdead;
1245 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1246 ok(ret, "%u\n", GetLastError());
1247
1248 SetLastError(0xdeadbeef);
1249 value = 0xdeadbeef;
1250 size = sizeof(DWORD);
1251 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1252 ok(ret, "%u\n", GetLastError());
1253 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1254
1255 SetLastError(0xdeadbeef);
1256 value = 0xbeefdead;
1257 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1258 ok(ret, "%u\n", GetLastError());
1259
1260 SetLastError(0xdeadbeef);
1261 value = 0xdeadbeef;
1262 size = sizeof(DWORD);
1263 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1264 ok(ret, "%u\n", GetLastError());
1265 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1266
1267 SetLastError(0xdeadbeef);
1268 value = 0xbeefdead;
1269 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1270 ok(ret, "%u\n", GetLastError());
1271
1272 SetLastError(0xdeadbeef);
1273 value = 0xdeadbeef;
1274 size = sizeof(DWORD);
1275 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1276 ok(ret, "%u\n", GetLastError());
1277 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1278
1279 SetLastError(0xdeadbeef);
1280 value = 0xbeefdead;
1281 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1282 ok(ret, "%u\n", GetLastError());
1283
1284 SetLastError(0xdeadbeef);
1285 value = 0xdeadbeef;
1286 size = sizeof(DWORD);
1287 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1288 ok(ret, "%u\n", GetLastError());
1289 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1290
1291 con = WinHttpConnect(ses, codeweavers, 0, 0);
1292 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1293
1294 /* Timeout values should match the last one set for session */
1295 SetLastError(0xdeadbeef);
1296 value = 0xdeadbeef;
1297 size = sizeof(DWORD);
1298 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1299 ok(ret, "%u\n", GetLastError());
1300 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1301
1302 SetLastError(0xdeadbeef);
1303 value = 0xdeadbeef;
1304 size = sizeof(DWORD);
1305 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1306 ok(ret, "%u\n", GetLastError());
1307 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1308
1309 SetLastError(0xdeadbeef);
1310 value = 0xdeadbeef;
1311 size = sizeof(DWORD);
1312 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1313 ok(ret, "%u\n", GetLastError());
1314 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1315
1316 SetLastError(0xdeadbeef);
1317 value = 0xdeadbeef;
1318 size = sizeof(DWORD);
1319 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1320 ok(ret, "%u\n", GetLastError());
1321 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1322
1323 SetLastError(0xdeadbeef);
1324 ret = WinHttpSetTimeouts(con, -2, 0, 0, 0);
1325 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1326 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1327
1328 SetLastError(0xdeadbeef);
1329 ret = WinHttpSetTimeouts(con, 0, -2, 0, 0);
1330 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1331 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1332
1333 SetLastError(0xdeadbeef);
1334 ret = WinHttpSetTimeouts(con, 0, 0, -2, 0);
1335 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1336 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1337
1338 SetLastError(0xdeadbeef);
1339 ret = WinHttpSetTimeouts(con, 0, 0, 0, -2);
1340 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1341 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1342
1343 SetLastError(0xdeadbeef);
1344 ret = WinHttpSetTimeouts(con, -1, -1, -1, -1);
1345 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1346 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1347
1348 SetLastError(0xdeadbeef);
1349 ret = WinHttpSetTimeouts(con, 0, 0, 0, 0);
1350 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1351 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1352
1353 SetLastError(0xdeadbeef);
1354 value = 0;
1355 ret = WinHttpSetOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1356 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1357 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1358
1359 SetLastError(0xdeadbeef);
1360 value = 0;
1361 ret = WinHttpSetOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1362 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1363 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1364
1365 SetLastError(0xdeadbeef);
1366 value = 0;
1367 ret = WinHttpSetOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1368 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1369 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1370
1371 SetLastError(0xdeadbeef);
1372 value = 0;
1373 ret = WinHttpSetOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1374 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1375 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1376
1377 /* Changing timeout values for session should affect the values for connection */
1378 SetLastError(0xdeadbeef);
1379 value = 0xdead;
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(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1387 ok(ret, "%u\n", GetLastError());
1388 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1389
1390 SetLastError(0xdeadbeef);
1391 value = 0xdead;
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(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1399 ok(ret, "%u\n", GetLastError());
1400 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1401
1402 SetLastError(0xdeadbeef);
1403 value = 0xdead;
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(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1411 ok(ret, "%u\n", GetLastError());
1412 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1413
1414 SetLastError(0xdeadbeef);
1415 value = 0xdead;
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(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1423 ok(ret, "%u\n", GetLastError());
1424 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1425
1426 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1427 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1428
1429 /* Timeout values should match the last one set for session */
1430 SetLastError(0xdeadbeef);
1431 value = 0xdeadbeef;
1432 size = sizeof(DWORD);
1433 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1434 ok(ret, "%u\n", GetLastError());
1435 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1436
1437 SetLastError(0xdeadbeef);
1438 value = 0xdeadbeef;
1439 size = sizeof(DWORD);
1440 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1441 ok(ret, "%u\n", GetLastError());
1442 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1443
1444 SetLastError(0xdeadbeef);
1445 value = 0xdeadbeef;
1446 size = sizeof(DWORD);
1447 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1448 ok(ret, "%u\n", GetLastError());
1449 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1450
1451 SetLastError(0xdeadbeef);
1452 value = 0xdeadbeef;
1453 size = sizeof(DWORD);
1454 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1455 ok(ret, "%u\n", GetLastError());
1456 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1457
1458 SetLastError(0xdeadbeef);
1459 ret = WinHttpSetTimeouts(req, -2, 0, 0, 0);
1460 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1461 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1462
1463 SetLastError(0xdeadbeef);
1464 ret = WinHttpSetTimeouts(req, 0, -2, 0, 0);
1465 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1466 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1467
1468 SetLastError(0xdeadbeef);
1469 ret = WinHttpSetTimeouts(req, 0, 0, -2, 0);
1470 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1471 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1472
1473 SetLastError(0xdeadbeef);
1474 ret = WinHttpSetTimeouts(req, 0, 0, 0, -2);
1475 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1476 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1477
1478 SetLastError(0xdeadbeef);
1479 ret = WinHttpSetTimeouts(req, -1, -1, -1, -1);
1480 ok(ret, "%u\n", GetLastError());
1481
1482 SetLastError(0xdeadbeef);
1483 ret = WinHttpSetTimeouts(req, 0, 0, 0, 0);
1484 ok(ret, "%u\n", GetLastError());
1485
1486 SetLastError(0xdeadbeef);
1487 ret = WinHttpSetTimeouts(req, 0xcdef, 0x89ab, 0x4567, 0x0123);
1488 ok(ret, "%u\n", GetLastError());
1489
1490 SetLastError(0xdeadbeef);
1491 value = 0xdeadbeef;
1492 size = sizeof(DWORD);
1493 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1494 ok(ret, "%u\n", GetLastError());
1495 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1496
1497 SetLastError(0xdeadbeef);
1498 value = 0xdeadbeef;
1499 size = sizeof(DWORD);
1500 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1501 ok(ret, "%u\n", GetLastError());
1502 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1503
1504 SetLastError(0xdeadbeef);
1505 value = 0xdeadbeef;
1506 size = sizeof(DWORD);
1507 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1508 ok(ret, "%u\n", GetLastError());
1509 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1510
1511 SetLastError(0xdeadbeef);
1512 value = 0xdeadbeef;
1513 size = sizeof(DWORD);
1514 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1515 ok(ret, "%u\n", GetLastError());
1516 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1517
1518 SetLastError(0xdeadbeef);
1519 value = 0;
1520 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1521 ok(ret, "%u\n", GetLastError());
1522
1523 SetLastError(0xdeadbeef);
1524 value = 0xdeadbeef;
1525 size = sizeof(DWORD);
1526 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1527 ok(ret, "%u\n", GetLastError());
1528 ok(value == 0, "Expected 0, got %u\n", value);
1529
1530 SetLastError(0xdeadbeef);
1531 value = 0;
1532 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1533 ok(ret, "%u\n", GetLastError());
1534
1535 SetLastError(0xdeadbeef);
1536 value = 0xdeadbeef;
1537 size = sizeof(DWORD);
1538 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1539 ok(ret, "%u\n", GetLastError());
1540 ok(value == 0, "Expected 0, got %u\n", value);
1541
1542 SetLastError(0xdeadbeef);
1543 value = 0;
1544 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1545 ok(ret, "%u\n", GetLastError());
1546
1547 SetLastError(0xdeadbeef);
1548 value = 0xdeadbeef;
1549 size = sizeof(DWORD);
1550 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1551 ok(ret, "%u\n", GetLastError());
1552 ok(value == 0, "Expected 0, got %u\n", value);
1553
1554 SetLastError(0xdeadbeef);
1555 value = 0;
1556 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1557 ok(ret, "%u\n", GetLastError());
1558
1559 SetLastError(0xdeadbeef);
1560 value = 0xdeadbeef;
1561 size = sizeof(DWORD);
1562 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1563 ok(ret, "%u\n", GetLastError());
1564 ok(value == 0, "Expected 0, got %u\n", value);
1565
1566 SetLastError(0xdeadbeef);
1567 value = 0xbeefdead;
1568 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1569 ok(ret, "%u\n", GetLastError());
1570
1571 SetLastError(0xdeadbeef);
1572 value = 0xdeadbeef;
1573 size = sizeof(DWORD);
1574 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1575 ok(ret, "%u\n", GetLastError());
1576 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1577
1578 SetLastError(0xdeadbeef);
1579 value = 0xbeefdead;
1580 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1581 ok(ret, "%u\n", GetLastError());
1582
1583 SetLastError(0xdeadbeef);
1584 value = 0xdeadbeef;
1585 size = sizeof(DWORD);
1586 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1587 ok(ret, "%u\n", GetLastError());
1588 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1589
1590 SetLastError(0xdeadbeef);
1591 value = 0xbeefdead;
1592 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1593 ok(ret, "%u\n", GetLastError());
1594
1595 SetLastError(0xdeadbeef);
1596 value = 0xdeadbeef;
1597 size = sizeof(DWORD);
1598 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1599 ok(ret, "%u\n", GetLastError());
1600 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1601
1602 SetLastError(0xdeadbeef);
1603 value = 0xbeefdead;
1604 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1605 ok(ret, "%u\n", GetLastError());
1606
1607 SetLastError(0xdeadbeef);
1608 value = 0xdeadbeef;
1609 size = sizeof(DWORD);
1610 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1611 ok(ret, "%u\n", GetLastError());
1612 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1613
1614 /* Changing timeout values for session should not affect the values for a request,
1615 * neither should the other way around.
1616 */
1617 SetLastError(0xdeadbeef);
1618 value = 0xbeefdead;
1619 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1620 ok(ret, "%u\n", GetLastError());
1621
1622 SetLastError(0xdeadbeef);
1623 value = 0xdeadbeef;
1624 size = sizeof(DWORD);
1625 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1626 ok(ret, "%u\n", GetLastError());
1627 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1628
1629 SetLastError(0xdeadbeef);
1630 value = 0xbeefdead;
1631 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1632 ok(ret, "%u\n", GetLastError());
1633
1634 SetLastError(0xdeadbeef);
1635 value = 0xdeadbeef;
1636 size = sizeof(DWORD);
1637 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1638 ok(ret, "%u\n", GetLastError());
1639 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1640
1641 SetLastError(0xdeadbeef);
1642 value = 0xbeefdead;
1643 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1644 ok(ret, "%u\n", GetLastError());
1645
1646 SetLastError(0xdeadbeef);
1647 value = 0xdeadbeef;
1648 size = sizeof(DWORD);
1649 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1650 ok(ret, "%u\n", GetLastError());
1651 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1652
1653 SetLastError(0xdeadbeef);
1654 value = 0xbeefdead;
1655 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1656 ok(ret, "%u\n", GetLastError());
1657
1658 SetLastError(0xdeadbeef);
1659 value = 0xdeadbeef;
1660 size = sizeof(DWORD);
1661 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1662 ok(ret, "%u\n", GetLastError());
1663 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1664
1665 SetLastError(0xdeadbeef);
1666 value = 0xbeef;
1667 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1668 ok(ret, "%u\n", GetLastError());
1669
1670 SetLastError(0xdeadbeef);
1671 value = 0xdeadbeef;
1672 size = sizeof(DWORD);
1673 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1674 ok(ret, "%u\n", GetLastError());
1675 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1676
1677 SetLastError(0xdeadbeef);
1678 value = 0xbeef;
1679 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1680 ok(ret, "%u\n", GetLastError());
1681
1682 SetLastError(0xdeadbeef);
1683 value = 0xdeadbeef;
1684 size = sizeof(DWORD);
1685 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1686 ok(ret, "%u\n", GetLastError());
1687 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1688
1689 SetLastError(0xdeadbeef);
1690 value = 0xbeef;
1691 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1692 ok(ret, "%u\n", GetLastError());
1693
1694 SetLastError(0xdeadbeef);
1695 value = 0xdeadbeef;
1696 size = sizeof(DWORD);
1697 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1698 ok(ret, "%u\n", GetLastError());
1699 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1700
1701 SetLastError(0xdeadbeef);
1702 value = 0xbeef;
1703 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_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_RECEIVE_TIMEOUT, &value, &size);
1710 ok(ret, "%u\n", GetLastError());
1711 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1712
1713 WinHttpCloseHandle(req);
1714 WinHttpCloseHandle(con);
1715 WinHttpCloseHandle(ses);
1716 }
1717
1718 static void test_resolve_timeout(void)
1719 {
1720 static const WCHAR codeweavers[] =
1721 {'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
1722 static const WCHAR nxdomain[] =
1723 {'n','x','d','o','m','a','i','n','.','c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};
1724
1725 HINTERNET ses, con, req;
1726 DWORD timeout;
1727 BOOL ret;
1728
1729 if (! proxy_active())
1730 {
1731 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1732 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1733
1734 timeout = 10000;
1735 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1736 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1737
1738 con = WinHttpConnect(ses, nxdomain, 0, 0);
1739 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1740
1741 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1742 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1743
1744 SetLastError(0xdeadbeef);
1745 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1746 ok(!ret, "sent request\n");
1747 ok(GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED,
1748 "expected ERROR_WINHTTP_NAME_NOT_RESOLVED got %u\n", GetLastError());
1749
1750 WinHttpCloseHandle(req);
1751 WinHttpCloseHandle(con);
1752 WinHttpCloseHandle(ses);
1753 }
1754 else
1755 skip("Skipping host resolution tests, host resolution preformed by proxy\n");
1756
1757 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1758 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1759
1760 timeout = 10000;
1761 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1762 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1763
1764 con = WinHttpConnect(ses, codeweavers, 0, 0);
1765 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1766
1767 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1768 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1769
1770 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1771 ok(ret, "failed to send request\n");
1772
1773 WinHttpCloseHandle(req);
1774 WinHttpCloseHandle(con);
1775 WinHttpCloseHandle(ses);
1776 }
1777
1778 static const char page1[] =
1779 "<HTML>\r\n"
1780 "<HEAD><TITLE>winhttp test page</TITLE></HEAD>\r\n"
1781 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
1782 "</HTML>\r\n\r\n";
1783
1784 static const char okmsg[] =
1785 "HTTP/1.1 200 OK\r\n"
1786 "Server: winetest\r\n"
1787 "\r\n";
1788
1789 static const char noauthmsg[] =
1790 "HTTP/1.1 401 Unauthorized\r\n"
1791 "Server: winetest\r\n"
1792 "Connection: close\r\n"
1793 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
1794 "\r\n";
1795
1796 static const char proxymsg[] =
1797 "HTTP/1.1 407 Proxy Authentication Required\r\n"
1798 "Server: winetest\r\n"
1799 "Proxy-Connection: close\r\n"
1800 "Proxy-Authenticate: Basic realm=\"placebo\"\r\n"
1801 "\r\n";
1802
1803 struct server_info
1804 {
1805 HANDLE event;
1806 int port;
1807 };
1808
1809 static DWORD CALLBACK server_thread(LPVOID param)
1810 {
1811 struct server_info *si = param;
1812 int r, c, i, on;
1813 SOCKET s;
1814 struct sockaddr_in sa;
1815 char buffer[0x100];
1816 WSADATA wsaData;
1817 int last_request = 0;
1818
1819 WSAStartup(MAKEWORD(1,1), &wsaData);
1820
1821 s = socket(AF_INET, SOCK_STREAM, 0);
1822 if (s == INVALID_SOCKET)
1823 return 1;
1824
1825 on = 1;
1826 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof on);
1827
1828 memset(&sa, 0, sizeof sa);
1829 sa.sin_family = AF_INET;
1830 sa.sin_port = htons(si->port);
1831 sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
1832
1833 r = bind(s, (struct sockaddr *)&sa, sizeof(sa));
1834 if (r < 0)
1835 return 1;
1836
1837 listen(s, 0);
1838 SetEvent(si->event);
1839 do
1840 {
1841 c = accept(s, NULL, NULL);
1842
1843 memset(buffer, 0, sizeof buffer);
1844 for(i = 0; i < sizeof buffer - 1; i++)
1845 {
1846 r = recv(c, &buffer[i], 1, 0);
1847 if (r != 1)
1848 break;
1849 if (i < 4) continue;
1850 if (buffer[i - 2] == '\n' && buffer[i] == '\n' &&
1851 buffer[i - 3] == '\r' && buffer[i - 1] == '\r')
1852 break;
1853 }
1854 if (strstr(buffer, "GET /basic"))
1855 {
1856 send(c, okmsg, sizeof okmsg - 1, 0);
1857 send(c, page1, sizeof page1 - 1, 0);
1858 }
1859 if (strstr(buffer, "/auth"))
1860 {
1861 if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
1862 send(c, okmsg, sizeof okmsg - 1, 0);
1863 else
1864 send(c, noauthmsg, sizeof noauthmsg - 1, 0);
1865 }
1866 if (strstr(buffer, "/no_headers"))
1867 {
1868 send(c, page1, sizeof page1 - 1, 0);
1869 }
1870 if (strstr(buffer, "GET /quit"))
1871 {
1872 send(c, okmsg, sizeof okmsg - 1, 0);
1873 send(c, page1, sizeof page1 - 1, 0);
1874 last_request = 1;
1875 }
1876 shutdown(c, 2);
1877 closesocket(c);
1878
1879 } while (!last_request);
1880
1881 closesocket(s);
1882 return 0;
1883 }
1884
1885 static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
1886 {
1887 HINTERNET ses, con, req;
1888 char buffer[0x100];
1889 DWORD count, status, size, error, supported, first, target;
1890 BOOL ret;
1891
1892 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1893 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1894
1895 con = WinHttpConnect(ses, localhostW, port, 0);
1896 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1897
1898 req = WinHttpOpenRequest(con, verb, path, NULL, NULL, NULL, 0);
1899 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1900
1901 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1902 ok(ret, "failed to send request %u\n", GetLastError());
1903
1904 ret = WinHttpReceiveResponse(req, NULL);
1905 ok(ret, "failed to receive response %u\n", GetLastError());
1906
1907 size = sizeof(status);
1908 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1909 ok(ret, "failed to query status code %u\n", GetLastError());
1910 ok(status == 200, "request failed unexpectedly %u\n", status);
1911
1912 supported = first = target = 0xdeadbeef;
1913 SetLastError(0xdeadbeef);
1914 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
1915 error = GetLastError();
1916 ok(!ret, "unexpected success\n");
1917 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
1918 ok(supported == 0xdeadbeef, "got %x\n", supported);
1919 ok(first == 0xdeadbeef, "got %x\n", first);
1920 ok(target == 0xdeadbeef, "got %x\n", target);
1921
1922 count = 0;
1923 memset(buffer, 0, sizeof(buffer));
1924 ret = WinHttpReadData(req, buffer, sizeof buffer, &count);
1925 ok(ret, "failed to read data %u\n", GetLastError());
1926 ok(count == sizeof page1 - 1, "count was wrong\n");
1927 ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
1928
1929 WinHttpCloseHandle(req);
1930 WinHttpCloseHandle(con);
1931 WinHttpCloseHandle(ses);
1932 }
1933
1934 static void test_basic_authentication(int port)
1935 {
1936 static const WCHAR authW[] = {'/','a','u','t','h',0};
1937 static const WCHAR userW[] = {'u','s','e','r',0};
1938 static const WCHAR passW[] = {'p','w','d',0};
1939 HINTERNET ses, con, req;
1940 DWORD status, size, error, supported, first, target;
1941 BOOL ret;
1942
1943 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1944 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1945
1946 con = WinHttpConnect(ses, localhostW, port, 0);
1947 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1948
1949 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
1950 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1951
1952 SetLastError(0xdeadbeef);
1953 ret = WinHttpQueryAuthSchemes(NULL, NULL, NULL, NULL);
1954 error = GetLastError();
1955 ok(!ret, "expected failure\n");
1956 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
1957
1958 SetLastError(0xdeadbeef);
1959 ret = WinHttpQueryAuthSchemes(req, NULL, NULL, NULL);
1960 error = GetLastError();
1961 ok(!ret, "expected failure\n");
1962 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
1963
1964 supported = 0xdeadbeef;
1965 SetLastError(0xdeadbeef);
1966 ret = WinHttpQueryAuthSchemes(req, &supported, NULL, NULL);
1967 error = GetLastError();
1968 ok(!ret, "expected failure\n");
1969 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
1970 ok(supported == 0xdeadbeef, "got %x\n", supported);
1971
1972 supported = first = 0xdeadbeef;
1973 SetLastError(0xdeadbeef);
1974 ret = WinHttpQueryAuthSchemes(req, &supported, &first, NULL);
1975 error = GetLastError();
1976 ok(!ret, "expected failure\n");
1977 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
1978 ok(supported == 0xdeadbeef, "got %x\n", supported);
1979 ok(first == 0xdeadbeef, "got %x\n", first);
1980
1981 supported = first = target = 0xdeadbeef;
1982 SetLastError(0xdeadbeef);
1983 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
1984 error = GetLastError();
1985 ok(!ret, "expected failure\n");
1986 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
1987 ok(supported == 0xdeadbeef, "got %x\n", supported);
1988 ok(first == 0xdeadbeef, "got %x\n", first);
1989 ok(target == 0xdeadbeef, "got %x\n", target);
1990
1991 supported = first = target = 0xdeadbeef;
1992 SetLastError(0xdeadbeef);
1993 ret = WinHttpQueryAuthSchemes(NULL, &supported, &first, &target);
1994 error = GetLastError();
1995 ok(!ret, "expected failure\n");
1996 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
1997 ok(supported == 0xdeadbeef, "got %x\n", supported);
1998 ok(first == 0xdeadbeef, "got %x\n", first);
1999 ok(target == 0xdeadbeef, "got %x\n", target);
2000
2001 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2002 ok(ret, "failed to send request %u\n", GetLastError());
2003
2004 ret = WinHttpReceiveResponse(req, NULL);
2005 ok(ret, "failed to receive response %u\n", GetLastError());
2006
2007 size = sizeof(status);
2008 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2009 ok(ret, "failed to query status code %u\n", GetLastError());
2010 ok(status == 401, "request failed unexpectedly %u\n", status);
2011
2012 supported = first = target = 0xdeadbeef;
2013 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2014 ok(ret, "failed to query authentication schemes %u\n", GetLastError());
2015 ok(supported == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", supported);
2016 ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
2017 ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
2018
2019 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, NULL, NULL, NULL);
2020 ok(ret, "failed to set credentials %u\n", GetLastError());
2021
2022 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_PASSPORT, NULL, NULL, NULL);
2023 ok(ret, "failed to set credentials %u\n", GetLastError());
2024
2025 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NEGOTIATE, NULL, NULL, NULL);
2026 ok(ret, "failed to set credentials %u\n", GetLastError());
2027
2028 SetLastError(0xdeadbeef);
2029 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_DIGEST, NULL, NULL, NULL);
2030 error = GetLastError();
2031 ok(!ret, "expected failure\n");
2032 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2033
2034 SetLastError(0xdeadbeef);
2035 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, NULL, NULL);
2036 error = GetLastError();
2037 ok(!ret, "expected failure\n");
2038 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2039
2040 SetLastError(0xdeadbeef);
2041 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
2042 error = GetLastError();
2043 ok(!ret, "expected failure\n");
2044 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2045
2046 SetLastError(0xdeadbeef);
2047 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
2048 error = GetLastError();
2049 ok(!ret, "expected failure\n");
2050 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2051
2052 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2053 ok(ret, "failed to set credentials %u\n", GetLastError());
2054
2055 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2056 ok(ret, "failed to send request %u\n", GetLastError());
2057
2058 ret = WinHttpReceiveResponse(req, NULL);
2059 ok(ret, "failed to receive response %u\n", GetLastError());
2060
2061 size = sizeof(status);
2062 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2063 ok(ret, "failed to query status code %u\n", GetLastError());
2064 ok(status == 200, "request failed unexpectedly %u\n", status);
2065
2066 WinHttpCloseHandle(req);
2067 WinHttpCloseHandle(con);
2068 WinHttpCloseHandle(ses);
2069 }
2070
2071 static void test_no_headers(int port)
2072 {
2073 static const WCHAR no_headersW[] = {'/','n','o','_','h','e','a','d','e','r','s',0};
2074 HINTERNET ses, con, req;
2075 DWORD error;
2076 BOOL ret;
2077
2078 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
2079 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2080
2081 con = WinHttpConnect(ses, localhostW, port, 0);
2082 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2083
2084 req = WinHttpOpenRequest(con, NULL, no_headersW, NULL, NULL, NULL, 0);
2085 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2086
2087 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2088 ok(ret, "failed to send request %u\n", GetLastError());
2089
2090 SetLastError(0xdeadbeef);
2091 ret = WinHttpReceiveResponse(req, NULL);
2092 error = GetLastError();
2093 ok(!ret, "expected failure\n");
2094 ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2095
2096 WinHttpCloseHandle(req);
2097 WinHttpCloseHandle(con);
2098 WinHttpCloseHandle(ses);
2099 }
2100
2101 static void test_bad_header( int port )
2102 {
2103 static const WCHAR bad_headerW[] =
2104 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',
2105 't','e','x','t','/','h','t','m','l','\n','\r',0};
2106 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
2107 static const WCHAR content_typeW[] = {'C','o','n','t','e','n','t','-','T','y','p','e',0};
2108 WCHAR buffer[32];
2109 HINTERNET ses, con, req;
2110 DWORD index, len;
2111 BOOL ret;
2112
2113 ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
2114 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2115
2116 con = WinHttpConnect( ses, localhostW, port, 0 );
2117 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2118
2119 req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
2120 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2121
2122 ret = WinHttpAddRequestHeaders( req, bad_headerW, ~0u, WINHTTP_ADDREQ_FLAG_ADD );
2123 ok( ret, "failed to add header %u\n", GetLastError() );
2124
2125 index = 0;
2126 buffer[0] = 0;
2127 len = sizeof(buffer);
2128 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CUSTOM|WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
2129 content_typeW, buffer, &len, &index );
2130 ok( ret, "failed to query headers %u\n", GetLastError() );
2131 ok( !lstrcmpW( buffer, text_htmlW ), "got %s\n", wine_dbgstr_w(buffer) );
2132
2133 WinHttpCloseHandle( req );
2134 WinHttpCloseHandle( con );
2135 WinHttpCloseHandle( ses );
2136 }
2137
2138 static void test_connection_info( int port )
2139 {
2140 static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
2141 HINTERNET ses, con, req;
2142 WINHTTP_CONNECTION_INFO info;
2143 DWORD size, error;
2144 BOOL ret;
2145
2146 ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
2147 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2148
2149 con = WinHttpConnect( ses, localhostW, port, 0 );
2150 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2151
2152 req = WinHttpOpenRequest( con, NULL, basicW, NULL, NULL, NULL, 0 );
2153 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2154
2155 size = sizeof(info);
2156 SetLastError( 0xdeadbeef );
2157 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2158 error = GetLastError();
2159 if (!ret && error == ERROR_INVALID_PARAMETER)
2160 {
2161 win_skip( "WINHTTP_OPTION_CONNECTION_INFO not supported\n" );
2162 return;
2163 }
2164 ok( !ret, "unexpected success\n" );
2165 ok( error == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "got %u\n", error );
2166
2167 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2168 ok( ret, "failed to send request %u\n", GetLastError() );
2169
2170 size = 0;
2171 SetLastError( 0xdeadbeef );
2172 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2173 error = GetLastError();
2174 ok( !ret, "unexpected success\n" );
2175 ok( error == ERROR_INSUFFICIENT_BUFFER, "got %u\n", error );
2176
2177 size = sizeof(info);
2178 memset( &info, 0, sizeof(info) );
2179 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2180 ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
2181 ok( info.cbSize == sizeof(info), "wrong size %u\n", info.cbSize );
2182
2183 ret = WinHttpReceiveResponse( req, NULL );
2184 ok( ret, "failed to receive response %u\n", GetLastError() );
2185
2186 size = sizeof(info);
2187 memset( &info, 0, sizeof(info) );
2188 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2189 ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
2190 ok( info.cbSize == sizeof(info), "wrong size %u\n", info.cbSize );
2191
2192 WinHttpCloseHandle( req );
2193 WinHttpCloseHandle( con );
2194 WinHttpCloseHandle( ses );
2195 }
2196
2197 static void test_credentials(void)
2198 {
2199 static WCHAR userW[] = {'u','s','e','r',0};
2200 static WCHAR passW[] = {'p','a','s','s',0};
2201 static WCHAR proxy_userW[] = {'p','r','o','x','y','u','s','e','r',0};
2202 static WCHAR proxy_passW[] = {'p','r','o','x','y','p','a','s','s',0};
2203 HINTERNET ses, con, req;
2204 DWORD size, error;
2205 WCHAR buffer[32];
2206 BOOL ret;
2207
2208 ses = WinHttpOpen(test_useragent, 0, proxy_userW, proxy_passW, 0);
2209 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2210
2211 con = WinHttpConnect(ses, localhostW, 0, 0);
2212 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2213
2214 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
2215 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2216
2217 size = sizeof(buffer)/sizeof(WCHAR);
2218 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
2219 ok(ret, "failed to query proxy username %u\n", GetLastError());
2220 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
2221 ok(!size, "expected 0, got %u\n", size);
2222
2223 size = sizeof(buffer)/sizeof(WCHAR);
2224 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
2225 ok(ret, "failed to query proxy password %u\n", GetLastError());
2226 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
2227 ok(!size, "expected 0, got %u\n", size);
2228
2229 ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_USERNAME, proxy_userW, lstrlenW(proxy_userW));
2230 ok(ret, "failed to set username %u\n", GetLastError());
2231
2232 size = sizeof(buffer)/sizeof(WCHAR);
2233 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
2234 ok(ret, "failed to query proxy username %u\n", GetLastError());
2235 ok(!winetest_strcmpW(buffer, proxy_userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
2236 ok(size == lstrlenW(proxy_userW) * sizeof(WCHAR), "unexpected result %u\n", size);
2237
2238 size = sizeof(buffer)/sizeof(WCHAR);
2239 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
2240 ok(ret, "failed to query username %u\n", GetLastError());
2241 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
2242 ok(!size, "expected 0, got %u\n", size);
2243
2244 size = sizeof(buffer)/sizeof(WCHAR);
2245 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
2246 ok(ret, "failed to query password %u\n", GetLastError());
2247 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
2248 ok(!size, "expected 0, got %u\n", size);
2249
2250 ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_PASSWORD, proxy_passW, lstrlenW(proxy_passW));
2251 ok(ret, "failed to set proxy password %u\n", GetLastError());
2252
2253 size = sizeof(buffer)/sizeof(WCHAR);
2254 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
2255 ok(ret, "failed to query proxy password %u\n", GetLastError());
2256 ok(!winetest_strcmpW(buffer, proxy_passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
2257 ok(size == lstrlenW(proxy_passW) * sizeof(WCHAR), "unexpected result %u\n", size);
2258
2259 ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2260 ok(ret, "failed to set username %u\n", GetLastError());
2261
2262 size = sizeof(buffer)/sizeof(WCHAR);
2263 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
2264 ok(ret, "failed to query username %u\n", GetLastError());
2265 ok(!winetest_strcmpW(buffer, userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
2266 ok(size == lstrlenW(userW) * sizeof(WCHAR), "unexpected result %u\n", size);
2267
2268 ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW));
2269 ok(ret, "failed to set password %u\n", GetLastError());
2270
2271 size = sizeof(buffer)/sizeof(WCHAR);
2272 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
2273 ok(ret, "failed to query password %u\n", GetLastError());
2274 ok(!winetest_strcmpW(buffer, passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
2275 ok(size == lstrlenW(passW) * sizeof(WCHAR), "unexpected result %u\n", size);
2276
2277 WinHttpCloseHandle(req);
2278
2279 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
2280 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2281
2282 SetLastError(0xdeadbeef);
2283 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
2284 error = GetLastError();
2285 ok(!ret, "expected failure\n");
2286 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2287
2288 SetLastError(0xdeadbeef);
2289 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
2290 error = GetLastError();
2291 ok(!ret, "expected failure\n");
2292 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2293
2294 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2295 ok(ret, "failed to set credentials %u\n", GetLastError());
2296
2297 size = sizeof(buffer)/sizeof(WCHAR);
2298 ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
2299 ok(ret, "failed to query username %u\n", GetLastError());
2300 todo_wine {
2301 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
2302 ok(!size, "expected 0, got %u\n", size);
2303 }
2304
2305 size = sizeof(buffer)/sizeof(WCHAR);
2306 ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
2307 ok(ret, "failed to query password %u\n", GetLastError());
2308 todo_wine {
2309 ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
2310 ok(!size, "expected 0, got %u\n", size);
2311 }
2312
2313 WinHttpCloseHandle(req);
2314 WinHttpCloseHandle(con);
2315 WinHttpCloseHandle(ses);
2316 }
2317
2318 static void test_IWinHttpRequest(void)
2319 {
2320 static const WCHAR usernameW[] = {'u','s','e','r','n','a','m','e',0};
2321 static const WCHAR passwordW[] = {'p','a','s','s','w','o','r','d',0};
2322 static const WCHAR url1W[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0};
2323 static const WCHAR url2W[] = {'w','i','n','e','h','q','.','o','r','g',0};
2324 static const WCHAR url3W[] = {'h','t','t','p',':','/','/','c','r','o','s','s','o','v','e','r','.',
2325 'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m','/',
2326 'p','o','s','t','t','e','s','t','.','p','h','p',0};
2327 static const WCHAR method1W[] = {'G','E','T',0};
2328 static const WCHAR method2W[] = {'I','N','V','A','L','I','D',0};
2329 static const WCHAR method3W[] = {'P','O','S','T',0};
2330 static const WCHAR proxy_serverW[] = {'p','r','o','x','y','s','e','r','v','e','r',0};
2331 static const WCHAR bypas_listW[] = {'b','y','p','a','s','s','l','i','s','t',0};
2332 static const WCHAR connectionW[] = {'C','o','n','n','e','c','t','i','o','n',0};
2333 static const WCHAR dateW[] = {'D','a','t','e',0};
2334 static const WCHAR test_dataW[] = {'t','e','s','t','d','a','t','a',128,0};
2335 HRESULT hr;
2336 IWinHttpRequest *req;
2337 BSTR method, url, username, password, response = NULL, status_text = NULL, headers = NULL;
2338 BSTR date, today, connection, value = NULL;
2339 VARIANT async, empty, timeout, body, proxy_server, bypass_list, data;
2340 VARIANT_BOOL succeeded;
2341 LONG status;
2342 WCHAR todayW[WINHTTP_TIME_FORMAT_BUFSIZE];
2343 SYSTEMTIME st;
2344
2345 GetSystemTime( &st );
2346 WinHttpTimeFromSystemTime( &st, todayW );
2347
2348 CoInitialize( NULL );
2349 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
2350 ok( hr == S_OK, "got %08x\n", hr );
2351
2352 V_VT( &empty ) = VT_ERROR;
2353 V_ERROR( &empty ) = 0xdeadbeef;
2354
2355 V_VT( &async ) = VT_BOOL;
2356 V_BOOL( &async ) = VARIANT_FALSE;
2357
2358 method = SysAllocString( method3W );
2359 url = SysAllocString( url3W );
2360 hr = IWinHttpRequest_Open( req, method, url, async );
2361 ok( hr == S_OK, "got %08x\n", hr );
2362 SysFreeString( method );
2363 SysFreeString( url );
2364
2365 V_VT( &data ) = VT_BSTR;
2366 V_BSTR( &data ) = SysAllocString( test_dataW );
2367 hr = IWinHttpRequest_Send( req, data );
2368 ok( hr == S_OK || broken(hr == HRESULT_FROM_WIN32(ERROR_WINHTTP_INVALID_SERVER_RESPONSE)),
2369 "got %08x\n", hr );
2370 SysFreeString( V_BSTR( &data ) );
2371
2372 hr = IWinHttpRequest_Open( req, NULL, NULL, empty );
2373 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2374
2375 method = SysAllocString( method1W );
2376 hr = IWinHttpRequest_Open( req, method, NULL, empty );
2377 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2378
2379 hr = IWinHttpRequest_Open( req, method, NULL, async );
2380 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2381
2382 url = SysAllocString( url1W );
2383 hr = IWinHttpRequest_Open( req, NULL, url, empty );
2384 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2385
2386 hr = IWinHttpRequest_Abort( req );
2387 ok( hr == S_OK, "got %08x\n", hr );
2388
2389 hr = IWinHttpRequest_Open( req, method, url, empty );
2390 ok( hr == S_OK, "got %08x\n", hr );
2391
2392 hr = IWinHttpRequest_Abort( req );
2393 ok( hr == S_OK, "got %08x\n", hr );
2394
2395 hr = IWinHttpRequest_Release( req );
2396 ok( hr == S_OK, "got %08x\n", hr );
2397
2398 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
2399 ok( hr == S_OK, "got %08x\n", hr );
2400
2401 SysFreeString( url );
2402 url = SysAllocString( url2W );
2403 hr = IWinHttpRequest_Open( req, method, url, async );
2404 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
2405
2406 SysFreeString( method );
2407 method = SysAllocString( method2W );
2408 hr = IWinHttpRequest_Open( req, method, url, async );
2409 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
2410
2411 SysFreeString( method );
2412 method = SysAllocString( method1W );
2413 SysFreeString( url );
2414 url = SysAllocString( url1W );
2415 hr = IWinHttpRequest_Open( req, method, url, async );
2416 ok( hr == S_OK, "got %08x\n", hr );
2417
2418 hr = IWinHttpRequest_Abort( req );
2419 ok( hr == S_OK, "got %08x\n", hr );
2420
2421 hr = IWinHttpRequest_Send( req, empty );
2422 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
2423
2424 hr = IWinHttpRequest_Abort( req );
2425 ok( hr == S_OK, "got %08x\n", hr );
2426
2427 hr = IWinHttpRequest_Release( req );
2428 ok( hr == S_OK, "got %08x\n", hr );
2429
2430 hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
2431 ok( hr == S_OK, "got %08x\n", hr );
2432
2433 hr = IWinHttpRequest_get_ResponseText( req, NULL );
2434 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2435
2436 hr = IWinHttpRequest_get_ResponseText( req, &response );
2437 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
2438
2439 hr = IWinHttpRequest_get_Status( req, NULL );
2440 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2441
2442 hr = IWinHttpRequest_get_Status( req, &status );
2443 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
2444
2445 hr = IWinHttpRequest_get_StatusText( req, NULL );
2446 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2447
2448 hr = IWinHttpRequest_get_StatusText( req, &status_text );
2449 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
2450
2451 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
2452 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2453
2454 hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
2455 ok( hr == S_OK, "got %08x\n", hr );
2456
2457 hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
2458 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
2459
2460 VariantInit( &proxy_server );
2461 V_VT( &proxy_server ) = VT_ERROR;
2462 VariantInit( &bypass_list );
2463 V_VT( &bypass_list ) = VT_ERROR;
2464 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
2465 ok( hr == S_OK, "got %08x\n", hr );
2466
2467 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
2468 ok( hr == S_OK, "got %08x\n", hr );
2469
2470 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
2471 ok( hr == S_OK, "got %08x\n", hr );
2472
2473 hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
2474 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2475
2476 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
2477 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
2478
2479 hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
2480 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
2481
2482 connection = SysAllocString( connectionW );
2483 hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
2484 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
2485
2486 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
2487 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
2488
2489 hr = IWinHttpRequest_SetRequestHeader( req, NULL, NULL );
2490 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2491
2492 date = SysAllocString( dateW );
2493 hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
2494 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
2495
2496 today = SysAllocString( todayW );
2497 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
2498 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
2499
2500 hr = IWinHttpRequest_SetAutoLogonPolicy( req, 0xdeadbeef );
2501 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2502
2503 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
2504 ok( hr == S_OK, "got %08x\n", hr );
2505
2506 SysFreeString( method );
2507 method = SysAllocString( method1W );
2508 SysFreeString( url );
2509 url = SysAllocString( url1W );
2510 hr = IWinHttpRequest_Open( req, method, url, async );
2511 ok( hr == S_OK, "got %08x\n", hr );
2512
2513 hr = IWinHttpRequest_get_ResponseText( req, NULL );
2514 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2515
2516 hr = IWinHttpRequest_get_ResponseText( req, &response );
2517 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
2518
2519 hr = IWinHttpRequest_get_Status( req, &status );
2520 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
2521
2522 hr = IWinHttpRequest_get_StatusText( req, &status_text );
2523 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
2524
2525 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
2526 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2527
2528 hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
2529 ok( hr == S_OK, "got %08x\n", hr );
2530
2531 hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
2532 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2533
2534 username = SysAllocString( usernameW );
2535 hr = IWinHttpRequest_SetCredentials( req, username, NULL, 0xdeadbeef );
2536 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2537
2538 password = SysAllocString( passwordW );
2539 hr = IWinHttpRequest_SetCredentials( req, NULL, password, 0xdeadbeef );
2540 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2541
2542 hr = IWinHttpRequest_SetCredentials( req, username, password, 0xdeadbeef );
2543 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2544
2545 hr = IWinHttpRequest_SetCredentials( req, NULL, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
2546 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2547
2548 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
2549 ok( hr == S_OK, "got %08x\n", hr );
2550
2551 V_VT( &proxy_server ) = VT_BSTR;
2552 V_BSTR( &proxy_server ) = SysAllocString( proxy_serverW );
2553 V_VT( &bypass_list ) = VT_BSTR;
2554 V_BSTR( &bypass_list ) = SysAllocString( bypas_listW );
2555 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
2556 ok( hr == S_OK, "got %08x\n", hr );
2557
2558 hr = IWinHttpRequest_SetProxy( req, 0xdeadbeef, proxy_server, bypass_list );
2559 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2560
2561 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
2562 ok( hr == S_OK, "got %08x\n", hr );
2563
2564 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
2565 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
2566
2567 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
2568 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
2569
2570 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
2571 ok( hr == S_OK, "got %08x\n", hr );
2572
2573 hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
2574 ok( hr == S_OK, "got %08x\n", hr );
2575
2576 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
2577 ok( hr == S_OK, "got %08x\n", hr );
2578
2579 hr = IWinHttpRequest_Send( req, empty );
2580 ok( hr == S_OK, "got %08x\n", hr );
2581
2582 hr = IWinHttpRequest_Send( req, empty );
2583 ok( hr == S_OK, "got %08x\n", hr );
2584
2585 hr = IWinHttpRequest_get_ResponseText( req, NULL );
2586 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2587
2588 hr = IWinHttpRequest_get_ResponseText( req, &response );
2589 ok( hr == S_OK, "got %08x\n", hr );
2590 SysFreeString( response );
2591
2592 hr = IWinHttpRequest_get_Status( req, NULL );
2593 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2594
2595 status = 0;
2596 hr = IWinHttpRequest_get_Status( req, &status );
2597 ok( hr == S_OK, "got %08x\n", hr );
2598 trace("Status=%d\n", status);
2599
2600 hr = IWinHttpRequest_get_StatusText( req, NULL );
2601 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2602
2603 hr = IWinHttpRequest_get_StatusText( req, &status_text );
2604 ok( hr == S_OK, "got %08x\n", hr );
2605 trace("StatusText=%s\n", wine_dbgstr_w(status_text));
2606 SysFreeString( status_text );
2607
2608 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
2609 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2610
2611 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
2612 ok( hr == S_OK, "got %08x\n", hr );
2613
2614 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
2615 ok( hr == S_OK, "got %08x\n", hr );
2616
2617 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
2618 ok( hr == S_OK, "got %08x\n", hr );
2619
2620 hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
2621 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2622
2623 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
2624 ok( hr == S_OK, "got %08x\n", hr );
2625 SysFreeString( headers );
2626
2627 hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
2628 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2629
2630 hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
2631 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2632
2633 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
2634 ok( hr == S_OK, "got %08x\n", hr );
2635 SysFreeString( value );
2636
2637 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
2638 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
2639
2640 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
2641 ok( hr == S_OK, "got %08x\n", hr );
2642
2643 VariantInit( &timeout );
2644 V_VT( &timeout ) = VT_I4;
2645 V_I4( &timeout ) = 10;
2646 hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
2647 ok( hr == S_OK, "got %08x\n", hr );
2648
2649 hr = IWinHttpRequest_get_Status( req, &status );
2650 ok( hr == S_OK, "got %08x\n", hr );
2651
2652 hr = IWinHttpRequest_get_StatusText( req, &status_text );
2653 ok( hr == S_OK, "got %08x\n", hr );
2654 SysFreeString( status_text );
2655
2656 hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
2657 ok( hr == S_OK, "got %08x\n", hr );
2658
2659 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
2660 ok( hr == S_OK, "got %08x\n", hr );
2661
2662 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
2663 ok( hr == S_OK, "got %08x\n", hr );
2664
2665 hr = IWinHttpRequest_Send( req, empty );
2666 ok( hr == S_OK, "got %08x\n", hr );
2667
2668 hr = IWinHttpRequest_get_ResponseText( req, NULL );
2669 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2670
2671 hr = IWinHttpRequest_get_ResponseText( req, &response );
2672 ok( hr == S_OK, "got %08x\n", hr );
2673 SysFreeString( response );
2674
2675 hr = IWinHttpRequest_get_ResponseBody( req, NULL );
2676 ok( hr == E_INVALIDARG, "got %08x\n", hr );
2677
2678 VariantInit( &body );
2679 V_VT( &body ) = VT_ERROR;
2680 hr = IWinHttpRequest_get_ResponseBody( req, &body );
2681 ok( hr == S_OK, "got %08x\n", hr );
2682 ok( V_VT( &body ) == (VT_ARRAY|VT_UI1), "got %08x\n", V_VT( &body ) );
2683
2684 hr = VariantClear( &body );
2685 ok( hr == S_OK, "got %08x\n", hr );
2686
2687 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
2688 ok( hr == S_OK, "got %08x\n", hr );
2689
2690 hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
2691 ok( hr == S_OK, "got %08x\n", hr );
2692
2693 hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
2694 ok( hr == S_OK, "got %08x\n", hr );
2695 SysFreeString( headers );
2696
2697 hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
2698 ok( hr == S_OK, "got %08x\n", hr );
2699 SysFreeString( value );
2700
2701 hr = IWinHttpRequest_SetRequestHeader( req, date, today );
2702 ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
2703
2704 hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
2705 ok( hr == S_OK, "got %08x\n", hr );
2706
2707 hr = IWinHttpRequest_Send( req, empty );
2708 ok( hr == S_OK, "got %08x\n", hr );
2709
2710 hr = IWinHttpRequest_Abort( req );
2711 ok( hr == S_OK, "got %08x\n", hr );
2712
2713 hr = IWinHttpRequest_Abort( req );
2714 ok( hr == S_OK, "got %08x\n", hr );
2715
2716 hr = IWinHttpRequest_Release( req );
2717 ok( hr == S_OK, "got %08x\n", hr );
2718
2719 SysFreeString( method );
2720 SysFreeString( url );
2721 SysFreeString( username );
2722 SysFreeString( password );
2723 SysFreeString( connection );
2724 SysFreeString( date );
2725 SysFreeString( today );
2726 VariantClear( &proxy_server );
2727 VariantClear( &bypass_list );
2728 CoUninitialize();
2729 }
2730
2731 static void test_WinHttpDetectAutoProxyConfigUrl(void)
2732 {
2733 BOOL ret;
2734 WCHAR *url;
2735 DWORD error;
2736
2737 if (0) /* crashes on some win2k systems */
2738 {
2739 SetLastError(0xdeadbeef);
2740 ret = WinHttpDetectAutoProxyConfigUrl( 0, NULL );
2741 error = GetLastError();
2742 ok( !ret, "expected failure\n" );
2743 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
2744 }
2745 url = NULL;
2746 SetLastError(0xdeadbeef);
2747 ret = WinHttpDetectAutoProxyConfigUrl( 0, &url );
2748 error = GetLastError();
2749 ok( !ret, "expected failure\n" );
2750 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
2751
2752 if (0) /* crashes on some win2k systems */
2753 {
2754 SetLastError(0xdeadbeef);
2755 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, NULL );
2756 error = GetLastError();
2757 ok( !ret, "expected failure\n" );
2758 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
2759 }
2760 url = (WCHAR *)0xdeadbeef;
2761 SetLastError(0xdeadbeef);
2762 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, &url );
2763 error = GetLastError();
2764 if (!ret)
2765 {
2766 ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
2767 ok( url == (WCHAR *)0xdeadbeef, "got %p\n", url );
2768 }
2769 else
2770 {
2771 trace("%s\n", wine_dbgstr_w(url));
2772 GlobalFree( url );
2773 }
2774
2775 url = (WCHAR *)0xdeadbeef;
2776 SetLastError(0xdeadbeef);
2777 ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DHCP, &url );
2778 error = GetLastError();
2779 if (!ret)
2780 {
2781 ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
2782 ok( url == (WCHAR *)0xdeadbeef, "got %p\n", url );
2783 }
2784 else
2785 {
2786 trace("%s\n", wine_dbgstr_w(url));
2787 GlobalFree( url );
2788 }
2789 }
2790
2791 static void test_WinHttpGetIEProxyConfigForCurrentUser(void)
2792 {
2793 BOOL ret;
2794 DWORD error;
2795 WINHTTP_CURRENT_USER_IE_PROXY_CONFIG cfg;
2796
2797 memset( &cfg, 0, sizeof(cfg) );
2798
2799 SetLastError(0xdeadbeef);
2800 ret = WinHttpGetIEProxyConfigForCurrentUser( NULL );
2801 error = GetLastError();
2802 ok( !ret, "expected failure\n" );
2803 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
2804
2805 ret = WinHttpGetIEProxyConfigForCurrentUser( &cfg );
2806 ok( ret, "expected success\n" );
2807 trace("IEProxy.AutoDetect=%d\n", cfg.fAutoDetect);
2808 trace("IEProxy.AutoConfigUrl=%s\n", wine_dbgstr_w(cfg.lpszAutoConfigUrl));
2809 trace("IEProxy.Proxy=%s\n", wine_dbgstr_w(cfg.lpszProxy));
2810 trace("IEProxy.ProxyBypass=%s\n", wine_dbgstr_w(cfg.lpszProxyBypass));
2811 GlobalFree( cfg.lpszAutoConfigUrl );
2812 GlobalFree( cfg.lpszProxy );
2813 GlobalFree( cfg.lpszProxyBypass );
2814 }
2815
2816 static void test_WinHttpGetProxyForUrl(void)
2817 {
2818 static const WCHAR urlW[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0};
2819 static const WCHAR wpadW[] = {'h','t','t','p',':','/','/','w','p','a','d','/','w','p','a','d','.','d','a','t',0};
2820 static const WCHAR emptyW[] = {0};
2821 BOOL ret;
2822 DWORD error;
2823 HINTERNET session;
2824 WINHTTP_AUTOPROXY_OPTIONS options;
2825 WINHTTP_PROXY_INFO info;
2826
2827 memset( &options, 0, sizeof(options) );
2828
2829 SetLastError(0xdeadbeef);
2830 ret = WinHttpGetProxyForUrl( NULL, NULL, NULL, NULL );
2831 error = GetLastError();
2832 ok( !ret, "expected failure\n" );
2833 ok( error == ERROR_INVALID_HANDLE, "got %u\n", error );
2834
2835 session = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
2836 ok( session != NULL, "failed to open session %u\n", GetLastError() );
2837
2838 SetLastError(0xdeadbeef);
2839 ret = WinHttpGetProxyForUrl( session, NULL, NULL, NULL );
2840 error = GetLastError();
2841 ok( !ret, "expected failure\n" );
2842 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
2843
2844 SetLastError(0xdeadbeef);
2845 ret = WinHttpGetProxyForUrl( session, emptyW, NULL, NULL );
2846 error = GetLastError();
2847 ok( !ret, "expected failure\n" );
2848 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
2849
2850 SetLastError(0xdeadbeef);
2851 ret = WinHttpGetProxyForUrl( session, urlW, NULL, NULL );
2852 error = GetLastError();
2853 ok( !ret, "expected failure\n" );
2854 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
2855
2856 SetLastError(0xdeadbeef);
2857 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
2858 error = GetLastError();
2859 ok( !ret, "expected failure\n" );
2860 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
2861
2862 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
2863 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
2864
2865 SetLastError(0xdeadbeef);
2866 ret = WinHttpGetProxyForUrl( session, urlW, &options, NULL );
2867 error = GetLastError();
2868 ok( !ret, "expected failure\n" );
2869 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
2870
2871 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
2872 options.dwAutoDetectFlags = 0;
2873
2874 SetLastError(0xdeadbeef);
2875 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
2876 error = GetLastError();
2877 ok( !ret, "expected failure\n" );
2878 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
2879
2880 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT | WINHTTP_AUTOPROXY_CONFIG_URL;
2881 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
2882
2883 SetLastError(0xdeadbeef);
2884 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
2885 error = GetLastError();
2886 ok( !ret, "expected failure\n" );
2887 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
2888
2889 options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
2890 options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
2891
2892 memset( &info, 0, sizeof(info) );
2893 SetLastError(0xdeadbeef);
2894 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
2895 error = GetLastError();
2896 if (!ret) ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED ||
2897 error == ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT, "got %u\n", error );
2898 else
2899 {
2900 trace("Proxy.AccessType=%u\n", info.dwAccessType);
2901 trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
2902 trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
2903 GlobalFree( info.lpszProxy );
2904 GlobalFree( info.lpszProxyBypass );
2905 }
2906
2907 options.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
2908 options.dwAutoDetectFlags = 0;
2909 options.lpszAutoConfigUrl = wpadW;
2910
2911 memset( &info, 0, sizeof(info) );
2912 SetLastError(0xdeadbeef);
2913 ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
2914 error = GetLastError();
2915 if (!ret) ok( error == ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT, "got %u\n", error );
2916 else
2917 {
2918 trace("Proxy.AccessType=%u\n", info.dwAccessType);
2919 trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
2920 trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
2921 GlobalFree( info.lpszProxy );
2922 GlobalFree( info.lpszProxyBypass );
2923 }
2924 WinHttpCloseHandle( session );
2925 }
2926
2927 static void test_chunked_read(void)
2928 {
2929 static const WCHAR host[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
2930 static const WCHAR verb[] = {'/','t','e','s','t','c','h','u','n','k','e','d',0};
2931 static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0};
2932 WCHAR header[32];
2933 DWORD len;
2934 HINTERNET ses, con = NULL, req = NULL;
2935 BOOL ret;
2936
2937 trace( "starting chunked read test\n" );
2938
2939 ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
2940 ok( ses != NULL, "WinHttpOpen failed with error %u\n", GetLastError() );
2941 if (!ses) goto done;
2942
2943 con = WinHttpConnect( ses, host, 0, 0 );
2944 ok( con != NULL, "WinHttpConnect failed with error %u\n", GetLastError() );
2945 if (!con) goto done;
2946
2947 req = WinHttpOpenRequest( con, NULL, verb, NULL, NULL, NULL, 0 );
2948 ok( req != NULL, "WinHttpOpenRequest failed with error %u\n", GetLastError() );
2949 if (!req) goto done;
2950
2951 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2952 ok( ret, "WinHttpSendRequest failed with error %u\n", GetLastError() );
2953
2954 ret = WinHttpReceiveResponse( req, NULL );
2955 ok( ret, "WinHttpReceiveResponse failed with error %u\n", GetLastError() );
2956
2957 header[0] = 0;
2958 len = sizeof(header);
2959 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, header, &len, 0 );
2960 ok( ret, "failed to get TRANSFER_ENCODING header (error %u)\n", GetLastError() );
2961 ok( !lstrcmpW( header, chunked ), "wrong transfer encoding %s\n", wine_dbgstr_w(header) );
2962 trace( "transfer encoding: %s\n", wine_dbgstr_w(header) );
2963
2964 header[0] = 0;
2965 len = sizeof(header);
2966 SetLastError( 0xdeadbeef );
2967 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CONTENT_LENGTH, NULL, &header, &len, 0 );
2968 ok( !ret, "unexpected CONTENT_LENGTH header %s\n", wine_dbgstr_w(header) );
2969 ok( GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError() );
2970
2971 trace( "entering query loop\n" );
2972 for (;;)
2973 {
2974 len = 0xdeadbeef;
2975 ret = WinHttpQueryDataAvailable( req, &len );
2976 ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
2977 if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
2978 trace( "got %u available\n", len );
2979 if (len)
2980 {
2981 DWORD bytes_read;
2982 char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
2983
2984 ret = WinHttpReadData( req, buf, len, &bytes_read );
2985
2986 buf[bytes_read] = 0;
2987 trace( "WinHttpReadData -> %d %u\n", ret, bytes_read );
2988 ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
2989 ok( buf[bytes_read - 1] == '\n', "received partial line '%s'\n", buf );
2990
2991 HeapFree( GetProcessHeap(), 0, buf );
2992 if (!bytes_read) break;
2993 }
2994 if (!len) break;
2995 }
2996 trace( "done\n" );
2997
2998 done:
2999 if (req) WinHttpCloseHandle( req );
3000 if (con) WinHttpCloseHandle( con );
3001 if (ses) WinHttpCloseHandle( ses );
3002 }
3003
3004 START_TEST (winhttp)
3005 {
3006 static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
3007 static const WCHAR quitW[] = {'/','q','u','i','t',0};
3008 struct server_info si;
3009 HANDLE thread;
3010 DWORD ret;
3011
3012 test_OpenRequest();
3013 test_SendRequest();
3014 test_WinHttpTimeFromSystemTime();
3015 test_WinHttpTimeToSystemTime();
3016 test_WinHttpAddHeaders();
3017 test_secure_connection();
3018 test_request_parameter_defaults();
3019 test_QueryOption();
3020 test_set_default_proxy_config();
3021 test_empty_headers_param();
3022 test_Timeouts();
3023 test_resolve_timeout();
3024 test_credentials();
3025 test_IWinHttpRequest();
3026 test_WinHttpDetectAutoProxyConfigUrl();
3027 test_WinHttpGetIEProxyConfigForCurrentUser();
3028 test_WinHttpGetProxyForUrl();
3029 test_chunked_read();
3030
3031 si.event = CreateEvent(NULL, 0, 0, NULL);
3032 si.port = 7532;
3033
3034 thread = CreateThread(NULL, 0, server_thread, (LPVOID)&si, 0, NULL);
3035 ok(thread != NULL, "failed to create thread %u\n", GetLastError());
3036
3037 ret = WaitForSingleObject(si.event, 10000);
3038 ok(ret == WAIT_OBJECT_0, "failed to start winhttp test server %u\n", GetLastError());
3039 if (ret != WAIT_OBJECT_0)
3040 return;
3041
3042 test_connection_info(si.port);
3043 test_basic_request(si.port, NULL, basicW);
3044 test_no_headers(si.port);
3045 test_basic_authentication(si.port);
3046 test_bad_header(si.port);
3047
3048 /* send the basic request again to shutdown the server thread */
3049 test_basic_request(si.port, NULL, quitW);
3050
3051 WaitForSingleObject(thread, 3000);
3052 }