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