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