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