1 /*
2  * WinHTTP - tests
3  *
4  * Copyright 2008 Google (Zac Brown)
5  * Copyright 2015 Dmitry Timoshkov
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #define COBJMACROS
23 #include <stdarg.h>
24 #include <windef.h>
25 #include <winsock2.h>
26 #include <ws2tcpip.h>
27 #include <winhttp.h>
28 #include <wincrypt.h>
29 #include <winreg.h>
30 #include <stdio.h>
31 #include <initguid.h>
32 #include <httprequest.h>
33 #include <httprequestid.h>
34 
35 #include "wine/test.h"
36 
37 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
38 
39 static const WCHAR test_useragent[] =
40     {'W','i','n','e',' ','R','e','g','r','e','s','s','i','o','n',' ','T','e','s','t',0};
41 static const WCHAR test_winehq[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
42 static const WCHAR test_winehq_https[] = {'h','t','t','p','s',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','4','4','3',0};
43 static const WCHAR localhostW[] = {'l','o','c','a','l','h','o','s','t',0};
44 
45 static BOOL proxy_active(void)
46 {
47     WINHTTP_PROXY_INFO proxy_info;
48     BOOL active = FALSE;
49 
50     SetLastError(0xdeadbeef);
51     if (WinHttpGetDefaultProxyConfiguration(&proxy_info))
52     {
53         ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
54            "got %u\n", GetLastError());
55         active = (proxy_info.lpszProxy != NULL);
56         if (active)
57             GlobalFree(proxy_info.lpszProxy);
58         if (proxy_info.lpszProxyBypass != NULL)
59             GlobalFree(proxy_info.lpszProxyBypass);
60     }
61     else
62        active = FALSE;
63 
64     return active;
65 }
66 
67 static void test_QueryOption(void)
68 {
69     BOOL ret;
70     HINTERNET session, request, connection;
71     DWORD feature, size;
72 
73     SetLastError(0xdeadbeef);
74     session = WinHttpOpen(test_useragent, 0, 0, 0, 0);
75     ok(session != NULL, "WinHttpOpen failed to open session, error %u\n", GetLastError());
76 
77     SetLastError(0xdeadbeef);
78     ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, NULL);
79     ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
80     ok(GetLastError() == ERROR_INVALID_PARAMETER,
81        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
82 
83     size = 0xdeadbeef;
84     SetLastError(0xdeadbeef);
85     ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, &size);
86     ok(!ret, "should fail to query option\n");
87     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
88        "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
89     ok(size == 4, "expected 4, got %u\n", size);
90 
91     feature = 0xdeadbeef;
92     size = sizeof(feature) - 1;
93     SetLastError(0xdeadbeef);
94     ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
95     ok(!ret, "should fail to query option\n");
96     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
97        "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
98     ok(size == 4, "expected 4, got %u\n", size);
99 
100     feature = 0xdeadbeef;
101     size = sizeof(feature) + 1;
102     SetLastError(0xdeadbeef);
103     ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
104     ok(ret, "failed to query option %u\n", GetLastError());
105     ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
106        "got %u\n", GetLastError());
107     ok(size == sizeof(feature), "WinHttpQueryOption should set the size: %u\n", size);
108     ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP,
109        "expected WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP, got %#x\n", feature);
110 
111     SetLastError(0xdeadbeef);
112     ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, NULL, sizeof(feature));
113     ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
114     ok(GetLastError() == ERROR_INVALID_PARAMETER,
115        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
116 
117     feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
118     SetLastError(0xdeadbeef);
119     ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) - 1);
120     ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
121     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
122        "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
123 
124     feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
125     SetLastError(0xdeadbeef);
126     ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature) + 1);
127     ok(!ret, "should fail to set redirect policy %u\n", GetLastError());
128     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
129        "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
130 
131     feature = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
132     SetLastError(0xdeadbeef);
133     ret = WinHttpSetOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, sizeof(feature));
134     ok(ret, "failed to set redirect policy %u\n", GetLastError());
135 
136     feature = 0xdeadbeef;
137     size = sizeof(feature);
138     SetLastError(0xdeadbeef);
139     ret = WinHttpQueryOption(session, WINHTTP_OPTION_REDIRECT_POLICY, &feature, &size);
140     ok(ret, "failed to query option %u\n", GetLastError());
141     ok(feature == WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS,
142        "expected WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS, got %#x\n", feature);
143 
144     feature = WINHTTP_DISABLE_COOKIES;
145     SetLastError(0xdeadbeef);
146     ret = WinHttpSetOption(session, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
147     ok(!ret, "should fail to set disable feature for a session\n");
148     ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
149        "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
150 
151     SetLastError(0xdeadbeef);
152     connection = WinHttpConnect(session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
153     ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u\n", GetLastError());
154 
155     feature = WINHTTP_DISABLE_COOKIES;
156     SetLastError(0xdeadbeef);
157     ret = WinHttpSetOption(connection, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
158     ok(!ret, "should fail to set disable feature for a connection\n");
159     ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
160        "expected ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, got %u\n", GetLastError());
161 
162     SetLastError(0xdeadbeef);
163     request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
164                                  WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
165     if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
166     {
167         skip("Network unreachable, skipping the test\n");
168         goto done;
169     }
170 
171     feature = 0xdeadbeef;
172     size = sizeof(feature);
173     SetLastError(0xdeadbeef);
174     ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, &size);
175     ok(!ret, "should fail to query disable feature for a request\n");
176     ok(GetLastError() == ERROR_INVALID_PARAMETER,
177        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
178 
179     feature = 0;
180     size = sizeof(feature);
181     SetLastError(0xdeadbeef);
182     ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
183     ok(ret, "failed to set feature %u\n", GetLastError());
184 
185     feature = 0xffffffff;
186     size = sizeof(feature);
187     SetLastError(0xdeadbeef);
188     ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
189     ok(ret, "failed to set feature %u\n", GetLastError());
190 
191     feature = WINHTTP_DISABLE_COOKIES;
192     size = sizeof(feature);
193     SetLastError(0xdeadbeef);
194     ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &feature, sizeof(feature));
195     ok(ret, "failed to set feature %u\n", GetLastError());
196 
197     size = 0;
198     SetLastError(0xdeadbeef);
199     ret = WinHttpQueryOption(request, WINHTTP_OPTION_DISABLE_FEATURE, NULL, &size);
200     ok(!ret, "should fail to query disable feature for a request\n");
201     ok(GetLastError() == ERROR_INVALID_PARAMETER,
202        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
203 
204     SetLastError(0xdeadbeef);
205     ret = WinHttpCloseHandle(request);
206     ok(ret, "WinHttpCloseHandle failed on closing request: %u\n", GetLastError());
207 
208 done:
209     SetLastError(0xdeadbeef);
210     ret = WinHttpCloseHandle(connection);
211     ok(ret, "WinHttpCloseHandle failed on closing connection: %u\n", GetLastError());
212     SetLastError(0xdeadbeef);
213     ret = WinHttpCloseHandle(session);
214     ok(ret, "WinHttpCloseHandle failed on closing session: %u\n", GetLastError());
215 }
216 
217 static void test_OpenRequest (void)
218 {
219     BOOL ret;
220     HINTERNET session, request, connection;
221     DWORD err;
222 
223     SetLastError(0xdeadbeef);
224     session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
225         WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
226     err = GetLastError();
227     ok(session != NULL, "WinHttpOpen failed to open session.\n");
228     ok(err == ERROR_SUCCESS, "got %u\n", err);
229 
230     /* Test with a bad server name */
231     SetLastError(0xdeadbeef);
232     connection = WinHttpConnect(session, NULL, INTERNET_DEFAULT_HTTP_PORT, 0);
233     err = GetLastError();
234     ok (connection == NULL, "WinHttpConnect succeeded in opening connection to NULL server argument.\n");
235     ok(err == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u.\n", err);
236 
237     /* Test with a valid server name */
238     SetLastError(0xdeadbeef);
239     connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
240     err = GetLastError();
241     ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", err);
242     ok(err == ERROR_SUCCESS || broken(err == WSAEINVAL) /* < win7 */, "got %u\n", err);
243 
244     SetLastError(0xdeadbeef);
245     request = WinHttpOpenRequest(connection, NULL, NULL, NULL, WINHTTP_NO_REFERER,
246         WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
247     err = GetLastError();
248     if (request == NULL && err == ERROR_WINHTTP_NAME_NOT_RESOLVED)
249     {
250         skip("Network unreachable, skipping.\n");
251         goto done;
252     }
253     ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", err);
254     ok(err == ERROR_SUCCESS, "got %u\n", err);
255 
256     SetLastError(0xdeadbeef);
257     ret = WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0);
258     err = GetLastError();
259     if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
260     {
261         skip("Connection failed, skipping.\n");
262         goto done;
263     }
264     ok(ret, "WinHttpSendRequest failed: %u\n", err);
265     ok(err == ERROR_SUCCESS, "got %u\n", err);
266 
267     SetLastError(0xdeadbeef);
268     ret = WinHttpCloseHandle(request);
269     err = GetLastError();
270     ok(ret, "WinHttpCloseHandle failed on closing request, got %u.\n", err);
271     ok(err == ERROR_SUCCESS, "got %u\n", err);
272 
273  done:
274     ret = WinHttpCloseHandle(connection);
275     ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
276     ret = WinHttpCloseHandle(session);
277     ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
278 
279 }
280 
281 static void test_empty_headers_param(void)
282 {
283     static const WCHAR empty[]  = {0};
284     HINTERNET ses, con, req;
285     DWORD err;
286     BOOL ret;
287 
288     ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
289     ok(ses != NULL, "failed to open session %u\n", GetLastError());
290 
291     con = WinHttpConnect(ses, test_winehq, 80, 0);
292     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
293 
294     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
295     ok(req != NULL, "failed to open a request %u\n", GetLastError());
296 
297     ret = WinHttpSendRequest(req, empty, 0, NULL, 0, 0, 0);
298     err = GetLastError();
299     if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
300     {
301         skip("connection failed, skipping\n");
302         goto done;
303     }
304     ok(ret, "failed to send request %u\n", GetLastError());
305 
306  done:
307     WinHttpCloseHandle(req);
308     WinHttpCloseHandle(con);
309     WinHttpCloseHandle(ses);
310 }
311 
312 static void test_SendRequest (void)
313 {
314     static const WCHAR content_type[] =
315         {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t','i','o','n',
316          '/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o','d','e','d',0};
317     static const WCHAR test_file[] = {'t','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
318     static const WCHAR test_verb[] = {'P','O','S','T',0};
319     static CHAR post_data[] = "mode=Test";
320     static const char test_post[] = "mode => Test\0\n";
321     HINTERNET session, request, connection;
322     DWORD header_len, optional_len, total_len, bytes_rw, size, err, disable;
323     DWORD_PTR context;
324     BOOL ret;
325     CHAR buffer[256];
326     int i;
327 
328     header_len = -1L;
329     total_len = optional_len = sizeof(post_data);
330     memset(buffer, 0xff, sizeof(buffer));
331 
332     session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
333         WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
334     ok(session != NULL, "WinHttpOpen failed to open session.\n");
335 
336     connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
337     ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
338 
339     request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
340         WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
341     if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
342     {
343         skip("Network unreachable, skipping.\n");
344         goto done;
345     }
346     ok(request != NULL, "WinHttpOpenrequest failed to open a request, error: %u.\n", GetLastError());
347     if (!request) goto done;
348 
349     context = 0xdeadbeef;
350     ret = WinHttpSetOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(context));
351     ok(ret, "WinHttpSetOption failed: %u\n", GetLastError());
352 
353     /* writing more data than promised by the content-length header causes an error when the connection
354        is resued, so disable keep-alive */
355     disable = WINHTTP_DISABLE_KEEP_ALIVE;
356     ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &disable, sizeof(disable));
357     ok(ret, "WinHttpSetOption failed: %u\n", GetLastError());
358 
359     context++;
360     ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, context);
361     err = GetLastError();
362     if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
363     {
364         skip("connection failed, skipping\n");
365         goto done;
366     }
367     ok(ret == TRUE, "WinHttpSendRequest failed: %u\n", GetLastError());
368 
369     context = 0;
370     size = sizeof(context);
371     ret = WinHttpQueryOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, &size);
372     ok(ret, "WinHttpQueryOption failed: %u\n", GetLastError());
373     ok(context == 0xdeadbef0, "expected 0xdeadbef0, got %lx\n", context);
374 
375     for (i = 3; post_data[i]; i++)
376     {
377         bytes_rw = -1;
378         SetLastError(0xdeadbeef);
379         ret = WinHttpWriteData(request, &post_data[i], 1, &bytes_rw);
380         if (ret)
381         {
382           ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %u.\n", GetLastError());
383           ok(bytes_rw == 1, "WinHttpWriteData failed, wrote %u bytes instead of 1 byte.\n", bytes_rw);
384         }
385         else /* Since we already passed all optional data in WinHttpSendRequest Win7 fails our WinHttpWriteData call */
386         {
387           ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER got %u.\n", GetLastError());
388           ok(bytes_rw == -1, "Expected bytes_rw to remain unchanged.\n");
389         }
390     }
391 
392     SetLastError(0xdeadbeef);
393     ret = WinHttpReceiveResponse(request, NULL);
394     ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == ERROR_NO_TOKEN) /* < win7 */,
395        "Expected ERROR_SUCCESS got %u.\n", GetLastError());
396     ok(ret == TRUE, "WinHttpReceiveResponse failed: %u.\n", GetLastError());
397 
398     bytes_rw = -1;
399     ret = WinHttpReadData(request, buffer, sizeof(buffer) - 1, &bytes_rw);
400     ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
401 
402     ok(bytes_rw == sizeof(test_post) - 1, "Read %u bytes\n", bytes_rw);
403     ok(!memcmp(buffer, test_post, sizeof(test_post) - 1), "Data read did not match.\n");
404 
405  done:
406     ret = WinHttpCloseHandle(request);
407     ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
408     ret = WinHttpCloseHandle(connection);
409     ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
410     ret = WinHttpCloseHandle(session);
411     ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
412 }
413 
414 static void test_WinHttpTimeFromSystemTime(void)
415 {
416     BOOL ret;
417     static const SYSTEMTIME time = {2008, 7, 1, 28, 10, 5, 52, 0};
418     static const WCHAR expected_string[] =
419         {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
420          '1','0',':','0','5',':','5','2',' ','G','M','T',0};
421     WCHAR time_string[WINHTTP_TIME_FORMAT_BUFSIZE+1];
422     DWORD err;
423 
424     SetLastError(0xdeadbeef);
425     ret = WinHttpTimeFromSystemTime(&time, NULL);
426     err = GetLastError();
427     ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
428     ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
429 
430     SetLastError(0xdeadbeef);
431     ret = WinHttpTimeFromSystemTime(NULL, time_string);
432     err = GetLastError();
433     ok(!ret, "WinHttpTimeFromSystemTime succeeded\n");
434     ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
435 
436     SetLastError(0xdeadbeef);
437     ret = WinHttpTimeFromSystemTime(&time, time_string);
438     err = GetLastError();
439     ok(ret, "WinHttpTimeFromSystemTime failed: %u\n", err);
440     ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
441     ok(memcmp(time_string, expected_string, sizeof(expected_string)) == 0,
442         "Time string returned did not match expected time string.\n");
443 }
444 
445 static void test_WinHttpTimeToSystemTime(void)
446 {
447     BOOL ret;
448     SYSTEMTIME time;
449     static const SYSTEMTIME expected_time = {2008, 7, 1, 28, 10, 5, 52, 0};
450     static const WCHAR time_string1[] =
451         {'M','o','n',',',' ','2','8',' ','J','u','l',' ','2','0','0','8',' ',
452          +          '1','0',':','0','5',':','5','2',' ','G','M','T','\n',0};
453     static const WCHAR time_string2[] =
454         {' ','m','o','n',' ','2','8',' ','j','u','l',' ','2','0','0','8',' ',
455          '1','0',' ','0','5',' ','5','2','\n',0};
456     DWORD err;
457 
458     SetLastError(0xdeadbeef);
459     ret = WinHttpTimeToSystemTime(time_string1, NULL);
460     err = GetLastError();
461     ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
462     ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
463 
464     SetLastError(0xdeadbeef);
465     ret = WinHttpTimeToSystemTime(NULL, &time);
466     err = GetLastError();
467     ok(!ret, "WinHttpTimeToSystemTime succeeded\n");
468     ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
469 
470     SetLastError(0xdeadbeef);
471     ret = WinHttpTimeToSystemTime(time_string1, &time);
472     err = GetLastError();
473     ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
474     ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
475     ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
476         "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
477 
478     SetLastError(0xdeadbeef);
479     ret = WinHttpTimeToSystemTime(time_string2, &time);
480     err = GetLastError();
481     ok(ret, "WinHttpTimeToSystemTime failed: %u\n", err);
482     ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
483     ok(memcmp(&time, &expected_time, sizeof(SYSTEMTIME)) == 0,
484         "Returned SYSTEMTIME structure did not match expected SYSTEMTIME structure.\n");
485 }
486 
487 static void test_WinHttpAddHeaders(void)
488 {
489     HINTERNET session, request, connection;
490     BOOL ret, reverse;
491     WCHAR buffer[MAX_PATH];
492     WCHAR check_buffer[MAX_PATH];
493     DWORD err, index, len, oldlen;
494 
495     static const WCHAR test_file[] = {'/','p','o','s','t','t','e','s','t','.','p','h','p',0};
496     static const WCHAR test_verb[] = {'P','O','S','T',0};
497     static const WCHAR test_header_begin[] =
498         {'P','O','S','T',' ','/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
499     static const WCHAR full_path_test_header_begin[] =
500         {'P','O','S','T',' ','h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','8','0',
501          '/','p','o','s','t','t','e','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
502     static const WCHAR test_header_end[] = {'\r','\n','\r','\n',0};
503     static const WCHAR test_header_name[] = {'W','a','r','n','i','n','g',0};
504     static const WCHAR test_header_name2[] = {'n','a','m','e',0};
505     static const WCHAR test_header_name3[] = {'a',0};
506     static const WCHAR test_header_range[] = {'R','a','n','g','e',0};
507     static const WCHAR test_header_range_bytes[] = {'R','a','n','g','e',':',' ','b','y','t','e','s','=','0','-','7','7','3','\r','\n',0};
508     static const WCHAR test_header_bytes[] = {'b','y','t','e','s','=','0','-','7','7','3',0};
509 
510     static const WCHAR test_flag_coalesce[] = {'t','e','s','t','2',',',' ','t','e','s','t','4',0};
511     static const WCHAR test_flag_coalesce_reverse[] = {'t','e','s','t','3',',',' ','t','e','s','t','4',0};
512     static const WCHAR test_flag_coalesce_comma[] =
513         {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
514     static const WCHAR test_flag_coalesce_comma_reverse[] =
515         {'t','e','s','t','3',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',0};
516     static const WCHAR test_flag_coalesce_semicolon[] =
517         {'t','e','s','t','2',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
518     static const WCHAR test_flag_coalesce_semicolon_reverse[] =
519         {'t','e','s','t','3',',',' ','t','e','s','t','4',',',' ','t','e','s','t','5',';',' ','t','e','s','t','6',0};
520 
521     static const WCHAR field[] = {'f','i','e','l','d',0};
522     static const WCHAR value[] = {'v','a','l','u','e',' ',0};
523     static const WCHAR value_nospace[] = {'v','a','l','u','e',0};
524     static const WCHAR empty[] = {0};
525 
526     static const WCHAR test_headers[][14] =
527         {
528             {'W','a','r','n','i','n','g',':','t','e','s','t','1',0},
529             {'W','a','r','n','i','n','g',':','t','e','s','t','2',0},
530             {'W','a','r','n','i','n','g',':','t','e','s','t','3',0},
531             {'W','a','r','n','i','n','g',':','t','e','s','t','4',0},
532             {'W','a','r','n','i','n','g',':','t','e','s','t','5',0},
533             {'W','a','r','n','i','n','g',':','t','e','s','t','6',0},
534             {'W','a','r','n','i','n','g',':','t','e','s','t','7',0},
535             {0},
536             {':',0},
537             {'a',':',0},
538             {':','b',0},
539             {'c','d',0},
540             {' ','e',' ',':','f',0},
541             {'f','i','e','l','d',':',' ','v','a','l','u','e',' ',0},
542             {'n','a','m','e',':',' ','v','a','l','u','e',0},
543             {'n','a','m','e',':',0}
544         };
545     static const WCHAR test_indices[][6] =
546         {
547             {'t','e','s','t','1',0},
548             {'t','e','s','t','2',0},
549             {'t','e','s','t','3',0},
550             {'t','e','s','t','4',0}
551         };
552 
553     session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
554         WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
555     ok(session != NULL, "WinHttpOpen failed to open session.\n");
556 
557     connection = WinHttpConnect (session, test_winehq, INTERNET_DEFAULT_HTTP_PORT, 0);
558     ok(connection != NULL, "WinHttpConnect failed to open a connection, error: %u.\n", GetLastError());
559 
560     request = WinHttpOpenRequest(connection, test_verb, test_file, NULL, WINHTTP_NO_REFERER,
561         WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
562     if (request == NULL && GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED)
563     {
564         skip("Network unreachable, skipping.\n");
565         goto done;
566     }
567     ok(request != NULL, "WinHttpOpenRequest failed to open a request, error: %u.\n", GetLastError());
568 
569     index = 0;
570     len = sizeof(buffer);
571     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
572         test_header_name, buffer, &len, &index);
573     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, found 'Warning' header.\n");
574     SetLastError(0xdeadbeef);
575     ret = WinHttpAddRequestHeaders(request, test_headers[0], -1L, WINHTTP_ADDREQ_FLAG_ADD);
576     err = GetLastError();
577     ok(ret, "WinHttpAddRequestHeaders failed to add new header, got %d with error %u.\n", ret, err);
578     ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
579 
580     index = 0;
581     len = sizeof(buffer);
582     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
583         test_header_name, buffer, &len, &index);
584     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
585     ok(index == 1, "WinHttpQueryHeaders failed: header index not incremented\n");
586     ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders failed: incorrect string returned\n");
587     ok(len == 5*sizeof(WCHAR), "WinHttpQueryHeaders failed: invalid length returned, expected 5, got %d\n", len);
588 
589     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
590         test_header_name, buffer, &len, &index);
591     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded, second index should not exist.\n");
592 
593     /* Try to fetch the header info with a buffer that's big enough to fit the
594      * string but not the NULL terminator.
595      */
596     index = 0;
597     len = 5*sizeof(WCHAR);
598     memset(check_buffer, 0xab, sizeof(check_buffer));
599     memcpy(buffer, check_buffer, sizeof(buffer));
600     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
601         test_header_name, buffer, &len, &index);
602     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded with a buffer that's too small.\n");
603     ok(memcmp(buffer, check_buffer, sizeof(buffer)) == 0,
604             "WinHttpQueryHeaders failed, modified the buffer when it should not have.\n");
605     ok(len == 6*sizeof(WCHAR), "WinHttpQueryHeaders returned invalid length, expected 12, got %d\n", len);
606 
607     /* Try with a NULL buffer */
608     index = 0;
609     len = sizeof(buffer);
610     SetLastError(0xdeadbeef);
611     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
612         test_header_name, NULL, &len, &index);
613     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
614     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
615     ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
616     ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
617 
618     /* Try with a NULL buffer and a length that's too small */
619     index = 0;
620     len = 10;
621     SetLastError(0xdeadbeef);
622     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
623         test_header_name, NULL, &len, &index);
624     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
625     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
626         "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICENT_BUFFER, got %u\n", GetLastError());
627     ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
628     ok(index == 0, "WinHttpQueryHeaders incorrectly incremented header index.\n");
629 
630     index = 0;
631     len = 0;
632     SetLastError(0xdeadbeef);
633     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
634         test_header_name, NULL, &len, &index);
635     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
636     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
637         "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
638     ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
639     ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
640 
641     /* valid query */
642     oldlen = len;
643     index = 0;
644     len = sizeof(buffer);
645     memset(buffer, 0xff, sizeof(buffer));
646     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS_CRLF | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
647         test_header_name, buffer, &len, &index);
648     ok(ret == TRUE, "WinHttpQueryHeaders failed: got %d\n", ret);
649     ok(len + sizeof(WCHAR) <= oldlen, "WinHttpQueryHeaders resulting length longer than advertized.\n");
650     ok((len < sizeof(buffer) - sizeof(WCHAR)) && buffer[len / sizeof(WCHAR)] == 0, "WinHttpQueryHeaders did not append NULL terminator\n");
651     ok(len == lstrlenW(buffer) * sizeof(WCHAR), "WinHttpQueryHeaders returned incorrect length.\n");
652     ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
653         memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
654         "WinHttpQueryHeaders returned invalid beginning of header string.\n");
655     ok(memcmp(buffer + lstrlenW(buffer) - 4, test_header_end, sizeof(test_header_end)) == 0,
656         "WinHttpQueryHeaders returned invalid end of header string.\n");
657     ok(index == 0, "WinHttpQueryHeaders incremented header index.\n");
658 
659     index = 0;
660     len = 0;
661     SetLastError(0xdeadbeef);
662     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
663         test_header_name, NULL, &len, &index);
664     ok(ret == FALSE, "WinHttpQueryHeaders unexpectedly succeeded.\n");
665     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
666         "WinHttpQueryHeaders set incorrect error: expected ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
667     ok(len > 40, "WinHttpQueryHeaders returned invalid length: expected greater than 40, got %d\n", len);
668     ok(index == 0, "WinHttpQueryHeaders failed: index was incremented.\n");
669 
670     oldlen = len;
671     index = 0;
672     len = sizeof(buffer);
673     memset(buffer, 0xff, sizeof(buffer));
674     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_RAW_HEADERS | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
675         test_header_name, buffer, &len, &index);
676     ok(ret == TRUE, "WinHttpQueryHeaders failed %u\n", GetLastError());
677     ok(len + sizeof(WCHAR) <= oldlen, "resulting length longer than advertized\n");
678     ok((len < sizeof(buffer) - sizeof(WCHAR)) && !buffer[len / sizeof(WCHAR)] && !buffer[len / sizeof(WCHAR) - 1],
679         "no double NULL terminator\n");
680     ok(memcmp(buffer, test_header_begin, sizeof(test_header_begin)) == 0 ||
681         memcmp(buffer, full_path_test_header_begin, sizeof(full_path_test_header_begin)) == 0,
682         "invalid beginning of header string.\n");
683     ok(index == 0, "header index was incremented\n");
684 
685     /* tests for more indices */
686     ret = WinHttpAddRequestHeaders(request, test_headers[1], -1L, WINHTTP_ADDREQ_FLAG_ADD);
687     ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header: %d\n", ret);
688 
689     index = 0;
690     len = sizeof(buffer);
691     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
692         test_header_name, buffer, &len, &index);
693     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
694     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
695     ok(memcmp(buffer, test_indices[0], sizeof(test_indices[0])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
696 
697     len = sizeof(buffer);
698     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
699         test_header_name, buffer, &len, &index);
700     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
701     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
702     ok(memcmp(buffer, test_indices[1], sizeof(test_indices[1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
703 
704     ret = WinHttpAddRequestHeaders(request, test_headers[2], -1L, WINHTTP_ADDREQ_FLAG_REPLACE);
705     ok(ret == TRUE, "WinHttpAddRequestHeaders failed to add duplicate header.\n");
706 
707     index = 0;
708     len = sizeof(buffer);
709     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
710         test_header_name, buffer, &len, &index);
711     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
712     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
713     reverse = (memcmp(buffer, test_indices[1], sizeof(test_indices[1])) != 0); /* Win7 returns values in reverse order of adding */
714     ok(memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
715 
716     len = sizeof(buffer);
717     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
718         test_header_name, buffer, &len, &index);
719     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
720     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
721     ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
722 
723     /* add if new flag */
724     ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW);
725     ok(ret == FALSE, "WinHttpAddRequestHeaders incorrectly replaced existing header.\n");
726 
727     index = 0;
728     len = sizeof(buffer);
729     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
730         test_header_name, buffer, &len, &index);
731     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
732     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
733     ok(memcmp(buffer, test_indices[reverse ? 2 : 1], sizeof(test_indices[reverse ? 2 : 1])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
734 
735     len = sizeof(buffer);
736     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
737         test_header_name, buffer, &len, &index);
738     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
739     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
740     ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
741 
742     len = sizeof(buffer);
743     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
744         test_header_name, buffer, &len, &index);
745     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
746 
747     /* coalesce flag */
748     ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_COALESCE);
749     ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE.\n");
750 
751     index = 0;
752     len = sizeof(buffer);
753     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
754         test_header_name, buffer, &len, &index);
755     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
756     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
757     ok(memcmp(buffer, reverse ? test_flag_coalesce_reverse : test_flag_coalesce,
758                       reverse ? sizeof(test_flag_coalesce_reverse) : sizeof(test_flag_coalesce)) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
759 
760     len = sizeof(buffer);
761     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
762         test_header_name, buffer, &len, &index);
763     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
764     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
765     ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
766 
767     len = sizeof(buffer);
768     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
769         test_header_name, buffer, &len, &index);
770     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
771 
772     /* coalesce with comma flag */
773     ret = WinHttpAddRequestHeaders(request, test_headers[4], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA);
774     ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA.\n");
775 
776     index = 0;
777     len = sizeof(buffer);
778     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
779         test_header_name, buffer, &len, &index);
780     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
781     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
782     ok(memcmp(buffer, reverse ? test_flag_coalesce_comma_reverse : test_flag_coalesce_comma,
783                       reverse ? sizeof(test_flag_coalesce_comma_reverse) : sizeof(test_flag_coalesce_comma)) == 0,
784         "WinHttpQueryHeaders returned incorrect string.\n");
785 
786     len = sizeof(buffer);
787     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
788         test_header_name, buffer, &len, &index);
789     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
790     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
791     ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
792 
793     len = sizeof(buffer);
794     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
795         test_header_name, buffer, &len, &index);
796     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
797 
798 
799     /* coalesce with semicolon flag */
800     ret = WinHttpAddRequestHeaders(request, test_headers[5], -1L, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON);
801     ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON.\n");
802 
803     index = 0;
804     len = sizeof(buffer);
805     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
806         test_header_name, buffer, &len, &index);
807     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
808     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
809     ok(memcmp(buffer, reverse ? test_flag_coalesce_semicolon_reverse : test_flag_coalesce_semicolon,
810                       reverse ? sizeof(test_flag_coalesce_semicolon_reverse) : sizeof(test_flag_coalesce_semicolon)) == 0,
811             "WinHttpQueryHeaders returned incorrect string.\n");
812 
813     len = sizeof(buffer);
814     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
815         test_header_name, buffer, &len, &index);
816     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
817     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
818     ok(memcmp(buffer, test_indices[reverse ? 1 : 2], sizeof(test_indices[reverse ? 1 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
819 
820     len = sizeof(buffer);
821     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
822         test_header_name, buffer, &len, &index);
823     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
824 
825     /* add and replace flags */
826     ret = WinHttpAddRequestHeaders(request, test_headers[3], -1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
827     ok(ret == TRUE, "WinHttpAddRequestHeaders failed with flag WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE.\n");
828 
829     index = 0;
830     len = sizeof(buffer);
831     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
832         test_header_name, buffer, &len, &index);
833     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
834     ok(index == 1, "WinHttpQueryHeaders failed to increment index.\n");
835     ok(memcmp(buffer, test_indices[reverse ? 3 : 2], sizeof(test_indices[reverse ? 3 : 2])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
836 
837     len = sizeof(buffer);
838     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
839         test_header_name, buffer, &len, &index);
840     ok(ret == TRUE, "WinHttpQueryHeaders failed: %u\n", GetLastError());
841     ok(index == 2, "WinHttpQueryHeaders failed to increment index.\n");
842     ok(memcmp(buffer, test_indices[reverse ? 1 : 3], sizeof(test_indices[reverse ? 1 : 3])) == 0, "WinHttpQueryHeaders returned incorrect string.\n");
843 
844     len = sizeof(buffer);
845     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
846         test_header_name, buffer, &len, &index);
847     ok(ret == FALSE, "WinHttpQueryHeaders succeeded unexpectedly, found third header.\n");
848 
849     ret = WinHttpAddRequestHeaders(request, test_headers[8], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
850     ok(!ret, "WinHttpAddRequestHeaders failed\n");
851 
852     ret = WinHttpAddRequestHeaders(request, test_headers[9], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
853     ok(ret, "WinHttpAddRequestHeaders failed\n");
854 
855     index = 0;
856     memset(buffer, 0xff, sizeof(buffer));
857     len = sizeof(buffer);
858     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
859                               test_header_name3, buffer, &len, &index);
860     ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
861     ok(!memcmp(buffer, empty, sizeof(empty)), "unexpected result\n");
862 
863     ret = WinHttpAddRequestHeaders(request, test_headers[10], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
864     ok(!ret, "WinHttpAddRequestHeaders failed\n");
865 
866     ret = WinHttpAddRequestHeaders(request, test_headers[11], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
867     ok(!ret, "WinHttpAddRequestHeaders failed\n");
868 
869     ret = WinHttpAddRequestHeaders(request, test_headers[12], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
870     ok(!ret, "WinHttpAddRequestHeaders failed\n");
871 
872     ret = WinHttpAddRequestHeaders(request, test_headers[13], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
873     ok(ret, "WinHttpAddRequestHeaders failed\n");
874 
875     index = 0;
876     buffer[0] = 0;
877     len = sizeof(buffer);
878     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
879         field, buffer, &len, &index);
880     ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
881     ok(!memcmp(buffer, value, sizeof(value)) || ! memcmp(buffer, value_nospace, sizeof(value_nospace)), "unexpected result\n");
882 
883     SetLastError(0xdeadbeef);
884     ret = WinHttpAddRequestHeaders(request, test_header_range_bytes, 0,
885                                    WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
886     err = GetLastError();
887     ok(!ret, "unexpected success\n");
888     ok(err == ERROR_INVALID_PARAMETER, "got %u\n", err);
889 
890     ret = WinHttpAddRequestHeaders(request, test_header_range_bytes, ~0u,
891                                    WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE);
892     ok(ret, "failed to add header: %u\n", GetLastError());
893 
894     index = 0;
895     len = sizeof(buffer);
896     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
897                               test_header_range, buffer, &len, &index);
898     ok(ret, "failed to get range header %u\n", GetLastError());
899     ok(!memcmp(buffer, test_header_bytes, sizeof(test_header_bytes)), "incorrect string returned\n");
900     ok(len == lstrlenW(test_header_bytes) * sizeof(WCHAR), "wrong length %u\n", len);
901     ok(index == 1, "wrong index %u\n", index);
902 
903     index = 0;
904     len = sizeof(buffer);
905     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
906                               test_header_name2, buffer, &len, &index);
907     ok(!ret, "unexpected success\n");
908 
909     SetLastError(0xdeadbeef);
910     ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
911     err = GetLastError();
912     ok(!ret, "unexpected success\n");
913     ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
914 
915     ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
916     ok(ret, "got %u\n", GetLastError());
917 
918     index = 0;
919     len = sizeof(buffer);
920     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
921                               test_header_name2, buffer, &len, &index);
922     ok(ret, "got %u\n", GetLastError());
923     ok(index == 1, "wrong index %u\n", index);
924     ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
925 
926     ret = WinHttpAddRequestHeaders(request, test_headers[15], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
927     ok(ret, "got %u\n", GetLastError());
928 
929     index = 0;
930     len = sizeof(buffer);
931     SetLastError(0xdeadbeef);
932     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
933                               test_header_name2, buffer, &len, &index);
934     err = GetLastError();
935     ok(!ret, "unexpected success\n");
936     ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
937 
938     ret = WinHttpAddRequestHeaders(request, test_headers[14], -1L, 0);
939     ok(ret, "got %u\n", GetLastError());
940 
941     index = 0;
942     len = sizeof(buffer);
943     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
944                               test_header_name2, buffer, &len, &index);
945     ok(ret, "got %u\n", GetLastError());
946     ok(index == 1, "wrong index %u\n", index);
947     ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
948 
949     ret = WinHttpCloseHandle(request);
950     ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
951  done:
952     ret = WinHttpCloseHandle(connection);
953     ok(ret == TRUE, "WinHttpCloseHandle failed on closing connection, got %d.\n", ret);
954     ret = WinHttpCloseHandle(session);
955     ok(ret == TRUE, "WinHttpCloseHandle failed on closing session, got %d.\n", ret);
956 
957 }
958 
959 static void CALLBACK cert_error(HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID buf, DWORD len)
960 {
961     DWORD flags = *(DWORD *)buf;
962 
963     if (!flags)
964     {
965         trace("WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR\n");
966         return;
967     }
968 #define X(x) if (flags & x) trace("%s\n", #x);
969     X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED)
970     X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT)
971     X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED)
972     X(WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA)
973     X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID)
974     X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID)
975     X(WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE)
976 #undef X
977 }
978 
979 static void test_secure_connection(void)
980 {
981     static const char data_start[] = "<!DOCTYPE html PUBLIC";
982     HINTERNET ses, con, req;
983     DWORD size, status, policy, bitness, read_size, err, available_size, protocols;
984     BOOL ret;
985     CERT_CONTEXT *cert;
986     WINHTTP_CERTIFICATE_INFO info;
987     char buffer[32];
988 
989     ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
990     ok(ses != NULL, "failed to open session %u\n", GetLastError());
991 
992     policy = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS;
993     ret = WinHttpSetOption(ses, WINHTTP_OPTION_REDIRECT_POLICY, &policy, sizeof(policy));
994     ok(ret, "failed to set redirect policy %u\n", GetLastError());
995 
996     protocols = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
997     ret = WinHttpSetOption(ses, WINHTTP_OPTION_SECURE_PROTOCOLS, &protocols, sizeof(protocols));
998     err = GetLastError();
999     ok(ret || err == ERROR_INVALID_PARAMETER /* < win7 */, "failed to set protocols %u\n", err);
1000 
1001     con = WinHttpConnect(ses, test_winehq, 443, 0);
1002     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1003 
1004     /* try without setting WINHTTP_FLAG_SECURE */
1005     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1006     ok(req != NULL, "failed to open a request %u\n", GetLastError());
1007 
1008     ret = WinHttpSetOption(req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
1009     err = GetLastError();
1010     ok(!ret, "unexpected success\n");
1011     ok(err == ERROR_WINHTTP_INCORRECT_HANDLE_STATE || broken(err == ERROR_INVALID_PARAMETER) /* winxp */,
1012        "setting client cert context returned %u\n", err);
1013 
1014     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1015     err = GetLastError();
1016     if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
1017     {
1018         skip("Connection failed, skipping.\n");
1019         goto cleanup;
1020     }
1021     ok(ret, "failed to send request %u\n", GetLastError());
1022 
1023     ret = WinHttpReceiveResponse(req, NULL);
1024     ok(ret, "failed to receive response %u\n", GetLastError());
1025 
1026     status = 0xdeadbeef;
1027     size = sizeof(status);
1028     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1029     ok(ret, "header query failed %u\n", GetLastError());
1030     ok(status == HTTP_STATUS_BAD_REQUEST, "got %u\n", status);
1031 
1032     WinHttpCloseHandle(req);
1033 
1034     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, WINHTTP_FLAG_SECURE);
1035     ok(req != NULL, "failed to open a request %u\n", GetLastError());
1036 
1037     ret = WinHttpSetOption(req, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0);
1038     err = GetLastError();
1039     ok(ret || broken(!ret && err == ERROR_INVALID_PARAMETER) /* winxp */, "failed to set client cert context %u\n", err);
1040 
1041     WinHttpSetStatusCallback(req, cert_error, WINHTTP_CALLBACK_STATUS_SECURE_FAILURE, 0);
1042 
1043     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1044     err = GetLastError();
1045     if (!ret && (err == ERROR_WINHTTP_SECURE_FAILURE || err == ERROR_WINHTTP_CANNOT_CONNECT ||
1046                  err == ERROR_WINHTTP_TIMEOUT))
1047     {
1048         skip("secure connection failed, skipping remaining secure tests\n");
1049         goto cleanup;
1050     }
1051     ok(ret, "failed to send request %u\n", GetLastError());
1052 
1053     size = sizeof(cert);
1054     ret = WinHttpQueryOption(req, WINHTTP_OPTION_SERVER_CERT_CONTEXT, &cert, &size );
1055     ok(ret, "failed to retrieve certificate context %u\n", GetLastError());
1056     if (ret) CertFreeCertificateContext(cert);
1057 
1058     size = sizeof(bitness);
1059     ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_KEY_BITNESS, &bitness, &size );
1060     ok(ret, "failed to retrieve key bitness %u\n", GetLastError());
1061 
1062     size = sizeof(info);
1063     ret = WinHttpQueryOption(req, WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT, &info, &size );
1064     ok(ret, "failed to retrieve certificate info %u\n", GetLastError());
1065 
1066     if (ret)
1067     {
1068         trace("lpszSubjectInfo %s\n", wine_dbgstr_w(info.lpszSubjectInfo));
1069         trace("lpszIssuerInfo %s\n", wine_dbgstr_w(info.lpszIssuerInfo));
1070         trace("lpszProtocolName %s\n", wine_dbgstr_w(info.lpszProtocolName));
1071         trace("lpszSignatureAlgName %s\n", wine_dbgstr_w(info.lpszSignatureAlgName));
1072         trace("lpszEncryptionAlgName %s\n", wine_dbgstr_w(info.lpszEncryptionAlgName));
1073         trace("dwKeySize %u\n", info.dwKeySize);
1074         LocalFree( info.lpszSubjectInfo );
1075         LocalFree( info.lpszIssuerInfo );
1076     }
1077 
1078     ret = WinHttpReceiveResponse(req, NULL);
1079     ok(ret, "failed to receive response %u\n", GetLastError());
1080 
1081     available_size = 0;
1082     ret = WinHttpQueryDataAvailable(req, &available_size);
1083     ok(ret, "failed to query available data %u\n", GetLastError());
1084     ok(available_size > 2014, "available_size = %u\n", available_size);
1085 
1086     status = 0xdeadbeef;
1087     size = sizeof(status);
1088     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1089     ok(ret, "failed unexpectedly %u\n", GetLastError());
1090     ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1091 
1092     size = 0;
1093     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, NULL, &size, NULL);
1094     ok(!ret, "succeeded unexpectedly\n");
1095 
1096     read_size = 0;
1097     for (;;)
1098     {
1099         size = 0;
1100         ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
1101         ok(ret == TRUE, "WinHttpReadData failed: %u.\n", GetLastError());
1102         if (!size) break;
1103         read_size += size;
1104 
1105         if (read_size <= 32)
1106             ok(!memcmp(buffer, data_start, sizeof(data_start)-1), "not expected: %.32s\n", buffer);
1107     }
1108     ok(read_size >= available_size, "read_size = %u, available_size = %u\n", read_size, available_size);
1109 
1110 cleanup:
1111     WinHttpCloseHandle(req);
1112     WinHttpCloseHandle(con);
1113     WinHttpCloseHandle(ses);
1114 }
1115 
1116 static void test_request_parameter_defaults(void)
1117 {
1118     static const WCHAR empty[] = {0};
1119     HINTERNET ses, con, req;
1120     DWORD size, status, error;
1121     WCHAR *version;
1122     BOOL ret;
1123 
1124     ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1125     ok(ses != NULL, "failed to open session %u\n", GetLastError());
1126 
1127     con = WinHttpConnect(ses, test_winehq, 0, 0);
1128     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1129 
1130     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1131     ok(req != NULL, "failed to open a request %u\n", GetLastError());
1132 
1133     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1134     error = GetLastError();
1135     if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1136     {
1137         skip("connection failed, skipping\n");
1138         goto done;
1139     }
1140     ok(ret, "failed to send request %u\n", GetLastError());
1141 
1142     ret = WinHttpReceiveResponse(req, NULL);
1143     if (!ret && GetLastError() == ERROR_WINHTTP_INVALID_SERVER_RESPONSE) /* win2k */
1144     {
1145         win_skip("invalid response\n");
1146         goto done;
1147     }
1148     ok(ret, "failed to receive response %u\n", GetLastError());
1149 
1150     status = 0xdeadbeef;
1151     size = sizeof(status);
1152     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1153     ok(ret, "failed unexpectedly %u\n", GetLastError());
1154     ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1155 
1156     WinHttpCloseHandle(req);
1157 
1158     req = WinHttpOpenRequest(con, empty, empty, empty, NULL, NULL, 0);
1159     ok(req != NULL, "failed to open a request %u\n", GetLastError());
1160 
1161     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1162     error = GetLastError();
1163     if (!ret && (error == ERROR_WINHTTP_CANNOT_CONNECT || error == ERROR_WINHTTP_TIMEOUT))
1164     {
1165         skip("connection failed, skipping\n");
1166         goto done;
1167     }
1168     ok(ret, "failed to send request %u\n", GetLastError());
1169 
1170     ret = WinHttpReceiveResponse(req, NULL);
1171     ok(ret, "failed to receive response %u\n", GetLastError());
1172 
1173     size = 0;
1174     SetLastError(0xdeadbeef);
1175     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, NULL, &size, NULL);
1176     error = GetLastError();
1177     ok(!ret, "succeeded unexpectedly\n");
1178     ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
1179 
1180     version = HeapAlloc(GetProcessHeap(), 0, size);
1181     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_VERSION, NULL, version, &size, NULL);
1182     ok(ret, "failed unexpectedly %u\n", GetLastError());
1183     ok(lstrlenW(version) == size / sizeof(WCHAR), "unexpected size %u\n", size);
1184     HeapFree(GetProcessHeap(), 0, version);
1185 
1186     status = 0xdeadbeef;
1187     size = sizeof(status);
1188     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
1189     ok(ret, "failed unexpectedly %u\n", GetLastError());
1190     ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
1191 
1192 done:
1193     WinHttpCloseHandle(req);
1194     WinHttpCloseHandle(con);
1195     WinHttpCloseHandle(ses);
1196 }
1197 
1198 static const WCHAR Connections[] = {
1199     'S','o','f','t','w','a','r','e','\\',
1200     'M','i','c','r','o','s','o','f','t','\\',
1201     'W','i','n','d','o','w','s','\\',
1202     'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1203     'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
1204     'C','o','n','n','e','c','t','i','o','n','s',0 };
1205 static const WCHAR WinHttpSettings[] = {
1206     'W','i','n','H','t','t','p','S','e','t','t','i','n','g','s',0 };
1207 
1208 static DWORD get_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD *type )
1209 {
1210     LONG l;
1211     HKEY key;
1212     DWORD ret = 0;
1213 
1214     l = RegOpenKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, KEY_READ, &key );
1215     if (!l)
1216     {
1217         DWORD size = 0;
1218 
1219         l = RegQueryValueExW( key, WinHttpSettings, NULL, type, NULL, &size );
1220         if (!l)
1221         {
1222             if (size <= len)
1223                 l = RegQueryValueExW( key, WinHttpSettings, NULL, type, buf,
1224                     &size );
1225             if (!l)
1226                 ret = size;
1227         }
1228         RegCloseKey( key );
1229     }
1230     return ret;
1231 }
1232 
1233 static void set_proxy( REGSAM access, BYTE *buf, DWORD len, DWORD type )
1234 {
1235     HKEY hkey;
1236     if (!RegCreateKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, NULL, 0, access, NULL, &hkey, NULL ))
1237     {
1238         if (len) RegSetValueExW( hkey, WinHttpSettings, 0, type, buf, len );
1239         else RegDeleteValueW( hkey, WinHttpSettings );
1240         RegCloseKey( hkey );
1241     }
1242 }
1243 
1244 static void set_default_proxy_reg_value( BYTE *buf, DWORD len, DWORD type )
1245 {
1246     BOOL wow64;
1247     IsWow64Process( GetCurrentProcess(), &wow64 );
1248     if (sizeof(void *) > sizeof(int) || wow64)
1249     {
1250         set_proxy( KEY_WRITE|KEY_WOW64_64KEY, buf, len, type );
1251         set_proxy( KEY_WRITE|KEY_WOW64_32KEY, buf, len, type );
1252     }
1253     else
1254         set_proxy( KEY_WRITE, buf, len, type );
1255 }
1256 
1257 static void test_set_default_proxy_config(void)
1258 {
1259     static WCHAR wideString[] = { 0x226f, 0x575b, 0 };
1260     static WCHAR normalString[] = { 'f','o','o',0 };
1261     DWORD type, len;
1262     BYTE *saved_proxy_settings = NULL;
1263     WINHTTP_PROXY_INFO info;
1264     BOOL ret;
1265 
1266     /* FIXME: it would be simpler to read the current settings using
1267      * WinHttpGetDefaultProxyConfiguration and save them using
1268      * WinHttpSetDefaultProxyConfiguration, but they appear to have a bug.
1269      *
1270      * If a proxy is configured in the registry, e.g. via 'proxcfg -p "foo"',
1271      * the access type reported by WinHttpGetDefaultProxyConfiguration is 1,
1272      * WINHTTP_ACCESS_TYPE_NO_PROXY, whereas it should be
1273      * WINHTTP_ACCESS_TYPE_NAMED_PROXY.
1274      * If WinHttpSetDefaultProxyConfiguration is called with dwAccessType = 1,
1275      * the lpszProxy and lpszProxyBypass values are ignored.
1276      * Thus, if a proxy is set with proxycfg, then calling
1277      * WinHttpGetDefaultProxyConfiguration followed by
1278      * WinHttpSetDefaultProxyConfiguration results in the proxy settings
1279      * getting deleted from the registry.
1280      *
1281      * Instead I read the current registry value and restore it directly.
1282      */
1283     len = get_default_proxy_reg_value( NULL, 0, &type );
1284     if (len)
1285     {
1286         saved_proxy_settings = HeapAlloc( GetProcessHeap(), 0, len );
1287         len = get_default_proxy_reg_value( saved_proxy_settings, len, &type );
1288     }
1289 
1290     if (0)
1291     {
1292         /* Crashes on Vista and higher */
1293         SetLastError(0xdeadbeef);
1294         ret = WinHttpSetDefaultProxyConfiguration(NULL);
1295         ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1296             "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1297     }
1298 
1299     /* test with invalid access type */
1300     info.dwAccessType = 0xdeadbeef;
1301     info.lpszProxy = info.lpszProxyBypass = NULL;
1302     SetLastError(0xdeadbeef);
1303     ret = WinHttpSetDefaultProxyConfiguration(&info);
1304     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1305         "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1306 
1307     /* at a minimum, the proxy server must be set */
1308     info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
1309     info.lpszProxy = info.lpszProxyBypass = NULL;
1310     SetLastError(0xdeadbeef);
1311     ret = WinHttpSetDefaultProxyConfiguration(&info);
1312     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1313         "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1314     info.lpszProxyBypass = normalString;
1315     SetLastError(0xdeadbeef);
1316     ret = WinHttpSetDefaultProxyConfiguration(&info);
1317     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1318         "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1319 
1320     /* the proxy server can't have wide characters */
1321     info.lpszProxy = wideString;
1322     SetLastError(0xdeadbeef);
1323     ret = WinHttpSetDefaultProxyConfiguration(&info);
1324     if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1325         skip("couldn't set default proxy configuration: access denied\n");
1326     else
1327         ok((!ret && GetLastError() == ERROR_INVALID_PARAMETER) ||
1328            broken(ret), /* Earlier winhttp versions on W2K/XP */
1329            "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
1330 
1331     info.lpszProxy = normalString;
1332     SetLastError(0xdeadbeef);
1333     ret = WinHttpSetDefaultProxyConfiguration(&info);
1334     if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
1335         skip("couldn't set default proxy configuration: access denied\n");
1336     else
1337     {
1338         ok(ret, "WinHttpSetDefaultProxyConfiguration failed: %u\n", GetLastError());
1339         ok(GetLastError() == ERROR_SUCCESS ||  broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1340            "got %u\n", GetLastError());
1341     }
1342     set_default_proxy_reg_value( saved_proxy_settings, len, type );
1343 }
1344 
1345 static void test_Timeouts (void)
1346 {
1347     BOOL ret;
1348     DWORD value, size;
1349     HINTERNET ses, req, con;
1350 
1351     ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1352     ok(ses != NULL, "failed to open session %u\n", GetLastError());
1353 
1354     SetLastError(0xdeadbeef);
1355     ret = WinHttpSetTimeouts(ses, -2, 0, 0, 0);
1356     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1357        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1358 
1359     SetLastError(0xdeadbeef);
1360     ret = WinHttpSetTimeouts(ses, 0, -2, 0, 0);
1361     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1362        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1363 
1364     SetLastError(0xdeadbeef);
1365     ret = WinHttpSetTimeouts(ses, 0, 0, -2, 0);
1366     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1367        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1368 
1369     SetLastError(0xdeadbeef);
1370     ret = WinHttpSetTimeouts(ses, 0, 0, 0, -2);
1371     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1372        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1373 
1374     SetLastError(0xdeadbeef);
1375     ret = WinHttpSetTimeouts(ses, -1, -1, -1, -1);
1376     ok(ret, "%u\n", GetLastError());
1377     ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
1378        "expected ERROR_SUCCESS, got %u\n", GetLastError());
1379 
1380     SetLastError(0xdeadbeef);
1381     ret = WinHttpSetTimeouts(ses, 0, 0, 0, 0);
1382     ok(ret, "%u\n", GetLastError());
1383 
1384     SetLastError(0xdeadbeef);
1385     ret = WinHttpSetTimeouts(ses, 0x0123, 0x4567, 0x89ab, 0xcdef);
1386     ok(ret, "%u\n", GetLastError());
1387 
1388     SetLastError(0xdeadbeef);
1389     value = 0xdeadbeef;
1390     size  = sizeof(DWORD);
1391     ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1392     ok(ret, "%u\n", GetLastError());
1393     ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1394 
1395     SetLastError(0xdeadbeef);
1396     value = 0xdeadbeef;
1397     size  = sizeof(DWORD);
1398     ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1399     ok(ret, "%u\n", GetLastError());
1400     ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1401 
1402     SetLastError(0xdeadbeef);
1403     value = 0xdeadbeef;
1404     size  = sizeof(DWORD);
1405     ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1406     ok(ret, "%u\n", GetLastError());
1407     ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1408 
1409     SetLastError(0xdeadbeef);
1410     value = 0xdeadbeef;
1411     size  = sizeof(DWORD);
1412     ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1413     ok(ret, "%u\n", GetLastError());
1414     ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1415 
1416     SetLastError(0xdeadbeef);
1417     value = 0;
1418     ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1419     ok(ret, "%u\n", GetLastError());
1420 
1421     SetLastError(0xdeadbeef);
1422     value = 0xdeadbeef;
1423     size  = sizeof(DWORD);
1424     ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1425     ok(ret, "%u\n", GetLastError());
1426     ok(value == 0, "Expected 0, got %u\n", value);
1427 
1428     SetLastError(0xdeadbeef);
1429     value = 0;
1430     ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1431     ok(ret, "%u\n", GetLastError());
1432 
1433     SetLastError(0xdeadbeef);
1434     value = 0xdeadbeef;
1435     size  = sizeof(DWORD);
1436     ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1437     ok(ret, "%u\n", GetLastError());
1438     ok(value == 0, "Expected 0, got %u\n", value);
1439 
1440     SetLastError(0xdeadbeef);
1441     value = 0;
1442     ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1443     ok(ret, "%u\n", GetLastError());
1444 
1445     SetLastError(0xdeadbeef);
1446     value = 0xdeadbeef;
1447     size  = sizeof(DWORD);
1448     ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1449     ok(ret, "%u\n", GetLastError());
1450     ok(value == 0, "Expected 0, got %u\n", value);
1451 
1452     SetLastError(0xdeadbeef);
1453     value = 0;
1454     ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1455     ok(ret, "%u\n", GetLastError());
1456 
1457     SetLastError(0xdeadbeef);
1458     value = 0xdeadbeef;
1459     size  = sizeof(DWORD);
1460     ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1461     ok(ret, "%u\n", GetLastError());
1462     ok(value == 0, "Expected 0, got %u\n", value);
1463 
1464     SetLastError(0xdeadbeef);
1465     value = 0xbeefdead;
1466     ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1467     ok(ret, "%u\n", GetLastError());
1468 
1469     SetLastError(0xdeadbeef);
1470     value = 0xdeadbeef;
1471     size  = sizeof(DWORD);
1472     ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1473     ok(ret, "%u\n", GetLastError());
1474     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1475 
1476     SetLastError(0xdeadbeef);
1477     value = 0xbeefdead;
1478     ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1479     ok(ret, "%u\n", GetLastError());
1480 
1481     SetLastError(0xdeadbeef);
1482     value = 0xdeadbeef;
1483     size  = sizeof(DWORD);
1484     ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1485     ok(ret, "%u\n", GetLastError());
1486     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1487 
1488     SetLastError(0xdeadbeef);
1489     value = 0xbeefdead;
1490     ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1491     ok(ret, "%u\n", GetLastError());
1492 
1493     SetLastError(0xdeadbeef);
1494     value = 0xdeadbeef;
1495     size  = sizeof(DWORD);
1496     ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1497     ok(ret, "%u\n", GetLastError());
1498     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1499 
1500     SetLastError(0xdeadbeef);
1501     value = 0xbeefdead;
1502     ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1503     ok(ret, "%u\n", GetLastError());
1504 
1505     SetLastError(0xdeadbeef);
1506     value = 0xdeadbeef;
1507     size  = sizeof(DWORD);
1508     ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1509     ok(ret, "%u\n", GetLastError());
1510     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1511 
1512     con = WinHttpConnect(ses, test_winehq, 0, 0);
1513     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1514 
1515     /* Timeout values should match the last one set for session */
1516     SetLastError(0xdeadbeef);
1517     value = 0xdeadbeef;
1518     size  = sizeof(DWORD);
1519     ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1520     ok(ret, "%u\n", GetLastError());
1521     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1522 
1523     SetLastError(0xdeadbeef);
1524     value = 0xdeadbeef;
1525     size  = sizeof(DWORD);
1526     ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1527     ok(ret, "%u\n", GetLastError());
1528     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1529 
1530     SetLastError(0xdeadbeef);
1531     value = 0xdeadbeef;
1532     size  = sizeof(DWORD);
1533     ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1534     ok(ret, "%u\n", GetLastError());
1535     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1536 
1537     SetLastError(0xdeadbeef);
1538     value = 0xdeadbeef;
1539     size  = sizeof(DWORD);
1540     ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1541     ok(ret, "%u\n", GetLastError());
1542     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1543 
1544     SetLastError(0xdeadbeef);
1545     ret = WinHttpSetTimeouts(con, -2, 0, 0, 0);
1546     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1547        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1548 
1549     SetLastError(0xdeadbeef);
1550     ret = WinHttpSetTimeouts(con, 0, -2, 0, 0);
1551     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1552        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1553 
1554     SetLastError(0xdeadbeef);
1555     ret = WinHttpSetTimeouts(con, 0, 0, -2, 0);
1556     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1557        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1558 
1559     SetLastError(0xdeadbeef);
1560     ret = WinHttpSetTimeouts(con, 0, 0, 0, -2);
1561     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1562        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1563 
1564     SetLastError(0xdeadbeef);
1565     ret = WinHttpSetTimeouts(con, -1, -1, -1, -1);
1566     ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1567        "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1568 
1569     SetLastError(0xdeadbeef);
1570     ret = WinHttpSetTimeouts(con, 0, 0, 0, 0);
1571     ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1572        "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1573 
1574     SetLastError(0xdeadbeef);
1575     value = 0;
1576     ret = WinHttpSetOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1577     ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1578        "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1579 
1580     SetLastError(0xdeadbeef);
1581     value = 0;
1582     ret = WinHttpSetOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1583     ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1584        "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1585 
1586     SetLastError(0xdeadbeef);
1587     value = 0;
1588     ret = WinHttpSetOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1589     ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1590        "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1591 
1592     SetLastError(0xdeadbeef);
1593     value = 0;
1594     ret = WinHttpSetOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1595     ok(!ret && GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE,
1596        "expected ERROR_WINHTTP_INVALID_TYPE, got %u\n", GetLastError());
1597 
1598     /* Changing timeout values for session should affect the values for connection */
1599     SetLastError(0xdeadbeef);
1600     value = 0xdead;
1601     ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1602     ok(ret, "%u\n", GetLastError());
1603 
1604     SetLastError(0xdeadbeef);
1605     value = 0xdeadbeef;
1606     size  = sizeof(DWORD);
1607     ret = WinHttpQueryOption(con, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1608     ok(ret, "%u\n", GetLastError());
1609     ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1610 
1611     SetLastError(0xdeadbeef);
1612     value = 0xdead;
1613     ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1614     ok(ret, "%u\n", GetLastError());
1615 
1616     SetLastError(0xdeadbeef);
1617     value = 0xdeadbeef;
1618     size  = sizeof(DWORD);
1619     ret = WinHttpQueryOption(con, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1620     ok(ret, "%u\n", GetLastError());
1621     ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1622 
1623     SetLastError(0xdeadbeef);
1624     value = 0xdead;
1625     ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1626     ok(ret, "%u\n", GetLastError());
1627 
1628     SetLastError(0xdeadbeef);
1629     value = 0xdeadbeef;
1630     size  = sizeof(DWORD);
1631     ret = WinHttpQueryOption(con, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1632     ok(ret, "%u\n", GetLastError());
1633     ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1634 
1635     SetLastError(0xdeadbeef);
1636     value = 0xdead;
1637     ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1638     ok(ret, "%u\n", GetLastError());
1639 
1640     SetLastError(0xdeadbeef);
1641     value = 0xdeadbeef;
1642     size  = sizeof(DWORD);
1643     ret = WinHttpQueryOption(con, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1644     ok(ret, "%u\n", GetLastError());
1645     ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1646 
1647     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1648     ok(req != NULL, "failed to open a request %u\n", GetLastError());
1649 
1650     /* Timeout values should match the last one set for session */
1651     SetLastError(0xdeadbeef);
1652     value = 0xdeadbeef;
1653     size  = sizeof(DWORD);
1654     ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1655     ok(ret, "%u\n", GetLastError());
1656     ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1657 
1658     SetLastError(0xdeadbeef);
1659     value = 0xdeadbeef;
1660     size  = sizeof(DWORD);
1661     ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1662     ok(ret, "%u\n", GetLastError());
1663     ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1664 
1665     SetLastError(0xdeadbeef);
1666     value = 0xdeadbeef;
1667     size  = sizeof(DWORD);
1668     ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1669     ok(ret, "%u\n", GetLastError());
1670     ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1671 
1672     SetLastError(0xdeadbeef);
1673     value = 0xdeadbeef;
1674     size  = sizeof(DWORD);
1675     ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1676     ok(ret, "%u\n", GetLastError());
1677     ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1678 
1679     SetLastError(0xdeadbeef);
1680     ret = WinHttpSetTimeouts(req, -2, 0, 0, 0);
1681     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1682        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1683 
1684     SetLastError(0xdeadbeef);
1685     ret = WinHttpSetTimeouts(req, 0, -2, 0, 0);
1686     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1687        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1688 
1689     SetLastError(0xdeadbeef);
1690     ret = WinHttpSetTimeouts(req, 0, 0, -2, 0);
1691     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1692        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1693 
1694     SetLastError(0xdeadbeef);
1695     ret = WinHttpSetTimeouts(req, 0, 0, 0, -2);
1696     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1697        "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1698 
1699     SetLastError(0xdeadbeef);
1700     ret = WinHttpSetTimeouts(req, -1, -1, -1, -1);
1701     ok(ret, "%u\n", GetLastError());
1702 
1703     SetLastError(0xdeadbeef);
1704     ret = WinHttpSetTimeouts(req, 0, 0, 0, 0);
1705     ok(ret, "%u\n", GetLastError());
1706 
1707     SetLastError(0xdeadbeef);
1708     ret = WinHttpSetTimeouts(req, 0xcdef, 0x89ab, 0x4567, 0x0123);
1709     ok(ret, "%u\n", GetLastError());
1710 
1711     SetLastError(0xdeadbeef);
1712     value = 0xdeadbeef;
1713     size  = sizeof(DWORD);
1714     ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1715     ok(ret, "%u\n", GetLastError());
1716     ok(value == 0xcdef, "Expected 0xcdef, got %u\n", value);
1717 
1718     SetLastError(0xdeadbeef);
1719     value = 0xdeadbeef;
1720     size  = sizeof(DWORD);
1721     ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1722     ok(ret, "%u\n", GetLastError());
1723     ok(value == 0x89ab, "Expected 0x89ab, got %u\n", value);
1724 
1725     SetLastError(0xdeadbeef);
1726     value = 0xdeadbeef;
1727     size  = sizeof(DWORD);
1728     ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1729     ok(ret, "%u\n", GetLastError());
1730     ok(value == 0x4567, "Expected 0x4567, got %u\n", value);
1731 
1732     SetLastError(0xdeadbeef);
1733     value = 0xdeadbeef;
1734     size  = sizeof(DWORD);
1735     ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1736     ok(ret, "%u\n", GetLastError());
1737     ok(value == 0x0123, "Expected 0x0123, got %u\n", value);
1738 
1739     SetLastError(0xdeadbeef);
1740     value = 0;
1741     ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1742     ok(ret, "%u\n", GetLastError());
1743 
1744     SetLastError(0xdeadbeef);
1745     value = 0xdeadbeef;
1746     size  = sizeof(DWORD);
1747     ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1748     ok(ret, "%u\n", GetLastError());
1749     ok(value == 0, "Expected 0, got %u\n", value);
1750 
1751     SetLastError(0xdeadbeef);
1752     value = 0;
1753     ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1754     ok(ret, "%u\n", GetLastError());
1755 
1756     SetLastError(0xdeadbeef);
1757     value = 0xdeadbeef;
1758     size  = sizeof(DWORD);
1759     ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1760     ok(ret, "%u\n", GetLastError());
1761     ok(value == 0, "Expected 0, got %u\n", value);
1762 
1763     SetLastError(0xdeadbeef);
1764     value = 0;
1765     ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1766     ok(ret, "%u\n", GetLastError());
1767 
1768     SetLastError(0xdeadbeef);
1769     value = 0xdeadbeef;
1770     size  = sizeof(DWORD);
1771     ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1772     ok(ret, "%u\n", GetLastError());
1773     ok(value == 0, "Expected 0, got %u\n", value);
1774 
1775     SetLastError(0xdeadbeef);
1776     value = 0;
1777     ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1778     ok(ret, "%u\n", GetLastError());
1779 
1780     SetLastError(0xdeadbeef);
1781     value = 0xdeadbeef;
1782     size  = sizeof(DWORD);
1783     ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1784     ok(ret, "%u\n", GetLastError());
1785     ok(value == 0, "Expected 0, got %u\n", value);
1786 
1787     SetLastError(0xdeadbeef);
1788     value = 0xbeefdead;
1789     ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1790     ok(ret, "%u\n", GetLastError());
1791 
1792     SetLastError(0xdeadbeef);
1793     value = 0xdeadbeef;
1794     size  = sizeof(DWORD);
1795     ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1796     ok(ret, "%u\n", GetLastError());
1797     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1798 
1799     SetLastError(0xdeadbeef);
1800     value = 0xbeefdead;
1801     ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1802     ok(ret, "%u\n", GetLastError());
1803 
1804     SetLastError(0xdeadbeef);
1805     value = 0xdeadbeef;
1806     size  = sizeof(DWORD);
1807     ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1808     ok(ret, "%u\n", GetLastError());
1809     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1810 
1811     SetLastError(0xdeadbeef);
1812     value = 0xbeefdead;
1813     ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1814     ok(ret, "%u\n", GetLastError());
1815 
1816     SetLastError(0xdeadbeef);
1817     value = 0xdeadbeef;
1818     size  = sizeof(DWORD);
1819     ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1820     ok(ret, "%u\n", GetLastError());
1821     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1822 
1823     SetLastError(0xdeadbeef);
1824     value = 0xbeefdead;
1825     ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1826     ok(ret, "%u\n", GetLastError());
1827 
1828     SetLastError(0xdeadbeef);
1829     value = 0xdeadbeef;
1830     size  = sizeof(DWORD);
1831     ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1832     ok(ret, "%u\n", GetLastError());
1833     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1834 
1835     /* Changing timeout values for session should not affect the values for a request,
1836      * neither should the other way around.
1837      */
1838     SetLastError(0xdeadbeef);
1839     value = 0xbeefdead;
1840     ret = WinHttpSetOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1841     ok(ret, "%u\n", GetLastError());
1842 
1843     SetLastError(0xdeadbeef);
1844     value = 0xdeadbeef;
1845     size  = sizeof(DWORD);
1846     ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1847     ok(ret, "%u\n", GetLastError());
1848     ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1849 
1850     SetLastError(0xdeadbeef);
1851     value = 0xbeefdead;
1852     ret = WinHttpSetOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1853     ok(ret, "%u\n", GetLastError());
1854 
1855     SetLastError(0xdeadbeef);
1856     value = 0xdeadbeef;
1857     size  = sizeof(DWORD);
1858     ret = WinHttpQueryOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1859     ok(ret, "%u\n", GetLastError());
1860     ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1861 
1862     SetLastError(0xdeadbeef);
1863     value = 0xbeefdead;
1864     ret = WinHttpSetOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1865     ok(ret, "%u\n", GetLastError());
1866 
1867     SetLastError(0xdeadbeef);
1868     value = 0xdeadbeef;
1869     size  = sizeof(DWORD);
1870     ret = WinHttpQueryOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1871     ok(ret, "%u\n", GetLastError());
1872     ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1873 
1874     SetLastError(0xdeadbeef);
1875     value = 0xbeefdead;
1876     ret = WinHttpSetOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1877     ok(ret, "%u\n", GetLastError());
1878 
1879     SetLastError(0xdeadbeef);
1880     value = 0xdeadbeef;
1881     size  = sizeof(DWORD);
1882     ret = WinHttpQueryOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1883     ok(ret, "%u\n", GetLastError());
1884     ok(value == 0xdead, "Expected 0xdead, got %u\n", value);
1885 
1886     SetLastError(0xdeadbeef);
1887     value = 0xbeef;
1888     ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, sizeof(value));
1889     ok(ret, "%u\n", GetLastError());
1890 
1891     SetLastError(0xdeadbeef);
1892     value = 0xdeadbeef;
1893     size  = sizeof(DWORD);
1894     ret = WinHttpQueryOption(req, WINHTTP_OPTION_RESOLVE_TIMEOUT, &value, &size);
1895     ok(ret, "%u\n", GetLastError());
1896     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1897 
1898     SetLastError(0xdeadbeef);
1899     value = 0xbeef;
1900     ret = WinHttpSetOption(ses, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, sizeof(value));
1901     ok(ret, "%u\n", GetLastError());
1902 
1903     SetLastError(0xdeadbeef);
1904     value = 0xdeadbeef;
1905     size  = sizeof(DWORD);
1906     ret = WinHttpQueryOption(req, WINHTTP_OPTION_CONNECT_TIMEOUT, &value, &size);
1907     ok(ret, "%u\n", GetLastError());
1908     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1909 
1910     SetLastError(0xdeadbeef);
1911     value = 0xbeef;
1912     ret = WinHttpSetOption(ses, WINHTTP_OPTION_SEND_TIMEOUT, &value, sizeof(value));
1913     ok(ret, "%u\n", GetLastError());
1914 
1915     SetLastError(0xdeadbeef);
1916     value = 0xdeadbeef;
1917     size  = sizeof(DWORD);
1918     ret = WinHttpQueryOption(req, WINHTTP_OPTION_SEND_TIMEOUT, &value, &size);
1919     ok(ret, "%u\n", GetLastError());
1920     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1921 
1922     SetLastError(0xdeadbeef);
1923     value = 0xbeef;
1924     ret = WinHttpSetOption(ses, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, sizeof(value));
1925     ok(ret, "%u\n", GetLastError());
1926 
1927     SetLastError(0xdeadbeef);
1928     value = 0xdeadbeef;
1929     size  = sizeof(DWORD);
1930     ret = WinHttpQueryOption(req, WINHTTP_OPTION_RECEIVE_TIMEOUT, &value, &size);
1931     ok(ret, "%u\n", GetLastError());
1932     ok(value == 0xbeefdead, "Expected 0xbeefdead, got %u\n", value);
1933 
1934     WinHttpCloseHandle(req);
1935     WinHttpCloseHandle(con);
1936     WinHttpCloseHandle(ses);
1937 }
1938 
1939 static void test_resolve_timeout(void)
1940 {
1941     static const WCHAR nxdomain[] =
1942         {'n','x','d','o','m','a','i','n','.','w','i','n','e','h','q','.','o','r','g',0};
1943     HINTERNET ses, con, req;
1944     DWORD timeout;
1945     BOOL ret;
1946 
1947     if (! proxy_active())
1948     {
1949         ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1950         ok(ses != NULL, "failed to open session %u\n", GetLastError());
1951 
1952         timeout = 10000;
1953         ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1954         ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1955 
1956         con = WinHttpConnect(ses, nxdomain, 0, 0);
1957         ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1958 
1959         req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1960         ok(req != NULL, "failed to open a request %u\n", GetLastError());
1961 
1962         SetLastError(0xdeadbeef);
1963         ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1964         if (ret)
1965         {
1966             skip("nxdomain returned success. Broken ISP redirects?\n");
1967             goto done;
1968         }
1969         ok(GetLastError() == ERROR_WINHTTP_NAME_NOT_RESOLVED,
1970            "expected ERROR_WINHTTP_NAME_NOT_RESOLVED got %u\n", GetLastError());
1971 
1972         WinHttpCloseHandle(req);
1973         WinHttpCloseHandle(con);
1974         WinHttpCloseHandle(ses);
1975     }
1976     else
1977        skip("Skipping host resolution tests, host resolution preformed by proxy\n");
1978 
1979     ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
1980     ok(ses != NULL, "failed to open session %u\n", GetLastError());
1981 
1982     timeout = 10000;
1983     ret = WinHttpSetOption(ses, WINHTTP_OPTION_RESOLVE_TIMEOUT, &timeout, sizeof(timeout));
1984     ok(ret, "failed to set resolve timeout %u\n", GetLastError());
1985 
1986     con = WinHttpConnect(ses, test_winehq, 0, 0);
1987     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
1988 
1989     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
1990     ok(req != NULL, "failed to open a request %u\n", GetLastError());
1991 
1992     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
1993     if (!ret && GetLastError() == ERROR_WINHTTP_CANNOT_CONNECT)
1994     {
1995         skip("connection failed, skipping\n");
1996         goto done;
1997     }
1998     ok(ret, "failed to send request\n");
1999 
2000  done:
2001     WinHttpCloseHandle(req);
2002     WinHttpCloseHandle(con);
2003     WinHttpCloseHandle(ses);
2004 }
2005 
2006 static const char page1[] =
2007 "<HTML>\r\n"
2008 "<HEAD><TITLE>winhttp test page</TITLE></HEAD>\r\n"
2009 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
2010 "</HTML>\r\n\r\n";
2011 
2012 static const char okmsg[] =
2013 "HTTP/1.1 200 OK\r\n"
2014 "Server: winetest\r\n"
2015 "\r\n";
2016 
2017 static const char notokmsg[] =
2018 "HTTP/1.1 400 Bad Request\r\n"
2019 "\r\n";
2020 
2021 static const char cookiemsg[] =
2022 "HTTP/1.1 200 OK\r\n"
2023 "Set-Cookie: name = value \r\n"
2024 "Set-Cookie: NAME = value \r\n"
2025 "\r\n";
2026 
2027 static const char cookiemsg2[] =
2028 "HTTP/1.1 200 OK\r\n"
2029 "Set-Cookie: name2=value; Domain = localhost; Path=/cookie5;Expires=Wed, 13 Jan 2021 22:23:01 GMT; HttpOnly; \r\n"
2030 "\r\n";
2031 
2032 static const char nocontentmsg[] =
2033 "HTTP/1.1 204 No Content\r\n"
2034 "Server: winetest\r\n"
2035 "\r\n";
2036 
2037 static const char notmodified[] =
2038 "HTTP/1.1 304 Not Modified\r\n"
2039 "\r\n";
2040 
2041 static const char noauthmsg[] =
2042 "HTTP/1.1 401 Unauthorized\r\n"
2043 "Server: winetest\r\n"
2044 "Connection: close\r\n"
2045 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2046 "Content-Length: 12\r\n"
2047 "Content-Type: text/plain\r\n"
2048 "\r\n";
2049 
2050 static const char okauthmsg[] =
2051 "HTTP/1.1 200 OK\r\n"
2052 "Server: winetest\r\n"
2053 "Connection: close\r\n"
2054 "Content-Length: 11\r\n"
2055 "Content-Type: text/plain\r\n"
2056 "\r\n";
2057 
2058 static const char headmsg[] =
2059 "HTTP/1.1 200 OK\r\n"
2060 "Content-Length: 100\r\n"
2061 "\r\n";
2062 
2063 static const char multiauth[] =
2064 "HTTP/1.1 401 Unauthorized\r\n"
2065 "Server: winetest\r\n"
2066 "WWW-Authenticate: Bearer\r\n"
2067 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2068 "WWW-Authenticate: NTLM\r\n"
2069 "Content-Length: 10\r\n"
2070 "Content-Type: text/plain\r\n"
2071 "\r\n";
2072 
2073 static const char largeauth[] =
2074 "HTTP/1.1 401 Unauthorized\r\n"
2075 "Server: winetest\r\n"
2076 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2077 "WWW-Authenticate: NTLM\r\n"
2078 "Content-Length: 10240\r\n"
2079 "Content-Type: text/plain\r\n"
2080 "\r\n";
2081 
2082 static const char unauthorized[] = "Unauthorized";
2083 static const char hello_world[] = "Hello World";
2084 static const char auth_unseen[] = "Auth Unseen";
2085 
2086 struct server_info
2087 {
2088     HANDLE event;
2089     int port;
2090 };
2091 
2092 #define BIG_BUFFER_LEN 0x2250
2093 
2094 static DWORD CALLBACK server_thread(LPVOID param)
2095 {
2096     struct server_info *si = param;
2097     int r, c = -1, i, on;
2098     SOCKET s;
2099     struct sockaddr_in sa;
2100     char buffer[0x100];
2101     WSADATA wsaData;
2102     int last_request = 0;
2103 
2104     WSAStartup(MAKEWORD(1,1), &wsaData);
2105 
2106     s = socket(AF_INET, SOCK_STREAM, 0);
2107     if (s == INVALID_SOCKET)
2108         return 1;
2109 
2110     on = 1;
2111     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof on);
2112 
2113     memset(&sa, 0, sizeof sa);
2114     sa.sin_family = AF_INET;
2115     sa.sin_port = htons(si->port);
2116     sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
2117 
2118     r = bind(s, (struct sockaddr *)&sa, sizeof(sa));
2119     if (r < 0)
2120         return 1;
2121 
2122     listen(s, 0);
2123     SetEvent(si->event);
2124     do
2125     {
2126         if (c == -1) c = accept(s, NULL, NULL);
2127 
2128         memset(buffer, 0, sizeof buffer);
2129         for(i = 0; i < sizeof buffer - 1; i++)
2130         {
2131             r = recv(c, &buffer[i], 1, 0);
2132             if (r != 1)
2133                 break;
2134             if (i < 4) continue;
2135             if (buffer[i - 2] == '\n' && buffer[i] == '\n' &&
2136                 buffer[i - 3] == '\r' && buffer[i - 1] == '\r')
2137                 break;
2138         }
2139         if (strstr(buffer, "GET /basic"))
2140         {
2141             send(c, okmsg, sizeof okmsg - 1, 0);
2142             send(c, page1, sizeof page1 - 1, 0);
2143         }
2144         if (strstr(buffer, "/auth_with_creds"))
2145         {
2146             send(c, okauthmsg, sizeof okauthmsg - 1, 0);
2147             if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2148                 send(c, hello_world, sizeof hello_world - 1, 0);
2149             else
2150                 send(c, auth_unseen, sizeof auth_unseen - 1, 0);
2151             continue;
2152         }
2153         if (strstr(buffer, "/auth"))
2154         {
2155             if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2156             {
2157                 send(c, okauthmsg, sizeof okauthmsg - 1, 0);
2158                 send(c, hello_world, sizeof hello_world - 1, 0);
2159             }
2160             else
2161             {
2162                 send(c, noauthmsg, sizeof noauthmsg - 1, 0);
2163                 send(c, unauthorized, sizeof unauthorized - 1, 0);
2164             }
2165             continue;
2166         }
2167         if (strstr(buffer, "/big"))
2168         {
2169             char msg[BIG_BUFFER_LEN];
2170             memset(msg, 'm', sizeof(msg));
2171             send(c, okmsg, sizeof(okmsg) - 1, 0);
2172             send(c, msg, sizeof(msg), 0);
2173         }
2174         if (strstr(buffer, "/no_headers"))
2175         {
2176             send(c, page1, sizeof page1 - 1, 0);
2177         }
2178         if (strstr(buffer, "GET /no_content"))
2179         {
2180             send(c, nocontentmsg, sizeof nocontentmsg - 1, 0);
2181             continue;
2182         }
2183         if (strstr(buffer, "GET /not_modified"))
2184         {
2185             if (strstr(buffer, "If-Modified-Since:")) send(c, notmodified, sizeof notmodified - 1, 0);
2186             else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2187             continue;
2188         }
2189         if (strstr(buffer, "HEAD /head"))
2190         {
2191             send(c, headmsg, sizeof headmsg - 1, 0);
2192             continue;
2193         }
2194         if (strstr(buffer, "GET /multiauth"))
2195         {
2196             send(c, multiauth, sizeof multiauth - 1, 0);
2197         }
2198         if (strstr(buffer, "GET /largeauth"))
2199         {
2200             if (strstr(buffer, "Authorization: NTLM"))
2201                 send(c, okmsg, sizeof(okmsg) - 1, 0);
2202             else
2203             {
2204                 send(c, largeauth, sizeof largeauth - 1, 0);
2205 #ifdef __REACTOS__
2206                 memset(buffer, 'A', sizeof(buffer));
2207                 for (i = 0; i < (10240 / sizeof(buffer)); i++) send(c, buffer, sizeof(buffer), 0);
2208 #else
2209                 for (i = 0; i < 10240; i++) send(c, "A", 1, 0);
2210 #endif
2211                 continue;
2212             }
2213         }
2214         if (strstr(buffer, "GET /cookie5"))
2215         {
2216             if (strstr(buffer, "Cookie: name2=value\r\n"))
2217                 send(c, okmsg, sizeof(okmsg) - 1, 0);
2218             else
2219                 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2220         }
2221         if (strstr(buffer, "GET /cookie4"))
2222         {
2223             send(c, cookiemsg2, sizeof(cookiemsg2) - 1, 0);
2224         }
2225         if (strstr(buffer, "GET /cookie3"))
2226         {
2227             if (strstr(buffer, "Cookie: name=value2; NAME=value; name=value\r\n") ||
2228                 broken(strstr(buffer, "Cookie: name=value2; name=value; NAME=value\r\n") != NULL))
2229                 send(c, okmsg, sizeof(okmsg) - 1, 0);
2230             else
2231                 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2232         }
2233         if (strstr(buffer, "GET /cookie2"))
2234         {
2235             if (strstr(buffer, "Cookie: NAME=value; name=value\r\n") ||
2236                 broken(strstr(buffer, "Cookie: name=value; NAME=value\r\n") != NULL))
2237                 send(c, okmsg, sizeof(okmsg) - 1, 0);
2238             else
2239                 send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2240         }
2241         else if (strstr(buffer, "GET /cookie"))
2242         {
2243             if (!strstr(buffer, "Cookie: name=value\r\n")) send(c, cookiemsg, sizeof(cookiemsg) - 1, 0);
2244             else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
2245         }
2246         if (strstr(buffer, "GET /quit"))
2247         {
2248             send(c, okmsg, sizeof okmsg - 1, 0);
2249             send(c, page1, sizeof page1 - 1, 0);
2250             last_request = 1;
2251         }
2252         shutdown(c, 2);
2253         closesocket(c);
2254         c = -1;
2255 
2256     } while (!last_request);
2257 
2258     closesocket(s);
2259     return 0;
2260 }
2261 
2262 static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
2263 {
2264     static const WCHAR test_header_end_clrf[] = {'\r','\n','\r','\n',0};
2265     static const WCHAR test_header_end_raw[] = {0,0};
2266     HINTERNET ses, con, req;
2267     char buffer[0x100];
2268     WCHAR buffer2[0x100];
2269     DWORD count, status, size, error, supported, first, target;
2270     BOOL ret;
2271 
2272     ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2273     ok(ses != NULL, "failed to open session %u\n", GetLastError());
2274 
2275     SetLastError(0xdeadbeef);
2276     ret = WinHttpSetOption(ses, 0, buffer, sizeof(buffer));
2277     ok(!ret && GetLastError() == ERROR_WINHTTP_INVALID_OPTION, "got %u\n", GetLastError());
2278 
2279     SetLastError(0xdeadbeef);
2280     ret = WinHttpQueryOption(ses, 0, buffer, &size);
2281     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %u\n", GetLastError());
2282 
2283     con = WinHttpConnect(ses, localhostW, port, 0);
2284     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2285 
2286     SetLastError(0xdeadbeef);
2287     ret = WinHttpSetOption(con, 0, buffer, sizeof(buffer));
2288     todo_wine ok(!ret && GetLastError() == ERROR_WINHTTP_INVALID_OPTION, "got %u\n", GetLastError());
2289 
2290     SetLastError(0xdeadbeef);
2291     ret = WinHttpQueryOption(con, 0, buffer, &size);
2292     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %u\n", GetLastError());
2293 
2294     req = WinHttpOpenRequest(con, verb, path, NULL, NULL, NULL, 0);
2295     ok(req != NULL, "failed to open a request %u\n", GetLastError());
2296 
2297     SetLastError(0xdeadbeef);
2298     ret = WinHttpSetOption(req, 0, buffer, sizeof(buffer));
2299     ok(!ret && GetLastError() == ERROR_WINHTTP_INVALID_OPTION, "got %u\n", GetLastError());
2300 
2301     SetLastError(0xdeadbeef);
2302     ret = WinHttpQueryOption(req, 0, buffer, &size);
2303     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "got %u\n", GetLastError());
2304 
2305     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2306     ok(ret, "failed to send request %u\n", GetLastError());
2307 
2308     ret = WinHttpReceiveResponse(req, NULL);
2309     ok(ret, "failed to receive response %u\n", GetLastError());
2310 
2311     status = 0xdeadbeef;
2312     size = sizeof(status);
2313     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2314     ok(ret, "failed to query status code %u\n", GetLastError());
2315     ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2316 
2317     supported = first = target = 0xdeadbeef;
2318     SetLastError(0xdeadbeef);
2319     ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2320     error = GetLastError();
2321     ok(!ret, "unexpected success\n");
2322     todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2323     ok(supported == 0xdeadbeef, "got %x\n", supported);
2324     ok(first == 0xdeadbeef, "got %x\n", first);
2325     ok(target == 0xdeadbeef, "got %x\n", target);
2326 
2327     size = sizeof(buffer2);
2328     memset(buffer2, 0, sizeof(buffer2));
2329     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buffer2, &size, NULL);
2330     ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2331     ok(!memcmp(buffer2 + lstrlenW(buffer2) - 4, test_header_end_clrf, sizeof(test_header_end_clrf)),
2332        "WinHttpQueryHeaders returned invalid end of header string\n");
2333 
2334     size = sizeof(buffer2);
2335     memset(buffer2, 0, sizeof(buffer2));
2336     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_RAW_HEADERS, NULL, buffer2, &size, NULL);
2337     ok(ret, "failed to query for raw headers: %u\n", GetLastError());
2338     ok(!memcmp(buffer2 + (size / sizeof(WCHAR)) - 1, test_header_end_raw, sizeof(test_header_end_raw)),
2339        "WinHttpQueryHeaders returned invalid end of header string\n");
2340     ok(buffer2[(size / sizeof(WCHAR)) - 2] != 0, "returned string has too many NULL characters\n");
2341 
2342     count = 0;
2343     memset(buffer, 0, sizeof(buffer));
2344     ret = WinHttpReadData(req, buffer, sizeof buffer, &count);
2345     ok(ret, "failed to read data %u\n", GetLastError());
2346     ok(count == sizeof page1 - 1, "count was wrong\n");
2347     ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
2348 
2349     WinHttpCloseHandle(req);
2350     WinHttpCloseHandle(con);
2351     WinHttpCloseHandle(ses);
2352 }
2353 
2354 static void test_basic_authentication(int port)
2355 {
2356     static const WCHAR authW[] = {'/','a','u','t','h',0};
2357     static const WCHAR auth_with_credsW[] = {'/','a','u','t','h','_','w','i','t','h','_','c','r','e','d','s',0};
2358     static WCHAR userW[] = {'u','s','e','r',0};
2359     static WCHAR passW[] = {'p','w','d',0};
2360     static WCHAR pass2W[] = {'p','w','d','2',0};
2361     HINTERNET ses, con, req;
2362     DWORD status, size, error, supported, first, target;
2363     char buffer[32];
2364     BOOL ret;
2365 
2366     ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2367     ok(ses != NULL, "failed to open session %u\n", GetLastError());
2368 
2369     con = WinHttpConnect(ses, localhostW, port, 0);
2370     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2371 
2372     req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2373     ok(req != NULL, "failed to open a request %u\n", GetLastError());
2374 
2375     SetLastError(0xdeadbeef);
2376     ret = WinHttpQueryAuthSchemes(NULL, NULL, NULL, NULL);
2377     error = GetLastError();
2378     ok(!ret, "expected failure\n");
2379     ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2380 
2381     SetLastError(0xdeadbeef);
2382     ret = WinHttpQueryAuthSchemes(req, NULL, NULL, NULL);
2383     error = GetLastError();
2384     ok(!ret, "expected failure\n");
2385     ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2386 
2387     supported = 0xdeadbeef;
2388     SetLastError(0xdeadbeef);
2389     ret = WinHttpQueryAuthSchemes(req, &supported, NULL, NULL);
2390     error = GetLastError();
2391     ok(!ret, "expected failure\n");
2392     ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2393     ok(supported == 0xdeadbeef, "got %x\n", supported);
2394 
2395     supported = first = 0xdeadbeef;
2396     SetLastError(0xdeadbeef);
2397     ret = WinHttpQueryAuthSchemes(req, &supported, &first, NULL);
2398     error = GetLastError();
2399     ok(!ret, "expected failure\n");
2400     ok(error == ERROR_INVALID_PARAMETER || error == ERROR_INVALID_OPERATION, "got %u\n", error);
2401     ok(supported == 0xdeadbeef, "got %x\n", supported);
2402     ok(first == 0xdeadbeef, "got %x\n", first);
2403 
2404     supported = first = target = 0xdeadbeef;
2405     SetLastError(0xdeadbeef);
2406     ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2407     error = GetLastError();
2408     ok(!ret, "expected failure\n");
2409     todo_wine ok(error == ERROR_INVALID_OPERATION, "expected ERROR_INVALID_OPERATION, got %u\n", error);
2410     ok(supported == 0xdeadbeef, "got %x\n", supported);
2411     ok(first == 0xdeadbeef, "got %x\n", first);
2412     ok(target == 0xdeadbeef, "got %x\n", target);
2413 
2414     supported = first = target = 0xdeadbeef;
2415     SetLastError(0xdeadbeef);
2416     ret = WinHttpQueryAuthSchemes(NULL, &supported, &first, &target);
2417     error = GetLastError();
2418     ok(!ret, "expected failure\n");
2419     ok(error == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", error);
2420     ok(supported == 0xdeadbeef, "got %x\n", supported);
2421     ok(first == 0xdeadbeef, "got %x\n", first);
2422     ok(target == 0xdeadbeef, "got %x\n", target);
2423 
2424     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2425     ok(ret, "failed to send request %u\n", GetLastError());
2426 
2427     ret = WinHttpReceiveResponse(req, NULL);
2428     ok(ret, "failed to receive response %u\n", GetLastError());
2429 
2430     status = 0xdeadbeef;
2431     size = sizeof(status);
2432     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2433     ok(ret, "failed to query status code %u\n", GetLastError());
2434     ok(status == HTTP_STATUS_DENIED, "request failed unexpectedly %u\n", status);
2435 
2436     size = 0;
2437     ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2438     error = GetLastError();
2439     ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2440     if (ret)
2441     {
2442         ok(size == 12, "expected 12, got %u\n", size);
2443         ok(!memcmp(buffer, unauthorized, 12), "got %s\n", buffer);
2444     }
2445 
2446     supported = first = target = 0xdeadbeef;
2447     SetLastError(0xdeadbeef);
2448     ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2449     error = GetLastError();
2450     ok(ret, "failed to query authentication schemes %u\n", error);
2451     ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2452     ok(supported == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", supported);
2453     ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
2454     ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
2455 
2456     SetLastError(0xdeadbeef);
2457     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, NULL, NULL, NULL);
2458     error = GetLastError();
2459     ok(ret, "failed to set credentials %u\n", error);
2460     ok(error == ERROR_SUCCESS || broken(error == 0xdeadbeef) /* < win7 */, "expected ERROR_SUCCESS, got %u\n", error);
2461 
2462     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_PASSPORT, NULL, NULL, NULL);
2463     ok(ret, "failed to set credentials %u\n", GetLastError());
2464 
2465     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NEGOTIATE, NULL, NULL, NULL);
2466     ok(ret, "failed to set credentials %u\n", GetLastError());
2467 
2468     SetLastError(0xdeadbeef);
2469     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_DIGEST, NULL, NULL, NULL);
2470     error = GetLastError();
2471     ok(!ret, "expected failure\n");
2472     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2473 
2474     SetLastError(0xdeadbeef);
2475     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, NULL, NULL);
2476     error = GetLastError();
2477     ok(!ret, "expected failure\n");
2478     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2479 
2480     SetLastError(0xdeadbeef);
2481     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
2482     error = GetLastError();
2483     ok(!ret, "expected failure\n");
2484     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2485 
2486     SetLastError(0xdeadbeef);
2487     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
2488     error = GetLastError();
2489     ok(!ret, "expected failure\n");
2490     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2491 
2492     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2493     ok(ret, "failed to set credentials %u\n", GetLastError());
2494 
2495     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2496     ok(ret, "failed to send request %u\n", GetLastError());
2497 
2498     ret = WinHttpReceiveResponse(req, NULL);
2499     ok(ret, "failed to receive response %u\n", GetLastError());
2500 
2501     status = 0xdeadbeef;
2502     size = sizeof(status);
2503     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2504     ok(ret, "failed to query status code %u\n", GetLastError());
2505     ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2506 
2507     size = 0;
2508     ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2509     error = GetLastError();
2510     ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2511     if (ret)
2512     {
2513         ok(size == 11, "expected 11, got %u\n", size);
2514         ok(!memcmp(buffer, hello_world, 11), "got %s\n", buffer);
2515     }
2516 
2517     WinHttpCloseHandle(req);
2518     WinHttpCloseHandle(con);
2519     WinHttpCloseHandle(ses);
2520 
2521     /* now set the credentials first to show that they get sent with the first request */
2522     ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2523     ok(ses != NULL, "failed to open session %u\n", GetLastError());
2524 
2525     con = WinHttpConnect(ses, localhostW, port, 0);
2526     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2527 
2528     req = WinHttpOpenRequest(con, NULL, auth_with_credsW, NULL, NULL, NULL, 0);
2529     ok(req != NULL, "failed to open a request %u\n", GetLastError());
2530 
2531     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2532     ok(ret, "failed to set credentials %u\n", GetLastError());
2533 
2534     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2535     ok(ret, "failed to send request %u\n", GetLastError());
2536 
2537     ret = WinHttpReceiveResponse(req, NULL);
2538     ok(ret, "failed to receive response %u\n", GetLastError());
2539 
2540     status = 0xdeadbeef;
2541     size = sizeof(status);
2542     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2543     ok(ret, "failed to query status code %u\n", GetLastError());
2544     ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2545 
2546     size = 0;
2547     ret = WinHttpReadData(req, buffer, sizeof(buffer), &size);
2548     error = GetLastError();
2549     ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError());
2550     if (ret)
2551     {
2552         ok(size == 11, "expected 11, got %u\n", size);
2553         ok(!memcmp(buffer, hello_world, 11), "got %s\n", buffer);
2554     }
2555 
2556     WinHttpCloseHandle(req);
2557     WinHttpCloseHandle(con);
2558     WinHttpCloseHandle(ses);
2559 
2560     /* credentials set with WinHttpSetCredentials take precedence over those set through options */
2561 
2562     ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2563     ok(ses != NULL, "failed to open session %u\n", GetLastError());
2564 
2565     con = WinHttpConnect(ses, localhostW, port, 0);
2566     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2567 
2568     req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2569     ok(req != NULL, "failed to open a request %u\n", GetLastError());
2570 
2571     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
2572     ok(ret, "failed to set credentials %u\n", GetLastError());
2573 
2574     ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2575     ok(ret, "failed to set username %u\n", GetLastError());
2576 
2577     ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, pass2W, lstrlenW(pass2W));
2578     ok(ret, "failed to set password %u\n", GetLastError());
2579 
2580     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2581     ok(ret, "failed to send request %u\n", GetLastError());
2582 
2583     ret = WinHttpReceiveResponse(req, NULL);
2584     ok(ret, "failed to receive response %u\n", GetLastError());
2585 
2586     status = 0xdeadbeef;
2587     size = sizeof(status);
2588     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2589     ok(ret, "failed to query status code %u\n", GetLastError());
2590     ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
2591 
2592     WinHttpCloseHandle(req);
2593     WinHttpCloseHandle(con);
2594     WinHttpCloseHandle(ses);
2595 
2596     ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2597     ok(ses != NULL, "failed to open session %u\n", GetLastError());
2598 
2599     con = WinHttpConnect(ses, localhostW, port, 0);
2600     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2601 
2602     req = WinHttpOpenRequest(con, NULL, authW, NULL, NULL, NULL, 0);
2603     ok(req != NULL, "failed to open a request %u\n", GetLastError());
2604 
2605     ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
2606     ok(ret, "failed to set username %u\n", GetLastError());
2607 
2608     ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW));
2609     ok(ret, "failed to set password %u\n", GetLastError());
2610 
2611     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, pass2W, NULL);
2612     ok(ret, "failed to set credentials %u\n", GetLastError());
2613 
2614     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2615     ok(ret, "failed to send request %u\n", GetLastError());
2616 
2617     ret = WinHttpReceiveResponse(req, NULL);
2618     ok(ret, "failed to receive response %u\n", GetLastError());
2619 
2620     status = 0xdeadbeef;
2621     size = sizeof(status);
2622     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL);
2623     ok(ret, "failed to query status code %u\n", GetLastError());
2624     ok(status == HTTP_STATUS_DENIED, "request failed unexpectedly %u\n", status);
2625 
2626     WinHttpCloseHandle(req);
2627     WinHttpCloseHandle(con);
2628     WinHttpCloseHandle(ses);
2629 }
2630 
2631 static void test_multi_authentication(int port)
2632 {
2633     static const WCHAR multiauthW[] = {'/','m','u','l','t','i','a','u','t','h',0};
2634     static const WCHAR getW[] = {'G','E','T',0};
2635     HINTERNET ses, con, req;
2636     DWORD supported, first, target;
2637     BOOL ret;
2638 
2639     ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2640     ok(ses != NULL, "failed to open session %u\n", GetLastError());
2641 
2642     con = WinHttpConnect(ses, localhostW, port, 0);
2643     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2644 
2645     req = WinHttpOpenRequest(con, getW, multiauthW, NULL, NULL, NULL, 0);
2646     ok(req != NULL, "failed to open a request %u\n", GetLastError());
2647 
2648     ret = WinHttpSendRequest(req, WINHTTP_NO_ADDITIONAL_HEADERS, 0,
2649                              WINHTTP_NO_REQUEST_DATA,0, 0, 0 );
2650     ok(ret, "expected success\n");
2651 
2652     ret = WinHttpReceiveResponse(req, NULL);
2653     ok(ret, "expected success\n");
2654 
2655     supported = first = target = 0xdeadbeef;
2656     ret = WinHttpQueryAuthSchemes(req, &supported, &first, &target);
2657     ok(ret, "expected success\n");
2658     ok(supported == (WINHTTP_AUTH_SCHEME_BASIC | WINHTTP_AUTH_SCHEME_NTLM), "got %x\n", supported);
2659     ok(target == WINHTTP_AUTH_TARGET_SERVER, "got %x\n", target);
2660     ok(first == WINHTTP_AUTH_SCHEME_BASIC, "got %x\n", first);
2661 
2662     WinHttpCloseHandle(req);
2663     WinHttpCloseHandle(con);
2664     WinHttpCloseHandle(ses);
2665 }
2666 
2667 static void test_large_data_authentication(int port)
2668 {
2669     static const WCHAR largeauthW[] = {'/','l','a','r','g','e','a','u','t','h',0};
2670     static const WCHAR getW[] = {'G','E','T',0};
2671     static WCHAR userW[] = {'u','s','e','r',0};
2672     static WCHAR passW[] = {'p','w','d',0};
2673     HINTERNET ses, con, req;
2674     DWORD status, size;
2675     BOOL ret;
2676 
2677     ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2678     ok(ses != NULL, "failed to open session %u\n", GetLastError());
2679 
2680     con = WinHttpConnect(ses, localhostW, port, 0);
2681     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2682 
2683     req = WinHttpOpenRequest(con, getW, largeauthW, NULL, NULL, NULL, 0);
2684     ok(req != NULL, "failed to open a request %u\n", GetLastError());
2685 
2686     ret = WinHttpSendRequest(req, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
2687     ok(ret, "expected success\n");
2688 
2689     ret = WinHttpReceiveResponse(req, NULL);
2690     ok(ret, "expected success\n");
2691 
2692     size = sizeof(status);
2693     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL,
2694                               &status, &size, NULL);
2695     ok(ret, "expected success\n");
2696     ok(status == HTTP_STATUS_DENIED, "got %d\n", status);
2697 
2698     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_NTLM, userW, passW, NULL);
2699     ok(ret, "expected success\n");
2700 
2701     ret = WinHttpSendRequest(req, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
2702     ok(ret, "expected success %d\n", GetLastError());
2703 
2704     ret = WinHttpReceiveResponse(req, NULL);
2705     ok(ret, "expected success\n");
2706 
2707     size = sizeof(status);
2708     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL,
2709                               &status, &size, NULL);
2710     ok(ret, "expected success\n");
2711     ok(status == HTTP_STATUS_OK, "got %d\n", status);
2712 
2713     WinHttpCloseHandle(req);
2714     WinHttpCloseHandle(con);
2715     WinHttpCloseHandle(ses);
2716 }
2717 
2718 static void test_no_headers(int port)
2719 {
2720     static const WCHAR no_headersW[] = {'/','n','o','_','h','e','a','d','e','r','s',0};
2721     HINTERNET ses, con, req;
2722     DWORD error;
2723     BOOL ret;
2724 
2725     ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2726     ok(ses != NULL, "failed to open session %u\n", GetLastError());
2727 
2728     con = WinHttpConnect(ses, localhostW, port, 0);
2729     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2730 
2731     req = WinHttpOpenRequest(con, NULL, no_headersW, NULL, NULL, NULL, 0);
2732     ok(req != NULL, "failed to open a request %u\n", GetLastError());
2733 
2734     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2735     if (!ret)
2736     {
2737         error = GetLastError();
2738         ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2739     }
2740     else
2741     {
2742         SetLastError(0xdeadbeef);
2743         ret = WinHttpReceiveResponse(req, NULL);
2744         error = GetLastError();
2745         ok(!ret, "expected failure\n");
2746         ok(error == ERROR_WINHTTP_INVALID_SERVER_RESPONSE, "got %u\n", error);
2747     }
2748 
2749     WinHttpCloseHandle(req);
2750     WinHttpCloseHandle(con);
2751     WinHttpCloseHandle(ses);
2752 }
2753 
2754 static void test_no_content(int port)
2755 {
2756     static const WCHAR no_contentW[] = {'/','n','o','_','c','o','n','t','e','n','t',0};
2757     HINTERNET ses, con, req;
2758     char buf[128];
2759     DWORD size, len = sizeof(buf), bytes_read, status;
2760     BOOL ret;
2761 
2762     ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2763     ok(ses != NULL, "failed to open session %u\n", GetLastError());
2764 
2765     con = WinHttpConnect(ses, localhostW, port, 0);
2766     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2767 
2768     req = WinHttpOpenRequest(con, NULL, no_contentW, NULL, NULL, NULL, 0);
2769     ok(req != NULL, "failed to open a request %u\n", GetLastError());
2770 
2771     size = 12345;
2772     SetLastError(0xdeadbeef);
2773     ret = WinHttpQueryDataAvailable(req, &size);
2774     todo_wine {
2775     ok(!ret, "expected error\n");
2776     ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_STATE,
2777        "expected ERROR_WINHTTP_INCORRECT_HANDLE_STATE, got 0x%08x\n", GetLastError());
2778     ok(size == 12345 || broken(size == 0) /* Win <= 2003 */,
2779        "expected 12345, got %u\n", size);
2780     }
2781 
2782     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2783     ok(ret, "expected success\n");
2784 
2785     ret = WinHttpReceiveResponse(req, NULL);
2786     ok(ret, "expected success\n");
2787 
2788     status = 0xdeadbeef;
2789     size = sizeof(status);
2790     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
2791                               NULL, &status, &size, NULL);
2792     ok(ret, "expected success\n");
2793     ok(status == HTTP_STATUS_NO_CONTENT, "expected status 204, got %d\n", status);
2794 
2795     SetLastError(0xdeadbeef);
2796     size = sizeof(status);
2797     status = 12345;
2798     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
2799                               NULL, &status, &size, 0);
2800     ok(!ret, "expected no content-length header\n");
2801     ok(GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError());
2802     ok(status == 12345, "expected 0, got %d\n", status);
2803 
2804     SetLastError(0xdeadbeef);
2805     size = 12345;
2806     ret = WinHttpQueryDataAvailable(req, &size);
2807     ok(ret, "expected success\n");
2808     ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
2809        "wrong error %u\n", GetLastError());
2810     ok(!size, "expected 0, got %u\n", size);
2811 
2812     SetLastError(0xdeadbeef);
2813     ret = WinHttpReadData(req, buf, len, &bytes_read);
2814     ok(ret, "expected success\n");
2815     ok(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == 0xdeadbeef) /* < win7 */,
2816        "wrong error %u\n", GetLastError());
2817     ok(!bytes_read, "expected 0, got %u\n", bytes_read);
2818 
2819     size = 12345;
2820     ret = WinHttpQueryDataAvailable(req, &size);
2821     ok(ret, "expected success\n");
2822     ok(size == 0, "expected 0, got %d\n", size);
2823 
2824     WinHttpCloseHandle(req);
2825 
2826     size = 12345;
2827     SetLastError(0xdeadbeef);
2828     ret = WinHttpQueryDataAvailable(req, &size);
2829     ok(!ret, "expected error\n");
2830     ok(GetLastError() == ERROR_INVALID_HANDLE,
2831        "expected ERROR_INVALID_HANDLE, got 0x%08x\n", GetLastError());
2832     ok(size == 12345, "expected 12345, got %u\n", size);
2833 
2834     WinHttpCloseHandle(con);
2835     WinHttpCloseHandle(ses);
2836 }
2837 
2838 static void test_head_request(int port)
2839 {
2840     static const WCHAR verbW[] = {'H','E','A','D',0};
2841     static const WCHAR headW[] = {'/','h','e','a','d',0};
2842     HINTERNET ses, con, req;
2843     char buf[128];
2844     DWORD size, len, count, status;
2845     BOOL ret;
2846 
2847     ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2848     ok(ses != NULL, "failed to open session %u\n", GetLastError());
2849 
2850     con = WinHttpConnect(ses, localhostW, port, 0);
2851     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
2852 
2853     req = WinHttpOpenRequest(con, verbW, headW, NULL, NULL, NULL, 0);
2854     ok(req != NULL, "failed to open a request %u\n", GetLastError());
2855 
2856     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
2857     ok(ret, "failed to send request %u\n", GetLastError());
2858 
2859     ret = WinHttpReceiveResponse(req, NULL);
2860     ok(ret, "failed to receive response %u\n", GetLastError());
2861 
2862     status = 0xdeadbeef;
2863     size = sizeof(status);
2864     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
2865                               NULL, &status, &size, NULL);
2866     ok(ret, "failed to get status code %u\n", GetLastError());
2867     ok(status == HTTP_STATUS_OK, "got %u\n", status);
2868 
2869     len = 0xdeadbeef;
2870     size = sizeof(len);
2871     ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
2872                               NULL, &len, &size, 0);
2873     ok(ret, "failed to get content-length header %u\n", GetLastError());
2874     ok(len == HTTP_STATUS_CONTINUE, "got %u\n", len);
2875 
2876     count = 0xdeadbeef;
2877     ret = WinHttpQueryDataAvailable(req, &count);
2878     ok(ret, "failed to query data available %u\n", GetLastError());
2879     ok(!count, "got %u\n", count);
2880 
2881     len = sizeof(buf);
2882     count = 0xdeadbeef;
2883     ret = WinHttpReadData(req, buf, len, &count);
2884     ok(ret, "failed to read data %u\n", GetLastError());
2885     ok(!count, "got %u\n", count);
2886 
2887     count = 0xdeadbeef;
2888     ret = WinHttpQueryDataAvailable(req, &count);
2889     ok(ret, "failed to query data available %u\n", GetLastError());
2890     ok(!count, "got %u\n", count);
2891 
2892     WinHttpCloseHandle(req);
2893     WinHttpCloseHandle(con);
2894     WinHttpCloseHandle(ses);
2895 }
2896 
2897 static void test_not_modified(int port)
2898 {
2899     static const WCHAR pathW[] = {'/','n','o','t','_','m','o','d','i','f','i','e','d',0};
2900     static const WCHAR ifmodifiedW[] = {'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',':',' '};
2901     static const WCHAR ifmodified2W[] = {'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',0};
2902     BOOL ret;
2903     HINTERNET session, request, connection;
2904     DWORD index, len, status, size, start = GetTickCount();
2905     SYSTEMTIME st;
2906     WCHAR today[(sizeof(ifmodifiedW) + WINHTTP_TIME_FORMAT_BUFSIZE)/sizeof(WCHAR) + 3], buffer[32];
2907 
2908     memcpy(today, ifmodifiedW, sizeof(ifmodifiedW));
2909     GetSystemTime(&st);
2910     WinHttpTimeFromSystemTime(&st, &today[sizeof(ifmodifiedW)/sizeof(WCHAR)]);
2911 
2912     session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY,
2913         WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
2914     ok(session != NULL, "WinHttpOpen failed: %u\n", GetLastError());
2915 
2916     connection = WinHttpConnect(session, localhostW, port, 0);
2917     ok(connection != NULL, "WinHttpConnect failed: %u\n", GetLastError());
2918 
2919     request = WinHttpOpenRequest(connection, NULL, pathW, NULL, WINHTTP_NO_REFERER,
2920         WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
2921     ok(request != NULL, "WinHttpOpenrequest failed: %u\n", GetLastError());
2922 
2923     ret = WinHttpSendRequest(request, today, 0, NULL, 0, 0, 0);
2924     ok(ret, "WinHttpSendRequest failed: %u\n", GetLastError());
2925 
2926     ret = WinHttpReceiveResponse(request, NULL);
2927     ok(ret, "WinHttpReceiveResponse failed: %u\n", GetLastError());
2928 
2929     index = 0;
2930     len = sizeof(buffer);
2931     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
2932                               ifmodified2W, buffer, &len, &index);
2933     ok(ret, "failed to get header %u\n", GetLastError());
2934 
2935     status = 0xdeadbeef;
2936     size = sizeof(status);
2937     ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER,
2938                               NULL, &status, &size, NULL);
2939     ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
2940     ok(status == HTTP_STATUS_NOT_MODIFIED, "got %u\n", status);
2941 
2942     size = 0xdeadbeef;
2943     ret = WinHttpQueryDataAvailable(request, &size);
2944     ok(ret, "WinHttpQueryDataAvailable failed: %u\n", GetLastError());
2945     ok(!size, "got %u\n", size);
2946 
2947     WinHttpCloseHandle(request);
2948     WinHttpCloseHandle(connection);
2949     WinHttpCloseHandle(session);
2950     start = GetTickCount() - start;
2951     ok(start <= 2000, "Expected less than 2 seconds for the test, got %u ms\n", start);
2952 }
2953 
2954 static void test_bad_header( int port )
2955 {
2956     static const WCHAR bad_headerW[] =
2957         {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',
2958          't','e','x','t','/','h','t','m','l','\n','\r',0};
2959     static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
2960     static const WCHAR content_typeW[] = {'C','o','n','t','e','n','t','-','T','y','p','e',0};
2961     WCHAR buffer[32];
2962     HINTERNET ses, con, req;
2963     DWORD index, len;
2964     BOOL ret;
2965 
2966     ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
2967     ok( ses != NULL, "failed to open session %u\n", GetLastError() );
2968 
2969     con = WinHttpConnect( ses, localhostW, port, 0 );
2970     ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
2971 
2972     req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
2973     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
2974 
2975     ret = WinHttpAddRequestHeaders( req, bad_headerW, ~0u, WINHTTP_ADDREQ_FLAG_ADD );
2976     ok( ret, "failed to add header %u\n", GetLastError() );
2977 
2978     index = 0;
2979     buffer[0] = 0;
2980     len = sizeof(buffer);
2981     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CUSTOM|WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
2982                                content_typeW, buffer, &len, &index );
2983     ok( ret, "failed to query headers %u\n", GetLastError() );
2984     ok( !lstrcmpW( buffer, text_htmlW ), "got %s\n", wine_dbgstr_w(buffer) );
2985 
2986     WinHttpCloseHandle( req );
2987     WinHttpCloseHandle( con );
2988     WinHttpCloseHandle( ses );
2989 }
2990 
2991 static void test_multiple_reads(int port)
2992 {
2993     static const WCHAR bigW[] = {'b','i','g',0};
2994     HINTERNET ses, con, req;
2995     DWORD total_len = 0;
2996     BOOL ret;
2997 
2998     ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
2999     ok(ses != NULL, "failed to open session %u\n", GetLastError());
3000 
3001     con = WinHttpConnect(ses, localhostW, port, 0);
3002     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
3003 
3004     req = WinHttpOpenRequest(con, NULL, bigW, NULL, NULL, NULL, 0);
3005     ok(req != NULL, "failed to open a request %u\n", GetLastError());
3006 
3007     ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
3008     ok(ret, "failed to send request %u\n", GetLastError());
3009 
3010     ret = WinHttpReceiveResponse(req, NULL);
3011     ok(ret == TRUE, "expected success\n");
3012 
3013     for (;;)
3014     {
3015         DWORD len = 0xdeadbeef;
3016         ret = WinHttpQueryDataAvailable( req, &len );
3017         ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
3018         if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
3019         if (len)
3020         {
3021             DWORD bytes_read;
3022             char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
3023 
3024             ret = WinHttpReadData( req, buf, len, &bytes_read );
3025             ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
3026 
3027             HeapFree( GetProcessHeap(), 0, buf );
3028             if (!bytes_read) break;
3029             total_len += bytes_read;
3030         }
3031         if (!len) break;
3032     }
3033     ok(total_len == BIG_BUFFER_LEN, "got wrong length: 0x%x\n", total_len);
3034 
3035     WinHttpCloseHandle(req);
3036     WinHttpCloseHandle(con);
3037     WinHttpCloseHandle(ses);
3038 }
3039 
3040 static void test_cookies( int port )
3041 {
3042     static const WCHAR cookieW[] = {'/','c','o','o','k','i','e',0};
3043     static const WCHAR cookie2W[] = {'/','c','o','o','k','i','e','2',0};
3044     static const WCHAR cookie3W[] = {'/','c','o','o','k','i','e','3',0};
3045     static const WCHAR cookie4W[] = {'/','c','o','o','k','i','e','4',0};
3046     static const WCHAR cookie5W[] = {'/','c','o','o','k','i','e','5',0};
3047     static const WCHAR cookieheaderW[] =
3048         {'C','o','o','k','i','e',':',' ','n','a','m','e','=','v','a','l','u','e','2','\r','\n',0};
3049     HINTERNET ses, con, req;
3050     DWORD status, size;
3051     BOOL ret;
3052 
3053     ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3054     ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3055 
3056     con = WinHttpConnect( ses, localhostW, port, 0 );
3057     ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3058 
3059     req = WinHttpOpenRequest( con, NULL, cookieW, NULL, NULL, NULL, 0 );
3060     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3061 
3062     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3063     ok( ret, "failed to send request %u\n", GetLastError() );
3064 
3065     ret = WinHttpReceiveResponse( req, NULL );
3066     ok( ret, "failed to receive response %u\n", GetLastError() );
3067 
3068     status = 0xdeadbeef;
3069     size = sizeof(status);
3070     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3071     ok( ret, "failed to query status code %u\n", GetLastError() );
3072     ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3073 
3074     WinHttpCloseHandle( req );
3075 
3076     req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
3077     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3078 
3079     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3080     ok( ret, "failed to send request %u\n", GetLastError() );
3081 
3082     ret = WinHttpReceiveResponse( req, NULL );
3083     ok( ret, "failed to receive response %u\n", GetLastError() );
3084 
3085     status = 0xdeadbeef;
3086     size = sizeof(status);
3087     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3088     ok( ret, "failed to query status code %u\n", GetLastError() );
3089     ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3090 
3091     WinHttpCloseHandle( req );
3092     WinHttpCloseHandle( con );
3093 
3094     con = WinHttpConnect( ses, localhostW, port, 0 );
3095     ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3096 
3097     req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
3098     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3099 
3100     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3101     ok( ret, "failed to send request %u\n", GetLastError() );
3102 
3103     ret = WinHttpReceiveResponse( req, NULL );
3104     ok( ret, "failed to receive response %u\n", GetLastError() );
3105 
3106     status = 0xdeadbeef;
3107     size = sizeof(status);
3108     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3109     ok( ret, "failed to query status code %u\n", GetLastError() );
3110     ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3111 
3112     WinHttpCloseHandle( req );
3113 
3114     req = WinHttpOpenRequest( con, NULL, cookie3W, NULL, NULL, NULL, 0 );
3115     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3116 
3117     ret = WinHttpSendRequest( req, cookieheaderW, ~0u, NULL, 0, 0, 0 );
3118     ok( ret, "failed to send request %u\n", GetLastError() );
3119 
3120     ret = WinHttpReceiveResponse( req, NULL );
3121     ok( ret, "failed to receive response %u\n", GetLastError() );
3122 
3123     status = 0xdeadbeef;
3124     size = sizeof(status);
3125     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3126     ok( ret, "failed to query status code %u\n", GetLastError() );
3127     ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST), "request failed unexpectedly %u\n", status );
3128 
3129     WinHttpCloseHandle( req );
3130     WinHttpCloseHandle( con );
3131     WinHttpCloseHandle( ses );
3132 
3133     ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3134     ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3135 
3136     con = WinHttpConnect( ses, localhostW, port, 0 );
3137     ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3138 
3139     req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
3140     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3141 
3142     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3143     ok( ret, "failed to send request %u\n", GetLastError() );
3144 
3145     ret = WinHttpReceiveResponse( req, NULL );
3146     ok( ret, "failed to receive response %u\n", GetLastError() );
3147 
3148     status = 0xdeadbeef;
3149     size = sizeof(status);
3150     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3151     ok( ret, "failed to query status code %u\n", GetLastError() );
3152     ok( status == HTTP_STATUS_BAD_REQUEST, "request failed unexpectedly %u\n", status );
3153 
3154     WinHttpCloseHandle( req );
3155     WinHttpCloseHandle( con );
3156     WinHttpCloseHandle( ses );
3157 
3158     ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3159     ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3160 
3161     con = WinHttpConnect( ses, localhostW, port, 0 );
3162     ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3163 
3164     req = WinHttpOpenRequest( con, NULL, cookie4W, NULL, NULL, NULL, 0 );
3165     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3166 
3167     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3168     ok( ret, "failed to send request %u\n", GetLastError() );
3169 
3170     ret = WinHttpReceiveResponse( req, NULL );
3171     ok( ret, "failed to receive response %u\n", GetLastError() );
3172 
3173     status = 0xdeadbeef;
3174     size = sizeof(status);
3175     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3176     ok( ret, "failed to query status code %u\n", GetLastError() );
3177     ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3178     WinHttpCloseHandle( req );
3179 
3180     req = WinHttpOpenRequest( con, NULL, cookie5W, NULL, NULL, NULL, 0 );
3181     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3182 
3183     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3184     ok( ret, "failed to send request %u\n", GetLastError() );
3185 
3186     ret = WinHttpReceiveResponse( req, NULL );
3187     ok( ret, "failed to receive response %u\n", GetLastError() );
3188 
3189     status = 0xdeadbeef;
3190     size = sizeof(status);
3191     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3192     ok( ret, "failed to query status code %u\n", GetLastError() );
3193     ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST) /* < win7 */,
3194         "request failed unexpectedly %u\n", status );
3195 
3196     WinHttpCloseHandle( req );
3197     WinHttpCloseHandle( con );
3198     WinHttpCloseHandle( ses );
3199 }
3200 
3201 static void test_connection_info( int port )
3202 {
3203     static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
3204     HINTERNET ses, con, req;
3205     WINHTTP_CONNECTION_INFO info;
3206     DWORD size, error;
3207     BOOL ret;
3208 
3209     ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3210     ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3211 
3212     con = WinHttpConnect( ses, localhostW, port, 0 );
3213     ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3214 
3215     req = WinHttpOpenRequest( con, NULL, basicW, NULL, NULL, NULL, 0 );
3216     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3217 
3218     size = sizeof(info);
3219     SetLastError( 0xdeadbeef );
3220     ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3221     error = GetLastError();
3222     if (!ret && error == ERROR_INVALID_PARAMETER)
3223     {
3224         win_skip( "WINHTTP_OPTION_CONNECTION_INFO not supported\n" );
3225         return;
3226     }
3227     ok( !ret, "unexpected success\n" );
3228     ok( error == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "got %u\n", error );
3229 
3230     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3231     ok( ret, "failed to send request %u\n", GetLastError() );
3232 
3233     size = 0;
3234     SetLastError( 0xdeadbeef );
3235     ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3236     error = GetLastError();
3237     ok( !ret, "unexpected success\n" );
3238     ok( error == ERROR_INSUFFICIENT_BUFFER, "got %u\n", error );
3239 
3240     size = sizeof(info);
3241     memset( &info, 0, sizeof(info) );
3242     ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3243     ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
3244     ok( info.cbSize == sizeof(info) || info.cbSize == sizeof(info) - sizeof(info.cbSize) /* Win7 */, "wrong size %u\n", info.cbSize );
3245 
3246     ret = WinHttpReceiveResponse( req, NULL );
3247     ok( ret, "failed to receive response %u\n", GetLastError() );
3248 
3249     size = sizeof(info);
3250     memset( &info, 0, sizeof(info) );
3251     ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3252     ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
3253     ok( info.cbSize == sizeof(info) || info.cbSize == sizeof(info) - sizeof(info.cbSize) /* Win7 */, "wrong size %u\n", info.cbSize );
3254 
3255     WinHttpCloseHandle( req );
3256     WinHttpCloseHandle( con );
3257     WinHttpCloseHandle( ses );
3258 }
3259 
3260 static void test_credentials(void)
3261 {
3262     static WCHAR userW[] = {'u','s','e','r',0};
3263     static WCHAR passW[] = {'p','a','s','s',0};
3264     static WCHAR proxy_userW[] = {'p','r','o','x','y','u','s','e','r',0};
3265     static WCHAR proxy_passW[] = {'p','r','o','x','y','p','a','s','s',0};
3266     HINTERNET ses, con, req;
3267     DWORD size, error;
3268     WCHAR buffer[32];
3269     BOOL ret;
3270 
3271     ses = WinHttpOpen(test_useragent, 0, proxy_userW, proxy_passW, 0);
3272     ok(ses != NULL, "failed to open session %u\n", GetLastError());
3273 
3274     con = WinHttpConnect(ses, localhostW, 0, 0);
3275     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
3276 
3277     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
3278     ok(req != NULL, "failed to open a request %u\n", GetLastError());
3279 
3280     size = sizeof(buffer)/sizeof(WCHAR);
3281     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
3282     ok(ret, "failed to query proxy username %u\n", GetLastError());
3283     ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3284     ok(!size, "expected 0, got %u\n", size);
3285 
3286     size = sizeof(buffer)/sizeof(WCHAR);
3287     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
3288     ok(ret, "failed to query proxy password %u\n", GetLastError());
3289     ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3290     ok(!size, "expected 0, got %u\n", size);
3291 
3292     ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_USERNAME, proxy_userW, lstrlenW(proxy_userW));
3293     ok(ret, "failed to set username %u\n", GetLastError());
3294 
3295     size = sizeof(buffer)/sizeof(WCHAR);
3296     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
3297     ok(ret, "failed to query proxy username %u\n", GetLastError());
3298     ok(!winetest_strcmpW(buffer, proxy_userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3299     ok(size == lstrlenW(proxy_userW) * sizeof(WCHAR), "unexpected result %u\n", size);
3300 
3301     size = sizeof(buffer)/sizeof(WCHAR);
3302     ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3303     ok(ret, "failed to query username %u\n", GetLastError());
3304     ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3305     ok(!size, "expected 0, got %u\n", size);
3306 
3307     size = sizeof(buffer)/sizeof(WCHAR);
3308     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3309     ok(ret, "failed to query password %u\n", GetLastError());
3310     ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3311     ok(!size, "expected 0, got %u\n", size);
3312 
3313     ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_PASSWORD, proxy_passW, lstrlenW(proxy_passW));
3314     ok(ret, "failed to set proxy password %u\n", GetLastError());
3315 
3316     size = sizeof(buffer)/sizeof(WCHAR);
3317     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
3318     ok(ret, "failed to query proxy password %u\n", GetLastError());
3319     ok(!winetest_strcmpW(buffer, proxy_passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3320     ok(size == lstrlenW(proxy_passW) * sizeof(WCHAR), "unexpected result %u\n", size);
3321 
3322     ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
3323     ok(ret, "failed to set username %u\n", GetLastError());
3324 
3325     size = sizeof(buffer)/sizeof(WCHAR);
3326     ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3327     ok(ret, "failed to query username %u\n", GetLastError());
3328     ok(!winetest_strcmpW(buffer, userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3329     ok(size == lstrlenW(userW) * sizeof(WCHAR), "unexpected result %u\n", size);
3330 
3331     ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW));
3332     ok(ret, "failed to set password %u\n", GetLastError());
3333 
3334     size = sizeof(buffer)/sizeof(WCHAR);
3335     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3336     ok(ret, "failed to query password %u\n", GetLastError());
3337     ok(!winetest_strcmpW(buffer, passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3338     ok(size == lstrlenW(passW) * sizeof(WCHAR), "unexpected result %u\n", size);
3339 
3340     WinHttpCloseHandle(req);
3341 
3342     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
3343     ok(req != NULL, "failed to open a request %u\n", GetLastError());
3344 
3345     SetLastError(0xdeadbeef);
3346     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
3347     error = GetLastError();
3348     ok(!ret, "expected failure\n");
3349     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3350 
3351     SetLastError(0xdeadbeef);
3352     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
3353     error = GetLastError();
3354     ok(!ret, "expected failure\n");
3355     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3356 
3357     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
3358     ok(ret, "failed to set credentials %u\n", GetLastError());
3359 
3360     size = sizeof(buffer)/sizeof(WCHAR);
3361     ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3362     ok(ret, "failed to query username %u\n", GetLastError());
3363     todo_wine {
3364     ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3365     ok(!size, "expected 0, got %u\n", size);
3366     }
3367 
3368     size = sizeof(buffer)/sizeof(WCHAR);
3369     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3370     ok(ret, "failed to query password %u\n", GetLastError());
3371     todo_wine {
3372     ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3373     ok(!size, "expected 0, got %u\n", size);
3374     }
3375 
3376     WinHttpCloseHandle(req);
3377     WinHttpCloseHandle(con);
3378     WinHttpCloseHandle(ses);
3379 }
3380 
3381 static void test_IWinHttpRequest(int port)
3382 {
3383     static const WCHAR data_start[] = {'<','!','D','O','C','T','Y','P','E',' ','h','t','m','l',' ','P','U','B','L','I','C'};
3384     static const WCHAR usernameW[] = {'u','s','e','r','n','a','m','e',0};
3385     static const WCHAR passwordW[] = {'p','a','s','s','w','o','r','d',0};
3386     static const WCHAR url1W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
3387     static const WCHAR url2W[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
3388     static const WCHAR url3W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.',
3389                                   'o','r','g','/','t','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
3390     static const WCHAR method1W[] = {'G','E','T',0};
3391     static const WCHAR method2W[] = {'I','N','V','A','L','I','D',0};
3392     static const WCHAR method3W[] = {'P','O','S','T',0};
3393     static const WCHAR proxy_serverW[] = {'p','r','o','x','y','s','e','r','v','e','r',0};
3394     static const WCHAR bypas_listW[] = {'b','y','p','a','s','s','l','i','s','t',0};
3395     static const WCHAR connectionW[] = {'C','o','n','n','e','c','t','i','o','n',0};
3396     static const WCHAR dateW[] = {'D','a','t','e',0};
3397     static const WCHAR test_dataW[] = {'t','e','s','t','d','a','t','a',128,0};
3398     static const WCHAR utf8W[] = {'u','t','f','-','8',0};
3399     static const WCHAR unauthW[] = {'U','n','a','u','t','h','o','r','i','z','e','d',0};
3400     HRESULT hr;
3401     IWinHttpRequest *req;
3402     BSTR method, url, username, password, response = NULL, status_text = NULL, headers = NULL;
3403     BSTR date, today, connection, value = NULL;
3404     VARIANT async, empty, timeout, body, body2, proxy_server, bypass_list, data, cp;
3405     VARIANT_BOOL succeeded;
3406     LONG status;
3407     WCHAR todayW[WINHTTP_TIME_FORMAT_BUFSIZE];
3408     SYSTEMTIME st;
3409     IStream *stream, *stream2;
3410     LARGE_INTEGER pos;
3411     char buf[128];
3412     WCHAR bufW[128];
3413     DWORD count;
3414 
3415     GetSystemTime( &st );
3416     WinHttpTimeFromSystemTime( &st, todayW );
3417 
3418     CoInitialize( NULL );
3419     hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3420     ok( hr == S_OK, "got %08x\n", hr );
3421 
3422     V_VT( &empty ) = VT_ERROR;
3423     V_ERROR( &empty ) = 0xdeadbeef;
3424 
3425     V_VT( &async ) = VT_BOOL;
3426     V_BOOL( &async ) = VARIANT_FALSE;
3427 
3428     method = SysAllocString( method3W );
3429     url = SysAllocString( url3W );
3430     hr = IWinHttpRequest_Open( req, method, url, async );
3431     ok( hr == S_OK, "got %08x\n", hr );
3432     SysFreeString( method );
3433     SysFreeString( url );
3434 
3435     V_VT( &data ) = VT_BSTR;
3436     V_BSTR( &data ) = SysAllocString( test_dataW );
3437     hr = IWinHttpRequest_Send( req, data );
3438     ok( hr == S_OK || broken(hr == HRESULT_FROM_WIN32(ERROR_WINHTTP_INVALID_SERVER_RESPONSE)),
3439         "got %08x\n", hr );
3440     SysFreeString( V_BSTR( &data ) );
3441 
3442     hr = IWinHttpRequest_Open( req, NULL, NULL, empty );
3443     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3444 
3445     method = SysAllocString( method1W );
3446     hr = IWinHttpRequest_Open( req, method, NULL, empty );
3447     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3448 
3449     hr = IWinHttpRequest_Open( req, method, NULL, async );
3450     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3451 
3452     url = SysAllocString( url1W );
3453     hr = IWinHttpRequest_Open( req, NULL, url, empty );
3454     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3455 
3456     hr = IWinHttpRequest_Abort( req );
3457     ok( hr == S_OK, "got %08x\n", hr );
3458 
3459     hr = IWinHttpRequest_Open( req, method, url, empty );
3460     ok( hr == S_OK, "got %08x\n", hr );
3461 
3462     hr = IWinHttpRequest_Abort( req );
3463     ok( hr == S_OK, "got %08x\n", hr );
3464 
3465     IWinHttpRequest_Release( req );
3466 
3467     hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3468     ok( hr == S_OK, "got %08x\n", hr );
3469 
3470     SysFreeString( url );
3471     url = SysAllocString( url2W );
3472     hr = IWinHttpRequest_Open( req, method, url, async );
3473     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3474 
3475     SysFreeString( method );
3476     method = SysAllocString( method2W );
3477     hr = IWinHttpRequest_Open( req, method, url, async );
3478     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3479 
3480     SysFreeString( method );
3481     method = SysAllocString( method1W );
3482     SysFreeString( url );
3483     url = SysAllocString( url1W );
3484     V_VT( &async ) = VT_ERROR;
3485     V_ERROR( &async ) = DISP_E_PARAMNOTFOUND;
3486     hr = IWinHttpRequest_Open( req, method, url, async );
3487     ok( hr == S_OK, "got %08x\n", hr );
3488 
3489     V_VT( &cp ) = VT_ERROR;
3490     V_ERROR( &cp ) = 0xdeadbeef;
3491     hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3492     ok( hr == S_OK, "got %08x\n", hr );
3493     ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3494     ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3495 
3496     V_VT( &cp ) = VT_UI4;
3497     V_UI4( &cp ) = CP_ACP;
3498     hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3499     ok( hr == S_OK, "got %08x\n", hr );
3500 
3501     V_VT( &cp ) = VT_ERROR;
3502     V_ERROR( &cp ) = 0xdeadbeef;
3503     hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3504     ok( hr == S_OK, "got %08x\n", hr );
3505     ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3506     ok( V_I4( &cp ) == CP_ACP, "got %u\n", V_I4( &cp ) );
3507 
3508     value = SysAllocString( utf8W );
3509     V_VT( &cp ) = VT_BSTR;
3510     V_BSTR( &cp ) = value;
3511     hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3512     ok( hr == S_OK, "got %08x\n", hr );
3513     SysFreeString( value );
3514 
3515     V_VT( &cp ) = VT_ERROR;
3516     V_ERROR( &cp ) = 0xdeadbeef;
3517     hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3518     ok( hr == S_OK, "got %08x\n", hr );
3519     ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3520     ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3521 
3522     hr = IWinHttpRequest_Abort( req );
3523     ok( hr == S_OK, "got %08x\n", hr );
3524 
3525     hr = IWinHttpRequest_Send( req, empty );
3526     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3527 
3528     hr = IWinHttpRequest_Abort( req );
3529     ok( hr == S_OK, "got %08x\n", hr );
3530 
3531     IWinHttpRequest_Release( req );
3532 
3533     hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3534     ok( hr == S_OK, "got %08x\n", hr );
3535 
3536     hr = IWinHttpRequest_get_ResponseText( req, NULL );
3537     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3538 
3539     hr = IWinHttpRequest_get_ResponseText( req, &response );
3540     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3541 
3542     hr = IWinHttpRequest_get_Status( req, NULL );
3543     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3544 
3545     hr = IWinHttpRequest_get_Status( req, &status );
3546     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3547 
3548     hr = IWinHttpRequest_get_StatusText( req, NULL );
3549     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3550 
3551     hr = IWinHttpRequest_get_StatusText( req, &status_text );
3552     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3553 
3554     hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3555     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3556 
3557     hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
3558     ok( hr == S_OK, "got %08x\n", hr );
3559 
3560     hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
3561     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3562 
3563     VariantInit( &proxy_server );
3564     V_VT( &proxy_server ) = VT_ERROR;
3565     VariantInit( &bypass_list );
3566     V_VT( &bypass_list ) = VT_ERROR;
3567     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3568     ok( hr == S_OK, "got %08x\n", hr );
3569 
3570     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3571     ok( hr == S_OK, "got %08x\n", hr );
3572 
3573     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3574     ok( hr == S_OK, "got %08x\n", hr );
3575 
3576     hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
3577     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3578 
3579     hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3580     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3581 
3582     hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
3583     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3584 
3585     connection = SysAllocString( connectionW );
3586     hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
3587     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3588 
3589     hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3590     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3591 
3592     hr = IWinHttpRequest_SetRequestHeader( req, NULL, NULL );
3593     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3594 
3595     date = SysAllocString( dateW );
3596     hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
3597     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3598 
3599     today = SysAllocString( todayW );
3600     hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3601     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3602 
3603     hr = IWinHttpRequest_SetAutoLogonPolicy( req, 0xdeadbeef );
3604     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3605 
3606     hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3607     ok( hr == S_OK, "got %08x\n", hr );
3608 
3609     SysFreeString( method );
3610     method = SysAllocString( method1W );
3611     SysFreeString( url );
3612     url = SysAllocString( url1W );
3613     hr = IWinHttpRequest_Open( req, method, url, async );
3614     ok( hr == S_OK, "got %08x\n", hr );
3615 
3616     hr = IWinHttpRequest_get_ResponseText( req, NULL );
3617     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3618 
3619     hr = IWinHttpRequest_get_ResponseText( req, &response );
3620     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3621 
3622     hr = IWinHttpRequest_get_Status( req, &status );
3623     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3624 
3625     hr = IWinHttpRequest_get_StatusText( req, &status_text );
3626     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3627 
3628     hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3629     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3630 
3631     hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
3632     ok( hr == S_OK, "got %08x\n", hr );
3633 
3634     hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
3635     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3636 
3637     username = SysAllocString( usernameW );
3638     hr = IWinHttpRequest_SetCredentials( req, username, NULL, 0xdeadbeef );
3639     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3640 
3641     password = SysAllocString( passwordW );
3642     hr = IWinHttpRequest_SetCredentials( req, NULL, password, 0xdeadbeef );
3643     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3644 
3645     hr = IWinHttpRequest_SetCredentials( req, username, password, 0xdeadbeef );
3646     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3647 
3648     hr = IWinHttpRequest_SetCredentials( req, NULL, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3649     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3650 
3651     hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3652     ok( hr == S_OK, "got %08x\n", hr );
3653 
3654     V_VT( &proxy_server ) = VT_BSTR;
3655     V_BSTR( &proxy_server ) = SysAllocString( proxy_serverW );
3656     V_VT( &bypass_list ) = VT_BSTR;
3657     V_BSTR( &bypass_list ) = SysAllocString( bypas_listW );
3658     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3659     ok( hr == S_OK, "got %08x\n", hr );
3660 
3661     hr = IWinHttpRequest_SetProxy( req, 0xdeadbeef, proxy_server, bypass_list );
3662     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3663 
3664     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3665     ok( hr == S_OK, "got %08x\n", hr );
3666 
3667     hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3668     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3669 
3670     hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3671     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3672 
3673     hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3674     ok( hr == S_OK, "got %08x\n", hr );
3675 
3676     hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
3677     ok( hr == S_OK, "got %08x\n", hr );
3678 
3679     hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3680     ok( hr == S_OK, "got %08x\n", hr );
3681 
3682     hr = IWinHttpRequest_Send( req, empty );
3683     ok( hr == S_OK, "got %08x\n", hr );
3684 
3685     hr = IWinHttpRequest_Send( req, empty );
3686     ok( hr == S_OK, "got %08x\n", hr );
3687 
3688     hr = IWinHttpRequest_get_ResponseText( req, NULL );
3689     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3690 
3691     hr = IWinHttpRequest_get_ResponseText( req, &response );
3692     ok( hr == S_OK, "got %08x\n", hr );
3693     ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) );
3694     SysFreeString( response );
3695 
3696     hr = IWinHttpRequest_get_Status( req, NULL );
3697     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3698 
3699     status = 0;
3700     hr = IWinHttpRequest_get_Status( req, &status );
3701     ok( hr == S_OK, "got %08x\n", hr );
3702     trace("Status=%d\n", status);
3703 
3704     hr = IWinHttpRequest_get_StatusText( req, NULL );
3705     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3706 
3707     hr = IWinHttpRequest_get_StatusText( req, &status_text );
3708     ok( hr == S_OK, "got %08x\n", hr );
3709     trace("StatusText=%s\n", wine_dbgstr_w(status_text));
3710     SysFreeString( status_text );
3711 
3712     hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3713     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3714 
3715     hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3716     ok( hr == S_OK, "got %08x\n", hr );
3717 
3718     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3719     ok( hr == S_OK, "got %08x\n", hr );
3720 
3721     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3722     ok( hr == S_OK, "got %08x\n", hr );
3723 
3724     hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
3725     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3726 
3727     hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3728     ok( hr == S_OK, "got %08x\n", hr );
3729     SysFreeString( headers );
3730 
3731     hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
3732     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3733 
3734     hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
3735     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3736 
3737     hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3738     ok( hr == S_OK, "got %08x\n", hr );
3739     SysFreeString( value );
3740 
3741     hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3742     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
3743 
3744     hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3745     ok( hr == S_OK, "got %08x\n", hr );
3746 
3747     VariantInit( &timeout );
3748     V_VT( &timeout ) = VT_I4;
3749     V_I4( &timeout ) = 10;
3750     hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
3751     ok( hr == S_OK, "got %08x\n", hr );
3752 
3753     hr = IWinHttpRequest_get_Status( req, &status );
3754     ok( hr == S_OK, "got %08x\n", hr );
3755 
3756     hr = IWinHttpRequest_get_StatusText( req, &status_text );
3757     ok( hr == S_OK, "got %08x\n", hr );
3758     SysFreeString( status_text );
3759 
3760     hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
3761     ok( hr == S_OK, "got %08x\n", hr );
3762 
3763     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3764     ok( hr == S_OK, "got %08x\n", hr );
3765 
3766     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3767     ok( hr == S_OK, "got %08x\n", hr );
3768 
3769     hr = IWinHttpRequest_Send( req, empty );
3770     ok( hr == S_OK, "got %08x\n", hr );
3771 
3772     hr = IWinHttpRequest_get_ResponseText( req, NULL );
3773     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3774 
3775     hr = IWinHttpRequest_get_ResponseText( req, &response );
3776     ok( hr == S_OK, "got %08x\n", hr );
3777     SysFreeString( response );
3778 
3779     hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3780     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3781 
3782     VariantInit( &body );
3783     V_VT( &body ) = VT_ERROR;
3784     hr = IWinHttpRequest_get_ResponseBody( req, &body );
3785     ok( hr == S_OK, "got %08x\n", hr );
3786     ok( V_VT( &body ) == (VT_ARRAY|VT_UI1), "got %08x\n", V_VT( &body ) );
3787 
3788     hr = VariantClear( &body );
3789     ok( hr == S_OK, "got %08x\n", hr );
3790 
3791     VariantInit( &body );
3792     V_VT( &body ) = VT_ERROR;
3793     hr = IWinHttpRequest_get_ResponseStream( req, &body );
3794     ok( hr == S_OK, "got %08x\n", hr );
3795     ok( V_VT( &body ) == VT_UNKNOWN, "got %08x\n", V_VT( &body ) );
3796 
3797     hr = IUnknown_QueryInterface( V_UNKNOWN( &body ), &IID_IStream, (void **)&stream );
3798     ok( hr == S_OK, "got %08x\n", hr );
3799     ok( V_UNKNOWN( &body ) == (IUnknown *)stream, "got different interface pointer\n" );
3800 
3801     buf[0] = 0;
3802     count = 0xdeadbeef;
3803     hr = IStream_Read( stream, buf, 128, &count );
3804     ok( hr == S_OK, "got %08x\n", hr );
3805     ok( count != 0xdeadbeef, "count not set\n" );
3806     ok( buf[0], "no data\n" );
3807 
3808     VariantInit( &body2 );
3809     V_VT( &body2 ) = VT_ERROR;
3810     hr = IWinHttpRequest_get_ResponseStream( req, &body2 );
3811     ok( hr == S_OK, "got %08x\n", hr );
3812     ok( V_VT( &body2 ) == VT_UNKNOWN, "got %08x\n", V_VT( &body2 ) );
3813     ok( V_UNKNOWN( &body ) != V_UNKNOWN( &body2 ), "got same interface pointer\n" );
3814 
3815     hr = IUnknown_QueryInterface( V_UNKNOWN( &body2 ), &IID_IStream, (void **)&stream2 );
3816     ok( hr == S_OK, "got %08x\n", hr );
3817     ok( V_UNKNOWN( &body2 ) == (IUnknown *)stream2, "got different interface pointer\n" );
3818     IStream_Release( stream2 );
3819 
3820     hr = VariantClear( &body );
3821     ok( hr == S_OK, "got %08x\n", hr );
3822 
3823     hr = VariantClear( &body2 );
3824     ok( hr == S_OK, "got %08x\n", hr );
3825 
3826     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3827     ok( hr == S_OK, "got %08x\n", hr );
3828 
3829     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3830     ok( hr == S_OK, "got %08x\n", hr );
3831 
3832     hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3833     ok( hr == S_OK, "got %08x\n", hr );
3834     SysFreeString( headers );
3835 
3836     hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3837     ok( hr == S_OK, "got %08x\n", hr );
3838     SysFreeString( value );
3839 
3840     hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3841     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
3842 
3843     hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3844     ok( hr == S_OK, "got %08x\n", hr );
3845 
3846     hr = IWinHttpRequest_Send( req, empty );
3847     ok( hr == S_OK, "got %08x\n", hr );
3848 
3849     hr = IWinHttpRequest_Abort( req );
3850     ok( hr == S_OK, "got %08x\n", hr );
3851 
3852     hr = IWinHttpRequest_Abort( req );
3853     ok( hr == S_OK, "got %08x\n", hr );
3854 
3855     IWinHttpRequest_Release( req );
3856 
3857     pos.QuadPart = 0;
3858     hr = IStream_Seek( stream, pos, STREAM_SEEK_SET, NULL );
3859     ok( hr == S_OK, "got %08x\n", hr );
3860 
3861     buf[0] = 0;
3862     count = 0xdeadbeef;
3863     hr = IStream_Read( stream, buf, 128, &count );
3864     ok( hr == S_OK, "got %08x\n", hr );
3865     ok( count != 0xdeadbeef, "count not set\n" );
3866     ok( buf[0], "no data\n" );
3867     IStream_Release( stream );
3868 
3869     hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3870     ok( hr == S_OK, "got %08x\n", hr );
3871 
3872     V_VT( &async ) = VT_I4;
3873     V_I4( &async ) = 1;
3874     hr = IWinHttpRequest_Open( req, method, url, async );
3875     ok( hr == S_OK, "got %08x\n", hr );
3876 
3877     hr = IWinHttpRequest_Send( req, empty );
3878     ok( hr == S_OK, "got %08x\n", hr );
3879 
3880     hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
3881     ok( hr == S_OK, "got %08x\n", hr );
3882 
3883     IWinHttpRequest_Release( req );
3884 
3885     SysFreeString( method );
3886     SysFreeString( url );
3887     SysFreeString( username );
3888     SysFreeString( password );
3889     SysFreeString( connection );
3890     SysFreeString( date );
3891     SysFreeString( today );
3892     VariantClear( &proxy_server );
3893     VariantClear( &bypass_list );
3894 
3895     hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3896     ok( hr == S_OK, "got %08x\n", hr );
3897 
3898     url = SysAllocString( test_winehq_https );
3899     method = SysAllocString( method3W );
3900     V_VT( &async ) = VT_BOOL;
3901     V_BOOL( &async ) = VARIANT_FALSE;
3902     hr = IWinHttpRequest_Open( req, method, url, async );
3903     ok( hr == S_OK, "got %08x\n", hr );
3904     SysFreeString( method );
3905     SysFreeString( url );
3906 
3907     hr = IWinHttpRequest_Send( req, empty );
3908     ok( hr == S_OK || broken(hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_INVALID_SERVER_RESPONSE )), "got %08x\n", hr );
3909     if (hr == S_OK)
3910     {
3911         hr = IWinHttpRequest_get_ResponseText( req, &response );
3912         ok( hr == S_OK, "got %08x\n", hr );
3913         ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) );
3914         SysFreeString( response );
3915     }
3916 
3917     IWinHttpRequest_Release( req );
3918 
3919     hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3920     ok( hr == S_OK, "got %08x\n", hr );
3921 
3922     sprintf( buf, "http://localhost:%d/auth", port );
3923     MultiByteToWideChar( CP_ACP, 0, buf, -1, bufW, sizeof(bufW)/sizeof(bufW[0]) );
3924     url = SysAllocString( bufW );
3925     method = SysAllocString( method3W );
3926     V_VT( &async ) = VT_BOOL;
3927     V_BOOL( &async ) = VARIANT_FALSE;
3928     hr = IWinHttpRequest_Open( req, method, url, async );
3929     ok( hr == S_OK, "got %08x\n", hr );
3930     SysFreeString( method );
3931     SysFreeString( url );
3932 
3933     hr = IWinHttpRequest_get_Status( req, &status );
3934     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3935 
3936     V_VT( &data ) = VT_BSTR;
3937     V_BSTR( &data ) = SysAllocString( test_dataW );
3938     hr = IWinHttpRequest_Send( req, data );
3939     ok( hr == S_OK, "got %08x\n", hr );
3940     SysFreeString( V_BSTR( &data ) );
3941 
3942     hr = IWinHttpRequest_get_ResponseText( req, &response );
3943     ok( hr == S_OK, "got %08x\n", hr );
3944     ok( !memcmp( response, unauthW, sizeof(unauthW) ), "got %s\n", wine_dbgstr_w(response) );
3945     SysFreeString( response );
3946 
3947     status = 0xdeadbeef;
3948     hr = IWinHttpRequest_get_Status( req, &status );
3949     ok( hr == S_OK, "got %08x\n", hr );
3950     ok( status == HTTP_STATUS_DENIED, "got %d\n", status );
3951 
3952     IWinHttpRequest_Release( req );
3953 
3954     CoUninitialize();
3955 }
3956 
3957 static void request_get_property(IWinHttpRequest *request, int property, VARIANT *ret)
3958 {
3959     DISPPARAMS params;
3960     VARIANT arg;
3961     HRESULT hr;
3962 
3963     memset(&params, 0, sizeof(params));
3964     params.cNamedArgs = 0;
3965     params.rgdispidNamedArgs = NULL;
3966     params.cArgs = 1;
3967     params.rgvarg = &arg;
3968     VariantInit(&arg);
3969     V_VT(&arg) = VT_I4;
3970     V_I4(&arg) = property;
3971     VariantInit(ret);
3972     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
3973                                 DISPATCH_PROPERTYGET, &params, ret, NULL, NULL);
3974     ok(hr == S_OK, "error %#x\n", hr);
3975 }
3976 
3977 static void test_IWinHttpRequest_Invoke(void)
3978 {
3979     static const WCHAR utf8W[] = {'U','T','F','-','8',0};
3980     static const WCHAR regid[] = {'W','i','n','H','t','t','p','.','W','i','n','H','t','t','p','R','e','q','u','e','s','t','.','5','.','1',0};
3981     WCHAR openW[] = {'O','p','e','n',0};
3982     WCHAR optionW[] = {'O','p','t','i','o','n',0};
3983     OLECHAR *open = openW, *option = optionW;
3984     BSTR utf8;
3985     CLSID clsid;
3986     IWinHttpRequest *request;
3987     IDispatch *dispatch;
3988     DISPID id;
3989     DISPPARAMS params;
3990     VARIANT arg[3], ret;
3991     UINT err;
3992     BOOL bret;
3993     HRESULT hr;
3994 
3995     CoInitialize(NULL);
3996 
3997     hr = CLSIDFromProgID(regid, &clsid);
3998     ok(hr == S_OK, "CLSIDFromProgID error %#x\n", hr);
3999     bret = IsEqualIID(&clsid, &CLSID_WinHttpRequest);
4000     ok(bret || broken(!bret) /* win2003 */, "not expected %s\n", wine_dbgstr_guid(&clsid));
4001 
4002     hr = CoCreateInstance(&CLSID_WinHttpRequest, 0, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&request);
4003     ok(hr == S_OK, "error %#x\n", hr);
4004 
4005     hr = IWinHttpRequest_QueryInterface(request, &IID_IDispatch, (void **)&dispatch);
4006     ok(hr == S_OK, "error %#x\n", hr);
4007     IDispatch_Release(dispatch);
4008 
4009     hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &open, 1, 0x0409, &id);
4010     ok(hr == S_OK, "error %#x\n", hr);
4011     ok(id == DISPID_HTTPREQUEST_OPEN, "expected DISPID_HTTPREQUEST_OPEN, got %u\n", id);
4012 
4013     hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &option, 1, 0x0409, &id);
4014     ok(hr == S_OK, "error %#x\n", hr);
4015     ok(id == DISPID_HTTPREQUEST_OPTION, "expected DISPID_HTTPREQUEST_OPTION, got %u\n", id);
4016 
4017     request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4018     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4019     ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4020 
4021     memset(&params, 0, sizeof(params));
4022     params.cArgs = 2;
4023     params.cNamedArgs = 0;
4024     params.rgvarg = arg;
4025     V_VT(&arg[0]) = VT_I4;
4026     V_I4(&arg[0]) = 1252;
4027     V_VT(&arg[1]) = VT_R8;
4028     V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
4029     VariantInit(&ret);
4030     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
4031                                 DISPATCH_METHOD, &params, NULL, NULL, &err);
4032     ok(hr == S_OK, "error %#x\n", hr);
4033 
4034     request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4035     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4036     ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4037 
4038     memset(&params, 0, sizeof(params));
4039     params.cArgs = 2;
4040     params.cNamedArgs = 0;
4041     params.rgvarg = arg;
4042     V_VT(&arg[0]) = VT_I4;
4043     V_I4(&arg[0]) = 1252;
4044     V_VT(&arg[1]) = VT_R8;
4045     V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
4046     VariantInit(&ret);
4047     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
4048                                 DISPATCH_METHOD | DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
4049     ok(hr == S_OK, "error %#x\n", hr);
4050 
4051     request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4052     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4053     ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4054 
4055     memset(&params, 0, sizeof(params));
4056     params.cArgs = 2;
4057     params.cNamedArgs = 0;
4058     params.rgvarg = arg;
4059     V_VT(&arg[0]) = VT_I4;
4060     V_I4(&arg[0]) = 1252;
4061     V_VT(&arg[1]) = VT_R8;
4062     V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
4063     VariantInit(&ret);
4064     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
4065                                 DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
4066     ok(hr == S_OK, "error %#x\n", hr);
4067 
4068     request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4069     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4070     ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
4071 
4072     memset(&params, 0, sizeof(params));
4073     params.cArgs = 2;
4074     params.cNamedArgs = 0;
4075     params.rgvarg = arg;
4076     V_VT(&arg[0]) = VT_BSTR;
4077     utf8 = SysAllocString(utf8W);
4078     V_BSTR(&arg[0]) = utf8;
4079     V_VT(&arg[1]) = VT_R8;
4080     V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
4081     hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, NULL, NULL, &err);
4082     ok(hr == S_OK, "error %#x\n", hr);
4083 
4084     request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4085     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4086     ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
4087 
4088     VariantInit(&ret);
4089     hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, &err);
4090     ok(hr == S_OK, "error %#x\n", hr);
4091 
4092     request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4093     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4094     ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
4095 
4096     VariantInit(&ret);
4097     hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4098     ok(hr == S_OK, "error %#x\n", hr);
4099 
4100     request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4101     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4102     ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4103 
4104     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
4105     ok(hr == S_OK, "error %#x\n", hr);
4106 
4107     hr = IWinHttpRequest_Invoke(request, 255, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
4108     ok(hr == DISP_E_MEMBERNOTFOUND, "error %#x\n", hr);
4109 
4110     VariantInit(&ret);
4111     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4112     ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
4113 
4114     VariantInit(&ret);
4115     if (0) /* crashes */
4116         hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, &ret, NULL, &err);
4117 
4118     params.cArgs = 1;
4119     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4120     ok(hr == DISP_E_TYPEMISMATCH, "error %#x\n", hr);
4121 
4122     VariantInit(&arg[2]);
4123     params.cArgs = 3;
4124     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4125 todo_wine
4126     ok(hr == S_OK, "error %#x\n", hr);
4127 
4128     VariantInit(&arg[0]);
4129     VariantInit(&arg[1]);
4130     VariantInit(&arg[2]);
4131 
4132     params.cArgs = 1;
4133     V_VT(&arg[0]) = VT_I4;
4134     V_I4(&arg[0]) = WinHttpRequestOption_URLCodePage;
4135     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4136     ok(hr == S_OK, "error %#x\n", hr);
4137 
4138     V_VT(&ret) = 0xdead;
4139     V_I4(&ret) = 0xbeef;
4140     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, &ret, NULL, NULL);
4141     ok(hr == S_OK, "error %#x\n", hr);
4142     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4143     ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4144 
4145     V_VT(&ret) = 0xdead;
4146     V_I4(&ret) = 0xbeef;
4147     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, NULL);
4148     ok(hr == S_OK, "error %#x\n", hr);
4149     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4150     ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4151 
4152     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4153     ok(hr == S_OK, "error %#x\n", hr);
4154 
4155     V_VT(&ret) = 0xdead;
4156     V_I4(&ret) = 0xbeef;
4157     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, &ret, NULL, NULL);
4158     ok(hr == S_OK, "error %#x\n", hr);
4159     ok(V_VT(&ret) == VT_EMPTY, "expected VT_EMPTY, got %d\n", V_VT(&ret));
4160     ok(V_I4(&ret) == 0xbeef || V_I4(&ret) == 0 /* Win8 */, "expected 0xdead, got %d\n", V_I4(&ret));
4161 
4162     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, NULL, NULL, NULL);
4163     ok(hr == S_OK, "error %#x\n", hr);
4164 
4165     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4166     ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
4167 
4168     params.cArgs = 2;
4169     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4170 todo_wine
4171     ok(hr == S_OK, "error %#x\n", hr);
4172 
4173     params.cArgs = 0;
4174     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4175     ok(hr == DISP_E_PARAMNOTFOUND, "error %#x\n", hr);
4176 
4177     SysFreeString(utf8);
4178 
4179     params.cArgs = 1;
4180     V_VT(&arg[0]) = VT_I4;
4181     V_I4(&arg[0]) = AutoLogonPolicy_Never;
4182     VariantInit(&ret);
4183     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_SETAUTOLOGONPOLICY, &IID_NULL, 0,
4184                                 DISPATCH_METHOD, &params, &ret, NULL, NULL);
4185     ok(hr == S_OK, "error %#x\n", hr);
4186 
4187     IWinHttpRequest_Release(request);
4188 
4189     CoUninitialize();
4190 }
4191 
4192 static void test_WinHttpDetectAutoProxyConfigUrl(void)
4193 {
4194     BOOL ret;
4195     WCHAR *url;
4196     DWORD error;
4197 
4198 if (0) /* crashes on some win2k systems */
4199 {
4200     SetLastError(0xdeadbeef);
4201     ret = WinHttpDetectAutoProxyConfigUrl( 0, NULL );
4202     error = GetLastError();
4203     ok( !ret, "expected failure\n" );
4204     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4205 }
4206     url = NULL;
4207     SetLastError(0xdeadbeef);
4208     ret = WinHttpDetectAutoProxyConfigUrl( 0, &url );
4209     error = GetLastError();
4210     ok( !ret, "expected failure\n" );
4211     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4212 
4213 if (0) /* crashes on some win2k systems */
4214 {
4215     SetLastError(0xdeadbeef);
4216     ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, NULL );
4217     error = GetLastError();
4218     ok( !ret, "expected failure\n" );
4219     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4220 }
4221     url = (WCHAR *)0xdeadbeef;
4222     SetLastError(0xdeadbeef);
4223     ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, &url );
4224     error = GetLastError();
4225     if (!ret)
4226     {
4227         ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
4228         ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
4229     }
4230     else
4231     {
4232         trace("%s\n", wine_dbgstr_w(url));
4233         GlobalFree( url );
4234     }
4235 
4236     url = (WCHAR *)0xdeadbeef;
4237     SetLastError(0xdeadbeef);
4238     ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DHCP, &url );
4239     error = GetLastError();
4240     if (!ret)
4241     {
4242         ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
4243         ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
4244     }
4245     else
4246     {
4247         ok( error == ERROR_SUCCESS, "got %u\n", error );
4248         trace("%s\n", wine_dbgstr_w(url));
4249         GlobalFree( url );
4250     }
4251 }
4252 
4253 static void test_WinHttpGetIEProxyConfigForCurrentUser(void)
4254 {
4255     BOOL ret;
4256     DWORD error;
4257     WINHTTP_CURRENT_USER_IE_PROXY_CONFIG cfg;
4258 
4259     memset( &cfg, 0, sizeof(cfg) );
4260 
4261     SetLastError(0xdeadbeef);
4262     ret = WinHttpGetIEProxyConfigForCurrentUser( NULL );
4263     error = GetLastError();
4264     ok( !ret, "expected failure\n" );
4265     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4266 
4267     SetLastError(0xdeadbeef);
4268     ret = WinHttpGetIEProxyConfigForCurrentUser( &cfg );
4269     error = GetLastError();
4270     ok( ret, "expected success\n" );
4271     ok( error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* < win7 */, "got %u\n", error );
4272 
4273     trace("IEProxy.AutoDetect=%d\n", cfg.fAutoDetect);
4274     trace("IEProxy.AutoConfigUrl=%s\n", wine_dbgstr_w(cfg.lpszAutoConfigUrl));
4275     trace("IEProxy.Proxy=%s\n", wine_dbgstr_w(cfg.lpszProxy));
4276     trace("IEProxy.ProxyBypass=%s\n", wine_dbgstr_w(cfg.lpszProxyBypass));
4277     GlobalFree( cfg.lpszAutoConfigUrl );
4278     GlobalFree( cfg.lpszProxy );
4279     GlobalFree( cfg.lpszProxyBypass );
4280 }
4281 
4282 static void test_WinHttpGetProxyForUrl(void)
4283 {
4284     static const WCHAR urlW[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0};
4285     static const WCHAR wpadW[] = {'h','t','t','p',':','/','/','w','p','a','d','/','w','p','a','d','.','d','a','t',0};
4286     static const WCHAR emptyW[] = {0};
4287     BOOL ret;
4288     DWORD error;
4289     HINTERNET session;
4290     WINHTTP_AUTOPROXY_OPTIONS options;
4291     WINHTTP_PROXY_INFO info;
4292 
4293     memset( &options, 0, sizeof(options) );
4294 
4295     SetLastError(0xdeadbeef);
4296     ret = WinHttpGetProxyForUrl( NULL, NULL, NULL, NULL );
4297     error = GetLastError();
4298     ok( !ret, "expected failure\n" );
4299     ok( error == ERROR_INVALID_HANDLE, "got %u\n", error );
4300 
4301     session = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
4302     ok( session != NULL, "failed to open session %u\n", GetLastError() );
4303 
4304     SetLastError(0xdeadbeef);
4305     ret = WinHttpGetProxyForUrl( session, NULL, NULL, NULL );
4306     error = GetLastError();
4307     ok( !ret, "expected failure\n" );
4308     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4309 
4310     SetLastError(0xdeadbeef);
4311     ret = WinHttpGetProxyForUrl( session, emptyW, NULL, NULL );
4312     error = GetLastError();
4313     ok( !ret, "expected failure\n" );
4314     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4315 
4316     SetLastError(0xdeadbeef);
4317     ret = WinHttpGetProxyForUrl( session, urlW, NULL, NULL );
4318     error = GetLastError();
4319     ok( !ret, "expected failure\n" );
4320     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4321 
4322     SetLastError(0xdeadbeef);
4323     ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4324     error = GetLastError();
4325     ok( !ret, "expected failure\n" );
4326     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4327 
4328     options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4329     options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4330 
4331     SetLastError(0xdeadbeef);
4332     ret = WinHttpGetProxyForUrl( session, urlW, &options, NULL );
4333     error = GetLastError();
4334     ok( !ret, "expected failure\n" );
4335     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4336 
4337     options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4338     options.dwAutoDetectFlags = 0;
4339 
4340     SetLastError(0xdeadbeef);
4341     ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4342     error = GetLastError();
4343     ok( !ret, "expected failure\n" );
4344     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4345 
4346     options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT | WINHTTP_AUTOPROXY_CONFIG_URL;
4347     options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4348 
4349     SetLastError(0xdeadbeef);
4350     ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4351     error = GetLastError();
4352     ok( !ret, "expected failure\n" );
4353     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4354 
4355     options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4356     options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4357 
4358     memset( &info, 0, sizeof(info) );
4359     SetLastError(0xdeadbeef);
4360     ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4361     error = GetLastError();
4362     if (ret)
4363     {
4364         ok( error == ERROR_SUCCESS, "got %u\n", error );
4365         trace("Proxy.AccessType=%u\n", info.dwAccessType);
4366         trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
4367         trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
4368         GlobalFree( info.lpszProxy );
4369         GlobalFree( info.lpszProxyBypass );
4370     }
4371 
4372     options.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
4373     options.dwAutoDetectFlags = 0;
4374     options.lpszAutoConfigUrl = wpadW;
4375 
4376     memset( &info, 0, sizeof(info) );
4377     ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4378     if (ret)
4379     {
4380         trace("Proxy.AccessType=%u\n", info.dwAccessType);
4381         trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
4382         trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
4383         GlobalFree( info.lpszProxy );
4384         GlobalFree( info.lpszProxyBypass );
4385     }
4386     WinHttpCloseHandle( session );
4387 }
4388 
4389 static void test_chunked_read(void)
4390 {
4391     static const WCHAR verb[] = {'/','t','e','s','t','c','h','u','n','k','e','d',0};
4392     static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0};
4393     WCHAR header[32];
4394     DWORD len, err;
4395     HINTERNET ses, con = NULL, req = NULL;
4396     BOOL ret;
4397 
4398     trace( "starting chunked read test\n" );
4399 
4400     ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
4401     ok( ses != NULL, "WinHttpOpen failed with error %u\n", GetLastError() );
4402     if (!ses) goto done;
4403 
4404     con = WinHttpConnect( ses, test_winehq, 0, 0 );
4405     ok( con != NULL, "WinHttpConnect failed with error %u\n", GetLastError() );
4406     if (!con) goto done;
4407 
4408     req = WinHttpOpenRequest( con, NULL, verb, NULL, NULL, NULL, 0 );
4409     ok( req != NULL, "WinHttpOpenRequest failed with error %u\n", GetLastError() );
4410     if (!req) goto done;
4411 
4412     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
4413     err = GetLastError();
4414     if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
4415     {
4416         skip("connection failed, skipping\n");
4417         goto done;
4418     }
4419     ok( ret, "WinHttpSendRequest failed with error %u\n", GetLastError() );
4420 
4421     ret = WinHttpReceiveResponse( req, NULL );
4422     ok( ret, "WinHttpReceiveResponse failed with error %u\n", GetLastError() );
4423 
4424     header[0] = 0;
4425     len = sizeof(header);
4426     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, header, &len, 0 );
4427     ok( ret, "failed to get TRANSFER_ENCODING header (error %u)\n", GetLastError() );
4428     ok( !lstrcmpW( header, chunked ), "wrong transfer encoding %s\n", wine_dbgstr_w(header) );
4429     trace( "transfer encoding: %s\n", wine_dbgstr_w(header) );
4430 
4431     header[0] = 0;
4432     len = sizeof(header);
4433     SetLastError( 0xdeadbeef );
4434     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CONTENT_LENGTH, NULL, &header, &len, 0 );
4435     ok( !ret, "unexpected CONTENT_LENGTH header %s\n", wine_dbgstr_w(header) );
4436     ok( GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError() );
4437 
4438     trace( "entering query loop\n" );
4439     for (;;)
4440     {
4441         len = 0xdeadbeef;
4442         ret = WinHttpQueryDataAvailable( req, &len );
4443         ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
4444         if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
4445         trace( "got %u available\n", len );
4446         if (len)
4447         {
4448             DWORD bytes_read;
4449             char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
4450 
4451             ret = WinHttpReadData( req, buf, len, &bytes_read );
4452 
4453             buf[bytes_read] = 0;
4454             trace( "WinHttpReadData -> %d %u\n", ret, bytes_read );
4455             ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
4456             ok( buf[bytes_read - 1] == '\n', "received partial line '%s'\n", buf );
4457 
4458             HeapFree( GetProcessHeap(), 0, buf );
4459             if (!bytes_read) break;
4460         }
4461         if (!len) break;
4462     }
4463     trace( "done\n" );
4464 
4465 done:
4466     if (req) WinHttpCloseHandle( req );
4467     if (con) WinHttpCloseHandle( con );
4468     if (ses) WinHttpCloseHandle( ses );
4469 }
4470 
4471 START_TEST (winhttp)
4472 {
4473     static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
4474     static const WCHAR quitW[] = {'/','q','u','i','t',0};
4475     struct server_info si;
4476     HANDLE thread;
4477     DWORD ret;
4478 
4479     test_OpenRequest();
4480     test_SendRequest();
4481     test_WinHttpTimeFromSystemTime();
4482     test_WinHttpTimeToSystemTime();
4483     test_WinHttpAddHeaders();
4484     test_secure_connection();
4485     test_request_parameter_defaults();
4486     test_QueryOption();
4487     test_set_default_proxy_config();
4488     test_empty_headers_param();
4489     test_Timeouts();
4490     test_resolve_timeout();
4491     test_credentials();
4492     test_IWinHttpRequest_Invoke();
4493     test_WinHttpDetectAutoProxyConfigUrl();
4494     test_WinHttpGetIEProxyConfigForCurrentUser();
4495     test_WinHttpGetProxyForUrl();
4496     test_chunked_read();
4497 
4498     si.event = CreateEventW(NULL, 0, 0, NULL);
4499     si.port = 7532;
4500 
4501     thread = CreateThread(NULL, 0, server_thread, (LPVOID)&si, 0, NULL);
4502     ok(thread != NULL, "failed to create thread %u\n", GetLastError());
4503 
4504     ret = WaitForSingleObject(si.event, 10000);
4505     ok(ret == WAIT_OBJECT_0, "failed to start winhttp test server %u\n", GetLastError());
4506     if (ret != WAIT_OBJECT_0)
4507     {
4508         CloseHandle(thread);
4509         return;
4510     }
4511 
4512     test_IWinHttpRequest(si.port);
4513     test_connection_info(si.port);
4514     test_basic_request(si.port, NULL, basicW);
4515     test_no_headers(si.port);
4516     test_no_content(si.port);
4517     test_head_request(si.port);
4518     test_not_modified(si.port);
4519     test_basic_authentication(si.port);
4520     test_multi_authentication(si.port);
4521     test_large_data_authentication(si.port);
4522     test_bad_header(si.port);
4523     test_multiple_reads(si.port);
4524     test_cookies(si.port);
4525 
4526     /* send the basic request again to shutdown the server thread */
4527     test_basic_request(si.port, NULL, quitW);
4528 
4529     WaitForSingleObject(thread, 3000);
4530     CloseHandle(thread);
4531 }
4532