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