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