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