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     ret = WinHttpReceiveResponse(req, NULL);
3232     ok(ret == TRUE, "expected success\n");
3233 
3234     for (;;)
3235     {
3236         DWORD len = 0xdeadbeef;
3237         ret = WinHttpQueryDataAvailable( req, &len );
3238         ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
3239         if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
3240         if (len)
3241         {
3242             DWORD bytes_read;
3243             char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
3244 
3245             ret = WinHttpReadData( req, buf, len, &bytes_read );
3246             ok(ret, "WinHttpReadData failed: %u.\n", GetLastError());
3247             ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
3248 
3249             HeapFree( GetProcessHeap(), 0, buf );
3250             if (!bytes_read) break;
3251             total_len += bytes_read;
3252         }
3253         if (!len) break;
3254     }
3255     ok(total_len == BIG_BUFFER_LEN, "got wrong length: 0x%x\n", total_len);
3256 
3257     WinHttpCloseHandle(req);
3258     WinHttpCloseHandle(con);
3259     WinHttpCloseHandle(ses);
3260 }
3261 
3262 static void test_cookies( int port )
3263 {
3264     static const WCHAR cookieW[] = {'/','c','o','o','k','i','e',0};
3265     static const WCHAR cookie2W[] = {'/','c','o','o','k','i','e','2',0};
3266     static const WCHAR cookie3W[] = {'/','c','o','o','k','i','e','3',0};
3267     static const WCHAR cookie4W[] = {'/','c','o','o','k','i','e','4',0};
3268     static const WCHAR cookie5W[] = {'/','c','o','o','k','i','e','5',0};
3269     static const WCHAR cookieheaderW[] =
3270         {'C','o','o','k','i','e',':',' ','n','a','m','e','=','v','a','l','u','e','2','\r','\n',0};
3271     HINTERNET ses, con, req;
3272     DWORD status, size;
3273     BOOL ret;
3274 
3275     ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3276     ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3277 
3278     con = WinHttpConnect( ses, localhostW, port, 0 );
3279     ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3280 
3281     req = WinHttpOpenRequest( con, NULL, cookieW, NULL, NULL, NULL, 0 );
3282     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3283 
3284     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3285     ok( ret, "failed to send request %u\n", GetLastError() );
3286 
3287     ret = WinHttpReceiveResponse( req, NULL );
3288     ok( ret, "failed to receive response %u\n", GetLastError() );
3289 
3290     status = 0xdeadbeef;
3291     size = sizeof(status);
3292     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3293     ok( ret, "failed to query status code %u\n", GetLastError() );
3294     ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3295 
3296     WinHttpCloseHandle( req );
3297 
3298     req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
3299     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3300 
3301     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3302     ok( ret, "failed to send request %u\n", GetLastError() );
3303 
3304     ret = WinHttpReceiveResponse( req, NULL );
3305     ok( ret, "failed to receive response %u\n", GetLastError() );
3306 
3307     status = 0xdeadbeef;
3308     size = sizeof(status);
3309     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3310     ok( ret, "failed to query status code %u\n", GetLastError() );
3311     ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3312 
3313     WinHttpCloseHandle( req );
3314     WinHttpCloseHandle( con );
3315 
3316     con = WinHttpConnect( ses, localhostW, port, 0 );
3317     ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3318 
3319     req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
3320     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3321 
3322     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3323     ok( ret, "failed to send request %u\n", GetLastError() );
3324 
3325     ret = WinHttpReceiveResponse( req, NULL );
3326     ok( ret, "failed to receive response %u\n", GetLastError() );
3327 
3328     status = 0xdeadbeef;
3329     size = sizeof(status);
3330     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3331     ok( ret, "failed to query status code %u\n", GetLastError() );
3332     ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3333 
3334     WinHttpCloseHandle( req );
3335 
3336     req = WinHttpOpenRequest( con, NULL, cookie3W, NULL, NULL, NULL, 0 );
3337     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3338 
3339     ret = WinHttpSendRequest( req, cookieheaderW, ~0u, NULL, 0, 0, 0 );
3340     ok( ret, "failed to send request %u\n", GetLastError() );
3341 
3342     ret = WinHttpReceiveResponse( req, NULL );
3343     ok( ret, "failed to receive response %u\n", GetLastError() );
3344 
3345     status = 0xdeadbeef;
3346     size = sizeof(status);
3347     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3348     ok( ret, "failed to query status code %u\n", GetLastError() );
3349     ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST), "request failed unexpectedly %u\n", status );
3350 
3351     WinHttpCloseHandle( req );
3352     WinHttpCloseHandle( con );
3353     WinHttpCloseHandle( ses );
3354 
3355     ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3356     ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3357 
3358     con = WinHttpConnect( ses, localhostW, port, 0 );
3359     ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3360 
3361     req = WinHttpOpenRequest( con, NULL, cookie2W, NULL, NULL, NULL, 0 );
3362     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3363 
3364     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3365     ok( ret, "failed to send request %u\n", GetLastError() );
3366 
3367     ret = WinHttpReceiveResponse( req, NULL );
3368     ok( ret, "failed to receive response %u\n", GetLastError() );
3369 
3370     status = 0xdeadbeef;
3371     size = sizeof(status);
3372     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3373     ok( ret, "failed to query status code %u\n", GetLastError() );
3374     ok( status == HTTP_STATUS_BAD_REQUEST, "request failed unexpectedly %u\n", status );
3375 
3376     WinHttpCloseHandle( req );
3377     WinHttpCloseHandle( con );
3378     WinHttpCloseHandle( ses );
3379 
3380     ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3381     ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3382 
3383     con = WinHttpConnect( ses, localhostW, port, 0 );
3384     ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3385 
3386     req = WinHttpOpenRequest( con, NULL, cookie4W, NULL, NULL, NULL, 0 );
3387     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3388 
3389     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3390     ok( ret, "failed to send request %u\n", GetLastError() );
3391 
3392     ret = WinHttpReceiveResponse( req, NULL );
3393     ok( ret, "failed to receive response %u\n", GetLastError() );
3394 
3395     status = 0xdeadbeef;
3396     size = sizeof(status);
3397     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3398     ok( ret, "failed to query status code %u\n", GetLastError() );
3399     ok( status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status );
3400     WinHttpCloseHandle( req );
3401 
3402     req = WinHttpOpenRequest( con, NULL, cookie5W, NULL, NULL, NULL, 0 );
3403     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3404 
3405     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3406     ok( ret, "failed to send request %u\n", GetLastError() );
3407 
3408     ret = WinHttpReceiveResponse( req, NULL );
3409     ok( ret, "failed to receive response %u\n", GetLastError() );
3410 
3411     status = 0xdeadbeef;
3412     size = sizeof(status);
3413     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3414     ok( ret, "failed to query status code %u\n", GetLastError() );
3415     ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST) /* < win7 */,
3416         "request failed unexpectedly %u\n", status );
3417 
3418     WinHttpCloseHandle( req );
3419     WinHttpCloseHandle( con );
3420     WinHttpCloseHandle( ses );
3421 }
3422 
3423 static void do_request( HINTERNET con, const WCHAR *obj, DWORD flags )
3424 {
3425     HINTERNET req;
3426     DWORD status, size;
3427     BOOL ret;
3428 
3429     req = WinHttpOpenRequest( con, NULL, obj, NULL, NULL, NULL, flags );
3430     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3431 
3432     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3433     ok( ret, "failed to send request %u\n", GetLastError() );
3434 
3435     ret = WinHttpReceiveResponse( req, NULL );
3436     ok( ret, "failed to receive response %u\n", GetLastError() );
3437 
3438     status = 0xdeadbeef;
3439     size = sizeof(status);
3440     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3441     ok( ret, "failed to query status code %u\n", GetLastError() );
3442     ok( status == HTTP_STATUS_OK || broken(status == HTTP_STATUS_BAD_REQUEST) /* < win7 */,
3443         "request %s with flags %08x failed %u\n", wine_dbgstr_w(obj), flags, status );
3444     WinHttpCloseHandle( req );
3445 }
3446 
3447 static void test_request_path_escapes( int port )
3448 {
3449     static const WCHAR objW[] =
3450         {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','o','n','e','?',0x1f,0x7f,' ','!','"','#',
3451          '$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_','`',
3452          '{','|','}','~','\r','\n',0};
3453     static const WCHAR obj2W[] =
3454         {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','t','w','o','?',0x1f,0x7f,' ','!','"','#',
3455          '$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_','`',
3456          '{','|','}','~','\r','\n',0};
3457     static const WCHAR obj3W[] =
3458         {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','t','h','r','e','e','?',0x1f,0x7f,' ','!',
3459          '"','#','$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^',
3460          '_','`','{','|','}','~','\r','\n',0};
3461     static const WCHAR obj4W[] =
3462         {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','f','o','u','r','?',0x1f,0x7f,' ','!','"',
3463          '#','$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_',
3464          '`','{','|','}','~','\r','\n',0};
3465     static const WCHAR obj5W[] =
3466         {'/','e','s','c','a','p','e','&','t','e','x','t','=','o','n','e',0x80,0x7f,0x7e,0};
3467     static const WCHAR obj6W[] =
3468         {'/','e','s','c','a','p','e','&','t','e','x','t','=','t','w','o',0x80,0x7f,0x7e,0};
3469     static const WCHAR obj7W[] =
3470         {'/','e','s','c','a','p','e','&','t','e','x','t','=',0x541b,0x306e,0x540d,0x306f,0};
3471     HINTERNET ses, con;
3472 
3473     ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3474     ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3475 
3476     con = WinHttpConnect( ses, localhostW, port, 0 );
3477     ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3478 
3479     do_request( con, objW, 0 );
3480     do_request( con, obj2W, WINHTTP_FLAG_ESCAPE_PERCENT );
3481     do_request( con, obj3W, WINHTTP_FLAG_ESCAPE_DISABLE );
3482     do_request( con, obj4W, WINHTTP_FLAG_ESCAPE_DISABLE_QUERY );
3483     do_request( con, obj5W, 0 );
3484     do_request( con, obj6W, WINHTTP_FLAG_ESCAPE_DISABLE );
3485     do_request( con, obj7W, WINHTTP_FLAG_ESCAPE_DISABLE );
3486 
3487     WinHttpCloseHandle( con );
3488     WinHttpCloseHandle( ses );
3489 }
3490 
3491 static void test_connection_info( int port )
3492 {
3493     static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
3494     HINTERNET ses, con, req;
3495     WINHTTP_CONNECTION_INFO info;
3496     DWORD size, error;
3497     BOOL ret;
3498 
3499     ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
3500     ok( ses != NULL, "failed to open session %u\n", GetLastError() );
3501 
3502     con = WinHttpConnect( ses, localhostW, port, 0 );
3503     ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
3504 
3505     req = WinHttpOpenRequest( con, NULL, basicW, NULL, NULL, NULL, 0 );
3506     ok( req != NULL, "failed to open a request %u\n", GetLastError() );
3507 
3508     size = sizeof(info);
3509     SetLastError( 0xdeadbeef );
3510     ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3511     error = GetLastError();
3512     if (!ret && error == ERROR_INVALID_PARAMETER)
3513     {
3514         win_skip( "WINHTTP_OPTION_CONNECTION_INFO not supported\n" );
3515         return;
3516     }
3517     ok( !ret, "unexpected success\n" );
3518     ok( error == ERROR_WINHTTP_INCORRECT_HANDLE_STATE, "got %u\n", error );
3519 
3520     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3521     ok( ret, "failed to send request %u\n", GetLastError() );
3522 
3523     size = 0;
3524     SetLastError( 0xdeadbeef );
3525     ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3526     error = GetLastError();
3527     ok( !ret, "unexpected success\n" );
3528     ok( error == ERROR_INSUFFICIENT_BUFFER, "got %u\n", error );
3529 
3530     size = sizeof(info);
3531     memset( &info, 0, sizeof(info) );
3532     ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3533     ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
3534     ok( info.cbSize == sizeof(info) || info.cbSize == sizeof(info) - sizeof(info.cbSize) /* Win7 */, "wrong size %u\n", info.cbSize );
3535 
3536     ret = WinHttpReceiveResponse( req, NULL );
3537     ok( ret, "failed to receive response %u\n", GetLastError() );
3538 
3539     size = sizeof(info);
3540     memset( &info, 0, sizeof(info) );
3541     ret = WinHttpQueryOption( req, WINHTTP_OPTION_CONNECTION_INFO, &info, &size );
3542     ok( ret, "failed to retrieve connection info %u\n", GetLastError() );
3543     ok( info.cbSize == sizeof(info) || info.cbSize == sizeof(info) - sizeof(info.cbSize) /* Win7 */, "wrong size %u\n", info.cbSize );
3544 
3545     WinHttpCloseHandle( req );
3546     WinHttpCloseHandle( con );
3547     WinHttpCloseHandle( ses );
3548 }
3549 
3550 static void test_passport_auth( int port )
3551 {
3552     static const WCHAR passportW[] =
3553         {'/','p','a','s','s','p','o','r','t',0};
3554     static const WCHAR foundW[] =
3555         {'F','o','u','n','d',0};
3556     static const WCHAR unauthorizedW[] =
3557         {'U','n','a','u','t','h','o','r','i','z','e','d',0};
3558     static const WCHAR headersW[] =
3559         {'H','T','T','P','/','1','.','1',' ','4','0','1',' ','F','o','u','n','d','\r','\n',
3560          'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','0','\r','\n',
3561          'L','o','c','a','t','i','o','n',':',' ','/','\r','\n',
3562          'W','W','W','-','A','u','t','h','e','n','t','i','c','a','t','e',':',' ',
3563          'P','a','s','s','p','o','r','t','1','.','4','\r','\n','\r','\n',0};
3564     HINTERNET ses, con, req;
3565     DWORD status, size, option;
3566     WCHAR buf[128];
3567     BOOL ret;
3568 
3569     ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
3570     ok( ses != NULL, "got %u\n", GetLastError() );
3571 
3572     option = WINHTTP_ENABLE_PASSPORT_AUTH;
3573     ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH, &option, sizeof(option) );
3574     ok( ret, "got %u\n", GetLastError() );
3575 
3576     con = WinHttpConnect( ses, localhostW, port, 0 );
3577     ok( con != NULL, "got %u\n", GetLastError() );
3578 
3579     req = WinHttpOpenRequest( con, NULL, passportW, NULL, NULL, NULL, 0 );
3580     ok( req != NULL, "got %u\n", GetLastError() );
3581 
3582     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
3583     ok( ret, "got %u\n", GetLastError() );
3584 
3585     ret = WinHttpReceiveResponse( req, NULL );
3586     ok( ret || broken(!ret && GetLastError() == ERROR_WINHTTP_LOGIN_FAILURE) /* winxp */, "got %u\n", GetLastError() );
3587     if (!ret && GetLastError() == ERROR_WINHTTP_LOGIN_FAILURE)
3588     {
3589         win_skip("no support for Passport redirects\n");
3590         goto cleanup;
3591     }
3592 
3593     status = 0xdeadbeef;
3594     size = sizeof(status);
3595     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
3596     ok( ret, "got %u\n", GetLastError() );
3597     ok( status == HTTP_STATUS_DENIED, "got %u\n", status );
3598 
3599     buf[0] = 0;
3600     size = sizeof(buf);
3601     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_TEXT, NULL, buf, &size, NULL );
3602     ok( ret, "got %u\n", GetLastError() );
3603     ok( !lstrcmpW(foundW, buf) || broken(!lstrcmpW(unauthorizedW, buf)) /* < win7 */, "got %s\n", wine_dbgstr_w(buf) );
3604 
3605     buf[0] = 0;
3606     size = sizeof(buf);
3607     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_RAW_HEADERS_CRLF, NULL, buf, &size, NULL );
3608     ok( ret || broken(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) /* < win7 */, "got %u\n", GetLastError() );
3609     if (ret)
3610     {
3611         ok( size == lstrlenW(headersW) * sizeof(WCHAR), "got %u\n", size );
3612         ok( !lstrcmpW(headersW, buf), "got %s\n", wine_dbgstr_w(buf) );
3613     }
3614 
3615 cleanup:
3616     WinHttpCloseHandle( req );
3617     WinHttpCloseHandle( con );
3618     WinHttpCloseHandle( ses );
3619 }
3620 
3621 static void test_credentials(void)
3622 {
3623     static WCHAR userW[] = {'u','s','e','r',0};
3624     static WCHAR passW[] = {'p','a','s','s',0};
3625     static WCHAR proxy_userW[] = {'p','r','o','x','y','u','s','e','r',0};
3626     static WCHAR proxy_passW[] = {'p','r','o','x','y','p','a','s','s',0};
3627     HINTERNET ses, con, req;
3628     DWORD size, error;
3629     WCHAR buffer[32];
3630     BOOL ret;
3631 
3632     ses = WinHttpOpen(test_useragent, 0, proxy_userW, proxy_passW, 0);
3633     ok(ses != NULL, "failed to open session %u\n", GetLastError());
3634 
3635     con = WinHttpConnect(ses, localhostW, 0, 0);
3636     ok(con != NULL, "failed to open a connection %u\n", GetLastError());
3637 
3638     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
3639     ok(req != NULL, "failed to open a request %u\n", GetLastError());
3640 
3641     size = ARRAY_SIZE(buffer);
3642     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
3643     ok(ret, "failed to query proxy username %u\n", GetLastError());
3644     ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3645     ok(!size, "expected 0, got %u\n", size);
3646 
3647     size = ARRAY_SIZE(buffer);
3648     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
3649     ok(ret, "failed to query proxy password %u\n", GetLastError());
3650     ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3651     ok(!size, "expected 0, got %u\n", size);
3652 
3653     ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_USERNAME, proxy_userW, lstrlenW(proxy_userW));
3654     ok(ret, "failed to set username %u\n", GetLastError());
3655 
3656     size = ARRAY_SIZE(buffer);
3657     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_USERNAME, &buffer, &size);
3658     ok(ret, "failed to query proxy username %u\n", GetLastError());
3659     ok(!winetest_strcmpW(buffer, proxy_userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3660     ok(size == lstrlenW(proxy_userW) * sizeof(WCHAR), "unexpected result %u\n", size);
3661 
3662     size = ARRAY_SIZE(buffer);
3663     ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3664     ok(ret, "failed to query username %u\n", GetLastError());
3665     ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3666     ok(!size, "expected 0, got %u\n", size);
3667 
3668     size = ARRAY_SIZE(buffer);
3669     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3670     ok(ret, "failed to query password %u\n", GetLastError());
3671     ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3672     ok(!size, "expected 0, got %u\n", size);
3673 
3674     ret = WinHttpSetOption(req, WINHTTP_OPTION_PROXY_PASSWORD, proxy_passW, lstrlenW(proxy_passW));
3675     ok(ret, "failed to set proxy password %u\n", GetLastError());
3676 
3677     size = ARRAY_SIZE(buffer);
3678     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PROXY_PASSWORD, &buffer, &size);
3679     ok(ret, "failed to query proxy password %u\n", GetLastError());
3680     ok(!winetest_strcmpW(buffer, proxy_passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3681     ok(size == lstrlenW(proxy_passW) * sizeof(WCHAR), "unexpected result %u\n", size);
3682 
3683     ret = WinHttpSetOption(req, WINHTTP_OPTION_USERNAME, userW, lstrlenW(userW));
3684     ok(ret, "failed to set username %u\n", GetLastError());
3685 
3686     size = ARRAY_SIZE(buffer);
3687     ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3688     ok(ret, "failed to query username %u\n", GetLastError());
3689     ok(!winetest_strcmpW(buffer, userW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3690     ok(size == lstrlenW(userW) * sizeof(WCHAR), "unexpected result %u\n", size);
3691 
3692     ret = WinHttpSetOption(req, WINHTTP_OPTION_PASSWORD, passW, lstrlenW(passW));
3693     ok(ret, "failed to set password %u\n", GetLastError());
3694 
3695     size = ARRAY_SIZE(buffer);
3696     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3697     ok(ret, "failed to query password %u\n", GetLastError());
3698     ok(!winetest_strcmpW(buffer, passW), "unexpected result %s\n", wine_dbgstr_w(buffer));
3699     ok(size == lstrlenW(passW) * sizeof(WCHAR), "unexpected result %u\n", size);
3700 
3701     WinHttpCloseHandle(req);
3702 
3703     req = WinHttpOpenRequest(con, NULL, NULL, NULL, NULL, NULL, 0);
3704     ok(req != NULL, "failed to open a request %u\n", GetLastError());
3705 
3706     SetLastError(0xdeadbeef);
3707     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, NULL, NULL);
3708     error = GetLastError();
3709     ok(!ret, "expected failure\n");
3710     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3711 
3712     SetLastError(0xdeadbeef);
3713     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, NULL, passW, NULL);
3714     error = GetLastError();
3715     ok(!ret, "expected failure\n");
3716     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
3717 
3718     ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL);
3719     ok(ret, "failed to set credentials %u\n", GetLastError());
3720 
3721     size = ARRAY_SIZE(buffer);
3722     ret = WinHttpQueryOption(req, WINHTTP_OPTION_USERNAME, &buffer, &size);
3723     ok(ret, "failed to query username %u\n", GetLastError());
3724     todo_wine {
3725     ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3726     ok(!size, "expected 0, got %u\n", size);
3727     }
3728 
3729     size = ARRAY_SIZE(buffer);
3730     ret = WinHttpQueryOption(req, WINHTTP_OPTION_PASSWORD, &buffer, &size);
3731     ok(ret, "failed to query password %u\n", GetLastError());
3732     todo_wine {
3733     ok(!buffer[0], "unexpected result %s\n", wine_dbgstr_w(buffer));
3734     ok(!size, "expected 0, got %u\n", size);
3735     }
3736 
3737     WinHttpCloseHandle(req);
3738     WinHttpCloseHandle(con);
3739     WinHttpCloseHandle(ses);
3740 }
3741 
3742 static void test_IWinHttpRequest(int port)
3743 {
3744     static const WCHAR data_start[] = {'<','!','D','O','C','T','Y','P','E',' ','h','t','m','l',' ','P','U','B','L','I','C'};
3745     static const WCHAR usernameW[] = {'u','s','e','r','n','a','m','e',0};
3746     static const WCHAR passwordW[] = {'p','a','s','s','w','o','r','d',0};
3747     static const WCHAR url1W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
3748     static const WCHAR url2W[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
3749     static const WCHAR url3W[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.',
3750                                   'o','r','g','/','t','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
3751     static const WCHAR method1W[] = {'G','E','T',0};
3752     static const WCHAR method2W[] = {'I','N','V','A','L','I','D',0};
3753     static const WCHAR method3W[] = {'P','O','S','T',0};
3754     static const WCHAR proxy_serverW[] = {'p','r','o','x','y','s','e','r','v','e','r',0};
3755     static const WCHAR bypas_listW[] = {'b','y','p','a','s','s','l','i','s','t',0};
3756     static const WCHAR connectionW[] = {'C','o','n','n','e','c','t','i','o','n',0};
3757     static const WCHAR dateW[] = {'D','a','t','e',0};
3758     static const WCHAR test_dataW[] = {'t','e','s','t','d','a','t','a',128,0};
3759     static const WCHAR utf8W[] = {'u','t','f','-','8',0};
3760     static const WCHAR unauthW[] = {'U','n','a','u','t','h','o','r','i','z','e','d',0};
3761     HRESULT hr;
3762     IWinHttpRequest *req;
3763     BSTR method, url, username, password, response = NULL, status_text = NULL, headers = NULL;
3764     BSTR date, today, connection, value = NULL;
3765     VARIANT async, empty, timeout, body, body2, proxy_server, bypass_list, data, cp;
3766     VARIANT_BOOL succeeded;
3767     LONG status;
3768     WCHAR todayW[WINHTTP_TIME_FORMAT_BUFSIZE];
3769     SYSTEMTIME st;
3770     IStream *stream, *stream2;
3771     LARGE_INTEGER pos;
3772     char buf[128];
3773     WCHAR bufW[128];
3774     DWORD count;
3775 
3776     GetSystemTime( &st );
3777     WinHttpTimeFromSystemTime( &st, todayW );
3778 
3779     CoInitialize( NULL );
3780     hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3781     ok( hr == S_OK, "got %08x\n", hr );
3782 
3783     V_VT( &empty ) = VT_ERROR;
3784     V_ERROR( &empty ) = 0xdeadbeef;
3785 
3786     V_VT( &async ) = VT_BOOL;
3787     V_BOOL( &async ) = VARIANT_FALSE;
3788 
3789     method = SysAllocString( method3W );
3790     url = SysAllocString( url3W );
3791     hr = IWinHttpRequest_Open( req, method, url, async );
3792     ok( hr == S_OK, "got %08x\n", hr );
3793     SysFreeString( method );
3794     SysFreeString( url );
3795 
3796     V_VT( &data ) = VT_BSTR;
3797     V_BSTR( &data ) = SysAllocString( test_dataW );
3798     hr = IWinHttpRequest_Send( req, data );
3799     ok( hr == S_OK || hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_INVALID_SERVER_RESPONSE ), "got %08x\n", hr );
3800     SysFreeString( V_BSTR( &data ) );
3801     if (hr != S_OK) goto done;
3802 
3803     hr = IWinHttpRequest_Open( req, NULL, NULL, empty );
3804     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3805 
3806     method = SysAllocString( method1W );
3807     hr = IWinHttpRequest_Open( req, method, NULL, empty );
3808     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3809 
3810     hr = IWinHttpRequest_Open( req, method, NULL, async );
3811     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3812 
3813     url = SysAllocString( url1W );
3814     hr = IWinHttpRequest_Open( req, NULL, url, empty );
3815     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3816 
3817     hr = IWinHttpRequest_Abort( req );
3818     ok( hr == S_OK, "got %08x\n", hr );
3819 
3820     hr = IWinHttpRequest_Open( req, method, url, empty );
3821     ok( hr == S_OK, "got %08x\n", hr );
3822 
3823     hr = IWinHttpRequest_Abort( req );
3824     ok( hr == S_OK, "got %08x\n", hr );
3825 
3826     IWinHttpRequest_Release( req );
3827 
3828     hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3829     ok( hr == S_OK, "got %08x\n", hr );
3830 
3831     SysFreeString( url );
3832     url = SysAllocString( url2W );
3833     hr = IWinHttpRequest_Open( req, method, url, async );
3834     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3835 
3836     SysFreeString( method );
3837     method = SysAllocString( method2W );
3838     hr = IWinHttpRequest_Open( req, method, url, async );
3839     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ), "got %08x\n", hr );
3840 
3841     SysFreeString( method );
3842     method = SysAllocString( method1W );
3843     SysFreeString( url );
3844     url = SysAllocString( url1W );
3845     V_VT( &async ) = VT_ERROR;
3846     V_ERROR( &async ) = DISP_E_PARAMNOTFOUND;
3847     hr = IWinHttpRequest_Open( req, method, url, async );
3848     ok( hr == S_OK, "got %08x\n", hr );
3849 
3850     V_VT( &cp ) = VT_ERROR;
3851     V_ERROR( &cp ) = 0xdeadbeef;
3852     hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3853     ok( hr == S_OK, "got %08x\n", hr );
3854     ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3855     ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3856 
3857     V_VT( &cp ) = VT_UI4;
3858     V_UI4( &cp ) = CP_ACP;
3859     hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3860     ok( hr == S_OK, "got %08x\n", hr );
3861 
3862     V_VT( &cp ) = VT_ERROR;
3863     V_ERROR( &cp ) = 0xdeadbeef;
3864     hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3865     ok( hr == S_OK, "got %08x\n", hr );
3866     ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3867     ok( V_I4( &cp ) == CP_ACP, "got %u\n", V_I4( &cp ) );
3868 
3869     value = SysAllocString( utf8W );
3870     V_VT( &cp ) = VT_BSTR;
3871     V_BSTR( &cp ) = value;
3872     hr = IWinHttpRequest_put_Option( req, WinHttpRequestOption_URLCodePage, cp );
3873     ok( hr == S_OK, "got %08x\n", hr );
3874     SysFreeString( value );
3875 
3876     V_VT( &cp ) = VT_ERROR;
3877     V_ERROR( &cp ) = 0xdeadbeef;
3878     hr = IWinHttpRequest_get_Option( req, WinHttpRequestOption_URLCodePage, &cp );
3879     ok( hr == S_OK, "got %08x\n", hr );
3880     ok( V_VT( &cp ) == VT_I4, "got %08x\n", V_VT( &cp ) );
3881     ok( V_I4( &cp ) == CP_UTF8, "got %u\n", V_I4( &cp ) );
3882 
3883     hr = IWinHttpRequest_Abort( req );
3884     ok( hr == S_OK, "got %08x\n", hr );
3885 
3886     hr = IWinHttpRequest_Send( req, empty );
3887     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3888 
3889     hr = IWinHttpRequest_Abort( req );
3890     ok( hr == S_OK, "got %08x\n", hr );
3891 
3892     IWinHttpRequest_Release( req );
3893 
3894     hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
3895     ok( hr == S_OK, "got %08x\n", hr );
3896 
3897     hr = IWinHttpRequest_get_ResponseText( req, NULL );
3898     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3899 
3900     hr = IWinHttpRequest_get_ResponseText( req, &response );
3901     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3902 
3903     hr = IWinHttpRequest_get_Status( req, NULL );
3904     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3905 
3906     hr = IWinHttpRequest_get_Status( req, &status );
3907     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3908 
3909     hr = IWinHttpRequest_get_StatusText( req, NULL );
3910     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3911 
3912     hr = IWinHttpRequest_get_StatusText( req, &status_text );
3913     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3914 
3915     hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3916     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3917 
3918     hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
3919     ok( hr == S_OK, "got %08x\n", hr );
3920 
3921     hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
3922     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3923 
3924     VariantInit( &proxy_server );
3925     V_VT( &proxy_server ) = VT_ERROR;
3926     VariantInit( &bypass_list );
3927     V_VT( &bypass_list ) = VT_ERROR;
3928     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3929     ok( hr == S_OK, "got %08x\n", hr );
3930 
3931     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
3932     ok( hr == S_OK, "got %08x\n", hr );
3933 
3934     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
3935     ok( hr == S_OK, "got %08x\n", hr );
3936 
3937     hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
3938     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3939 
3940     hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
3941     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3942 
3943     hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
3944     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3945 
3946     connection = SysAllocString( connectionW );
3947     hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
3948     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3949 
3950     hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
3951     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3952 
3953     hr = IWinHttpRequest_SetRequestHeader( req, NULL, NULL );
3954     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3955 
3956     date = SysAllocString( dateW );
3957     hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
3958     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3959 
3960     today = SysAllocString( todayW );
3961     hr = IWinHttpRequest_SetRequestHeader( req, date, today );
3962     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN ), "got %08x\n", hr );
3963 
3964     hr = IWinHttpRequest_SetAutoLogonPolicy( req, 0xdeadbeef );
3965     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3966 
3967     hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
3968     ok( hr == S_OK, "got %08x\n", hr );
3969 
3970     SysFreeString( method );
3971     method = SysAllocString( method1W );
3972     SysFreeString( url );
3973     url = SysAllocString( url1W );
3974     hr = IWinHttpRequest_Open( req, method, url, async );
3975     ok( hr == S_OK, "got %08x\n", hr );
3976 
3977     hr = IWinHttpRequest_get_ResponseText( req, NULL );
3978     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3979 
3980     hr = IWinHttpRequest_get_ResponseText( req, &response );
3981     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3982 
3983     hr = IWinHttpRequest_get_Status( req, &status );
3984     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3985 
3986     hr = IWinHttpRequest_get_StatusText( req, &status_text );
3987     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
3988 
3989     hr = IWinHttpRequest_get_ResponseBody( req, NULL );
3990     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3991 
3992     hr = IWinHttpRequest_SetTimeouts( req, 10000, 10000, 10000, 10000 );
3993     ok( hr == S_OK, "got %08x\n", hr );
3994 
3995     hr = IWinHttpRequest_SetCredentials( req, NULL, NULL, 0xdeadbeef );
3996     ok( hr == E_INVALIDARG, "got %08x\n", hr );
3997 
3998     username = SysAllocString( usernameW );
3999     hr = IWinHttpRequest_SetCredentials( req, username, NULL, 0xdeadbeef );
4000     ok( hr == E_INVALIDARG, "got %08x\n", hr );
4001 
4002     password = SysAllocString( passwordW );
4003     hr = IWinHttpRequest_SetCredentials( req, NULL, password, 0xdeadbeef );
4004     ok( hr == E_INVALIDARG, "got %08x\n", hr );
4005 
4006     hr = IWinHttpRequest_SetCredentials( req, username, password, 0xdeadbeef );
4007     ok( hr == E_INVALIDARG, "got %08x\n", hr );
4008 
4009     hr = IWinHttpRequest_SetCredentials( req, NULL, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
4010     ok( hr == E_INVALIDARG, "got %08x\n", hr );
4011 
4012     hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
4013     ok( hr == S_OK, "got %08x\n", hr );
4014 
4015     V_VT( &proxy_server ) = VT_BSTR;
4016     V_BSTR( &proxy_server ) = SysAllocString( proxy_serverW );
4017     V_VT( &bypass_list ) = VT_BSTR;
4018     V_BSTR( &bypass_list ) = SysAllocString( bypas_listW );
4019     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
4020     ok( hr == S_OK, "got %08x\n", hr );
4021 
4022     hr = IWinHttpRequest_SetProxy( req, 0xdeadbeef, proxy_server, bypass_list );
4023     ok( hr == E_INVALIDARG, "got %08x\n", hr );
4024 
4025     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
4026     ok( hr == S_OK, "got %08x\n", hr );
4027 
4028     hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
4029     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
4030 
4031     hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
4032     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
4033 
4034     hr = IWinHttpRequest_SetRequestHeader( req, date, today );
4035     ok( hr == S_OK, "got %08x\n", hr );
4036 
4037     hr = IWinHttpRequest_SetRequestHeader( req, date, NULL );
4038     ok( hr == S_OK, "got %08x\n", hr );
4039 
4040     hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
4041     ok( hr == S_OK, "got %08x\n", hr );
4042 
4043     hr = IWinHttpRequest_Send( req, empty );
4044     ok( hr == S_OK, "got %08x\n", hr );
4045 
4046     hr = IWinHttpRequest_Send( req, empty );
4047     ok( hr == S_OK, "got %08x\n", hr );
4048 
4049     hr = IWinHttpRequest_get_ResponseText( req, NULL );
4050     ok( hr == E_INVALIDARG, "got %08x\n", hr );
4051 
4052     hr = IWinHttpRequest_get_ResponseText( req, &response );
4053     ok( hr == S_OK, "got %08x\n", hr );
4054     ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) );
4055     SysFreeString( response );
4056 
4057     hr = IWinHttpRequest_get_Status( req, NULL );
4058     ok( hr == E_INVALIDARG, "got %08x\n", hr );
4059 
4060     status = 0;
4061     hr = IWinHttpRequest_get_Status( req, &status );
4062     ok( hr == S_OK, "got %08x\n", hr );
4063     trace("Status=%d\n", status);
4064 
4065     hr = IWinHttpRequest_get_StatusText( req, NULL );
4066     ok( hr == E_INVALIDARG, "got %08x\n", hr );
4067 
4068     hr = IWinHttpRequest_get_StatusText( req, &status_text );
4069     ok( hr == S_OK, "got %08x\n", hr );
4070     trace("StatusText=%s\n", wine_dbgstr_w(status_text));
4071     SysFreeString( status_text );
4072 
4073     hr = IWinHttpRequest_get_ResponseBody( req, NULL );
4074     ok( hr == E_INVALIDARG, "got %08x\n", hr );
4075 
4076     hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
4077     ok( hr == S_OK, "got %08x\n", hr );
4078 
4079     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
4080     ok( hr == S_OK, "got %08x\n", hr );
4081 
4082     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
4083     ok( hr == S_OK, "got %08x\n", hr );
4084 
4085     hr = IWinHttpRequest_GetAllResponseHeaders( req, NULL );
4086     ok( hr == E_INVALIDARG, "got %08x\n", hr );
4087 
4088     hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
4089     ok( hr == S_OK, "got %08x\n", hr );
4090     SysFreeString( headers );
4091 
4092     hr = IWinHttpRequest_GetResponseHeader( req, NULL, NULL );
4093     ok( hr == E_INVALIDARG, "got %08x\n", hr );
4094 
4095     hr = IWinHttpRequest_GetResponseHeader( req, connection, NULL );
4096     ok( hr == E_INVALIDARG, "got %08x\n", hr );
4097 
4098     hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
4099     ok( hr == S_OK, "got %08x\n", hr );
4100     SysFreeString( value );
4101 
4102     hr = IWinHttpRequest_SetRequestHeader( req, date, today );
4103     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
4104 
4105     hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
4106     ok( hr == S_OK, "got %08x\n", hr );
4107 
4108     VariantInit( &timeout );
4109     V_VT( &timeout ) = VT_I4;
4110     V_I4( &timeout ) = 10;
4111     hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
4112     ok( hr == S_OK, "got %08x\n", hr );
4113 
4114     hr = IWinHttpRequest_get_Status( req, &status );
4115     ok( hr == S_OK, "got %08x\n", hr );
4116 
4117     hr = IWinHttpRequest_get_StatusText( req, &status_text );
4118     ok( hr == S_OK, "got %08x\n", hr );
4119     SysFreeString( status_text );
4120 
4121     hr = IWinHttpRequest_SetCredentials( req, username, password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER );
4122     ok( hr == S_OK, "got %08x\n", hr );
4123 
4124     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
4125     ok( hr == S_OK, "got %08x\n", hr );
4126 
4127     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
4128     ok( hr == S_OK, "got %08x\n", hr );
4129 
4130     hr = IWinHttpRequest_Send( req, empty );
4131     ok( hr == S_OK, "got %08x\n", hr );
4132 
4133     hr = IWinHttpRequest_get_ResponseText( req, NULL );
4134     ok( hr == E_INVALIDARG, "got %08x\n", hr );
4135 
4136     hr = IWinHttpRequest_get_ResponseText( req, &response );
4137     ok( hr == S_OK, "got %08x\n", hr );
4138     SysFreeString( response );
4139 
4140     hr = IWinHttpRequest_get_ResponseBody( req, NULL );
4141     ok( hr == E_INVALIDARG, "got %08x\n", hr );
4142 
4143     VariantInit( &body );
4144     V_VT( &body ) = VT_ERROR;
4145     hr = IWinHttpRequest_get_ResponseBody( req, &body );
4146     ok( hr == S_OK, "got %08x\n", hr );
4147     ok( V_VT( &body ) == (VT_ARRAY|VT_UI1), "got %08x\n", V_VT( &body ) );
4148 
4149     hr = VariantClear( &body );
4150     ok( hr == S_OK, "got %08x\n", hr );
4151 
4152     VariantInit( &body );
4153     V_VT( &body ) = VT_ERROR;
4154     hr = IWinHttpRequest_get_ResponseStream( req, &body );
4155     ok( hr == S_OK, "got %08x\n", hr );
4156     ok( V_VT( &body ) == VT_UNKNOWN, "got %08x\n", V_VT( &body ) );
4157 
4158     hr = IUnknown_QueryInterface( V_UNKNOWN( &body ), &IID_IStream, (void **)&stream );
4159     ok( hr == S_OK, "got %08x\n", hr );
4160     ok( V_UNKNOWN( &body ) == (IUnknown *)stream, "got different interface pointer\n" );
4161 
4162     buf[0] = 0;
4163     count = 0xdeadbeef;
4164     hr = IStream_Read( stream, buf, 128, &count );
4165     ok( hr == S_OK, "got %08x\n", hr );
4166     ok( count != 0xdeadbeef, "count not set\n" );
4167     ok( buf[0], "no data\n" );
4168 
4169     VariantInit( &body2 );
4170     V_VT( &body2 ) = VT_ERROR;
4171     hr = IWinHttpRequest_get_ResponseStream( req, &body2 );
4172     ok( hr == S_OK, "got %08x\n", hr );
4173     ok( V_VT( &body2 ) == VT_UNKNOWN, "got %08x\n", V_VT( &body2 ) );
4174     ok( V_UNKNOWN( &body ) != V_UNKNOWN( &body2 ), "got same interface pointer\n" );
4175 
4176     hr = IUnknown_QueryInterface( V_UNKNOWN( &body2 ), &IID_IStream, (void **)&stream2 );
4177     ok( hr == S_OK, "got %08x\n", hr );
4178     ok( V_UNKNOWN( &body2 ) == (IUnknown *)stream2, "got different interface pointer\n" );
4179     IStream_Release( stream2 );
4180 
4181     hr = VariantClear( &body );
4182     ok( hr == S_OK, "got %08x\n", hr );
4183 
4184     hr = VariantClear( &body2 );
4185     ok( hr == S_OK, "got %08x\n", hr );
4186 
4187     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_PROXY, proxy_server, bypass_list );
4188     ok( hr == S_OK, "got %08x\n", hr );
4189 
4190     hr = IWinHttpRequest_SetProxy( req, HTTPREQUEST_PROXYSETTING_DIRECT, proxy_server, bypass_list );
4191     ok( hr == S_OK, "got %08x\n", hr );
4192 
4193     hr = IWinHttpRequest_GetAllResponseHeaders( req, &headers );
4194     ok( hr == S_OK, "got %08x\n", hr );
4195     SysFreeString( headers );
4196 
4197     hr = IWinHttpRequest_GetResponseHeader( req, connection, &value );
4198     ok( hr == S_OK, "got %08x\n", hr );
4199     SysFreeString( value );
4200 
4201     hr = IWinHttpRequest_SetRequestHeader( req, date, today );
4202     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND ), "got %08x\n", hr );
4203 
4204     hr = IWinHttpRequest_SetAutoLogonPolicy( req, AutoLogonPolicy_OnlyIfBypassProxy );
4205     ok( hr == S_OK, "got %08x\n", hr );
4206 
4207     hr = IWinHttpRequest_Send( req, empty );
4208     ok( hr == S_OK, "got %08x\n", hr );
4209 
4210     hr = IWinHttpRequest_Abort( req );
4211     ok( hr == S_OK, "got %08x\n", hr );
4212 
4213     hr = IWinHttpRequest_Abort( req );
4214     ok( hr == S_OK, "got %08x\n", hr );
4215 
4216     IWinHttpRequest_Release( req );
4217 
4218     pos.QuadPart = 0;
4219     hr = IStream_Seek( stream, pos, STREAM_SEEK_SET, NULL );
4220     ok( hr == S_OK, "got %08x\n", hr );
4221 
4222     buf[0] = 0;
4223     count = 0xdeadbeef;
4224     hr = IStream_Read( stream, buf, 128, &count );
4225     ok( hr == S_OK, "got %08x\n", hr );
4226     ok( count != 0xdeadbeef, "count not set\n" );
4227     ok( buf[0], "no data\n" );
4228     IStream_Release( stream );
4229 
4230     hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
4231     ok( hr == S_OK, "got %08x\n", hr );
4232 
4233     V_VT( &async ) = VT_I4;
4234     V_I4( &async ) = 1;
4235     hr = IWinHttpRequest_Open( req, method, url, async );
4236     ok( hr == S_OK, "got %08x\n", hr );
4237 
4238     hr = IWinHttpRequest_Send( req, empty );
4239     ok( hr == S_OK, "got %08x\n", hr );
4240 
4241     hr = IWinHttpRequest_WaitForResponse( req, timeout, &succeeded );
4242     ok( hr == S_OK, "got %08x\n", hr );
4243 
4244     IWinHttpRequest_Release( req );
4245 
4246     SysFreeString( method );
4247     SysFreeString( url );
4248     SysFreeString( username );
4249     SysFreeString( password );
4250     SysFreeString( connection );
4251     SysFreeString( date );
4252     SysFreeString( today );
4253     VariantClear( &proxy_server );
4254     VariantClear( &bypass_list );
4255 
4256     hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
4257     ok( hr == S_OK, "got %08x\n", hr );
4258 
4259     url = SysAllocString( test_winehq_https );
4260     method = SysAllocString( method3W );
4261     V_VT( &async ) = VT_BOOL;
4262     V_BOOL( &async ) = VARIANT_FALSE;
4263     hr = IWinHttpRequest_Open( req, method, url, async );
4264     ok( hr == S_OK, "got %08x\n", hr );
4265     SysFreeString( method );
4266     SysFreeString( url );
4267 
4268     hr = IWinHttpRequest_Send( req, empty );
4269     ok( hr == S_OK || hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_INVALID_SERVER_RESPONSE ) ||
4270         hr == SEC_E_ILLEGAL_MESSAGE /* winxp */, "got %08x\n", hr );
4271     if (hr != S_OK) goto done;
4272 
4273     hr = IWinHttpRequest_get_ResponseText( req, &response );
4274     ok( hr == S_OK, "got %08x\n", hr );
4275     ok( !memcmp(response, data_start, sizeof(data_start)), "got %s\n", wine_dbgstr_wn(response, 32) );
4276     SysFreeString( response );
4277 
4278     IWinHttpRequest_Release( req );
4279 
4280     hr = CoCreateInstance( &CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IWinHttpRequest, (void **)&req );
4281     ok( hr == S_OK, "got %08x\n", hr );
4282 
4283     sprintf( buf, "http://localhost:%d/auth", port );
4284     MultiByteToWideChar( CP_ACP, 0, buf, -1, bufW, ARRAY_SIZE( bufW ));
4285     url = SysAllocString( bufW );
4286     method = SysAllocString( method3W );
4287     V_VT( &async ) = VT_BOOL;
4288     V_BOOL( &async ) = VARIANT_FALSE;
4289     hr = IWinHttpRequest_Open( req, method, url, async );
4290     ok( hr == S_OK, "got %08x\n", hr );
4291     SysFreeString( method );
4292     SysFreeString( url );
4293 
4294     hr = IWinHttpRequest_get_Status( req, &status );
4295     ok( hr == HRESULT_FROM_WIN32( ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND ), "got %08x\n", hr );
4296 
4297     V_VT( &data ) = VT_BSTR;
4298     V_BSTR( &data ) = SysAllocString( test_dataW );
4299     hr = IWinHttpRequest_Send( req, data );
4300     ok( hr == S_OK, "got %08x\n", hr );
4301     SysFreeString( V_BSTR( &data ) );
4302 
4303     hr = IWinHttpRequest_get_ResponseText( req, &response );
4304     ok( hr == S_OK, "got %08x\n", hr );
4305     ok( !memcmp( response, unauthW, sizeof(unauthW) ), "got %s\n", wine_dbgstr_w(response) );
4306     SysFreeString( response );
4307 
4308     status = 0xdeadbeef;
4309     hr = IWinHttpRequest_get_Status( req, &status );
4310     ok( hr == S_OK, "got %08x\n", hr );
4311     ok( status == HTTP_STATUS_DENIED, "got %d\n", status );
4312 
4313 done:
4314     IWinHttpRequest_Release( req );
4315     CoUninitialize();
4316 }
4317 
4318 static void request_get_property(IWinHttpRequest *request, int property, VARIANT *ret)
4319 {
4320     DISPPARAMS params;
4321     VARIANT arg;
4322     HRESULT hr;
4323 
4324     memset(&params, 0, sizeof(params));
4325     params.cNamedArgs = 0;
4326     params.rgdispidNamedArgs = NULL;
4327     params.cArgs = 1;
4328     params.rgvarg = &arg;
4329     VariantInit(&arg);
4330     V_VT(&arg) = VT_I4;
4331     V_I4(&arg) = property;
4332     VariantInit(ret);
4333     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
4334                                 DISPATCH_PROPERTYGET, &params, ret, NULL, NULL);
4335     ok(hr == S_OK, "error %#x\n", hr);
4336 }
4337 
4338 static void test_IWinHttpRequest_Invoke(void)
4339 {
4340     static const WCHAR utf8W[] = {'U','T','F','-','8',0};
4341     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};
4342     WCHAR openW[] = {'O','p','e','n',0};
4343     WCHAR optionW[] = {'O','p','t','i','o','n',0};
4344     OLECHAR *open = openW, *option = optionW;
4345     BSTR utf8;
4346     CLSID clsid;
4347     IWinHttpRequest *request;
4348     IDispatch *dispatch;
4349     DISPID id;
4350     DISPPARAMS params;
4351     VARIANT arg[3], ret;
4352     UINT err;
4353     BOOL bret;
4354     HRESULT hr;
4355 
4356     CoInitialize(NULL);
4357 
4358     hr = CLSIDFromProgID(regid, &clsid);
4359     ok(hr == S_OK, "CLSIDFromProgID error %#x\n", hr);
4360     bret = IsEqualIID(&clsid, &CLSID_WinHttpRequest);
4361     ok(bret || broken(!bret) /* win2003 */, "not expected %s\n", wine_dbgstr_guid(&clsid));
4362 
4363     hr = CoCreateInstance(&CLSID_WinHttpRequest, 0, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&request);
4364     ok(hr == S_OK, "error %#x\n", hr);
4365 
4366     hr = IWinHttpRequest_QueryInterface(request, &IID_IDispatch, (void **)&dispatch);
4367     ok(hr == S_OK, "error %#x\n", hr);
4368     IDispatch_Release(dispatch);
4369 
4370     hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &open, 1, 0x0409, &id);
4371     ok(hr == S_OK, "error %#x\n", hr);
4372     ok(id == DISPID_HTTPREQUEST_OPEN, "expected DISPID_HTTPREQUEST_OPEN, got %u\n", id);
4373 
4374     hr = IWinHttpRequest_GetIDsOfNames(request, &IID_NULL, &option, 1, 0x0409, &id);
4375     ok(hr == S_OK, "error %#x\n", hr);
4376     ok(id == DISPID_HTTPREQUEST_OPTION, "expected DISPID_HTTPREQUEST_OPTION, got %u\n", id);
4377 
4378     request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4379     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4380     ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4381 
4382     memset(&params, 0, sizeof(params));
4383     params.cArgs = 2;
4384     params.cNamedArgs = 0;
4385     params.rgvarg = arg;
4386     V_VT(&arg[0]) = VT_I4;
4387     V_I4(&arg[0]) = 1252;
4388     V_VT(&arg[1]) = VT_R8;
4389     V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
4390     VariantInit(&ret);
4391     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
4392                                 DISPATCH_METHOD, &params, NULL, NULL, &err);
4393     ok(hr == S_OK, "error %#x\n", hr);
4394 
4395     request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4396     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4397     ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4398 
4399     memset(&params, 0, sizeof(params));
4400     params.cArgs = 2;
4401     params.cNamedArgs = 0;
4402     params.rgvarg = arg;
4403     V_VT(&arg[0]) = VT_I4;
4404     V_I4(&arg[0]) = 1252;
4405     V_VT(&arg[1]) = VT_R8;
4406     V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
4407     VariantInit(&ret);
4408     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
4409                                 DISPATCH_METHOD | DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
4410     ok(hr == S_OK, "error %#x\n", hr);
4411 
4412     request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4413     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4414     ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4415 
4416     memset(&params, 0, sizeof(params));
4417     params.cArgs = 2;
4418     params.cNamedArgs = 0;
4419     params.rgvarg = arg;
4420     V_VT(&arg[0]) = VT_I4;
4421     V_I4(&arg[0]) = 1252;
4422     V_VT(&arg[1]) = VT_R8;
4423     V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
4424     VariantInit(&ret);
4425     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0,
4426                                 DISPATCH_PROPERTYPUT, &params, NULL, NULL, &err);
4427     ok(hr == S_OK, "error %#x\n", hr);
4428 
4429     request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4430     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4431     ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
4432 
4433     memset(&params, 0, sizeof(params));
4434     params.cArgs = 2;
4435     params.cNamedArgs = 0;
4436     params.rgvarg = arg;
4437     V_VT(&arg[0]) = VT_BSTR;
4438     utf8 = SysAllocString(utf8W);
4439     V_BSTR(&arg[0]) = utf8;
4440     V_VT(&arg[1]) = VT_R8;
4441     V_R8(&arg[1]) = 2.0; /* WinHttpRequestOption_URLCodePage */
4442     hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, NULL, NULL, &err);
4443     ok(hr == S_OK, "error %#x\n", hr);
4444 
4445     request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4446     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4447     ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
4448 
4449     VariantInit(&ret);
4450     hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, &err);
4451     ok(hr == S_OK, "error %#x\n", hr);
4452 
4453     request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4454     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4455     ok(V_I4(&ret) == 1252, "expected 1252, got %d\n", V_I4(&ret));
4456 
4457     VariantInit(&ret);
4458     hr = IWinHttpRequest_Invoke(request, id, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4459     ok(hr == S_OK, "error %#x\n", hr);
4460 
4461     request_get_property(request, WinHttpRequestOption_URLCodePage, &ret);
4462     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4463     ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4464 
4465     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
4466     ok(hr == S_OK, "error %#x\n", hr);
4467 
4468     hr = IWinHttpRequest_Invoke(request, 255, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
4469     ok(hr == DISP_E_MEMBERNOTFOUND, "error %#x\n", hr);
4470 
4471     VariantInit(&ret);
4472     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4473     ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
4474 
4475     VariantInit(&ret);
4476     if (0) /* crashes */
4477         hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, NULL, &ret, NULL, &err);
4478 
4479     params.cArgs = 1;
4480     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4481     ok(hr == DISP_E_TYPEMISMATCH, "error %#x\n", hr);
4482 
4483     VariantInit(&arg[2]);
4484     params.cArgs = 3;
4485     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &params, &ret, NULL, &err);
4486 todo_wine
4487     ok(hr == S_OK, "error %#x\n", hr);
4488 
4489     VariantInit(&arg[0]);
4490     VariantInit(&arg[1]);
4491     VariantInit(&arg[2]);
4492 
4493     params.cArgs = 1;
4494     V_VT(&arg[0]) = VT_I4;
4495     V_I4(&arg[0]) = WinHttpRequestOption_URLCodePage;
4496     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4497     ok(hr == S_OK, "error %#x\n", hr);
4498 
4499     V_VT(&ret) = 0xdead;
4500     V_I4(&ret) = 0xbeef;
4501     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, &ret, NULL, NULL);
4502     ok(hr == S_OK, "error %#x\n", hr);
4503     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4504     ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4505 
4506     V_VT(&ret) = 0xdead;
4507     V_I4(&ret) = 0xbeef;
4508     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD, &params, &ret, NULL, NULL);
4509     ok(hr == S_OK, "error %#x\n", hr);
4510     ok(V_VT(&ret) == VT_I4, "expected VT_I4, got %d\n", V_VT(&ret));
4511     ok(V_I4(&ret) == CP_UTF8, "expected CP_UTF8, got %d\n", V_I4(&ret));
4512 
4513     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_METHOD|DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4514     ok(hr == S_OK, "error %#x\n", hr);
4515 
4516     V_VT(&ret) = 0xdead;
4517     V_I4(&ret) = 0xbeef;
4518     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, &ret, NULL, NULL);
4519     ok(hr == S_OK, "error %#x\n", hr);
4520     ok(V_VT(&ret) == VT_EMPTY, "expected VT_EMPTY, got %d\n", V_VT(&ret));
4521     ok(V_I4(&ret) == 0xbeef || V_I4(&ret) == 0 /* Win8 */, "expected 0xdead, got %d\n", V_I4(&ret));
4522 
4523     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, 0, &params, NULL, NULL, NULL);
4524     ok(hr == S_OK, "error %#x\n", hr);
4525 
4526     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_IUnknown, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4527     ok(hr == DISP_E_UNKNOWNINTERFACE, "error %#x\n", hr);
4528 
4529     params.cArgs = 2;
4530     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4531 todo_wine
4532     ok(hr == S_OK, "error %#x\n", hr);
4533 
4534     params.cArgs = 0;
4535     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_OPTION, &IID_NULL, 0, DISPATCH_PROPERTYGET, &params, NULL, NULL, NULL);
4536     ok(hr == DISP_E_PARAMNOTFOUND, "error %#x\n", hr);
4537 
4538     SysFreeString(utf8);
4539 
4540     params.cArgs = 1;
4541     V_VT(&arg[0]) = VT_I4;
4542     V_I4(&arg[0]) = AutoLogonPolicy_Never;
4543     VariantInit(&ret);
4544     hr = IWinHttpRequest_Invoke(request, DISPID_HTTPREQUEST_SETAUTOLOGONPOLICY, &IID_NULL, 0,
4545                                 DISPATCH_METHOD, &params, &ret, NULL, NULL);
4546     ok(hr == S_OK, "error %#x\n", hr);
4547 
4548     IWinHttpRequest_Release(request);
4549 
4550     CoUninitialize();
4551 }
4552 
4553 static void test_WinHttpDetectAutoProxyConfigUrl(void)
4554 {
4555     BOOL ret;
4556     WCHAR *url;
4557     DWORD error;
4558 
4559     SetLastError(0xdeadbeef);
4560     ret = WinHttpDetectAutoProxyConfigUrl( 0, NULL );
4561     error = GetLastError();
4562     ok( !ret, "expected failure\n" );
4563     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4564 
4565     url = NULL;
4566     SetLastError(0xdeadbeef);
4567     ret = WinHttpDetectAutoProxyConfigUrl( 0, &url );
4568     error = GetLastError();
4569     ok( !ret, "expected failure\n" );
4570     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4571 
4572     SetLastError(0xdeadbeef);
4573     ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, NULL );
4574     error = GetLastError();
4575     ok( !ret, "expected failure\n" );
4576     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4577 
4578     url = (WCHAR *)0xdeadbeef;
4579     SetLastError(0xdeadbeef);
4580     ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DNS_A, &url );
4581     error = GetLastError();
4582     if (!ret)
4583     {
4584         ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
4585         ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
4586     }
4587     else
4588     {
4589         trace("%s\n", wine_dbgstr_w(url));
4590         GlobalFree( url );
4591     }
4592 
4593     url = (WCHAR *)0xdeadbeef;
4594     SetLastError(0xdeadbeef);
4595     ret = WinHttpDetectAutoProxyConfigUrl( WINHTTP_AUTO_DETECT_TYPE_DHCP, &url );
4596     error = GetLastError();
4597     if (!ret)
4598     {
4599         ok( error == ERROR_WINHTTP_AUTODETECTION_FAILED, "got %u\n", error );
4600         ok( !url || broken(url == (WCHAR *)0xdeadbeef), "got %p\n", url );
4601     }
4602     else
4603     {
4604         ok( error == ERROR_SUCCESS, "got %u\n", error );
4605         trace("%s\n", wine_dbgstr_w(url));
4606         GlobalFree( url );
4607     }
4608 }
4609 
4610 static void test_WinHttpGetIEProxyConfigForCurrentUser(void)
4611 {
4612     BOOL ret;
4613     DWORD error;
4614     WINHTTP_CURRENT_USER_IE_PROXY_CONFIG cfg;
4615 
4616     memset( &cfg, 0, sizeof(cfg) );
4617 
4618     SetLastError(0xdeadbeef);
4619     ret = WinHttpGetIEProxyConfigForCurrentUser( NULL );
4620     error = GetLastError();
4621     ok( !ret, "expected failure\n" );
4622     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4623 
4624     SetLastError(0xdeadbeef);
4625     ret = WinHttpGetIEProxyConfigForCurrentUser( &cfg );
4626     error = GetLastError();
4627     ok( ret, "expected success\n" );
4628     ok( error == ERROR_SUCCESS || broken(error == ERROR_NO_TOKEN) /* < win7 */, "got %u\n", error );
4629 
4630     trace("IEProxy.AutoDetect=%d\n", cfg.fAutoDetect);
4631     trace("IEProxy.AutoConfigUrl=%s\n", wine_dbgstr_w(cfg.lpszAutoConfigUrl));
4632     trace("IEProxy.Proxy=%s\n", wine_dbgstr_w(cfg.lpszProxy));
4633     trace("IEProxy.ProxyBypass=%s\n", wine_dbgstr_w(cfg.lpszProxyBypass));
4634     GlobalFree( cfg.lpszAutoConfigUrl );
4635     GlobalFree( cfg.lpszProxy );
4636     GlobalFree( cfg.lpszProxyBypass );
4637 }
4638 
4639 static void test_WinHttpGetProxyForUrl(void)
4640 {
4641     static const WCHAR urlW[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0};
4642     static const WCHAR wpadW[] = {'h','t','t','p',':','/','/','w','p','a','d','/','w','p','a','d','.','d','a','t',0};
4643     static const WCHAR emptyW[] = {0};
4644     BOOL ret;
4645     DWORD error;
4646     HINTERNET session;
4647     WINHTTP_AUTOPROXY_OPTIONS options;
4648     WINHTTP_PROXY_INFO info;
4649 
4650     memset( &options, 0, sizeof(options) );
4651 
4652     SetLastError(0xdeadbeef);
4653     ret = WinHttpGetProxyForUrl( NULL, NULL, NULL, NULL );
4654     error = GetLastError();
4655     ok( !ret, "expected failure\n" );
4656     ok( error == ERROR_INVALID_HANDLE, "got %u\n", error );
4657 
4658     session = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
4659     ok( session != NULL, "failed to open session %u\n", GetLastError() );
4660 
4661     SetLastError(0xdeadbeef);
4662     ret = WinHttpGetProxyForUrl( session, NULL, NULL, NULL );
4663     error = GetLastError();
4664     ok( !ret, "expected failure\n" );
4665     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4666 
4667     SetLastError(0xdeadbeef);
4668     ret = WinHttpGetProxyForUrl( session, emptyW, NULL, NULL );
4669     error = GetLastError();
4670     ok( !ret, "expected failure\n" );
4671     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4672 
4673     SetLastError(0xdeadbeef);
4674     ret = WinHttpGetProxyForUrl( session, urlW, NULL, NULL );
4675     error = GetLastError();
4676     ok( !ret, "expected failure\n" );
4677     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4678 
4679     SetLastError(0xdeadbeef);
4680     ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4681     error = GetLastError();
4682     ok( !ret, "expected failure\n" );
4683     ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error );
4684 
4685     options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
4686     options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4687 
4688     SetLastError(0xdeadbeef);
4689     ret = WinHttpGetProxyForUrl( session, urlW, &options, NULL );
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 = 0;
4696 
4697     SetLastError(0xdeadbeef);
4698     ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
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 | WINHTTP_AUTOPROXY_CONFIG_URL;
4704     options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
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;
4713     options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DNS_A;
4714 
4715     memset( &info, 0, sizeof(info) );
4716     SetLastError(0xdeadbeef);
4717     ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4718     error = GetLastError();
4719     if (ret)
4720     {
4721         ok( error == ERROR_SUCCESS, "got %u\n", error );
4722         trace("Proxy.AccessType=%u\n", info.dwAccessType);
4723         trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
4724         trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
4725         GlobalFree( info.lpszProxy );
4726         GlobalFree( info.lpszProxyBypass );
4727     }
4728 
4729     options.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
4730     options.dwAutoDetectFlags = 0;
4731     options.lpszAutoConfigUrl = wpadW;
4732 
4733     memset( &info, 0, sizeof(info) );
4734     ret = WinHttpGetProxyForUrl( session, urlW, &options, &info );
4735     if (ret)
4736     {
4737         trace("Proxy.AccessType=%u\n", info.dwAccessType);
4738         trace("Proxy.Proxy=%s\n", wine_dbgstr_w(info.lpszProxy));
4739         trace("Proxy.ProxyBypass=%s\n", wine_dbgstr_w(info.lpszProxyBypass));
4740         GlobalFree( info.lpszProxy );
4741         GlobalFree( info.lpszProxyBypass );
4742     }
4743     WinHttpCloseHandle( session );
4744 }
4745 
4746 static void test_chunked_read(void)
4747 {
4748     static const WCHAR verb[] = {'/','t','e','s','t','s','/','c','h','u','n','k','e','d',0};
4749     static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0};
4750     WCHAR header[32];
4751     DWORD len, err;
4752     HINTERNET ses, con = NULL, req = NULL;
4753     BOOL ret;
4754 
4755     trace( "starting chunked read test\n" );
4756 
4757     ses = WinHttpOpen( test_useragent, 0, NULL, NULL, 0 );
4758     ok( ses != NULL, "WinHttpOpen failed with error %u\n", GetLastError() );
4759     if (!ses) goto done;
4760 
4761     con = WinHttpConnect( ses, test_winehq, 0, 0 );
4762     ok( con != NULL, "WinHttpConnect failed with error %u\n", GetLastError() );
4763     if (!con) goto done;
4764 
4765     req = WinHttpOpenRequest( con, NULL, verb, NULL, NULL, NULL, 0 );
4766     ok( req != NULL, "WinHttpOpenRequest failed with error %u\n", GetLastError() );
4767     if (!req) goto done;
4768 
4769     ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
4770     err = GetLastError();
4771     if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
4772     {
4773         skip("connection failed, skipping\n");
4774         goto done;
4775     }
4776     ok( ret, "WinHttpSendRequest failed with error %u\n", GetLastError() );
4777     if (!ret) goto done;
4778 
4779     ret = WinHttpReceiveResponse( req, NULL );
4780     ok( ret, "WinHttpReceiveResponse failed with error %u\n", GetLastError() );
4781     if (!ret) goto done;
4782 
4783     header[0] = 0;
4784     len = sizeof(header);
4785     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, header, &len, 0 );
4786     ok( ret, "failed to get TRANSFER_ENCODING header (error %u)\n", GetLastError() );
4787     ok( !lstrcmpW( header, chunked ), "wrong transfer encoding %s\n", wine_dbgstr_w(header) );
4788     trace( "transfer encoding: %s\n", wine_dbgstr_w(header) );
4789 
4790     header[0] = 0;
4791     len = sizeof(header);
4792     SetLastError( 0xdeadbeef );
4793     ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_CONTENT_LENGTH, NULL, &header, &len, 0 );
4794     ok( !ret, "unexpected CONTENT_LENGTH header %s\n", wine_dbgstr_w(header) );
4795     ok( GetLastError() == ERROR_WINHTTP_HEADER_NOT_FOUND, "wrong error %u\n", GetLastError() );
4796 
4797     trace( "entering query loop\n" );
4798     for (;;)
4799     {
4800         len = 0xdeadbeef;
4801         ret = WinHttpQueryDataAvailable( req, &len );
4802         ok( ret, "WinHttpQueryDataAvailable failed with error %u\n", GetLastError() );
4803         if (ret) ok( len != 0xdeadbeef, "WinHttpQueryDataAvailable return wrong length\n" );
4804         trace( "got %u available\n", len );
4805         if (len)
4806         {
4807             DWORD bytes_read;
4808             char *buf = HeapAlloc( GetProcessHeap(), 0, len + 1 );
4809 
4810             ret = WinHttpReadData( req, buf, len, &bytes_read );
4811             ok(ret, "WinHttpReadData failed: %u.\n", GetLastError());
4812 
4813             buf[bytes_read] = 0;
4814             trace( "WinHttpReadData -> %d %u\n", ret, bytes_read );
4815             ok( len == bytes_read, "only got %u of %u available\n", bytes_read, len );
4816             ok( buf[bytes_read - 1] == '\n', "received partial line '%s'\n", buf );
4817 
4818             HeapFree( GetProcessHeap(), 0, buf );
4819             if (!bytes_read) break;
4820         }
4821         if (!len) break;
4822     }
4823     trace( "done\n" );
4824 
4825 done:
4826     if (req) WinHttpCloseHandle( req );
4827     if (con) WinHttpCloseHandle( con );
4828     if (ses) WinHttpCloseHandle( ses );
4829 }
4830 
4831 START_TEST (winhttp)
4832 {
4833     static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
4834     static const WCHAR quitW[] = {'/','q','u','i','t',0};
4835     struct server_info si;
4836     HANDLE thread;
4837     DWORD ret;
4838 
4839     test_WinHttpOpenRequest();
4840     test_WinHttpSendRequest();
4841     test_WinHttpTimeFromSystemTime();
4842     test_WinHttpTimeToSystemTime();
4843     test_WinHttpAddHeaders();
4844     test_secure_connection();
4845     test_request_parameter_defaults();
4846     test_WinHttpQueryOption();
4847     test_set_default_proxy_config();
4848     test_empty_headers_param();
4849     test_timeouts();
4850     test_resolve_timeout();
4851     test_credentials();
4852     test_IWinHttpRequest_Invoke();
4853     test_WinHttpDetectAutoProxyConfigUrl();
4854     test_WinHttpGetIEProxyConfigForCurrentUser();
4855     test_WinHttpGetProxyForUrl();
4856     test_chunked_read();
4857 
4858     si.event = CreateEventW(NULL, 0, 0, NULL);
4859     si.port = 7532;
4860 
4861     thread = CreateThread(NULL, 0, server_thread, &si, 0, NULL);
4862     ok(thread != NULL, "failed to create thread %u\n", GetLastError());
4863 
4864     ret = WaitForSingleObject(si.event, 10000);
4865     ok(ret == WAIT_OBJECT_0, "failed to start winhttp test server %u\n", GetLastError());
4866     if (ret != WAIT_OBJECT_0)
4867     {
4868         CloseHandle(thread);
4869         return;
4870     }
4871 
4872     test_IWinHttpRequest(si.port);
4873     test_connection_info(si.port);
4874     test_basic_request(si.port, NULL, basicW);
4875     test_no_headers(si.port);
4876     test_no_content(si.port);
4877     test_head_request(si.port);
4878     test_not_modified(si.port);
4879     test_basic_authentication(si.port);
4880     test_multi_authentication(si.port);
4881     test_large_data_authentication(si.port);
4882     test_bad_header(si.port);
4883     test_multiple_reads(si.port);
4884     test_cookies(si.port);
4885     test_request_path_escapes(si.port);
4886     test_passport_auth(si.port);
4887 
4888     /* send the basic request again to shutdown the server thread */
4889     test_basic_request(si.port, NULL, quitW);
4890 
4891     WaitForSingleObject(thread, 3000);
4892     CloseHandle(thread);
4893 }
4894