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