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