[WINHTTP_WINETEST] Sync with Wine Staging 1.7.37. CORE-9246
[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 if (ret)
886 {
887 trace("lpszSubjectInfo %s\n", wine_dbgstr_w(info.lpszSubjectInfo));
888 trace("lpszIssuerInfo %s\n", wine_dbgstr_w(info.lpszIssuerInfo));
889 trace("lpszProtocolName %s\n", wine_dbgstr_w(info.lpszProtocolName));
890 trace("lpszSignatureAlgName %s\n", wine_dbgstr_w(info.lpszSignatureAlgName));
891 trace("lpszEncryptionAlgName %s\n", wine_dbgstr_w(info.lpszEncryptionAlgName));
892 trace("dwKeySize %u\n", info.dwKeySize);
893 }
894
895 ret = WinHttpReceiveResponse(req, NULL);
896 ok(ret, "failed to receive response %u\n", GetLastError());
897
898 size = sizeof(status);
899 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
900 ok(ret, "failed unexpectedly %u\n", GetLastError());
901 ok(status == 200, "request failed unexpectedly %u\n", status);
902
903 size = 0;
904 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
905 ok(!ret, "succeeded unexpectedly\n");
906
907 read_size = 0;
908 for (;;)
909 {
910 size = 0;
911 ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
912 ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
913 if (!size) break;
914 read_size += size;
915 }
916 ok(read_size > 2014, "read_size = %u\n", read_size);
917
918 cleanup:
919 WinHttpCloseHandle(req);
920 WinHttpCloseHandle(con);
921 WinHttpCloseHandle(ses);
922 }
923
924 static void test_request_parameter_defaults(void)
925 {
926 static const WCHAR empty[] = {0};
927 HINTERNET ses, con, req;
928 DWORD size, status, error;
929 WCHAR *version;
930 BOOL ret;
931
932 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
933 ok(ses != NULL, "failed to open session %u\n", GetLastError());
934
935 con = WinHttpConnect(ses, test_winehq, 0, 0);
936 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
937
938 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
939 ok(req != NULL, "failed to open a request %u\n", GetLastError());
940
941 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
942 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
943 {
944 skip("connection failed, skipping\n");
945 goto done;
946 }
947 ok(ret, "failed to send request %u\n", GetLastError());
948
949 ret = WinHttpReceiveResponse(req, NULL);
950 ok(ret, "failed to receive response %u\n", GetLastError());
951
952 size = sizeof(status);
953 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
954 ok(ret, "failed unexpectedly %u\n", GetLastError());
955 ok(status == 200, "request failed unexpectedly %u\n", status);
956
957 WinHttpCloseHandle(req);
958
959 req = WinHttpOpenRequest(con, empty, empty, empty, NULL, NULL, 0);
960 ok(req != NULL, "failed to open a request %u\n", GetLastError());
961
962 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
963 if (!ret && (GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT || GetLastError() == ERROR_WINHTTP_TIMEOUT))
964 {
965 skip("connection failed, skipping\n");
966 goto done;
967 }
968 ok(ret, "failed to send request %u\n", GetLastError());
969
970 ret = WinHttpReceiveResponse(req, NULL);
971 ok(ret, "failed to receive response %u\n", GetLastError());
972
973 size = 0;
974 SetLastError(0xdeadbeef);
975 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, NULL, &size, NULL);
976 error = GetLastError();
977 ok(!ret, "succeeded unexpectedly\n");
978 ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
979
980 version = HeapAlloc(GetProcessHeap(), 0, size);
981 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, version, &size, NULL);
982 ok(ret, "failed unexpectedly %u\n", GetLastError());
983 ok(lstrlenW(version) == size / sizeof(WCHAR), "unexpected size %u\n", size);
984 HeapFree(GetProcessHeap(), 0, version);
985
986 size = sizeof(status);
987 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
988 ok(ret, "failed unexpectedly %u\n", GetLastError());
989 ok(status == 200, "request failed unexpectedly %u\n", status);
990
991 done:
992 WinHttpCloseHandle(req);
993 WinHttpCloseHandle(con);
994 WinHttpCloseHandle(ses);
995 }
996
997 static const WCHAR Connections[] = {
998 'S','o','f','t','w','a','r','e','\\',
999 'M','i','c','r','o','s','o','f','t','\\',
1000 'W','i','n','d','o','w','s','\\',
1001 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1002 'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
1003 'C','o','n','n','e','c','t','i','o','n','s',0 };
1004 static const WCHAR WinHttpSettings[] = {
1005 'W','i','n','H','t','t','p','S','e','t','t','i','n','g','s',0 };
1006
1007 static DWORD get_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD *type )
1008 {
1009 LONG l;
1010 HKEY key;
1011 DWORD ret = 0;
1012
1013 l = RegOpenKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, KEY_READ, &key );
1014 if (!l)
1015 {
1016 DWORD size = 0;
1017
1018 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, NULL, &size );
1019 if (!l)
1020 {
1021 if (size <= len)
1022 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, buf,
1023 &size );
1024 if (!l)
1025 ret = size;
1026 }
1027 RegCloseKey( key );
1028 }
1029 return ret;
1030 }
1031
1032 static void set_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD type )
1033 {
1034 LONG l;
1035 HKEY key;
1036
1037 l = RegCreateKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, NULL, 0,
1038 KEY_WRITE, NULL, &key, NULL );
1039 if (!l)
1040 {
1041 if (len)
1042 RegSetValueExW( key, WinHttpSettings, 0, type, buf, len );
1043 else
1044 RegDeleteValueW( key, WinHttpSettings );
1045 RegCloseKey( key );
1046 }
1047 }
1048
1049 static void test_set_default_proxy_config(void)
1050 {
1051 static WCHAR wideString[] = { 0x226f, 0x575b, 0 };
1052 static WCHAR normalString[] = { 'f','o','o',0 };
1053 DWORD type, len;
1054 BYTE *saved_proxy_settings = NULL;
1055 WINHTTP_PROXY_INFO info;
1056 BOOL ret;
1057
1058 /* FIXME: it would be simpler to read the current settings using
1059 * WinHttpGetDefaultProxyConfiguration and save them using
1060 * WinHttpSetDefaultProxyConfiguration, but they appear to have a bug.
1061 *
1062 * If a proxy is configured in the registry, e.g. via 'proxcfg -p "foo"',
1063 * the access type reported by WinHttpGetDefaultProxyConfiguration is 1,
1064 * WINHTTP_ACCESS_TYPE_NO_PROXY, whereas it should be
1065 * WINHTTP_ACCESS_TYPE_NAMED_PROXY.
1066 * If WinHttpSetDefaultProxyConfiguration is called with dwAccessType = 1,
1067 * the lpszProxy and lpszProxyBypass values are ignored.
1068 * Thus, if a proxy is set with proxycfg, then calling
1069 * WinHttpGetDefaultProxyConfiguration followed by
1070 * WinHttpSetDefaultProxyConfiguration results in the proxy settings
1071 * getting deleted from the registry.
1072 *
1073 * Instead I read the current registry value and restore it directly.
1074 */
1075 len = get_default_proxy_reg_value( NULL, 0, &type );
1076 if (len)
1077 {
1078 saved_proxy_settings = HeapAlloc( GetProcessHeap(), 0, len );
1079 len = get_default_proxy_reg_value( saved_proxy_settings, len, &type );
1080 }
1081
1082 if (0)
1083 {
1084 /* Crashes on Vista and higher */
1085 SetLastError(0xdeadbeef);
1086 ret = WinHttpSetDefaultProxyConfiguration(NULL);
1087 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1088 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1089 }
1090
1091 /* test with invalid access type */
1092 info.dwAccessType = 0xdeadbeef;
1093 info.lpszProxy = info.lpszProxyBypass = NULL;
1094 SetLastError(0xdeadbeef);
1095 ret = WinHttpSetDefaultProxyConfiguration(&info);
1096 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1097 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1098
1099 /* at a minimum, the proxy server must be set */
1100 info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1101 info.lpszProxy = info.lpszProxyBypass = NULL;
1102 SetLastError(0xdeadbeef);
1103 ret = WinHttpSetDefaultProxyConfiguration(&info);
1104 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1105 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1106 info.lpszProxyBypass = normalString;
1107 SetLastError(0xdeadbeef);
1108 ret = WinHttpSetDefaultProxyConfiguration(&info);
1109 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1110 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1111
1112 /* the proxy server can't have wide characters */
1113 info.lpszProxy = wideString;
1114 SetLastError(0xdeadbeef);
1115 ret = WinHttpSetDefaultProxyConfiguration(&info);
1116 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1117 skip("couldn't set default proxy configuration: access denied\n");
1118 else
1119 ok((!ret && GetLastError() == ERROR_INVALID_PARAMETER) ||
1120 broken(ret), /* Earlier winhttp versions on W2K/XP */
1121 "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1122
1123 info.lpszProxy = normalString;
1124 SetLastError(0xdeadbeef);
1125 ret = WinHttpSetDefaultProxyConfiguration(&info);
1126 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1127 skip("couldn't set default proxy configuration: access denied\n");
1128 else
1129 ok(ret, "WinHttpSetDefaultProxyConfiguration failed: %d\n",
1130 GetLastError());
1131
1132 set_default_proxy_reg_value( saved_proxy_settings, len, type );
1133 }
1134
1135 static void test_Timeouts (void)
1136 {
1137 BOOL ret;
1138 DWORD value, size;
1139 HINTERNET ses, req, con;
1140
1141 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1142 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1143
1144 SetLastError(0xdeadbeef);
1145 ret = WinHttpSetTimeouts(ses, -2, 0, 0, 0);
1146 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1147 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1148
1149 SetLastError(0xdeadbeef);
1150 ret = WinHttpSetTimeouts(ses, 0, -2, 0, 0);
1151 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1152 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1153
1154 SetLastError(0xdeadbeef);
1155 ret = WinHttpSetTimeouts(ses, 0, 0, -2, 0);
1156 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1157 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1158
1159 SetLastError(0xdeadbeef);
1160 ret = WinHttpSetTimeouts(ses, 0, 0, 0, -2);
1161 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1162 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1163
1164 SetLastError(0xdeadbeef);
1165 ret = WinHttpSetTimeouts(ses, -1, -1, -1, -1);
1166 ok(ret, "%u\n", GetLastError());
1167
1168 SetLastError(0xdeadbeef);
1169 ret = WinHttpSetTimeouts(ses, 0, 0, 0, 0);
1170 ok(ret, "%u\n", GetLastError());
1171
1172 SetLastError(0xdeadbeef);
1173 ret = WinHttpSetTimeouts(ses, 0x0123, 0x4567, 0x89ab, 0xcdef);
1174 ok(ret, "%u\n", GetLastError());
1175
1176 SetLastError(0xdeadbeef);
1177 value = 0xdeadbeef;
1178 size = sizeof(DWORD);
1179 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1180 ok(ret, "%u\n", GetLastError());
1181 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1182
1183 SetLastError(0xdeadbeef);
1184 value = 0xdeadbeef;
1185 size = sizeof(DWORD);
1186 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1187 ok(ret, "%u\n", GetLastError());
1188 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1189
1190 SetLastError(0xdeadbeef);
1191 value = 0xdeadbeef;
1192 size = sizeof(DWORD);
1193 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1194 ok(ret, "%u\n", GetLastError());
1195 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1196
1197 SetLastError(0xdeadbeef);
1198 value = 0xdeadbeef;
1199 size = sizeof(DWORD);
1200 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1201 ok(ret, "%u\n", GetLastError());
1202 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1203
1204 SetLastError(0xdeadbeef);
1205 value = 0;
1206 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1207 ok(ret, "%u\n", GetLastError());
1208
1209 SetLastError(0xdeadbeef);
1210 value = 0xdeadbeef;
1211 size = sizeof(DWORD);
1212 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1213 ok(ret, "%u\n", GetLastError());
1214 ok(value == 0, "Expected 0, got %u\n", value);
1215
1216 SetLastError(0xdeadbeef);
1217 value = 0;
1218 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1219 ok(ret, "%u\n", GetLastError());
1220
1221 SetLastError(0xdeadbeef);
1222 value = 0xdeadbeef;
1223 size = sizeof(DWORD);
1224 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1225 ok(ret, "%u\n", GetLastError());
1226 ok(value == 0, "Expected 0, got %u\n", value);
1227
1228 SetLastError(0xdeadbeef);
1229 value = 0;
1230 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1231 ok(ret, "%u\n", GetLastError());
1232
1233 SetLastError(0xdeadbeef);
1234 value = 0xdeadbeef;
1235 size = sizeof(DWORD);
1236 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1237 ok(ret, "%u\n", GetLastError());
1238 ok(value == 0, "Expected 0, got %u\n", value);
1239
1240 SetLastError(0xdeadbeef);
1241 value = 0;
1242 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1243 ok(ret, "%u\n", GetLastError());
1244
1245 SetLastError(0xdeadbeef);
1246 value = 0xdeadbeef;
1247 size = sizeof(DWORD);
1248 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1249 ok(ret, "%u\n", GetLastError());
1250 ok(value == 0, "Expected 0, got %u\n", value);
1251
1252 SetLastError(0xdeadbeef);
1253 value = 0xbeefdead;
1254 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1255 ok(ret, "%u\n", GetLastError());
1256
1257 SetLastError(0xdeadbeef);
1258 value = 0xdeadbeef;
1259 size = sizeof(DWORD);
1260 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1261 ok(ret, "%u\n", GetLastError());
1262 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1263
1264 SetLastError(0xdeadbeef);
1265 value = 0xbeefdead;
1266 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1267 ok(ret, "%u\n", GetLastError());
1268
1269 SetLastError(0xdeadbeef);
1270 value = 0xdeadbeef;
1271 size = sizeof(DWORD);
1272 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1273 ok(ret, "%u\n", GetLastError());
1274 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1275
1276 SetLastError(0xdeadbeef);
1277 value = 0xbeefdead;
1278 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1279 ok(ret, "%u\n", GetLastError());
1280
1281 SetLastError(0xdeadbeef);
1282 value = 0xdeadbeef;
1283 size = sizeof(DWORD);
1284 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1285 ok(ret, "%u\n", GetLastError());
1286 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1287
1288 SetLastError(0xdeadbeef);
1289 value = 0xbeefdead;
1290 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1291 ok(ret, "%u\n", GetLastError());
1292
1293 SetLastError(0xdeadbeef);
1294 value = 0xdeadbeef;
1295 size = sizeof(DWORD);
1296 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1297 ok(ret, "%u\n", GetLastError());
1298 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1299
1300 con = WinHttpConnect(ses, test_winehq, 0, 0);
1301 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1302
1303 /* Timeout values should match the last one set for session */
1304 SetLastError(0xdeadbeef);
1305 value = 0xdeadbeef;
1306 size = sizeof(DWORD);
1307 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1308 ok(ret, "%u\n", GetLastError());
1309 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1310
1311 SetLastError(0xdeadbeef);
1312 value = 0xdeadbeef;
1313 size = sizeof(DWORD);
1314 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1315 ok(ret, "%u\n", GetLastError());
1316 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1317
1318 SetLastError(0xdeadbeef);
1319 value = 0xdeadbeef;
1320 size = sizeof(DWORD);
1321 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1322 ok(ret, "%u\n", GetLastError());
1323 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1324
1325 SetLastError(0xdeadbeef);
1326 value = 0xdeadbeef;
1327 size = sizeof(DWORD);
1328 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1329 ok(ret, "%u\n", GetLastError());
1330 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1331
1332 SetLastError(0xdeadbeef);
1333 ret = WinHttpSetTimeouts(con, -2, 0, 0, 0);
1334 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1335 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1336
1337 SetLastError(0xdeadbeef);
1338 ret = WinHttpSetTimeouts(con, 0, -2, 0, 0);
1339 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1340 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1341
1342 SetLastError(0xdeadbeef);
1343 ret = WinHttpSetTimeouts(con, 0, 0, -2, 0);
1344 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1345 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1346
1347 SetLastError(0xdeadbeef);
1348 ret = WinHttpSetTimeouts(con, 0, 0, 0, -2);
1349 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1350 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1351
1352 SetLastError(0xdeadbeef);
1353 ret = WinHttpSetTimeouts(con, -1, -1, -1, -1);
1354 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1355 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1356
1357 SetLastError(0xdeadbeef);
1358 ret = WinHttpSetTimeouts(con, 0, 0, 0, 0);
1359 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1360 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1361
1362 SetLastError(0xdeadbeef);
1363 value = 0;
1364 ret = WinHttpSetOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1365 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1366 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1367
1368 SetLastError(0xdeadbeef);
1369 value = 0;
1370 ret = WinHttpSetOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1371 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1372 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1373
1374 SetLastError(0xdeadbeef);
1375 value = 0;
1376 ret = WinHttpSetOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1377 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1378 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1379
1380 SetLastError(0xdeadbeef);
1381 value = 0;
1382 ret = WinHttpSetOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1383 ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1384 "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1385
1386 /* Changing timeout values for session should affect the values for connection */
1387 SetLastError(0xdeadbeef);
1388 value = 0xdead;
1389 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1390 ok(ret, "%u\n", GetLastError());
1391
1392 SetLastError(0xdeadbeef);
1393 value = 0xdeadbeef;
1394 size = sizeof(DWORD);
1395 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1396 ok(ret, "%u\n", GetLastError());
1397 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1398
1399 SetLastError(0xdeadbeef);
1400 value = 0xdead;
1401 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1402 ok(ret, "%u\n", GetLastError());
1403
1404 SetLastError(0xdeadbeef);
1405 value = 0xdeadbeef;
1406 size = sizeof(DWORD);
1407 ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1408 ok(ret, "%u\n", GetLastError());
1409 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1410
1411 SetLastError(0xdeadbeef);
1412 value = 0xdead;
1413 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1414 ok(ret, "%u\n", GetLastError());
1415
1416 SetLastError(0xdeadbeef);
1417 value = 0xdeadbeef;
1418 size = sizeof(DWORD);
1419 ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1420 ok(ret, "%u\n", GetLastError());
1421 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1422
1423 SetLastError(0xdeadbeef);
1424 value = 0xdead;
1425 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1426 ok(ret, "%u\n", GetLastError());
1427
1428 SetLastError(0xdeadbeef);
1429 value = 0xdeadbeef;
1430 size = sizeof(DWORD);
1431 ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1432 ok(ret, "%u\n", GetLastError());
1433 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1434
1435 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1436 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1437
1438 /* Timeout values should match the last one set for session */
1439 SetLastError(0xdeadbeef);
1440 value = 0xdeadbeef;
1441 size = sizeof(DWORD);
1442 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1443 ok(ret, "%u\n", GetLastError());
1444 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1445
1446 SetLastError(0xdeadbeef);
1447 value = 0xdeadbeef;
1448 size = sizeof(DWORD);
1449 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1450 ok(ret, "%u\n", GetLastError());
1451 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1452
1453 SetLastError(0xdeadbeef);
1454 value = 0xdeadbeef;
1455 size = sizeof(DWORD);
1456 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1457 ok(ret, "%u\n", GetLastError());
1458 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1459
1460 SetLastError(0xdeadbeef);
1461 value = 0xdeadbeef;
1462 size = sizeof(DWORD);
1463 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1464 ok(ret, "%u\n", GetLastError());
1465 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1466
1467 SetLastError(0xdeadbeef);
1468 ret = WinHttpSetTimeouts(req, -2, 0, 0, 0);
1469 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1470 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1471
1472 SetLastError(0xdeadbeef);
1473 ret = WinHttpSetTimeouts(req, 0, -2, 0, 0);
1474 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1475 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1476
1477 SetLastError(0xdeadbeef);
1478 ret = WinHttpSetTimeouts(req, 0, 0, -2, 0);
1479 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1480 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1481
1482 SetLastError(0xdeadbeef);
1483 ret = WinHttpSetTimeouts(req, 0, 0, 0, -2);
1484 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1485 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1486
1487 SetLastError(0xdeadbeef);
1488 ret = WinHttpSetTimeouts(req, -1, -1, -1, -1);
1489 ok(ret, "%u\n", GetLastError());
1490
1491 SetLastError(0xdeadbeef);
1492 ret = WinHttpSetTimeouts(req, 0, 0, 0, 0);
1493 ok(ret, "%u\n", GetLastError());
1494
1495 SetLastError(0xdeadbeef);
1496 ret = WinHttpSetTimeouts(req, 0xcdef, 0x89ab, 0x4567, 0x0123);
1497 ok(ret, "%u\n", GetLastError());
1498
1499 SetLastError(0xdeadbeef);
1500 value = 0xdeadbeef;
1501 size = sizeof(DWORD);
1502 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1503 ok(ret, "%u\n", GetLastError());
1504 ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1505
1506 SetLastError(0xdeadbeef);
1507 value = 0xdeadbeef;
1508 size = sizeof(DWORD);
1509 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1510 ok(ret, "%u\n", GetLastError());
1511 ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1512
1513 SetLastError(0xdeadbeef);
1514 value = 0xdeadbeef;
1515 size = sizeof(DWORD);
1516 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1517 ok(ret, "%u\n", GetLastError());
1518 ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1519
1520 SetLastError(0xdeadbeef);
1521 value = 0xdeadbeef;
1522 size = sizeof(DWORD);
1523 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1524 ok(ret, "%u\n", GetLastError());
1525 ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1526
1527 SetLastError(0xdeadbeef);
1528 value = 0;
1529 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1530 ok(ret, "%u\n", GetLastError());
1531
1532 SetLastError(0xdeadbeef);
1533 value = 0xdeadbeef;
1534 size = sizeof(DWORD);
1535 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1536 ok(ret, "%u\n", GetLastError());
1537 ok(value == 0, "Expected 0, got %u\n", value);
1538
1539 SetLastError(0xdeadbeef);
1540 value = 0;
1541 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1542 ok(ret, "%u\n", GetLastError());
1543
1544 SetLastError(0xdeadbeef);
1545 value = 0xdeadbeef;
1546 size = sizeof(DWORD);
1547 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1548 ok(ret, "%u\n", GetLastError());
1549 ok(value == 0, "Expected 0, got %u\n", value);
1550
1551 SetLastError(0xdeadbeef);
1552 value = 0;
1553 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1554 ok(ret, "%u\n", GetLastError());
1555
1556 SetLastError(0xdeadbeef);
1557 value = 0xdeadbeef;
1558 size = sizeof(DWORD);
1559 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1560 ok(ret, "%u\n", GetLastError());
1561 ok(value == 0, "Expected 0, got %u\n", value);
1562
1563 SetLastError(0xdeadbeef);
1564 value = 0;
1565 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1566 ok(ret, "%u\n", GetLastError());
1567
1568 SetLastError(0xdeadbeef);
1569 value = 0xdeadbeef;
1570 size = sizeof(DWORD);
1571 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1572 ok(ret, "%u\n", GetLastError());
1573 ok(value == 0, "Expected 0, got %u\n", value);
1574
1575 SetLastError(0xdeadbeef);
1576 value = 0xbeefdead;
1577 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1578 ok(ret, "%u\n", GetLastError());
1579
1580 SetLastError(0xdeadbeef);
1581 value = 0xdeadbeef;
1582 size = sizeof(DWORD);
1583 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1584 ok(ret, "%u\n", GetLastError());
1585 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1586
1587 SetLastError(0xdeadbeef);
1588 value = 0xbeefdead;
1589 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1590 ok(ret, "%u\n", GetLastError());
1591
1592 SetLastError(0xdeadbeef);
1593 value = 0xdeadbeef;
1594 size = sizeof(DWORD);
1595 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1596 ok(ret, "%u\n", GetLastError());
1597 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1598
1599 SetLastError(0xdeadbeef);
1600 value = 0xbeefdead;
1601 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1602 ok(ret, "%u\n", GetLastError());
1603
1604 SetLastError(0xdeadbeef);
1605 value = 0xdeadbeef;
1606 size = sizeof(DWORD);
1607 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1608 ok(ret, "%u\n", GetLastError());
1609 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1610
1611 SetLastError(0xdeadbeef);
1612 value = 0xbeefdead;
1613 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1614 ok(ret, "%u\n", GetLastError());
1615
1616 SetLastError(0xdeadbeef);
1617 value = 0xdeadbeef;
1618 size = sizeof(DWORD);
1619 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1620 ok(ret, "%u\n", GetLastError());
1621 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1622
1623 /* Changing timeout values for session should not affect the values for a request,
1624 * neither should the other way around.
1625 */
1626 SetLastError(0xdeadbeef);
1627 value = 0xbeefdead;
1628 ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1629 ok(ret, "%u\n", GetLastError());
1630
1631 SetLastError(0xdeadbeef);
1632 value = 0xdeadbeef;
1633 size = sizeof(DWORD);
1634 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1635 ok(ret, "%u\n", GetLastError());
1636 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1637
1638 SetLastError(0xdeadbeef);
1639 value = 0xbeefdead;
1640 ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1641 ok(ret, "%u\n", GetLastError());
1642
1643 SetLastError(0xdeadbeef);
1644 value = 0xdeadbeef;
1645 size = sizeof(DWORD);
1646 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1647 ok(ret, "%u\n", GetLastError());
1648 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1649
1650 SetLastError(0xdeadbeef);
1651 value = 0xbeefdead;
1652 ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1653 ok(ret, "%u\n", GetLastError());
1654
1655 SetLastError(0xdeadbeef);
1656 value = 0xdeadbeef;
1657 size = sizeof(DWORD);
1658 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1659 ok(ret, "%u\n", GetLastError());
1660 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1661
1662 SetLastError(0xdeadbeef);
1663 value = 0xbeefdead;
1664 ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1665 ok(ret, "%u\n", GetLastError());
1666
1667 SetLastError(0xdeadbeef);
1668 value = 0xdeadbeef;
1669 size = sizeof(DWORD);
1670 ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1671 ok(ret, "%u\n", GetLastError());
1672 ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1673
1674 SetLastError(0xdeadbeef);
1675 value = 0xbeef;
1676 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1677 ok(ret, "%u\n", GetLastError());
1678
1679 SetLastError(0xdeadbeef);
1680 value = 0xdeadbeef;
1681 size = sizeof(DWORD);
1682 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1683 ok(ret, "%u\n", GetLastError());
1684 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1685
1686 SetLastError(0xdeadbeef);
1687 value = 0xbeef;
1688 ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1689 ok(ret, "%u\n", GetLastError());
1690
1691 SetLastError(0xdeadbeef);
1692 value = 0xdeadbeef;
1693 size = sizeof(DWORD);
1694 ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1695 ok(ret, "%u\n", GetLastError());
1696 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1697
1698 SetLastError(0xdeadbeef);
1699 value = 0xbeef;
1700 ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1701 ok(ret, "%u\n", GetLastError());
1702
1703 SetLastError(0xdeadbeef);
1704 value = 0xdeadbeef;
1705 size = sizeof(DWORD);
1706 ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1707 ok(ret, "%u\n", GetLastError());
1708 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1709
1710 SetLastError(0xdeadbeef);
1711 value = 0xbeef;
1712 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1713 ok(ret, "%u\n", GetLastError());
1714
1715 SetLastError(0xdeadbeef);
1716 value = 0xdeadbeef;
1717 size = sizeof(DWORD);
1718 ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1719 ok(ret, "%u\n", GetLastError());
1720 ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1721
1722 WinHttpCloseHandle(req);
1723 WinHttpCloseHandle(con);
1724 WinHttpCloseHandle(ses);
1725 }
1726
1727 static void test_resolve_timeout(void)
1728 {
1729 static const WCHAR nxdomain[] =
1730 {'n','x','d','o','m','a','i','n','.','w','i','n','e','h','q','.','o','r','g',0};
1731 HINTERNET ses, con, req;
1732 DWORD timeout;
1733 BOOL ret;
1734
1735 if (! proxy_active())
1736 {
1737 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1738 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1739
1740 timeout = 10000;
1741 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1742 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1743
1744 con = WinHttpConnect(ses, nxdomain, 0, 0);
1745 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1746
1747 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1748 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1749
1750 SetLastError(0xdeadbeef);
1751 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1752 if (ret)
1753 {
1754 skip("nxdomain returned success. Broken ISP redirects?\n");
1755 goto done;
1756 }
1757 ok(GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED,
1758 "expected ERROR_WINHTTP_NAME_NOT_RESOLVED got %u\n", GetLastError());
1759
1760 WinHttpCloseHandle(req);
1761 WinHttpCloseHandle(con);
1762 WinHttpCloseHandle(ses);
1763 }
1764 else
1765 skip("Skipping host resolution tests, host resolution preformed by proxy\n");
1766
1767 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1768 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1769
1770 timeout = 10000;
1771 ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1772 ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1773
1774 con = WinHttpConnect(ses, test_winehq, 0, 0);
1775 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1776
1777 req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1778 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1779
1780 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1781 if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
1782 {
1783 skip("connection failed, skipping\n");
1784 goto done;
1785 }
1786 ok(ret, "failed to send request\n");
1787
1788 done:
1789 WinHttpCloseHandle(req);
1790 WinHttpCloseHandle(con);
1791 WinHttpCloseHandle(ses);
1792 }
1793
1794 static const char page1[] =
1795 "<HTML>\r\n"
1796 "<HEAD><TITLE>winhttp test page</TITLE></HEAD>\r\n"
1797 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
1798 "</HTML>\r\n\r\n";
1799
1800 static const char okmsg[] =
1801 "HTTP/1.1 200 OK\r\n"
1802 "Server: winetest\r\n"
1803 "\r\n";
1804
1805 static const char nocontentmsg[] =
1806 "HTTP/1.1 204 No Content\r\n"
1807 "Server: winetest\r\n"
1808 "\r\n";
1809
1810 static const char notmodified[] =
1811 "HTTP/1.1 304 Not Modified\r\n"
1812 "\r\n";
1813
1814 static const char noauthmsg[] =
1815 "HTTP/1.1 401 Unauthorized\r\n"
1816 "Server: winetest\r\n"
1817 "Connection: close\r\n"
1818 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
1819 "\r\n";
1820
1821 static const char okauthmsg[] =
1822 "HTTP/1.1 200 OK\r\n"
1823 "Server: winetest\r\n"
1824 "Connection: close\r\n"
1825 "\r\n";
1826
1827 static const char headmsg[] =
1828 "HTTP/1.1 200 OK\r\n"
1829 "Content-Length: 100\r\n"
1830 "\r\n";
1831
1832 struct server_info
1833 {
1834 HANDLE event;
1835 int port;
1836 };
1837
1838 #define BIG_BUFFER_LEN 0x2250
1839
1840 static DWORD CALLBACK server_thread(LPVOID param)
1841 {
1842 struct server_info *si = param;
1843 int r, c = -1, i, on;
1844 SOCKET s;
1845 struct sockaddr_in sa;
1846 char buffer[0x100];
1847 WSADATA wsaData;
1848 int last_request = 0;
1849
1850 WSAStartup(MAKEWORD(1,1), &wsaData);
1851
1852 s = socket(AF_INET, SOCK_STREAM, 0);
1853 if (s == INVALID_SOCKET)
1854 return 1;
1855
1856 on = 1;
1857 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof on);
1858
1859 memset(&sa, 0, sizeof sa);
1860 sa.sin_family = AF_INET;
1861 sa.sin_port = htons(si->port);
1862 sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
1863
1864 r = bind(s, (struct sockaddr *)&sa, sizeof(sa));
1865 if (r < 0)
1866 return 1;
1867
1868 listen(s, 0);
1869 SetEvent(si->event);
1870 do
1871 {
1872 if (c == -1) c = accept(s, NULL, NULL);
1873
1874 memset(buffer, 0, sizeof buffer);
1875 for(i = 0; i < sizeof buffer - 1; i++)
1876 {
1877 r = recv(c, &buffer[i], 1, 0);
1878 if (r != 1)
1879 break;
1880 if (i < 4) continue;
1881 if (buffer[i - 2] == '\n' && buffer[i] == '\n' &&
1882 buffer[i - 3] == '\r' && buffer[i - 1] == '\r')
1883 break;
1884 }
1885 if (strstr(buffer, "GET /basic"))
1886 {
1887 send(c, okmsg, sizeof okmsg - 1, 0);
1888 send(c, page1, sizeof page1 - 1, 0);
1889 }
1890 if (strstr(buffer, "/auth"))
1891 {
1892 if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
1893 send(c, okauthmsg, sizeof okauthmsg - 1, 0);
1894 else
1895 send(c, noauthmsg, sizeof noauthmsg - 1, 0);
1896 }
1897 if (strstr(buffer, "/big"))
1898 {
1899 char msg[BIG_BUFFER_LEN];
1900 memset(msg, 'm', sizeof(msg));
1901 send(c, okmsg, sizeof(okmsg) - 1, 0);
1902 send(c, msg, sizeof(msg), 0);
1903 }
1904 if (strstr(buffer, "/no_headers"))
1905 {
1906 send(c, page1, sizeof page1 - 1, 0);
1907 }
1908 if (strstr(buffer, "GET /no_content"))
1909 {
1910 send(c, nocontentmsg, sizeof nocontentmsg - 1, 0);
1911 continue;
1912 }
1913 if (strstr(buffer, "GET /not_modified"))
1914 {
1915 send(c, notmodified, sizeof notmodified - 1, 0);
1916 continue;
1917 }
1918 if (strstr(buffer, "HEAD /head"))
1919 {
1920 send(c, headmsg, sizeof headmsg - 1, 0);
1921 continue;
1922 }
1923 if (strstr(buffer, "GET /quit"))
1924 {
1925 send(c, okmsg, sizeof okmsg - 1, 0);
1926 send(c, page1, sizeof page1 - 1, 0);
1927 last_request = 1;
1928 }
1929 shutdown(c, 2);
1930 closesocket(c);
1931 c = -1;
1932
1933 } while (!last_request);
1934
1935 closesocket(s);
1936 return 0;
1937 }
1938
1939 static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
1940 {
1941 HINTERNET ses, con, req;
1942 char buffer[0x100];
1943 DWORD count, status, size, error, supported, first, target;
1944 BOOL ret;
1945
1946 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1947 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1948
1949 con = WinHttpConnect(ses, localhostW, port, 0);
1950 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1951
1952 req = WinHttpOpenRequest(con, verb, path, NULL, NULL, NULL, 0);
1953 ok(req != NULL, "failed to open a request %u\n", GetLastError());
1954
1955 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1956 ok(ret, "failed to send request %u\n", GetLastError());
1957
1958 ret = WinHttpReceiveResponse(req, NULL);
1959 ok(ret, "failed to receive response %u\n", GetLastError());
1960
1961 size = sizeof(status);
1962 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1963 ok(ret, "failed to query status code %u\n", GetLastError());
1964 ok(status == 200, "request failed unexpectedly %u\n", status);
1965
1966 supported = first = target = 0xdeadbeef;
1967 SetLastError(0xdeadbeef);
1968 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
1969 error = GetLastError();
1970 ok(!ret, "unexpected success\n");
1971 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
1972 ok(supported == 0xdeadbeef, "got %x\n", supported);
1973 ok(first == 0xdeadbeef, "got %x\n", first);
1974 ok(target == 0xdeadbeef, "got %x\n", target);
1975
1976 count = 0;
1977 memset(buffer, 0, sizeof(buffer));
1978 ret = WinHttpReadData(req, buffer, sizeof buffer, &count);
1979 ok(ret, "failed to read data %u\n", GetLastError());
1980 ok(count == sizeof page1 - 1, "count was wrong\n");
1981 ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
1982
1983 WinHttpCloseHandle(req);
1984 WinHttpCloseHandle(con);
1985 WinHttpCloseHandle(ses);
1986 }
1987
1988 static void test_basic_authentication(int port)
1989 {
1990 static const WCHAR authW[] = {'/','a','u','t','h',0};
1991 static const WCHAR userW[] = {'u','s','e','r',0};
1992 static const WCHAR passW[] = {'p','w','d',0};
1993 HINTERNET ses, con, req;
1994 DWORD status, size, error, supported, first, target;
1995 BOOL ret;
1996
1997 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1998 ok(ses != NULL, "failed to open session %u\n", GetLastError());
1999
2000 con = WinHttpConnect(ses, localhostW, port, 0);
2001 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2002
2003 req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2004 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2005
2006 SetLastError(0xdeadbeef);
2007 ret = WinHttpQueryAuthSchemes(NULL, NULL, NULL, NULL);
2008 error = GetLastError();
2009 ok(!ret, "expected failure\n");
2010 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2011
2012 SetLastError(0xdeadbeef);
2013 ret = WinHttpQueryAuthSchemes(req, NULL, NULL, NULL);
2014 error = GetLastError();
2015 ok(!ret, "expected failure\n");
2016 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2017
2018 supported = 0xdeadbeef;
2019 SetLastError(0xdeadbeef);
2020 ret = WinHttpQueryAuthSchemes(req, &supported, NULL, NULL);
2021 error = GetLastError();
2022 ok(!ret, "expected failure\n");
2023 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2024 ok(supported == 0xdeadbeef, "got %x\n", supported);
2025
2026 supported = first = 0xdeadbeef;
2027 SetLastError(0xdeadbeef);
2028 ret = WinHttpQueryAuthSchemes(req, &supported, &first, NULL);
2029 error = GetLastError();
2030 ok(!ret, "expected failure\n");
2031 ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2032 ok(supported == 0xdeadbeef, "got %x\n", supported);
2033 ok(first == 0xdeadbeef, "got %x\n", first);
2034
2035 supported = first = target = 0xdeadbeef;
2036 SetLastError(0xdeadbeef);
2037 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2038 error = GetLastError();
2039 ok(!ret, "expected failure\n");
2040 todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2041 ok(supported == 0xdeadbeef, "got %x\n", supported);
2042 ok(first == 0xdeadbeef, "got %x\n", first);
2043 ok(target == 0xdeadbeef, "got %x\n", target);
2044
2045 supported = first = target = 0xdeadbeef;
2046 SetLastError(0xdeadbeef);
2047 ret = WinHttpQueryAuthSchemes(NULL, &supported, &first, &target);
2048 error = GetLastError();
2049 ok(!ret, "expected failure\n");
2050 ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2051 ok(supported == 0xdeadbeef, "got %x\n", supported);
2052 ok(first == 0xdeadbeef, "got %x\n", first);
2053 ok(target == 0xdeadbeef, "got %x\n", target);
2054
2055 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2056 ok(ret, "failed to send request %u\n", GetLastError());
2057
2058 ret = WinHttpReceiveResponse(req, NULL);
2059 ok(ret, "failed to receive response %u\n", GetLastError());
2060
2061 size = sizeof(status);
2062 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2063 ok(ret, "failed to query status code %u\n", GetLastError());
2064 ok(status == 401, "request failed unexpectedly %u\n", status);
2065
2066 supported = first = target = 0xdeadbeef;
2067 ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2068 ok(ret, "failed to query authentication schemes %u\n", GetLastError());
2069 ok(supported == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", supported);
2070 ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
2071 ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
2072
2073 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, NULL, NULL, NULL);
2074 ok(ret, "failed to set credentials %u\n", GetLastError());
2075
2076 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_PASSPORT, NULL, NULL, NULL);
2077 ok(ret, "failed to set credentials %u\n", GetLastError());
2078
2079 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NEGOTIATE, NULL, NULL, NULL);
2080 ok(ret, "failed to set credentials %u\n", GetLastError());
2081
2082 SetLastError(0xdeadbeef);
2083 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_DIGEST, NULL, NULL, NULL);
2084 error = GetLastError();
2085 ok(!ret, "expected failure\n");
2086 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2087
2088 SetLastError(0xdeadbeef);
2089 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, NULL, NULL);
2090 error = GetLastError();
2091 ok(!ret, "expected failure\n");
2092 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2093
2094 SetLastError(0xdeadbeef);
2095 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
2096 error = GetLastError();
2097 ok(!ret, "expected failure\n");
2098 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2099
2100 SetLastError(0xdeadbeef);
2101 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
2102 error = GetLastError();
2103 ok(!ret, "expected failure\n");
2104 ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2105
2106 ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2107 ok(ret, "failed to set credentials %u\n", GetLastError());
2108
2109 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2110 ok(ret, "failed to send request %u\n", GetLastError());
2111
2112 ret = WinHttpReceiveResponse(req, NULL);
2113 ok(ret, "failed to receive response %u\n", GetLastError());
2114
2115 size = sizeof(status);
2116 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2117 ok(ret, "failed to query status code %u\n", GetLastError());
2118 ok(status == 200, "request failed unexpectedly %u\n", status);
2119
2120 WinHttpCloseHandle(req);
2121 WinHttpCloseHandle(con);
2122 WinHttpCloseHandle(ses);
2123 }
2124
2125 static void test_no_headers(int port)
2126 {
2127 static const WCHAR no_headersW[] = {'/','n','o','_','h','e','a','d','e','r','s',0};
2128 HINTERNET ses, con, req;
2129 DWORD error;
2130 BOOL ret;
2131
2132 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
2133 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2134
2135 con = WinHttpConnect(ses, localhostW, port, 0);
2136 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2137
2138 req = WinHttpOpenRequest(con, NULL, no_headersW, NULL, NULL, NULL, 0);
2139 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2140
2141 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2142 if (!ret)
2143 {
2144 error = GetLastError();
2145 ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2146 }
2147 else
2148 {
2149 SetLastError(0xdeadbeef);
2150 ret = WinHttpReceiveResponse(req, NULL);
2151 error = GetLastError();
2152 ok(!ret, "expected failure\n");
2153 ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2154 }
2155
2156 WinHttpCloseHandle(req);
2157 WinHttpCloseHandle(con);
2158 WinHttpCloseHandle(ses);
2159 }
2160
2161 static void test_no_content(int port)
2162 {
2163 static const WCHAR no_contentW[] = {'/','n','o','_','c','o','n','t','e','n','t',0};
2164 HINTERNET ses, con, req;
2165 char buf[128];
2166 DWORD size, len = sizeof(buf), bytes_read, status;
2167 BOOL ret;
2168
2169 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
2170 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2171
2172 con = WinHttpConnect(ses, localhostW, port, 0);
2173 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2174
2175 req = WinHttpOpenRequest(con, NULL, no_contentW, NULL, NULL, NULL, 0);
2176 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2177
2178 size = 12345;
2179 SetLastError(0xdeadbeef);
2180 ret = WinHttpQueryDataAvailable(req, &size);
2181 todo_wine {
2182 ok(!ret, "expected error\n");
2183 ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_STATE,
2184 "expected ERROR_WINHTTP_INCORRECT_HANDLE_STATE, got 0x%08x\n", GetLastError());
2185 ok(size == 12345 || broken(size == 0) /* Win <= 2003 */,
2186 "expected 12345, got %u\n", size);
2187 }
2188
2189 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2190 ok(ret, "expected success\n");
2191
2192 ret = WinHttpReceiveResponse(req, NULL);
2193 ok(ret, "expected success\n");
2194
2195 size = sizeof(status);
2196 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
2197 NULL, &status, &size, NULL);
2198 ok(ret, "expected success\n");
2199 ok(status == 204, "expected status 204, got %d\n", status);
2200
2201 SetLastError(0xdeadbeef);
2202 size = sizeof(status);
2203 status = 12345;
2204 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
2205 NULL, &status, &size, 0);
2206 ok(!ret, "expected no content-length header\n");
2207 ok(GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND,
2208 "wrong error %u\n", GetLastError() );
2209 ok(status == 12345, "expected 0, got %d\n", status);
2210
2211 size = 12345;
2212 ret = WinHttpQueryDataAvailable(req, &size);
2213 ok(ret, "expected success\n");
2214 ok(size == 0, "expected 0, got %d\n", size);
2215
2216 ret = WinHttpReadData(req, buf, len, &bytes_read);
2217 ok(ret, "expected success\n");
2218 ok( bytes_read == 0, "expected 0, got %u available\n", bytes_read );
2219
2220 size = 12345;
2221 ret = WinHttpQueryDataAvailable(req, &size);
2222 ok(ret, "expected success\n");
2223 ok(size == 0, "expected 0, got %d\n", size);
2224
2225 WinHttpCloseHandle(req);
2226
2227 size = 12345;
2228 SetLastError(0xdeadbeef);
2229 ret = WinHttpQueryDataAvailable(req, &size);
2230 ok(!ret, "expected error\n");
2231 ok(GetLastError() == ERROR_INVALID_HANDLE,
2232 "expected ERROR_INVALID_HANDLE, got 0x%08x\n", GetLastError());
2233 ok(size == 12345, "expected 12345, got %u\n", size);
2234
2235 WinHttpCloseHandle(con);
2236 WinHttpCloseHandle(ses);
2237 }
2238
2239 static void test_head_request(int port)
2240 {
2241 static const WCHAR verbW[] = {'H','E','A','D',0};
2242 static const WCHAR headW[] = {'/','h','e','a','d',0};
2243 HINTERNET ses, con, req;
2244 char buf[128];
2245 DWORD size, len, count, status;
2246 BOOL ret;
2247
2248 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
2249 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2250
2251 con = WinHttpConnect(ses, localhostW, port, 0);
2252 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2253
2254 req = WinHttpOpenRequest(con, verbW, headW, NULL, NULL, NULL, 0);
2255 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2256
2257 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2258 ok(ret, "failed to send request %u\n", GetLastError());
2259
2260 ret = WinHttpReceiveResponse(req, NULL);
2261 ok(ret, "failed to receive response %u\n", GetLastError());
2262
2263 status = 0xdeadbeef;
2264 size = sizeof(status);
2265 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
2266 NULL, &status, &size, NULL);
2267 ok(ret, "failed to get status code %u\n", GetLastError());
2268 ok(status == 200, "got %u\n", status);
2269
2270 len = 0xdeadbeef;
2271 size = sizeof(len);
2272 ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
2273 NULL, &len, &size, 0);
2274 ok(ret, "failed to get content-length header %u\n", GetLastError());
2275 ok(len == 100, "got %u\n", len);
2276
2277 count = 0xdeadbeef;
2278 ret = WinHttpQueryDataAvailable(req, &count);
2279 ok(ret, "failed to query data available %u\n", GetLastError());
2280 ok(!count, "got %u\n", count);
2281
2282 len = sizeof(buf);
2283 count = 0xdeadbeef;
2284 ret = WinHttpReadData(req, buf, len, &count);
2285 ok(ret, "failed to read data %u\n", GetLastError());
2286 ok(!count, "got %u\n", count);
2287
2288 count = 0xdeadbeef;
2289 ret = WinHttpQueryDataAvailable(req, &count);
2290 ok(ret, "failed to query data available %u\n", GetLastError());
2291 ok(!count, "got %u\n", count);
2292
2293 WinHttpCloseHandle(req);
2294 WinHttpCloseHandle(con);
2295 WinHttpCloseHandle(ses);
2296 }
2297
2298 static void test_not_modified(int port)
2299 {
2300 static const WCHAR pathW[] = {'/','n','o','t','_','m','o','d','i','f','i','e','d',0};
2301 static const WCHAR ifmodifiedW[] = {'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',':',' '};
2302 BOOL ret;
2303 HINTERNET session, request, connection;
2304 DWORD status, size, start = GetTickCount();
2305 SYSTEMTIME st;
2306 WCHAR today[(sizeof(ifmodifiedW) + WINHTTP_TIME_FORMAT_BUFSIZE)/sizeof(WCHAR) + 3];
2307
2308 memcpy(today, ifmodifiedW, sizeof(ifmodifiedW));
2309 GetSystemTime(&st);
2310 WinHttpTimeFromSystemTime(&st, &today[sizeof(ifmodifiedW)/sizeof(WCHAR)]);
2311
2312 session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
2313 WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
2314 ok(session != NULL, "WinHttpOpen failed: %u\n", GetLastError());
2315
2316 connection = WinHttpConnect(session, localhostW, port, 0);
2317 ok(connection != NULL, "WinHttpConnect failed: %u\n", GetLastError());
2318
2319 request = WinHttpOpenRequest(connection, NULL, pathW, NULL, WINHTTP_NO_REFERER,
2320 WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
2321 ok(request != NULL, "WinHttpOpenrequest failed: %u\n", GetLastError());
2322
2323 ret = WinHttpSendRequest(request, today, ~0u, NULL, 0, 0, 0);
2324 ok(ret, "WinHttpSendRequest failed: %u\n", GetLastError());
2325
2326 ret = WinHttpReceiveResponse(request, NULL);
2327 ok(ret, "WinHttpReceiveResponse failed: %u\n", GetLastError());
2328
2329 size = sizeof(status);
2330 ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER,
2331 NULL, &status, &size, NULL);
2332 ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
2333 ok(status == HTTP_STATUS_NOT_MODIFIED, "got %u\n", status);
2334
2335 size = 0xdeadbeef;
2336 ret = WinHttpQueryDataAvailable(request, &size);
2337 ok(ret, "WinHttpQueryDataAvailable failed: %u\n", GetLastError());
2338 ok(!size, "got %u\n", size);
2339
2340 WinHttpCloseHandle(request);
2341 WinHttpCloseHandle(connection);
2342 WinHttpCloseHandle(session);
2343 start = GetTickCount() - start;
2344 ok(start <= 2000, "Expected less than 2 seconds for the test, got %u ms\n", start);
2345 }
2346
2347 static void test_bad_header( int port )
2348 {
2349 static const WCHAR bad_headerW[] =
2350 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',
2351 't','e','x','t','/','h','t','m','l','\n','\r',0};
2352 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
2353 static const WCHAR content_typeW[] = {'C','o','n','t','e','n','t','-','T','y','p','e',0};
2354 WCHAR buffer[32];
2355 HINTERNET ses, con, req;
2356 DWORD index, len;
2357 BOOL ret;
2358
2359 ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
2360 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2361
2362 con = WinHttpConnect( ses, localhostW, port, 0 );
2363 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2364
2365 req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
2366 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2367
2368 ret = WinHttpAddRequestHeaders( req, bad_headerW, ~0u, WINHTTP_ADDREQ_FLAG_ADD );
2369 ok( ret, "failed to add header %u\n", GetLastError() );
2370
2371 index = 0;
2372 buffer[0] = 0;
2373 len = sizeof(buffer);
2374 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CUSTOM|WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
2375 content_typeW, buffer, &len, &index );
2376 ok( ret, "failed to query headers %u\n", GetLastError() );
2377 ok( !lstrcmpW( buffer, text_htmlW ), "got %s\n", wine_dbgstr_w(buffer) );
2378
2379 WinHttpCloseHandle( req );
2380 WinHttpCloseHandle( con );
2381 WinHttpCloseHandle( ses );
2382 }
2383
2384 static void test_multiple_reads(int port)
2385 {
2386 static const WCHAR bigW[] = {'b','i','g',0};
2387 HINTERNET ses, con, req;
2388 DWORD total_len = 0;
2389 BOOL ret;
2390
2391 ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
2392 ok(ses != NULL, "failed to open session %u\n", GetLastError());
2393
2394 con = WinHttpConnect(ses, localhostW, port, 0);
2395 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2396
2397 req = WinHttpOpenRequest(con, NULL, bigW, NULL, NULL, NULL, 0);
2398 ok(req != NULL, "failed to open a request %u\n", GetLastError());
2399
2400 ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2401 ok(ret, "failed to send request %u\n", GetLastError());
2402
2403 ret = WinHttpReceiveResponse(req, NULL);
2404 ok(ret == TRUE, "expected success\n");
2405
2406 for (;;)
2407 {
2408 DWORD len = 0xdeadbeef;
2409 ret = WinHttpQueryDataAvailable( req, &len );
2410 ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
2411 if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
2412 if (len)
2413 {
2414 DWORD bytes_read;
2415 char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
2416
2417 ret = WinHttpReadData( req, buf, len, &bytes_read );
2418 ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
2419
2420 HeapFree( GetProcessHeap(), 0, buf );
2421 if (!bytes_read) break;
2422 total_len += bytes_read;
2423 }
2424 if (!len) break;
2425 }
2426 ok(total_len == BIG_BUFFER_LEN, "got wrong length: 0x%x\n", total_len);
2427
2428 WinHttpCloseHandle(req);
2429 WinHttpCloseHandle(con);
2430 WinHttpCloseHandle(ses);
2431 }
2432
2433 static void test_connection_info( int port )
2434 {
2435 static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
2436 HINTERNET ses, con, req;
2437 WINHTTP_CONNECTION_INFO info;
2438 DWORD size, error;
2439 BOOL ret;
2440
2441 ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
2442 ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2443
2444 con = WinHttpConnect( ses, localhostW, port, 0 );
2445 ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2446
2447 req = WinHttpOpenRequest( con, NULL, basicW, NULL, NULL, NULL, 0 );
2448 ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2449
2450 size = sizeof(info);
2451 SetLastError( 0xdeadbeef );
2452 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2453 error = GetLastError();
2454 if (!ret && error == ERROR_INVALID_PARAMETER)
2455 {
2456 win_skip( "WINHTTP_OPTION_CONNECTION_INFO not supported\n" );
2457 return;
2458 }
2459 ok( !ret, "unexpected success\n" );
2460 ok( error == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "got %u\n", error );
2461
2462 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
2463 ok( ret, "failed to send request %u\n", GetLastError() );
2464
2465 size = 0;
2466 SetLastError( 0xdeadbeef );
2467 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2468 error = GetLastError();
2469 ok( !ret, "unexpected success\n" );
2470 ok( error == ERROR_INSUFFICIENT_BUFFER, "got %u\n", error );
2471
2472 size = sizeof(info);
2473 memset( &info, 0, sizeof(info) );
2474 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2475 ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
2476 ok( info.cbSize == sizeof(info), "wrong size %u\n", info.cbSize );
2477
2478 ret = WinHttpReceiveResponse( req, NULL );
2479 ok( ret, "failed to receive response %u\n", GetLastError() );
2480
2481 size = sizeof(info);
2482 memset( &info, 0, sizeof(info) );
2483 ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
2484 ok( ret,