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