1 /*
2  * Wininet - HTTP tests
3  *
4  * Copyright 2002 Aric Stewart
5  * Copyright 2004 Mike McCormack
6  * Copyright 2005 Hans Leidekker
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <limits.h>
27 
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wininet.h"
31 #include "winineti.h"
32 #include "winsock2.h"
33 
34 #include "wine/test.h"
35 
36 /* Undocumented security flags */
37 #define _SECURITY_FLAG_CERT_REV_FAILED    0x00800000
38 #define _SECURITY_FLAG_CERT_INVALID_CA    0x01000000
39 #define _SECURITY_FLAG_CERT_INVALID_CN    0x02000000
40 #define _SECURITY_FLAG_CERT_INVALID_DATE  0x04000000
41 
42 #define TEST_URL "http://test.winehq.org/tests/hello.html"
43 
44 static BOOL first_connection_to_test_url = TRUE;
45 
46 /* Adapted from dlls/urlmon/tests/protocol.c */
47 
48 #define SET_EXPECT2(status, num) \
49     expect[status] = num
50 
51 #define SET_EXPECT(status) \
52     SET_EXPECT2(status, 1)
53 
54 #define SET_OPTIONAL2(status, num) \
55     optional[status] = num
56 
57 #define SET_OPTIONAL(status) \
58     SET_OPTIONAL2(status, 1)
59 
60 /* SET_WINE_ALLOW's should be used with an appropriate
61  * todo_wine CHECK_NOTIFIED at a later point in the code */
62 #define SET_WINE_ALLOW2(status, num) \
63     wine_allow[status] = num
64 
65 #define SET_WINE_ALLOW(status) \
66     SET_WINE_ALLOW2(status, 1)
67 
68 #define CHECK_EXPECT(status) \
69     do { \
70         if (!expect[status] && !optional[status] && wine_allow[status]) \
71         { \
72             todo_wine ok(expect[status], "unexpected status %d (%s)\n", status, \
73                          status < MAX_INTERNET_STATUS && status_string[status] ? \
74                          status_string[status] : "unknown");            \
75             wine_allow[status]--; \
76         } \
77         else \
78         { \
79             ok(expect[status] || optional[status], "unexpected status %d (%s)\n", status,   \
80                status < MAX_INTERNET_STATUS && status_string[status] ? \
81                status_string[status] : "unknown");                      \
82             if (expect[status]) expect[status]--; \
83             else if(optional[status]) optional[status]--; \
84         } \
85         notified[status]++; \
86     }while(0)
87 
88 /* CLEAR_NOTIFIED used in cases when notification behavior
89  * differs between Windows versions */
90 #define CLEAR_NOTIFIED(status) \
91     expect[status] = optional[status] = wine_allow[status] = notified[status] = 0;
92 
93 #define CHECK_NOTIFIED2(status, num) \
94     do { \
95         ok(notified[status] + optional[status] == (num), \
96            "expected status %d (%s) %d times, received %d times\n", \
97            status, status < MAX_INTERNET_STATUS && status_string[status] ? \
98            status_string[status] : "unknown", (num), notified[status]); \
99         CLEAR_NOTIFIED(status);                                         \
100     }while(0)
101 
102 #define CHECK_NOTIFIED(status) \
103     CHECK_NOTIFIED2(status, 1)
104 
105 #define CHECK_NOT_NOTIFIED(status) \
106     CHECK_NOTIFIED2(status, 0)
107 
108 #define MAX_INTERNET_STATUS (INTERNET_STATUS_COOKIE_HISTORY+1)
109 static int expect[MAX_INTERNET_STATUS], optional[MAX_INTERNET_STATUS],
110     wine_allow[MAX_INTERNET_STATUS], notified[MAX_INTERNET_STATUS];
111 static const char *status_string[MAX_INTERNET_STATUS];
112 
113 static HANDLE complete_event, conn_close_event, conn_wait_event, server_req_rec_event, request_sent_event;
114 static DWORD req_error;
115 static BOOL is_ie7plus = TRUE;
116 
117 #define TESTF_REDIRECT      0x01
118 #define TESTF_COMPRESSED    0x02
119 #define TESTF_CHUNKED       0x04
120 
121 typedef struct {
122     const char *url;
123     const char *redirected_url;
124     const char *host;
125     const char *path;
126     const char *headers;
127     DWORD flags;
128     const char *post_data;
129     const char *content;
130 } test_data_t;
131 
132 static const test_data_t test_data[] = {
133     {
134         "http://test.winehq.org/tests/data.php",
135         "http://test.winehq.org/tests/data.php",
136         "test.winehq.org",
137         "/tests/data.php",
138         "",
139         TESTF_CHUNKED
140     },
141     {
142         "http://test.winehq.org/tests/redirect",
143         "http://test.winehq.org/tests/hello.html",
144         "test.winehq.org",
145         "/tests/redirect",
146         "",
147         TESTF_REDIRECT
148     },
149     {
150         "http://test.winehq.org/tests/gzip.php",
151         "http://test.winehq.org/tests/gzip.php",
152         "test.winehq.org",
153         "/tests/gzip.php",
154         "Accept-Encoding: gzip, deflate",
155         TESTF_COMPRESSED
156     },
157     {
158         "http://test.winehq.org/tests/post.php",
159         "http://test.winehq.org/tests/post.php",
160         "test.winehq.org",
161         "/tests/post.php",
162         "Content-Type: application/x-www-form-urlencoded",
163         0,
164         "mode=Test",
165         "mode => Test\n"
166     }
167 };
168 
169 static INTERNET_STATUS_CALLBACK (WINAPI *pInternetSetStatusCallbackA)(HINTERNET ,INTERNET_STATUS_CALLBACK);
170 static INTERNET_STATUS_CALLBACK (WINAPI *pInternetSetStatusCallbackW)(HINTERNET ,INTERNET_STATUS_CALLBACK);
171 static BOOL (WINAPI *pInternetGetSecurityInfoByURLA)(LPSTR,PCCERT_CHAIN_CONTEXT*,DWORD*);
172 
173 static int strcmp_wa(LPCWSTR strw, const char *stra)
174 {
175     WCHAR buf[512];
176     MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, ARRAY_SIZE(buf));
177     return lstrcmpW(strw, buf);
178 }
179 
180 static BOOL proxy_active(void)
181 {
182     HKEY internet_settings;
183     DWORD proxy_enable;
184     DWORD size;
185 
186     if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
187                       0, KEY_QUERY_VALUE, &internet_settings) != ERROR_SUCCESS)
188         return FALSE;
189 
190     size = sizeof(DWORD);
191     if (RegQueryValueExA(internet_settings, "ProxyEnable", NULL, NULL, (LPBYTE) &proxy_enable, &size) != ERROR_SUCCESS)
192         proxy_enable = 0;
193 
194     RegCloseKey(internet_settings);
195 
196     return proxy_enable != 0;
197 }
198 
199 static void init_events(void)
200 {
201     complete_event = CreateEventW(NULL, FALSE, FALSE, NULL);
202     conn_close_event = CreateEventW(NULL, FALSE, FALSE, NULL);
203     conn_wait_event = CreateEventW(NULL, FALSE, FALSE, NULL);
204     server_req_rec_event = CreateEventW(NULL, FALSE, FALSE, NULL);
205     request_sent_event = CreateEventW(NULL, FALSE, FALSE, NULL);
206 }
207 
208 static void free_events(void)
209 {
210     CloseHandle(complete_event);
211     CloseHandle(conn_close_event);
212     CloseHandle(conn_wait_event);
213     CloseHandle(server_req_rec_event);
214     CloseHandle(request_sent_event);
215 }
216 
217 static void reset_events(void)
218 {
219     ResetEvent(complete_event);
220     ResetEvent(conn_close_event);
221     ResetEvent(conn_wait_event);
222     ResetEvent(server_req_rec_event);
223     ResetEvent(request_sent_event);
224 }
225 
226 #define test_status_code(a,b) _test_status_code(__LINE__,a,b, FALSE)
227 #define test_status_code_todo(a,b) _test_status_code(__LINE__,a,b, TRUE)
228 static void _test_status_code(unsigned line, HINTERNET req, DWORD excode, BOOL is_todo)
229 {
230     DWORD code, size, index;
231     char exbuf[12], bufa[10];
232     WCHAR bufw[10];
233     BOOL res;
234 
235     code = 0xdeadbeef;
236     size = sizeof(code);
237     res = HttpQueryInfoA(req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &code, &size, NULL);
238     ok_(__FILE__,line)(res, "[1] HttpQueryInfoA(HTTP_QUERY_STATUS_CODE|number) failed: %u\n", GetLastError());
239     todo_wine_if (is_todo)
240         ok_(__FILE__,line)(code == excode, "code = %d, expected %d\n", code, excode);
241     ok_(__FILE__,line)(size == sizeof(code), "size = %u\n", size);
242 
243     code = 0xdeadbeef;
244     index = 0;
245     size = sizeof(code);
246     res = HttpQueryInfoA(req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &code, &size, &index);
247     ok_(__FILE__,line)(res, "[2] HttpQueryInfoA(HTTP_QUERY_STATUS_CODE|number index) failed: %u\n", GetLastError());
248     ok_(__FILE__,line)(!index, "index = %d, expected 0\n", index);
249     ok_(__FILE__,line)(size == sizeof(code), "size = %u\n", size);
250 
251     sprintf(exbuf, "%u", excode);
252 
253     size = sizeof(bufa);
254     res = HttpQueryInfoA(req, HTTP_QUERY_STATUS_CODE, bufa, &size, NULL);
255     ok_(__FILE__,line)(res, "[3] HttpQueryInfoA(HTTP_QUERY_STATUS_CODE) failed: %u\n", GetLastError());
256     todo_wine_if (is_todo)
257         ok_(__FILE__,line)(!strcmp(bufa, exbuf), "unexpected status code %s, expected %s\n", bufa, exbuf);
258     ok_(__FILE__,line)(size == strlen(exbuf), "unexpected size %d for \"%s\"\n", size, exbuf);
259 
260     size = 0;
261     res = HttpQueryInfoA(req, HTTP_QUERY_STATUS_CODE, NULL, &size, NULL);
262     ok_(__FILE__,line)(!res && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
263                        "[4] HttpQueryInfoA(HTTP_QUERY_STATUS_CODE) failed: %u\n", GetLastError());
264     ok_(__FILE__,line)(size == strlen(exbuf)+1, "unexpected size %d for \"%s\"\n", size, exbuf);
265 
266     size = sizeof(bufw);
267     res = HttpQueryInfoW(req, HTTP_QUERY_STATUS_CODE, bufw, &size, NULL);
268     ok_(__FILE__,line)(res, "[5] HttpQueryInfoW(HTTP_QUERY_STATUS_CODE) failed: %u\n", GetLastError());
269     todo_wine_if (is_todo)
270         ok_(__FILE__,line)(!strcmp_wa(bufw, exbuf), "unexpected status code %s, expected %s\n", bufa, exbuf);
271     ok_(__FILE__,line)(size == strlen(exbuf)*sizeof(WCHAR), "unexpected size %d for \"%s\"\n", size, exbuf);
272 
273     size = 0;
274     res = HttpQueryInfoW(req, HTTP_QUERY_STATUS_CODE, bufw, &size, NULL);
275     ok_(__FILE__,line)(!res && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
276                        "[6] HttpQueryInfoW(HTTP_QUERY_STATUS_CODE) failed: %u\n", GetLastError());
277     ok_(__FILE__,line)(size == (strlen(exbuf)+1)*sizeof(WCHAR), "unexpected size %d for \"%s\"\n", size, exbuf);
278 
279     if(0) {
280     size = sizeof(bufw);
281     res = HttpQueryInfoW(req, HTTP_QUERY_STATUS_CODE, NULL, &size, NULL);
282     ok(!res && GetLastError() == ERROR_INVALID_PARAMETER, "HttpQueryInfo(HTTP_QUERY_STATUS_CODE) failed: %u\n", GetLastError());
283     ok(size == sizeof(bufw), "unexpected size %d\n", size);
284     }
285 
286     code = 0xdeadbeef;
287     index = 1;
288     size = sizeof(code);
289     res = HttpQueryInfoA(req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &code, &size, &index);
290     ok_(__FILE__,line)(!res && GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND,
291                        "[7] HttpQueryInfoA failed: %x(%d)\n", res, GetLastError());
292 
293     code = 0xdeadbeef;
294     size = sizeof(code);
295     res = HttpQueryInfoA(req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_REQUEST_HEADERS, &code, &size, NULL);
296     ok_(__FILE__,line)(!res && GetLastError() == ERROR_HTTP_INVALID_QUERY_REQUEST,
297                        "[8] HttpQueryInfoA failed: %x(%d)\n", res, GetLastError());
298 }
299 
300 #define test_request_flags(a,b) _test_request_flags(__LINE__,a,b,FALSE)
301 #define test_request_flags_todo(a,b) _test_request_flags(__LINE__,a,b,TRUE)
302 static void _test_request_flags(unsigned line, HINTERNET req, DWORD exflags, BOOL is_todo)
303 {
304     DWORD flags, size;
305     BOOL res;
306 
307     flags = 0xdeadbeef;
308     size = sizeof(flags);
309     res = InternetQueryOptionW(req, INTERNET_OPTION_REQUEST_FLAGS, &flags, &size);
310     ok_(__FILE__,line)(res, "InternetQueryOptionW(INTERNET_OPTION_REQUEST_FLAGS) failed: %u\n", GetLastError());
311 
312     /* FIXME: Remove once we have INTERNET_REQFLAG_CACHE_WRITE_DISABLED implementation */
313     flags &= ~INTERNET_REQFLAG_CACHE_WRITE_DISABLED;
314     todo_wine_if (is_todo)
315         ok_(__FILE__,line)(flags == exflags, "flags = %x, expected %x\n", flags, exflags);
316 }
317 
318 #define test_request_url(a,b) _test_request_url(__LINE__,a,b)
319 static void _test_request_url(unsigned line, HINTERNET req, const char *expected_url)
320 {
321     char buf[INTERNET_MAX_URL_LENGTH];
322     DWORD size = sizeof(buf);
323     BOOL res;
324 
325     res = InternetQueryOptionA(req, INTERNET_OPTION_URL, buf, &size);
326     ok_(__FILE__,line)(res, "InternetQueryOptionA(INTERNET_OPTION_URL) failed: %u\n", GetLastError());
327     ok_(__FILE__,line)(size == strlen(expected_url), "size = %u\n", size);
328     ok_(__FILE__,line)(!strcmp(buf, expected_url), "unexpected URL %s, expected %s\n", buf, expected_url);
329 }
330 
331 #define test_http_version(a) _test_http_version(__LINE__,a)
332 static void _test_http_version(unsigned line, HINTERNET req)
333 {
334     HTTP_VERSION_INFO v = {0xdeadbeef, 0xdeadbeef};
335     DWORD size;
336     BOOL res;
337 
338     size = sizeof(v);
339     res = InternetQueryOptionW(req, INTERNET_OPTION_HTTP_VERSION, &v, &size);
340     ok_(__FILE__,line)(res, "InternetQueryOptionW(INTERNET_OPTION_HTTP_VERSION) failed: %u\n", GetLastError());
341     ok_(__FILE__,line)(v.dwMajorVersion == 1, "dwMajorVersion = %d\n", v.dwMajorVersion);
342     ok_(__FILE__,line)(v.dwMinorVersion == 1, "dwMinorVersion = %d\n", v.dwMinorVersion);
343 }
344 
345 static int close_handle_cnt;
346 
347 static VOID WINAPI callback(
348      HINTERNET hInternet,
349      DWORD_PTR dwContext,
350      DWORD dwInternetStatus,
351      LPVOID lpvStatusInformation,
352      DWORD dwStatusInformationLength
353 )
354 {
355     ros_skip_flaky
356     CHECK_EXPECT(dwInternetStatus);
357     switch (dwInternetStatus)
358     {
359         case INTERNET_STATUS_RESOLVING_NAME:
360             if(winetest_debug > 1)
361                 trace("%04x:Callback %p 0x%lx INTERNET_STATUS_RESOLVING_NAME \"%s\" %d\n",
362                       GetCurrentThreadId(), hInternet, dwContext,
363                       (LPCSTR)lpvStatusInformation,dwStatusInformationLength);
364             *(LPSTR)lpvStatusInformation = '\0';
365             break;
366         case INTERNET_STATUS_NAME_RESOLVED:
367             if(winetest_debug > 1)
368                 trace("%04x:Callback %p 0x%lx INTERNET_STATUS_NAME_RESOLVED \"%s\" %d\n",
369                       GetCurrentThreadId(), hInternet, dwContext,
370                       (LPCSTR)lpvStatusInformation,dwStatusInformationLength);
371             *(LPSTR)lpvStatusInformation = '\0';
372             break;
373         case INTERNET_STATUS_CONNECTING_TO_SERVER:
374             if(winetest_debug > 1)
375                 trace("%04x:Callback %p 0x%lx INTERNET_STATUS_CONNECTING_TO_SERVER \"%s\" %d\n",
376                       GetCurrentThreadId(), hInternet, dwContext,
377                       (LPCSTR)lpvStatusInformation,dwStatusInformationLength);
378             ok(dwStatusInformationLength == strlen(lpvStatusInformation)+1, "unexpected size %u\n",
379                dwStatusInformationLength);
380             *(LPSTR)lpvStatusInformation = '\0';
381             break;
382         case INTERNET_STATUS_CONNECTED_TO_SERVER:
383             if(winetest_debug > 1)
384                 trace("%04x:Callback %p 0x%lx INTERNET_STATUS_CONNECTED_TO_SERVER \"%s\" %d\n",
385                       GetCurrentThreadId(), hInternet, dwContext,
386                       (LPCSTR)lpvStatusInformation,dwStatusInformationLength);
387             ok(dwStatusInformationLength == strlen(lpvStatusInformation)+1, "unexpected size %u\n",
388                dwStatusInformationLength);
389             *(LPSTR)lpvStatusInformation = '\0';
390             break;
391         case INTERNET_STATUS_SENDING_REQUEST:
392             if(winetest_debug > 1)
393                 trace("%04x:Callback %p 0x%lx INTERNET_STATUS_SENDING_REQUEST %p %d\n",
394                       GetCurrentThreadId(), hInternet, dwContext,
395                       lpvStatusInformation,dwStatusInformationLength);
396             break;
397         case INTERNET_STATUS_REQUEST_SENT:
398             ok(dwStatusInformationLength == sizeof(DWORD),
399                 "info length should be sizeof(DWORD) instead of %d\n",
400                 dwStatusInformationLength);
401             if(winetest_debug > 1)
402                 trace("%04x:Callback %p 0x%lx INTERNET_STATUS_REQUEST_SENT 0x%x %d\n",
403                       GetCurrentThreadId(), hInternet, dwContext,
404                       *(DWORD *)lpvStatusInformation,dwStatusInformationLength);
405             break;
406         case INTERNET_STATUS_RECEIVING_RESPONSE:
407             if(winetest_debug > 1)
408                 trace("%04x:Callback %p 0x%lx INTERNET_STATUS_RECEIVING_RESPONSE %p %d\n",
409                       GetCurrentThreadId(), hInternet, dwContext,
410                       lpvStatusInformation,dwStatusInformationLength);
411             break;
412         case INTERNET_STATUS_RESPONSE_RECEIVED:
413             ok(dwStatusInformationLength == sizeof(DWORD),
414                 "info length should be sizeof(DWORD) instead of %d\n",
415                 dwStatusInformationLength);
416             if(winetest_debug > 1)
417                 trace("%04x:Callback %p 0x%lx INTERNET_STATUS_RESPONSE_RECEIVED 0x%x %d\n",
418                       GetCurrentThreadId(), hInternet, dwContext,
419                       *(DWORD *)lpvStatusInformation,dwStatusInformationLength);
420             break;
421         case INTERNET_STATUS_CTL_RESPONSE_RECEIVED:
422             if(winetest_debug > 1)
423                 trace("%04x:Callback %p 0x%lx INTERNET_STATUS_CTL_RESPONSE_RECEIVED %p %d\n",
424                       GetCurrentThreadId(), hInternet,dwContext,
425                       lpvStatusInformation,dwStatusInformationLength);
426             break;
427         case INTERNET_STATUS_PREFETCH:
428             if(winetest_debug > 1)
429                 trace("%04x:Callback %p 0x%lx INTERNET_STATUS_PREFETCH %p %d\n",
430                       GetCurrentThreadId(), hInternet, dwContext,
431                       lpvStatusInformation,dwStatusInformationLength);
432             break;
433         case INTERNET_STATUS_CLOSING_CONNECTION:
434             if(winetest_debug > 1)
435                 trace("%04x:Callback %p 0x%lx INTERNET_STATUS_CLOSING_CONNECTION %p %d\n",
436                       GetCurrentThreadId(), hInternet, dwContext,
437                       lpvStatusInformation,dwStatusInformationLength);
438             break;
439         case INTERNET_STATUS_CONNECTION_CLOSED:
440             if(winetest_debug > 1)
441                 trace("%04x:Callback %p 0x%lx INTERNET_STATUS_CONNECTION_CLOSED %p %d\n",
442                       GetCurrentThreadId(), hInternet, dwContext,
443                       lpvStatusInformation,dwStatusInformationLength);
444             break;
445         case INTERNET_STATUS_HANDLE_CREATED:
446             ok(dwStatusInformationLength == sizeof(HINTERNET),
447                 "info length should be sizeof(HINTERNET) instead of %d\n",
448                 dwStatusInformationLength);
449             if(winetest_debug > 1)
450                 trace("%04x:Callback %p 0x%lx INTERNET_STATUS_HANDLE_CREATED %p %d\n",
451                       GetCurrentThreadId(), hInternet, dwContext,
452                       *(HINTERNET *)lpvStatusInformation,dwStatusInformationLength);
453             CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
454             SET_EXPECT(INTERNET_STATUS_DETECTING_PROXY);
455             break;
456         case INTERNET_STATUS_HANDLE_CLOSING:
457             ok(dwStatusInformationLength == sizeof(HINTERNET),
458                 "info length should be sizeof(HINTERNET) instead of %d\n",
459                 dwStatusInformationLength);
460             if(winetest_debug > 1)
461                 trace("%04x:Callback %p 0x%lx INTERNET_STATUS_HANDLE_CLOSING %p %d\n",
462                       GetCurrentThreadId(), hInternet, dwContext,
463                       *(HINTERNET *)lpvStatusInformation, dwStatusInformationLength);
464             if(!InterlockedDecrement(&close_handle_cnt))
465                 SetEvent(complete_event);
466             break;
467         case INTERNET_STATUS_REQUEST_COMPLETE:
468         {
469             INTERNET_ASYNC_RESULT *iar = (INTERNET_ASYNC_RESULT *)lpvStatusInformation;
470             ok(dwStatusInformationLength == sizeof(INTERNET_ASYNC_RESULT),
471                 "info length should be sizeof(INTERNET_ASYNC_RESULT) instead of %d\n",
472                 dwStatusInformationLength);
473             ok(iar->dwResult == 1 || iar->dwResult == 0, "iar->dwResult = %ld\n", iar->dwResult);
474             if(winetest_debug > 1)
475                 trace("%04x:Callback %p 0x%lx INTERNET_STATUS_REQUEST_COMPLETE {%ld,%d} %d\n",
476                       GetCurrentThreadId(), hInternet, dwContext,
477                       iar->dwResult,iar->dwError,dwStatusInformationLength);
478             req_error = iar->dwError;
479             if(!close_handle_cnt)
480                 SetEvent(complete_event);
481             break;
482         }
483         case INTERNET_STATUS_REDIRECT:
484             if(winetest_debug > 1)
485                 trace("%04x:Callback %p 0x%lx INTERNET_STATUS_REDIRECT \"%s\" %d\n",
486                       GetCurrentThreadId(), hInternet, dwContext,
487                       (LPCSTR)lpvStatusInformation, dwStatusInformationLength);
488             *(LPSTR)lpvStatusInformation = '\0';
489             CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
490             SET_EXPECT(INTERNET_STATUS_DETECTING_PROXY);
491             break;
492         case INTERNET_STATUS_INTERMEDIATE_RESPONSE:
493             if(winetest_debug > 1)
494                 trace("%04x:Callback %p 0x%lx INTERNET_STATUS_INTERMEDIATE_RESPONSE %p %d\n",
495                       GetCurrentThreadId(), hInternet, dwContext,
496                       lpvStatusInformation, dwStatusInformationLength);
497             break;
498         default:
499             if(winetest_debug > 1)
500                 trace("%04x:Callback %p 0x%lx %d %p %d\n",
501                       GetCurrentThreadId(), hInternet, dwContext, dwInternetStatus,
502                       lpvStatusInformation, dwStatusInformationLength);
503     }
504 }
505 
506 typedef struct {
507     HINTERNET session;
508     HINTERNET connection;
509     HINTERNET request;
510 } test_request_t;
511 
512 #define open_simple_request(a,b,c,d,e) _open_simple_request(__LINE__,a,b,c,d,e)
513 static void _open_simple_request(unsigned line, test_request_t *req, const char *host,
514         int port, const char *verb, const char *url)
515 {
516     req->session = InternetOpenA(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
517     ok_(__FILE__,line)(req->session != NULL, "InternetOpenA failed: %u\n", GetLastError());
518 
519     req->connection = InternetConnectA(req->session, host, port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
520     ok_(__FILE__,line)(req->connection != NULL, "InternetConnectA failed: %u\n", GetLastError());
521 
522     req->request = HttpOpenRequestA(req->connection, verb, url, NULL, NULL, NULL, 0, 0);
523     ok_(__FILE__,line)(req->request != NULL, "HttpOpenRequest failed: %u\n", GetLastError());
524 }
525 
526 #define close_request(a) _close_request(__LINE__,a)
527 static void _close_request(unsigned line, test_request_t *req)
528 {
529     BOOL ret;
530 
531     ret = InternetCloseHandle(req->request);
532     ok_(__FILE__,line)(ret, "InternetCloseHandle(request) failed: %u\n", GetLastError());
533     ret = InternetCloseHandle(req->connection);
534     ok_(__FILE__,line)(ret, "InternetCloseHandle(connection) failed: %u\n", GetLastError());
535     ret = InternetCloseHandle(req->session);
536     ok_(__FILE__,line)(ret, "InternetCloseHandle(session) failed: %u\n", GetLastError());
537 }
538 
539 #define receive_simple_request(a,b,c) _receive_simple_request(__LINE__,a,b,c)
540 static DWORD _receive_simple_request(unsigned line, HINTERNET req, char *buf, size_t buf_size)
541 {
542     DWORD read = 0;
543     BOOL ret;
544 
545     ret = InternetReadFile(req, buf, buf_size, &read);
546     ok_(__FILE__,line)(ret, "InternetReadFile failed: %u\n", GetLastError());
547 
548     return read;
549 }
550 
551 static void close_async_handle(HINTERNET handle, int handle_cnt)
552 {
553     BOOL res;
554 
555     close_handle_cnt = handle_cnt;
556 
557     SET_EXPECT2(INTERNET_STATUS_HANDLE_CLOSING, handle_cnt);
558     res = InternetCloseHandle(handle);
559     ok(res, "InternetCloseHandle failed: %u\n", GetLastError());
560     WaitForSingleObject(complete_event, INFINITE);
561     CHECK_NOTIFIED2(INTERNET_STATUS_HANDLE_CLOSING, handle_cnt);
562 }
563 
564 static void InternetReadFile_test(int flags, const test_data_t *test)
565 {
566     char *post_data = NULL;
567     BOOL res, on_async = TRUE;
568     CHAR buffer[4000];
569     WCHAR wbuffer[4000];
570     DWORD length, length2, index, exlen = 0, post_len = 0;
571     const char *types[2] = { "*", NULL };
572     HINTERNET hi, hic = 0, hor = 0;
573 
574     trace("Starting InternetReadFile test with flags 0x%x on url %s\n",flags,test->url);
575     reset_events();
576 
577     trace("InternetOpenA <--\n");
578     hi = InternetOpenA((test->flags & TESTF_COMPRESSED) ? "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" : "",
579             INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, flags);
580     ok((hi != 0x0),"InternetOpen failed with error %u\n", GetLastError());
581     trace("InternetOpenA -->\n");
582 
583     if (hi == 0x0) goto abort;
584 
585     pInternetSetStatusCallbackA(hi,&callback);
586 
587     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
588 
589     trace("InternetConnectA <--\n");
590     hic=InternetConnectA(hi, test->host, INTERNET_INVALID_PORT_NUMBER,
591                          NULL, NULL, INTERNET_SERVICE_HTTP, 0x0, 0xdeadbeef);
592     ok((hic != 0x0),"InternetConnect failed with error %u\n", GetLastError());
593     trace("InternetConnectA -->\n");
594 
595     if (hic == 0x0) goto abort;
596 
597     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
598     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
599 
600     trace("HttpOpenRequestA <--\n");
601     hor = HttpOpenRequestA(hic, test->post_data ? "POST" : "GET", test->path, NULL, NULL, types,
602                            INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RELOAD,
603                            0xdeadbead);
604     if (hor == 0x0 && GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED) {
605         /*
606          * If the internet name can't be resolved we are probably behind
607          * a firewall or in some other way not directly connected to the
608          * Internet. Not enough reason to fail the test. Just ignore and
609          * abort.
610          */
611     } else  {
612         ok((hor != 0x0),"HttpOpenRequest failed with error %u\n", GetLastError());
613     }
614     trace("HttpOpenRequestA -->\n");
615 
616     if (hor == 0x0) goto abort;
617 
618     test_request_flags(hor, INTERNET_REQFLAG_NO_HEADERS);
619     test_request_url(hor, test->url);
620 
621     length = sizeof(buffer);
622     res = HttpQueryInfoA(hor, HTTP_QUERY_RAW_HEADERS, buffer, &length, 0x0);
623     ok(res, "HttpQueryInfoA(HTTP_QUERY_RAW_HEADERS) failed with error %d\n", GetLastError());
624     ok(length == 0 || (length == 1 && !*buffer) /* win10 */, "HTTP_QUERY_RAW_HEADERS: expected length 0, but got %d\n", length);
625     ok(!strcmp(buffer, ""), "HTTP_QUERY_RAW_HEADERS: expected string \"\", but got \"%s\"\n", buffer);
626 
627     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
628     CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME);
629     CHECK_NOT_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED);
630     SET_OPTIONAL2(INTERNET_STATUS_COOKIE_SENT,2);
631     SET_OPTIONAL2(INTERNET_STATUS_COOKIE_RECEIVED,2);
632     if (first_connection_to_test_url)
633     {
634         SET_EXPECT(INTERNET_STATUS_RESOLVING_NAME);
635         SET_EXPECT(INTERNET_STATUS_NAME_RESOLVED);
636     }
637     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
638     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
639     SET_EXPECT2(INTERNET_STATUS_SENDING_REQUEST, (test->flags & TESTF_REDIRECT) ? 2 : 1);
640     SET_EXPECT2(INTERNET_STATUS_REQUEST_SENT, (test->flags & TESTF_REDIRECT) ? 2 : 1);
641     SET_EXPECT2(INTERNET_STATUS_RECEIVING_RESPONSE, (test->flags & TESTF_REDIRECT) ? 2 : 1);
642     SET_EXPECT2(INTERNET_STATUS_RESPONSE_RECEIVED, (test->flags & TESTF_REDIRECT) ? 2 : 1);
643     if(test->flags & TESTF_REDIRECT) {
644         SET_OPTIONAL2(INTERNET_STATUS_CLOSING_CONNECTION, 2);
645         SET_OPTIONAL2(INTERNET_STATUS_CONNECTION_CLOSED, 2);
646     }
647     SET_EXPECT(INTERNET_STATUS_REDIRECT);
648     SET_OPTIONAL(INTERNET_STATUS_CONNECTING_TO_SERVER);
649     SET_OPTIONAL(INTERNET_STATUS_CONNECTED_TO_SERVER);
650     if (flags & INTERNET_FLAG_ASYNC)
651         SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
652 
653     if(test->flags & TESTF_COMPRESSED) {
654         BOOL b = TRUE;
655 
656         res = InternetSetOptionA(hor, INTERNET_OPTION_HTTP_DECODING, &b, sizeof(b));
657         ok(res || broken(!res && GetLastError() == ERROR_INTERNET_INVALID_OPTION),
658            "InternetSetOption failed: %u\n", GetLastError());
659         if(!res)
660             goto abort;
661     }
662 
663     test_status_code(hor, 0);
664 
665     trace("HttpSendRequestA -->\n");
666     if(test->post_data) {
667         post_len = strlen(test->post_data);
668         post_data = HeapAlloc(GetProcessHeap(), 0, post_len);
669         memcpy(post_data, test->post_data, post_len);
670     }
671     SetLastError(0xdeadbeef);
672     res = HttpSendRequestA(hor, test->headers, -1, post_data, post_len);
673     if (flags & INTERNET_FLAG_ASYNC)
674         ok(!res && (GetLastError() == ERROR_IO_PENDING),
675             "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n");
676     else
677         ok(res || (GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED),
678            "Synchronous HttpSendRequest returning 0, error %u\n", GetLastError());
679     trace("HttpSendRequestA <--\n");
680 
681     if (flags & INTERNET_FLAG_ASYNC) {
682         WaitForSingleObject(complete_event, INFINITE);
683         ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error);
684     }
685     HeapFree(GetProcessHeap(), 0, post_data);
686 
687     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
688     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_RECEIVED);
689     if (first_connection_to_test_url)
690     {
691         if (! proxy_active())
692         {
693             CHECK_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME);
694             CHECK_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED);
695         }
696         else
697         {
698             CLEAR_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME);
699             CLEAR_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED);
700         }
701     }
702     else
703     {
704         CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME);
705         CHECK_NOT_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED);
706     }
707     CHECK_NOTIFIED2(INTERNET_STATUS_SENDING_REQUEST, (test->flags & TESTF_REDIRECT) ? 2 : 1);
708     CHECK_NOTIFIED2(INTERNET_STATUS_REQUEST_SENT, (test->flags & TESTF_REDIRECT) ? 2 : 1);
709     CHECK_NOTIFIED2(INTERNET_STATUS_RECEIVING_RESPONSE, (test->flags & TESTF_REDIRECT) ? 2 : 1);
710     CHECK_NOTIFIED2(INTERNET_STATUS_RESPONSE_RECEIVED, (test->flags & TESTF_REDIRECT) ? 2 : 1);
711     if(test->flags & TESTF_REDIRECT)
712         CHECK_NOTIFIED(INTERNET_STATUS_REDIRECT);
713     if (flags & INTERNET_FLAG_ASYNC)
714         CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
715     /* Sent on WinXP only if first_connection_to_test_url is TRUE, on Win98 always sent */
716     CLEAR_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
717     CLEAR_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
718 
719     test_request_flags(hor, 0);
720 
721     length = 100;
722     res = InternetQueryOptionA(hor,INTERNET_OPTION_URL,buffer,&length);
723     ok(res, "InternetQueryOptionA(INTERNET_OPTION_URL) failed with error %d\n", GetLastError());
724 
725     length = sizeof(buffer)-2;
726     memset(buffer, 0x77, sizeof(buffer));
727     SetLastError(0xdeadbeef);
728     res = HttpQueryInfoA(hor,HTTP_QUERY_RAW_HEADERS,buffer,&length,0x0);
729     ok(res, "HttpQueryInfoA(HTTP_QUERY_RAW_HEADERS) failed with error %d\n", GetLastError());
730     ok(GetLastError() == 0 ||
731                 broken(GetLastError() == 0xdeadbeef /* XP/W2K3 */), "Last Error not reset %u\n", GetLastError());
732     /* show that the function writes data past the length returned */
733     ok(buffer[length-2], "Expected any header character, got 0x00\n");
734     ok(!buffer[length-1], "Expected 0x00, got %02X\n", buffer[length-1]);
735     ok(!buffer[length], "Expected 0x00, got %02X\n", buffer[length]);
736     ok(buffer[length+1] == 0x77, "Expected 0x77, got %02X\n", buffer[length+1]);
737 
738     length2 = length;
739     res = HttpQueryInfoA(hor,HTTP_QUERY_RAW_HEADERS,buffer,&length2,0x0);
740     ok(!res, "Expected 0x00, got %d\n", res);
741     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected last error: %d\n", GetLastError());
742     ok(length2 == length+1, "Expected %d, got %d\n", length+1, length2);
743     /* the in length of the buffer must be +1 but the length returned does not count this */
744     length2 = length+1;
745     memset(buffer, 0x77, sizeof(buffer));
746     res = HttpQueryInfoA(hor,HTTP_QUERY_RAW_HEADERS,buffer,&length2,0x0);
747     ok(res, "HttpQueryInfoA(HTTP_QUERY_RAW_HEADERS) failed with error %d\n", GetLastError());
748     ok(buffer[length2] == 0x00, "Expected 0x00, got %02X\n", buffer[length2]);
749     ok(buffer[length2+1] == 0x77, "Expected 0x77, got %02X\n", buffer[length2+1]);
750     ok(length2 == length, "Value should not have changed: %d != %d\n", length2, length);
751 
752     length = sizeof(wbuffer)-2*sizeof(WCHAR);
753     memset(wbuffer, 0x77, sizeof(wbuffer));
754     res = HttpQueryInfoW(hor, HTTP_QUERY_RAW_HEADERS, wbuffer, &length, 0x0);
755     ok(res, "HttpQueryInfoW(HTTP_QUERY_RAW_HEADERS) failed with error %d\n", GetLastError());
756     ok(length % sizeof(WCHAR) == 0, "Expected that length is a multiple of sizeof(WCHAR), got %d.\n", length);
757     length /= sizeof(WCHAR);
758     /* show that the function writes data past the length returned */
759     ok(wbuffer[length-2], "Expected any header character, got 0x0000\n");
760     ok(!wbuffer[length-1], "Expected 0x0000, got %04X\n", wbuffer[length-1]);
761     ok(!wbuffer[length], "Expected 0x0000, got %04X\n", wbuffer[length]);
762     ok(wbuffer[length+1] == 0x7777 || broken(wbuffer[length+1] != 0x7777),
763        "Expected 0x7777, got %04X\n", wbuffer[length+1]);
764 
765     length2 = length*sizeof(WCHAR);
766     res = HttpQueryInfoW(hor,HTTP_QUERY_RAW_HEADERS,wbuffer,&length2,0x0);
767     ok(!res, "Expected 0x00, got %d\n", res);
768     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected last error: %d\n", GetLastError());
769     ok(length2 % sizeof(WCHAR) == 0, "Expected that length is a multiple of sizeof(WCHAR), got %d.\n", length2);
770     length2 /= sizeof(WCHAR);
771     ok(length2 == length+1, "Expected %d, got %d\n", length+1, length2);
772     /* the in length of the buffer must be +1 but the length returned does not count this */
773     length2 = (length+1)*sizeof(WCHAR);
774     memset(wbuffer, 0x77, sizeof(wbuffer));
775     res = HttpQueryInfoW(hor,HTTP_QUERY_RAW_HEADERS,wbuffer,&length2,0x0);
776     ok(res, "HttpQueryInfoW(HTTP_QUERY_RAW_HEADERS) failed with error %d\n", GetLastError());
777     ok(length2 % sizeof(WCHAR) == 0, "Expected that length is a multiple of sizeof(WCHAR), got %d.\n", length2);
778     length2 /= sizeof(WCHAR);
779     ok(!wbuffer[length2], "Expected 0x0000, got %04X\n", wbuffer[length2]);
780     ok(wbuffer[length2+1] == 0x7777, "Expected 0x7777, got %04X\n", wbuffer[length2+1]);
781     ok(length2 == length, "Value should not have changed: %d != %d\n", length2, length);
782 
783     test_request_url(hor, test->redirected_url);
784 
785     index = 0;
786     length = 0;
787     SetLastError(0xdeadbeef);
788     ok(HttpQueryInfoA(hor,HTTP_QUERY_CONTENT_LENGTH,NULL,&length,&index) == FALSE,"Query worked\n");
789     if(test->flags & TESTF_COMPRESSED)
790         ok(GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND,
791            "expected ERROR_HTTP_HEADER_NOT_FOUND, got %u\n", GetLastError());
792     ok(index == 0, "Index was incremented\n");
793 
794     index = 0;
795     length = 16;
796     res = HttpQueryInfoA(hor,HTTP_QUERY_CONTENT_LENGTH,&buffer,&length,&index);
797     trace("Option HTTP_QUERY_CONTENT_LENGTH -> %i  %s  (%u)\n",res,buffer,GetLastError());
798     if(test->flags & TESTF_COMPRESSED)
799         ok(!res && GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND,
800            "expected ERROR_HTTP_HEADER_NOT_FOUND, got %x (%u)\n", res, GetLastError());
801     ok(!res || index == 1, "Index was not incremented although result is %x (index = %u)\n", res, index);
802 
803     length = 100;
804     res = HttpQueryInfoA(hor,HTTP_QUERY_CONTENT_TYPE,buffer,&length,0x0);
805     buffer[length]=0;
806     trace("Option HTTP_QUERY_CONTENT_TYPE -> %i  %s\n",res,buffer);
807 
808     length = 100;
809     res = HttpQueryInfoA(hor,HTTP_QUERY_CONTENT_ENCODING,buffer,&length,0x0);
810     buffer[length]=0;
811     trace("Option HTTP_QUERY_CONTENT_ENCODING -> %i  %s\n",res,buffer);
812 
813     SetLastError(0xdeadbeef);
814     res = InternetReadFile(NULL, buffer, 100, &length);
815     ok(!res, "InternetReadFile should have failed\n");
816     ok(GetLastError() == ERROR_INVALID_HANDLE,
817         "InternetReadFile should have set last error to ERROR_INVALID_HANDLE instead of %u\n",
818         GetLastError());
819 
820     length = 100;
821     if(winetest_debug > 1)
822         trace("Entering Query loop\n");
823 
824     while (TRUE)
825     {
826         if (flags & INTERNET_FLAG_ASYNC)
827             SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
828 
829         /* IE11 calls those in InternetQueryDataAvailable call. */
830         SET_OPTIONAL(INTERNET_STATUS_RECEIVING_RESPONSE);
831         SET_OPTIONAL(INTERNET_STATUS_RESPONSE_RECEIVED);
832 
833         length = 0;
834         res = InternetQueryDataAvailable(hor,&length,0x0,0x0);
835 
836         CLEAR_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
837 
838         if (flags & INTERNET_FLAG_ASYNC)
839         {
840             if (res)
841             {
842                 CHECK_NOT_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
843                 if(exlen) {
844                     ok(length >= exlen, "length %u < exlen %u\n", length, exlen);
845                     exlen = 0;
846                 }
847             }
848             else if (GetLastError() == ERROR_IO_PENDING)
849             {
850                 if(winetest_debug > 1)
851                     trace("pending\n");
852                 /* on some tests, InternetQueryDataAvailable returns non-zero length and ERROR_IO_PENDING */
853                 if(!(test->flags & TESTF_CHUNKED))
854                     ok(!length, "InternetQueryDataAvailable returned ERROR_IO_PENDING and %u length\n", length);
855                 WaitForSingleObject(complete_event, INFINITE);
856                 exlen = length;
857                 ok(exlen, "length = 0\n");
858                 CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
859                 CLEAR_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
860                 ok(req_error, "req_error = 0\n");
861                 continue;
862             }else {
863                 ok(0, "InternetQueryDataAvailable failed: %u\n", GetLastError());
864             }
865         }else {
866             ok(res, "InternetQueryDataAvailable failed: %u\n", GetLastError());
867         }
868         CLEAR_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
869 
870         if(winetest_debug > 1)
871             trace("length %u\n", length);
872         if(test->flags & TESTF_CHUNKED)
873             ok(length <= 8192, "length = %d, expected <= 8192\n", length);
874         if (length)
875         {
876             char *buffer;
877             buffer = HeapAlloc(GetProcessHeap(),0,length+1);
878 
879             res = InternetReadFile(hor,buffer,length,&length);
880 
881             buffer[length]=0;
882 
883             if(winetest_debug > 1)
884                 trace("ReadFile -> %s %i\n", res ? "TRUE" : "FALSE", length);
885 
886             if(test->content)
887                 ok(!strcmp(buffer, test->content), "buffer = '%s', expected '%s'\n", buffer, test->content);
888             HeapFree(GetProcessHeap(),0,buffer);
889         }else {
890             ok(!on_async, "Returned zero size in response to request complete\n");
891             break;
892         }
893         on_async = FALSE;
894     }
895     if(test->flags & TESTF_REDIRECT) {
896         CHECK_NOTIFIED2(INTERNET_STATUS_CLOSING_CONNECTION, 2);
897         CHECK_NOTIFIED2(INTERNET_STATUS_CONNECTION_CLOSED, 2);
898     }
899 abort:
900     if(winetest_debug > 1)
901         trace("aborting\n");
902     close_async_handle(hi, 2);
903     first_connection_to_test_url = FALSE;
904 }
905 
906 static void InternetReadFile_chunked_test(void)
907 {
908     BOOL res;
909     CHAR buffer[4000];
910     DWORD length, got;
911     const char *types[2] = { "*", NULL };
912     HINTERNET hi, hic = 0, hor = 0;
913 
914     trace("Starting InternetReadFile chunked test\n");
915 
916     trace("InternetOpenA <--\n");
917     hi = InternetOpenA("", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
918     ok((hi != 0x0),"InternetOpen failed with error %u\n", GetLastError());
919     trace("InternetOpenA -->\n");
920 
921     if (hi == 0x0) goto abort;
922 
923     trace("InternetConnectA <--\n");
924     hic=InternetConnectA(hi, "test.winehq.org", INTERNET_INVALID_PORT_NUMBER,
925                          NULL, NULL, INTERNET_SERVICE_HTTP, 0x0, 0xdeadbeef);
926     ok((hic != 0x0),"InternetConnect failed with error %u\n", GetLastError());
927     trace("InternetConnectA -->\n");
928 
929     if (hic == 0x0) goto abort;
930 
931     trace("HttpOpenRequestA <--\n");
932     hor = HttpOpenRequestA(hic, "GET", "/tests/chunked", NULL, NULL, types,
933                            INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RELOAD,
934                            0xdeadbead);
935     if (hor == 0x0 && GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED) {
936         /*
937          * If the internet name can't be resolved we are probably behind
938          * a firewall or in some other way not directly connected to the
939          * Internet. Not enough reason to fail the test. Just ignore and
940          * abort.
941          */
942     } else  {
943         ok((hor != 0x0),"HttpOpenRequest failed with error %u\n", GetLastError());
944     }
945     trace("HttpOpenRequestA -->\n");
946 
947     if (hor == 0x0) goto abort;
948 
949     trace("HttpSendRequestA -->\n");
950     SetLastError(0xdeadbeef);
951     res = HttpSendRequestA(hor, "", -1, NULL, 0);
952     ok(res || (GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED),
953        "Synchronous HttpSendRequest returning 0, error %u\n", GetLastError());
954     trace("HttpSendRequestA <--\n");
955 
956     test_request_flags(hor, 0);
957 
958     length = 100;
959     res = HttpQueryInfoA(hor,HTTP_QUERY_CONTENT_TYPE,buffer,&length,0x0);
960     buffer[length]=0;
961     trace("Option CONTENT_TYPE -> %i  %s\n",res,buffer);
962 
963     SetLastError( 0xdeadbeef );
964     length = 100;
965     res = HttpQueryInfoA(hor,HTTP_QUERY_TRANSFER_ENCODING,buffer,&length,0x0);
966     buffer[length]=0;
967     trace("Option TRANSFER_ENCODING -> %i  %s\n",res,buffer);
968     ok( res || ( proxy_active() && GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND ),
969         "Failed to get TRANSFER_ENCODING option, error %u\n", GetLastError() );
970     ok( !strcmp( buffer, "chunked" ) || ( ! res && proxy_active() && GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND ),
971         "Wrong transfer encoding '%s'\n", buffer );
972 
973     SetLastError( 0xdeadbeef );
974     length = 16;
975     res = HttpQueryInfoA(hor,HTTP_QUERY_CONTENT_LENGTH,&buffer,&length,0x0);
976     ok( !res, "Found CONTENT_LENGTH option '%s'\n", buffer );
977     ok( GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND, "Wrong error %u\n", GetLastError() );
978 
979     length = 100;
980     trace("Entering Query loop\n");
981 
982     while (TRUE)
983     {
984         res = InternetQueryDataAvailable(hor,&length,0x0,0x0);
985         ok(!(!res && length != 0),"InternetQueryDataAvailable failed with non-zero length\n");
986         ok(res, "InternetQueryDataAvailable failed, error %d\n", GetLastError());
987         trace("got %u available\n",length);
988         if (length)
989         {
990             char *buffer = HeapAlloc(GetProcessHeap(),0,length+1);
991 
992             SetLastError(0xdeadbeef);
993             res = InternetReadFile(hor,buffer,length,&got);
994             ok(GetLastError() == 0 ||
995                 broken(GetLastError() == 0xdeadbeef /* XP/W2K3 */), "Last Error not reset %u\n", GetLastError());
996 
997             buffer[got]=0;
998             trace("ReadFile -> %i %i\n",res,got);
999             ok( length == got, "only got %u of %u available\n", got, length );
1000             ok( buffer[got-1] == '\n', "received partial line '%s'\n", buffer );
1001 
1002             HeapFree(GetProcessHeap(),0,buffer);
1003             if (!got) break;
1004         }
1005         if (length == 0)
1006         {
1007             got = 0xdeadbeef;
1008             SetLastError(0xdeadbeef);
1009             res = InternetReadFile( hor, buffer, 1, &got );
1010             ok( res, "InternetReadFile failed: %u\n", GetLastError() );
1011             ok(GetLastError() == 0 ||
1012                 broken(GetLastError() == 0xdeadbeef /* XP/W2K3 */), "Last Error not reset %u\n", GetLastError());
1013             ok( !got, "got %u\n", got );
1014             break;
1015         }
1016     }
1017 abort:
1018     trace("aborting\n");
1019     if (hor != 0x0) {
1020         res = InternetCloseHandle(hor);
1021         ok (res, "InternetCloseHandle of handle opened by HttpOpenRequestA failed\n");
1022     }
1023     if (hi != 0x0) {
1024         res = InternetCloseHandle(hi);
1025         ok (res, "InternetCloseHandle of handle opened by InternetOpenA failed\n");
1026     }
1027 }
1028 
1029 static void InternetReadFileExA_test(int flags)
1030 {
1031     DWORD rc;
1032     DWORD length;
1033     const char *types[2] = { "*", NULL };
1034     HINTERNET hi, hic = 0, hor = 0;
1035     INTERNET_BUFFERSA inetbuffers;
1036 
1037     trace("Starting InternetReadFileExA test with flags 0x%x\n",flags);
1038     reset_events();
1039 
1040     trace("InternetOpenA <--\n");
1041     hi = InternetOpenA("", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, flags);
1042     ok((hi != 0x0),"InternetOpen failed with error %u\n", GetLastError());
1043     trace("InternetOpenA -->\n");
1044 
1045     if (hi == 0x0) goto abort;
1046 
1047     pInternetSetStatusCallbackA(hi,&callback);
1048 
1049     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
1050 
1051     trace("InternetConnectA <--\n");
1052     hic=InternetConnectA(hi, "test.winehq.org", INTERNET_INVALID_PORT_NUMBER,
1053                          NULL, NULL, INTERNET_SERVICE_HTTP, 0x0, 0xdeadbeef);
1054     ok((hic != 0x0),"InternetConnect failed with error %u\n", GetLastError());
1055     trace("InternetConnectA -->\n");
1056 
1057     if (hic == 0x0) goto abort;
1058 
1059     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
1060     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
1061 
1062     trace("HttpOpenRequestA <--\n");
1063     hor = HttpOpenRequestA(hic, "GET", "/tests/redirect", NULL, NULL, types,
1064                            INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RELOAD,
1065                            0xdeadbead);
1066     if (hor == 0x0 && GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED) {
1067         /*
1068          * If the internet name can't be resolved we are probably behind
1069          * a firewall or in some other way not directly connected to the
1070          * Internet. Not enough reason to fail the test. Just ignore and
1071          * abort.
1072          */
1073     } else  {
1074         ok((hor != 0x0),"HttpOpenRequest failed with error %u\n", GetLastError());
1075     }
1076     trace("HttpOpenRequestA -->\n");
1077 
1078     if (hor == 0x0) goto abort;
1079 
1080     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
1081     CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME);
1082     CHECK_NOT_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED);
1083     if (first_connection_to_test_url)
1084     {
1085         SET_EXPECT(INTERNET_STATUS_RESOLVING_NAME);
1086         SET_EXPECT(INTERNET_STATUS_NAME_RESOLVED);
1087     }
1088     SET_OPTIONAL2(INTERNET_STATUS_COOKIE_SENT, 2);
1089     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
1090     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
1091     SET_EXPECT2(INTERNET_STATUS_SENDING_REQUEST, 2);
1092     SET_EXPECT2(INTERNET_STATUS_REQUEST_SENT, 2);
1093     SET_EXPECT2(INTERNET_STATUS_RECEIVING_RESPONSE, 2);
1094     SET_EXPECT2(INTERNET_STATUS_RESPONSE_RECEIVED, 2);
1095     SET_OPTIONAL2(INTERNET_STATUS_CLOSING_CONNECTION, 2);
1096     SET_OPTIONAL2(INTERNET_STATUS_CONNECTION_CLOSED, 2);
1097     SET_EXPECT(INTERNET_STATUS_REDIRECT);
1098     SET_OPTIONAL(INTERNET_STATUS_CONNECTING_TO_SERVER);
1099     SET_OPTIONAL(INTERNET_STATUS_CONNECTED_TO_SERVER);
1100     if (flags & INTERNET_FLAG_ASYNC)
1101         SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
1102     else
1103         SET_WINE_ALLOW(INTERNET_STATUS_REQUEST_COMPLETE);
1104 
1105     trace("HttpSendRequestA -->\n");
1106     SetLastError(0xdeadbeef);
1107     rc = HttpSendRequestA(hor, "", -1, NULL, 0);
1108     if (flags & INTERNET_FLAG_ASYNC)
1109         ok(((rc == 0)&&(GetLastError() == ERROR_IO_PENDING)),
1110             "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n");
1111     else
1112         ok((rc != 0) || GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED,
1113            "Synchronous HttpSendRequest returning 0, error %u\n", GetLastError());
1114     trace("HttpSendRequestA <--\n");
1115 
1116     if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
1117         WaitForSingleObject(complete_event, INFINITE);
1118         ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error);
1119     }
1120 
1121     if (first_connection_to_test_url)
1122     {
1123         CHECK_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME);
1124         CHECK_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED);
1125     }
1126     else
1127     {
1128         CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME);
1129         CHECK_NOT_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED);
1130     }
1131     CHECK_NOTIFIED2(INTERNET_STATUS_SENDING_REQUEST, 2);
1132     CHECK_NOTIFIED2(INTERNET_STATUS_REQUEST_SENT, 2);
1133     CHECK_NOTIFIED2(INTERNET_STATUS_RECEIVING_RESPONSE, 2);
1134     CHECK_NOTIFIED2(INTERNET_STATUS_RESPONSE_RECEIVED, 2);
1135     CHECK_NOTIFIED2(INTERNET_STATUS_CLOSING_CONNECTION, 2);
1136     CHECK_NOTIFIED2(INTERNET_STATUS_CONNECTION_CLOSED, 2);
1137     CHECK_NOTIFIED(INTERNET_STATUS_REDIRECT);
1138     if (flags & INTERNET_FLAG_ASYNC)
1139         CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
1140     else
1141         todo_wine CHECK_NOT_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
1142     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
1143     /* Sent on WinXP only if first_connection_to_test_url is TRUE, on Win98 always sent */
1144     CLEAR_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
1145     CLEAR_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
1146 
1147     if(is_ie7plus) {
1148         rc = InternetReadFileExW(hor, NULL, 0, 0xdeadcafe);
1149         ok(!rc && (GetLastError() == ERROR_INVALID_PARAMETER),
1150            "InternetReadFileEx should have failed with ERROR_INVALID_PARAMETER instead of %s, %u\n",
1151            rc ? "TRUE" : "FALSE", GetLastError());
1152     }
1153 
1154     /* tests invalid dwStructSize */
1155     inetbuffers.dwStructSize = sizeof(inetbuffers)+1;
1156     inetbuffers.lpcszHeader = NULL;
1157     inetbuffers.dwHeadersLength = 0;
1158     inetbuffers.dwBufferLength = 10;
1159     inetbuffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, 10);
1160     inetbuffers.dwOffsetHigh = 1234;
1161     inetbuffers.dwOffsetLow = 5678;
1162     rc = InternetReadFileExA(hor, &inetbuffers, 0, 0xdeadcafe);
1163     ok(!rc && (GetLastError() == ERROR_INVALID_PARAMETER),
1164         "InternetReadFileEx should have failed with ERROR_INVALID_PARAMETER instead of %s, %u\n",
1165         rc ? "TRUE" : "FALSE", GetLastError());
1166     HeapFree(GetProcessHeap(), 0, inetbuffers.lpvBuffer);
1167 
1168     test_request_flags(hor, 0);
1169 
1170     /* tests to see whether lpcszHeader is used - it isn't */
1171     inetbuffers.dwStructSize = sizeof(inetbuffers);
1172     inetbuffers.lpcszHeader = (LPCSTR)0xdeadbeef;
1173     inetbuffers.dwHeadersLength = 255;
1174     inetbuffers.dwBufferLength = 0;
1175     inetbuffers.lpvBuffer = NULL;
1176     inetbuffers.dwOffsetHigh = 1234;
1177     inetbuffers.dwOffsetLow = 5678;
1178     rc = InternetReadFileExA(hor, &inetbuffers, 0, 0xdeadcafe);
1179     ok(rc, "InternetReadFileEx failed with error %u\n", GetLastError());
1180     trace("read %i bytes\n", inetbuffers.dwBufferLength);
1181 
1182     rc = InternetReadFileExA(NULL, &inetbuffers, 0, 0xdeadcafe);
1183     ok(!rc && (GetLastError() == ERROR_INVALID_HANDLE),
1184         "InternetReadFileEx should have failed with ERROR_INVALID_HANDLE instead of %s, %u\n",
1185         rc ? "TRUE" : "FALSE", GetLastError());
1186 
1187     length = 0;
1188     trace("Entering Query loop\n");
1189 
1190     while (TRUE)
1191     {
1192         inetbuffers.dwStructSize = sizeof(inetbuffers);
1193         inetbuffers.dwBufferLength = 1024;
1194         inetbuffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, inetbuffers.dwBufferLength+1);
1195         inetbuffers.dwOffsetHigh = 1234;
1196         inetbuffers.dwOffsetLow = 5678;
1197 
1198         SET_WINE_ALLOW(INTERNET_STATUS_RECEIVING_RESPONSE);
1199         SET_WINE_ALLOW(INTERNET_STATUS_RESPONSE_RECEIVED);
1200         SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
1201         rc = InternetReadFileExA(hor, &inetbuffers, IRF_ASYNC | IRF_USE_CONTEXT, 0xcafebabe);
1202         if (!rc)
1203         {
1204             if (GetLastError() == ERROR_IO_PENDING)
1205             {
1206                 trace("InternetReadFileEx -> PENDING\n");
1207                 ok(flags & INTERNET_FLAG_ASYNC,
1208                    "Should not get ERROR_IO_PENDING without INTERNET_FLAG_ASYNC\n");
1209                 CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
1210                 WaitForSingleObject(complete_event, INFINITE);
1211                 CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
1212                 CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
1213                 ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error);
1214             }
1215             else
1216             {
1217                 trace("InternetReadFileEx -> FAILED %u\n", GetLastError());
1218                 break;
1219             }
1220         }
1221         else
1222         {
1223             trace("InternetReadFileEx -> SUCCEEDED\n");
1224             CHECK_NOT_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
1225             if (inetbuffers.dwBufferLength)
1226             {
1227                 CHECK_NOT_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
1228                 CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
1229             }
1230             else
1231             {
1232                 /* Win98 still sends these when 0 bytes are read, WinXP does not */
1233                 CLEAR_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
1234                 CLEAR_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
1235             }
1236         }
1237 
1238         trace("read %i bytes\n", inetbuffers.dwBufferLength);
1239         ((char *)inetbuffers.lpvBuffer)[inetbuffers.dwBufferLength] = '\0';
1240 
1241         ok(inetbuffers.dwOffsetHigh == 1234 && inetbuffers.dwOffsetLow == 5678,
1242             "InternetReadFileEx sets offsets to 0x%x%08x\n",
1243             inetbuffers.dwOffsetHigh, inetbuffers.dwOffsetLow);
1244 
1245         HeapFree(GetProcessHeap(), 0, inetbuffers.lpvBuffer);
1246 
1247         if (!inetbuffers.dwBufferLength)
1248             break;
1249 
1250         length += inetbuffers.dwBufferLength;
1251     }
1252     ok(length > 0, "failed to read any of the document\n");
1253     trace("Finished. Read %d bytes\n", length);
1254 
1255 abort:
1256     close_async_handle(hi, 2);
1257     first_connection_to_test_url = FALSE;
1258 }
1259 
1260 static void InternetOpenUrlA_test(void)
1261 {
1262   HINTERNET myhinternet, myhttp;
1263   char buffer[0x400];
1264   DWORD size, readbytes, totalbytes=0;
1265   BOOL ret;
1266 
1267   ret = DeleteUrlCacheEntryA(TEST_URL);
1268   ok(ret || GetLastError() == ERROR_FILE_NOT_FOUND,
1269           "DeleteUrlCacheEntry returned %x, GetLastError() = %d\n", ret, GetLastError());
1270 
1271   myhinternet = InternetOpenA("Winetest",0,NULL,NULL,INTERNET_FLAG_NO_CACHE_WRITE);
1272   ok((myhinternet != 0), "InternetOpen failed, error %u\n",GetLastError());
1273   size = 0x400;
1274   ret = InternetCanonicalizeUrlA(TEST_URL, buffer, &size,ICU_BROWSER_MODE);
1275   ok( ret, "InternetCanonicalizeUrl failed, error %u\n",GetLastError());
1276 
1277   SetLastError(0);
1278   myhttp = InternetOpenUrlA(myhinternet, TEST_URL, 0, 0,
1279 			   INTERNET_FLAG_RELOAD|INTERNET_FLAG_NO_CACHE_WRITE|INTERNET_FLAG_TRANSFER_BINARY,0);
1280   if (GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED)
1281     return; /* WinXP returns this when not connected to the net */
1282   ok((myhttp != 0),"InternetOpenUrl failed, error %u\n",GetLastError());
1283   ret = InternetReadFile(myhttp, buffer,0x400,&readbytes);
1284   ok( ret, "InternetReadFile failed, error %u\n",GetLastError());
1285   totalbytes += readbytes;
1286   while (readbytes && InternetReadFile(myhttp, buffer,0x400,&readbytes))
1287     totalbytes += readbytes;
1288   trace("read 0x%08x bytes\n",totalbytes);
1289 
1290   InternetCloseHandle(myhttp);
1291   InternetCloseHandle(myhinternet);
1292 
1293   ret = DeleteUrlCacheEntryA(TEST_URL);
1294   ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, "INTERNET_FLAG_NO_CACHE_WRITE flag doesn't work\n");
1295 }
1296 
1297 static void HttpSendRequestEx_test(void)
1298 {
1299     HINTERNET hSession;
1300     HINTERNET hConnect;
1301     HINTERNET hRequest;
1302 
1303     INTERNET_BUFFERSA BufferIn;
1304     DWORD dwBytesWritten, dwBytesRead, error;
1305     CHAR szBuffer[256];
1306     int i;
1307     BOOL ret;
1308 
1309     static char szPostData[] = "mode=Test";
1310     static const char szContentType[] = "Content-Type: application/x-www-form-urlencoded";
1311 
1312     hSession = InternetOpenA("Wine Regression Test",
1313             INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
1314     ok( hSession != NULL ,"Unable to open Internet session\n");
1315     hConnect = InternetConnectA(hSession, "test.winehq.org",
1316             INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0,
1317             0);
1318     ok( hConnect != NULL, "Unable to connect to http://test.winehq.org\n");
1319     hRequest = HttpOpenRequestA(hConnect, "POST", "/tests/post.php",
1320             NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
1321     if (!hRequest && GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED)
1322     {
1323         skip( "Network unreachable, skipping test\n" );
1324         goto done;
1325     }
1326     ok( hRequest != NULL, "Failed to open request handle err %u\n", GetLastError());
1327 
1328     test_request_flags(hRequest, INTERNET_REQFLAG_NO_HEADERS);
1329 
1330     BufferIn.dwStructSize = sizeof(BufferIn);
1331     BufferIn.Next = (INTERNET_BUFFERSA*)0xdeadcab;
1332     BufferIn.lpcszHeader = szContentType;
1333     BufferIn.dwHeadersLength = sizeof(szContentType)-1;
1334     BufferIn.dwHeadersTotal = sizeof(szContentType)-1;
1335     BufferIn.lpvBuffer = szPostData;
1336     BufferIn.dwBufferLength = 3;
1337     BufferIn.dwBufferTotal = sizeof(szPostData)-1;
1338     BufferIn.dwOffsetLow = 0;
1339     BufferIn.dwOffsetHigh = 0;
1340 
1341     SetLastError(0xdeadbeef);
1342     ret = HttpSendRequestExA(hRequest, &BufferIn, NULL, 0 ,0);
1343     error = GetLastError();
1344     ok(ret, "HttpSendRequestEx Failed with error %u\n", error);
1345     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", error);
1346 
1347     test_request_flags(hRequest, INTERNET_REQFLAG_NO_HEADERS);
1348 
1349     for (i = 3; szPostData[i]; i++)
1350         ok(InternetWriteFile(hRequest, &szPostData[i], 1, &dwBytesWritten),
1351                 "InternetWriteFile failed\n");
1352 
1353     test_request_flags(hRequest, INTERNET_REQFLAG_NO_HEADERS);
1354 
1355     ok(HttpEndRequestA(hRequest, NULL, 0, 0), "HttpEndRequest Failed\n");
1356 
1357     test_request_flags(hRequest, 0);
1358 
1359     ok(InternetReadFile(hRequest, szBuffer, 255, &dwBytesRead),
1360             "Unable to read response\n");
1361     szBuffer[dwBytesRead] = 0;
1362 
1363     ok(dwBytesRead == 13,"Read %u bytes instead of 13\n",dwBytesRead);
1364     ok(strncmp(szBuffer,"mode => Test\n",dwBytesRead)==0 || broken(proxy_active()),"Got string %s\n",szBuffer);
1365 
1366     ok(InternetCloseHandle(hRequest), "Close request handle failed\n");
1367 done:
1368     ok(InternetCloseHandle(hConnect), "Close connect handle failed\n");
1369     ok(InternetCloseHandle(hSession), "Close session handle failed\n");
1370 }
1371 
1372 static void InternetOpenRequest_test(void)
1373 {
1374     HINTERNET session, connect, request;
1375     static const char *types[] = { "*", "", NULL };
1376     static const WCHAR slash[] = {'/', 0}, any[] = {'*', 0}, empty[] = {0};
1377     static const WCHAR *typesW[] = { any, empty, NULL };
1378     BOOL ret;
1379 
1380     session = InternetOpenA("Wine Regression Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
1381     ok(session != NULL ,"Unable to open Internet session\n");
1382 
1383     connect = InternetConnectA(session, NULL, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
1384                               INTERNET_SERVICE_HTTP, 0, 0);
1385     ok(connect == NULL, "InternetConnectA should have failed\n");
1386     ok(GetLastError() == ERROR_INVALID_PARAMETER, "InternetConnectA with NULL server named should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
1387 
1388     connect = InternetConnectA(session, "", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
1389                               INTERNET_SERVICE_HTTP, 0, 0);
1390     ok(connect == NULL, "InternetConnectA should have failed\n");
1391     ok(GetLastError() == ERROR_INVALID_PARAMETER, "InternetConnectA with blank server named should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
1392 
1393     connect = InternetConnectA(session, "test.winehq.org", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
1394                               INTERNET_SERVICE_HTTP, 0, 0);
1395     ok(connect != NULL, "Unable to connect to http://test.winehq.org with error %d\n", GetLastError());
1396 
1397     request = HttpOpenRequestA(connect, NULL, "/", NULL, NULL, types, INTERNET_FLAG_NO_CACHE_WRITE, 0);
1398     if (!request && GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED)
1399     {
1400         skip( "Network unreachable, skipping test\n" );
1401         goto done;
1402     }
1403     ok(request != NULL, "Failed to open request handle err %u\n", GetLastError());
1404 
1405     ret = HttpSendRequestW(request, NULL, 0, NULL, 0);
1406     ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
1407     ok(InternetCloseHandle(request), "Close request handle failed\n");
1408 
1409     request = HttpOpenRequestW(connect, NULL, slash, NULL, NULL, typesW, INTERNET_FLAG_NO_CACHE_WRITE, 0);
1410     ok(request != NULL, "Failed to open request handle err %u\n", GetLastError());
1411 
1412     ret = HttpSendRequestA(request, NULL, 0, NULL, 0);
1413     ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
1414     ok(InternetCloseHandle(request), "Close request handle failed\n");
1415 
1416 done:
1417     ok(InternetCloseHandle(connect), "Close connect handle failed\n");
1418     ok(InternetCloseHandle(session), "Close session handle failed\n");
1419 }
1420 
1421 static void test_cache_read(void)
1422 {
1423     HINTERNET session, connection, req;
1424     FILETIME now, tomorrow, yesterday;
1425     BYTE content[1000], buf[2000];
1426     char file_path[MAX_PATH];
1427     ULARGE_INTEGER li;
1428     HANDLE file;
1429     DWORD size;
1430     unsigned i;
1431     BOOL res;
1432 
1433     static const char cache_only_url[] = "http://test.winehq.org/tests/cache-only";
1434     BYTE cache_headers[] = "HTTP/1.1 200 OK\r\n\r\n";
1435 
1436     trace("Testing cache read...\n");
1437     reset_events();
1438 
1439     for(i = 0; i < sizeof(content); i++)
1440         content[i] = '0' + (i%10);
1441 
1442     GetSystemTimeAsFileTime(&now);
1443     li.u.HighPart = now.dwHighDateTime;
1444     li.u.LowPart = now.dwLowDateTime;
1445     li.QuadPart += (LONGLONG)10000000 * 3600 * 24;
1446     tomorrow.dwHighDateTime = li.u.HighPart;
1447     tomorrow.dwLowDateTime = li.u.LowPart;
1448     li.QuadPart -= (LONGLONG)10000000 * 3600 * 24 * 2;
1449     yesterday.dwHighDateTime = li.u.HighPart;
1450     yesterday.dwLowDateTime = li.u.LowPart;
1451 
1452     res = CreateUrlCacheEntryA(cache_only_url, sizeof(content), "", file_path, 0);
1453     ok(res, "CreateUrlCacheEntryA failed: %u\n", GetLastError());
1454 
1455     file = CreateFileA(file_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1456     ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1457 
1458     WriteFile(file, content, sizeof(content), &size, NULL);
1459     CloseHandle(file);
1460 
1461     res = CommitUrlCacheEntryA(cache_only_url, file_path, tomorrow, yesterday, NORMAL_CACHE_ENTRY,
1462                                cache_headers, sizeof(cache_headers)-1, "", 0);
1463     ok(res, "CommitUrlCacheEntryA failed: %u\n", GetLastError());
1464 
1465     session = InternetOpenA("", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);
1466     ok(session != NULL,"InternetOpen failed with error %u\n", GetLastError());
1467 
1468     pInternetSetStatusCallbackA(session, callback);
1469 
1470     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
1471     connection = InternetConnectA(session, "test.winehq.org", INTERNET_DEFAULT_HTTP_PORT,
1472             NULL, NULL, INTERNET_SERVICE_HTTP, 0x0, 0xdeadbeef);
1473     ok(connection != NULL,"InternetConnect failed with error %u\n", GetLastError());
1474     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
1475 
1476     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
1477     req = HttpOpenRequestA(connection, "GET", "/tests/cache-only", NULL, NULL, NULL, 0, 0xdeadbead);
1478     ok(req != NULL, "HttpOpenRequest failed: %u\n", GetLastError());
1479     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
1480 
1481     SET_WINE_ALLOW(INTERNET_STATUS_CONNECTING_TO_SERVER);
1482     SET_WINE_ALLOW(INTERNET_STATUS_CONNECTED_TO_SERVER);
1483     SET_WINE_ALLOW(INTERNET_STATUS_SENDING_REQUEST);
1484     SET_WINE_ALLOW(INTERNET_STATUS_REQUEST_SENT);
1485     SET_WINE_ALLOW(INTERNET_STATUS_RECEIVING_RESPONSE);
1486     SET_WINE_ALLOW(INTERNET_STATUS_RESPONSE_RECEIVED);
1487     SET_WINE_ALLOW(INTERNET_STATUS_REQUEST_COMPLETE);
1488 
1489     res = HttpSendRequestA(req, NULL, -1, NULL, 0);
1490     todo_wine
1491     ok(res, "HttpSendRequest failed: %u\n", GetLastError());
1492 
1493     if(res) {
1494         size = 0;
1495         res = InternetQueryDataAvailable(req, &size, 0, 0);
1496         ok(res, "InternetQueryDataAvailable failed: %u\n", GetLastError());
1497         ok(size  == sizeof(content), "size = %u\n", size);
1498 
1499         size = sizeof(buf);
1500         res = InternetReadFile(req, buf, sizeof(buf), &size);
1501         ok(res, "InternetReadFile failed: %u\n", GetLastError());
1502         ok(size == sizeof(content), "size = %u\n", size);
1503         ok(!memcmp(content, buf, sizeof(content)), "unexpected content\n");
1504     }
1505 
1506     close_async_handle(session, 2);
1507 
1508     CLEAR_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
1509     CLEAR_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
1510     CLEAR_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
1511     CLEAR_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
1512     CLEAR_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
1513     CLEAR_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
1514     CLEAR_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
1515 
1516     res = DeleteUrlCacheEntryA(cache_only_url);
1517     ok(res, "DeleteUrlCacheEntryA failed: %u\n", GetLastError());
1518 }
1519 
1520 static void test_http_cache(void)
1521 {
1522     HINTERNET session, connect, request;
1523     char file_name[MAX_PATH], url[INTERNET_MAX_URL_LENGTH];
1524     DWORD size, file_size;
1525     BYTE buf[100];
1526     HANDLE file;
1527     BOOL ret;
1528     FILETIME filetime_zero = {0};
1529 
1530     static const char cached_content[] = "data read from cache";
1531     static const char *types[] = { "*", "", NULL };
1532 
1533     session = InternetOpenA("Wine Regression Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
1534     ok(session != NULL ,"Unable to open Internet session\n");
1535 
1536     connect = InternetConnectA(session, "test.winehq.org", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
1537                               INTERNET_SERVICE_HTTP, 0, 0);
1538     ok(connect != NULL, "Unable to connect to http://test.winehq.org with error %d\n", GetLastError());
1539 
1540     request = HttpOpenRequestA(connect, NULL, "/tests/hello.html", NULL, NULL, types, INTERNET_FLAG_NEED_FILE, 0);
1541     if (!request && GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED)
1542     {
1543         skip( "Network unreachable, skipping test\n" );
1544 
1545         ok(InternetCloseHandle(connect), "Close connect handle failed\n");
1546         ok(InternetCloseHandle(session), "Close session handle failed\n");
1547 
1548         return;
1549     }
1550     ok(request != NULL, "Failed to open request handle err %u\n", GetLastError());
1551 
1552     size = sizeof(url);
1553     ret = InternetQueryOptionA(request, INTERNET_OPTION_URL, url, &size);
1554     ok(ret, "InternetQueryOptionA(INTERNET_OPTION_URL) failed: %u\n", GetLastError());
1555     ok(!strcmp(url, "http://test.winehq.org/tests/hello.html"), "Wrong URL %s\n", url);
1556 
1557     size = sizeof(file_name);
1558     ret = InternetQueryOptionA(request, INTERNET_OPTION_DATAFILE_NAME, file_name, &size);
1559     ok(!ret, "InternetQueryOptionA(INTERNET_OPTION_DATAFILE_NAME) succeeded\n");
1560     ok(GetLastError() == ERROR_INTERNET_ITEM_NOT_FOUND, "GetLastError()=%u\n", GetLastError());
1561     ok(!size, "size = %d\n", size);
1562 
1563     ret = HttpSendRequestA(request, NULL, 0, NULL, 0);
1564     ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
1565 
1566     size = sizeof(file_name);
1567     ret = InternetQueryOptionA(request, INTERNET_OPTION_DATAFILE_NAME, file_name, &size);
1568     ok(ret, "InternetQueryOptionA(INTERNET_OPTION_DATAFILE_NAME) failed: %u\n", GetLastError());
1569 
1570     file = CreateFileA(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
1571                       FILE_ATTRIBUTE_NORMAL, NULL);
1572     ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError());
1573     file_size = GetFileSize(file, NULL);
1574     ok(file_size == 106, "file size = %u\n", file_size);
1575 
1576     size = sizeof(buf);
1577     ret = InternetReadFile(request, buf, sizeof(buf), &size);
1578     ok(ret, "InternetReadFile failed: %u\n", GetLastError());
1579     ok(size == 100, "size = %u\n", size);
1580 
1581     file_size = GetFileSize(file, NULL);
1582     ok(file_size == 106, "file size = %u\n", file_size);
1583     CloseHandle(file);
1584 
1585     ret = DeleteFileA(file_name);
1586     ok(!ret && GetLastError() == ERROR_SHARING_VIOLATION, "Deleting file returned %x(%u)\n", ret, GetLastError());
1587 
1588     ok(InternetCloseHandle(request), "Close request handle failed\n");
1589 
1590     file = CreateFileA(file_name, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
1591             FILE_ATTRIBUTE_NORMAL, NULL);
1592     ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError());
1593     ret = WriteFile(file, cached_content, sizeof(cached_content), &size, NULL);
1594     ok(ret && size, "WriteFile failed: %d, %d\n", ret, size);
1595     ret = CommitUrlCacheEntryA(url, file_name, filetime_zero, filetime_zero, NORMAL_CACHE_ENTRY, NULL, 0, NULL, 0);
1596     ok(ret, "CommitUrlCacheEntry failed: %d\n", GetLastError());
1597     CloseHandle(file);
1598 
1599     /* Send the same request, requiring it to be retrieved from the cache */
1600     request = HttpOpenRequestA(connect, "GET", "/tests/hello.html", NULL, NULL, NULL, INTERNET_FLAG_FROM_CACHE, 0);
1601 
1602     ret = HttpSendRequestA(request, NULL, 0, NULL, 0);
1603     ok(ret, "HttpSendRequest failed\n");
1604 
1605     size = sizeof(buf);
1606     ret = InternetReadFile(request, buf, sizeof(buf), &size);
1607     ok(ret, "InternetReadFile failed: %u\n", GetLastError());
1608     ok(size == 100, "size = %u\n", size);
1609     buf[99] = 0;
1610     todo_wine ok(!strcmp((char*)buf, cached_content), "incorrect page data: %s\n", (char*)buf);
1611 
1612     ok(InternetCloseHandle(request), "Close request handle failed\n");
1613 
1614     DeleteUrlCacheEntryA(url);
1615     request = HttpOpenRequestA(connect, "GET", "/tests/hello.html", NULL, NULL, NULL, INTERNET_FLAG_FROM_CACHE, 0);
1616     ret = HttpSendRequestA(request, NULL, 0, NULL, 0);
1617     todo_wine ok(!ret, "HttpSendRequest succeeded\n");
1618     if(!ret)
1619         ok(GetLastError() == ERROR_FILE_NOT_FOUND, "GetLastError() = %d\n", GetLastError());
1620     ok(InternetCloseHandle(request), "Close request handle failed\n");
1621 
1622     request = HttpOpenRequestA(connect, NULL, "/", NULL, NULL, types, INTERNET_FLAG_NO_CACHE_WRITE, 0);
1623     ok(request != NULL, "Failed to open request handle err %u\n", GetLastError());
1624 
1625     size = sizeof(file_name);
1626     ret = InternetQueryOptionA(request, INTERNET_OPTION_DATAFILE_NAME, file_name, &size);
1627     ok(!ret, "InternetQueryOptionA(INTERNET_OPTION_DATAFILE_NAME) succeeded\n");
1628     ok(GetLastError() == ERROR_INTERNET_ITEM_NOT_FOUND, "GetLastError()=%u\n", GetLastError());
1629     ok(!size, "size = %d\n", size);
1630 
1631     ret = HttpSendRequestA(request, NULL, 0, NULL, 0);
1632     ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
1633 
1634     size = sizeof(file_name);
1635     file_name[0] = 0;
1636     ret = InternetQueryOptionA(request, INTERNET_OPTION_DATAFILE_NAME, file_name, &size);
1637     if (ret)
1638     {
1639         file = CreateFileA(file_name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
1640                       FILE_ATTRIBUTE_NORMAL, NULL);
1641         ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError());
1642         CloseHandle(file);
1643     }
1644     else
1645     {
1646         /* < IE8 */
1647         ok(file_name[0] == 0, "Didn't expect a file name\n");
1648     }
1649 
1650     ok(InternetCloseHandle(request), "Close request handle failed\n");
1651     ok(InternetCloseHandle(connect), "Close connect handle failed\n");
1652     ok(InternetCloseHandle(session), "Close session handle failed\n");
1653 
1654     test_cache_read();
1655 }
1656 
1657 static void InternetLockRequestFile_test(void)
1658 {
1659     char file_name[MAX_PATH];
1660     test_request_t req;
1661     HANDLE lock, lock2;
1662     DWORD size;
1663     BOOL ret;
1664 
1665     open_simple_request(&req, "test.winehq.org", INTERNET_DEFAULT_HTTP_PORT, NULL, "/tests/hello.html");
1666 
1667     size = sizeof(file_name);
1668     ret = InternetQueryOptionA(req.request, INTERNET_OPTION_DATAFILE_NAME, file_name, &size);
1669     ok(!ret, "InternetQueryOptionA(INTERNET_OPTION_DATAFILE_NAME) succeeded\n");
1670     ok(GetLastError() == ERROR_INTERNET_ITEM_NOT_FOUND, "GetLastError()=%u\n", GetLastError());
1671     ok(!size, "size = %d\n", size);
1672 
1673     lock = NULL;
1674     ret = InternetLockRequestFile(req.request, &lock);
1675     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, "InternetLockRequestFile returned: %x(%u)\n", ret, GetLastError());
1676 
1677     ret = HttpSendRequestA(req.request, NULL, 0, NULL, 0);
1678     ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
1679 
1680     size = sizeof(file_name);
1681     ret = InternetQueryOptionA(req.request, INTERNET_OPTION_DATAFILE_NAME, file_name, &size);
1682     ok(ret, "InternetQueryOptionA(INTERNET_OPTION_DATAFILE_NAME) failed: %u\n", GetLastError());
1683 
1684     ret = InternetLockRequestFile(req.request, &lock);
1685     ok(ret, "InternetLockRequestFile returned: %x(%u)\n", ret, GetLastError());
1686     ok(lock != NULL, "lock == NULL\n");
1687 
1688     ret = InternetLockRequestFile(req.request, &lock2);
1689     ok(ret, "InternetLockRequestFile returned: %x(%u)\n", ret, GetLastError());
1690     ok(lock == lock2, "lock != lock2\n");
1691 
1692     ret = InternetUnlockRequestFile(lock2);
1693     ok(ret, "InternetUnlockRequestFile failed: %u\n", GetLastError());
1694 
1695     ret = DeleteFileA(file_name);
1696     ok(!ret && GetLastError() == ERROR_SHARING_VIOLATION, "Deleting file returned %x(%u)\n", ret, GetLastError());
1697 
1698     ok(InternetCloseHandle(req.request), "Close request handle failed\n");
1699 
1700     ret = DeleteFileA(file_name);
1701     ok(!ret && GetLastError() == ERROR_SHARING_VIOLATION, "Deleting file returned %x(%u)\n", ret, GetLastError());
1702 
1703     ret = InternetUnlockRequestFile(lock);
1704     ok(ret, "InternetUnlockRequestFile failed: %u\n", GetLastError());
1705 
1706     ret = DeleteFileA(file_name);
1707     ok(ret, "Deleting file returned %x(%u)\n", ret, GetLastError());
1708 }
1709 
1710 static void HttpHeaders_test(void)
1711 {
1712     HINTERNET hSession;
1713     HINTERNET hConnect;
1714     HINTERNET hRequest;
1715     CHAR      buffer[256];
1716     WCHAR     wbuffer[256];
1717     DWORD     len = 256;
1718     DWORD     oldlen;
1719     DWORD     index = 0;
1720     BOOL      ret;
1721 
1722     hSession = InternetOpenA("Wine Regression Test",
1723             INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
1724     ok( hSession != NULL ,"Unable to open Internet session\n");
1725     hConnect = InternetConnectA(hSession, "test.winehq.org",
1726             INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0,
1727             0);
1728     ok( hConnect != NULL, "Unable to connect to http://test.winehq.org\n");
1729     hRequest = HttpOpenRequestA(hConnect, "POST", "/tests/post.php",
1730             NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
1731     if (!hRequest && GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED)
1732     {
1733         skip( "Network unreachable, skipping test\n" );
1734         goto done;
1735     }
1736     ok( hRequest != NULL, "Failed to open request handle\n");
1737 
1738     index = 0;
1739     len = sizeof(buffer);
1740     strcpy(buffer,"Warning");
1741     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1742                buffer,&len,&index)==0,"Warning hearder reported as Existing\n");
1743 
1744     ok(HttpAddRequestHeadersA(hRequest,"Warning:test1",-1,HTTP_ADDREQ_FLAG_ADD),
1745             "Failed to add new header\n");
1746 
1747     index = 0;
1748     len = sizeof(buffer);
1749     strcpy(buffer,"Warning");
1750     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1751                 buffer,&len,&index),"Unable to query header\n");
1752     ok(index == 1, "Index was not incremented\n");
1753     ok(strcmp(buffer,"test1")==0, "incorrect string was returned(%s)\n",buffer);
1754     ok(len == 5, "Invalid length (exp. 5, got %d)\n", len);
1755     ok((len < sizeof(buffer)) && (buffer[len] == 0), "Buffer not NULL-terminated\n"); /* len show only 5 characters but the buffer is NULL-terminated*/
1756     len = sizeof(buffer);
1757     strcpy(buffer,"Warning");
1758     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1759                 buffer,&len,&index)==0,"Second Index Should Not Exist\n");
1760 
1761     index = 0;
1762     len = 5; /* could store the string but not the NULL terminator */
1763     strcpy(buffer,"Warning");
1764     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1765                 buffer,&len,&index) == FALSE,"Query succeeded on a too small buffer\n");
1766     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected last error: %d\n", GetLastError());
1767     ok(index == 0, "Index was incremented\n");
1768     ok(strcmp(buffer,"Warning")==0, "incorrect string was returned(%s)\n",buffer); /* string not touched */
1769     ok(len == 6, "Invalid length (exp. 6, got %d)\n", len); /* unlike success, the length includes the NULL-terminator */
1770 
1771     /* a call with NULL will fail but will return the length */
1772     index = 0;
1773     len = sizeof(buffer);
1774     SetLastError(0xdeadbeef);
1775     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1776                 NULL,&len,&index) == FALSE,"Query worked\n");
1777     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected last error: %d\n", GetLastError());
1778     ok(len > 40, "Invalid length (exp. more than 40, got %d)\n", len);
1779     ok(index == 0, "Index was incremented\n");
1780 
1781     /* even for a len that is too small */
1782     index = 0;
1783     len = 15;
1784     SetLastError(0xdeadbeef);
1785     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1786                 NULL,&len,&index) == FALSE,"Query worked\n");
1787     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected last error: %d\n", GetLastError());
1788     ok(len > 40, "Invalid length (exp. more than 40, got %d)\n", len);
1789     ok(index == 0, "Index was incremented\n");
1790 
1791     index = 0;
1792     len = 0;
1793     SetLastError(0xdeadbeef);
1794     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1795                 NULL,&len,&index) == FALSE,"Query worked\n");
1796     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected last error: %d\n", GetLastError());
1797     ok(len > 40, "Invalid length (exp. more than 40, got %d)\n", len);
1798     ok(index == 0, "Index was incremented\n");
1799     oldlen = len;   /* bytes; at least long enough to hold buffer & nul */
1800 
1801 
1802     /* a working query */
1803     index = 0;
1804     len = sizeof(buffer);
1805     memset(buffer, 'x', sizeof(buffer));
1806     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1807                 buffer,&len,&index),"Unable to query header\n");
1808     ok(len + sizeof(CHAR) <= oldlen, "Result longer than advertised\n");
1809     ok((len < sizeof(buffer)-sizeof(CHAR)) && (buffer[len/sizeof(CHAR)] == 0),"No NUL at end\n");
1810     ok(len == strlen(buffer) * sizeof(CHAR), "Length wrong\n");
1811     /* what's in the middle differs between Wine and Windows so currently we check only the beginning and the end */
1812     ok(strncmp(buffer, "POST /tests/post.php HTTP/1", 25)==0, "Invalid beginning of headers string\n");
1813     ok(strcmp(buffer + strlen(buffer) - 4, "\r\n\r\n")==0, "Invalid end of headers string\n");
1814     ok(index == 0, "Index was incremented\n");
1815 
1816     /* Like above two tests, but for W version */
1817 
1818     index = 0;
1819     len = 0;
1820     SetLastError(0xdeadbeef);
1821     ok(HttpQueryInfoW(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1822                 NULL,&len,&index) == FALSE,"Query worked\n");
1823     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected last error: %d\n", GetLastError());
1824     ok(len > 80, "Invalid length (exp. more than 80, got %d)\n", len);
1825     ok(index == 0, "Index was incremented\n");
1826     oldlen = len;   /* bytes; at least long enough to hold buffer & nul */
1827 
1828     /* a working query */
1829     index = 0;
1830     len = sizeof(wbuffer);
1831     memset(wbuffer, 'x', sizeof(wbuffer));
1832     ok(HttpQueryInfoW(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1833                 wbuffer,&len,&index),"Unable to query header\n");
1834     ok(len + sizeof(WCHAR) <= oldlen, "Result longer than advertised\n");
1835     ok(len == lstrlenW(wbuffer) * sizeof(WCHAR), "Length wrong\n");
1836     ok((len < sizeof(wbuffer)-sizeof(WCHAR)) && (wbuffer[len/sizeof(WCHAR)] == 0),"No NUL at end\n");
1837     ok(index == 0, "Index was incremented\n");
1838 
1839     /* end of W version tests */
1840 
1841     /* Without HTTP_QUERY_FLAG_REQUEST_HEADERS */
1842     index = 0;
1843     len = sizeof(buffer);
1844     memset(buffer, 'x', sizeof(buffer));
1845     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF,
1846                 buffer,&len,&index) == TRUE,"Query failed\n");
1847     ok(len == 2 || len == 4 /* win10 */, "Expected 2 or 4, got %d\n", len);
1848     ok(memcmp(buffer, "\r\n\r\n", len) == 0, "Expected CRLF, got '%s'\n", buffer);
1849     ok(index == 0, "Index was incremented\n");
1850 
1851     ok(HttpAddRequestHeadersA(hRequest,"Warning:test2",-1,HTTP_ADDREQ_FLAG_ADD),
1852             "Failed to add duplicate header using HTTP_ADDREQ_FLAG_ADD\n");
1853 
1854     index = 0;
1855     len = sizeof(buffer);
1856     strcpy(buffer,"Warning");
1857     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1858                 buffer,&len,&index),"Unable to query header\n");
1859     ok(index == 1, "Index was not incremented\n");
1860     ok(strcmp(buffer,"test1")==0, "incorrect string was returned(%s)\n",buffer);
1861     len = sizeof(buffer);
1862     strcpy(buffer,"Warning");
1863     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1864                 buffer,&len,&index),"Failed to get second header\n");
1865     ok(index == 2, "Index was not incremented\n");
1866     ok(strcmp(buffer,"test2")==0, "incorrect string was returned(%s)\n",buffer);
1867     len = sizeof(buffer);
1868     strcpy(buffer,"Warning");
1869     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1870                 buffer,&len,&index)==0,"Third Header Should Not Exist\n");
1871 
1872     ok(HttpAddRequestHeadersA(hRequest,"Warning:test3",-1,HTTP_ADDREQ_FLAG_REPLACE), "Failed to replace header using HTTP_ADDREQ_FLAG_REPLACE\n");
1873 
1874     index = 0;
1875     len = sizeof(buffer);
1876     strcpy(buffer,"Warning");
1877     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1878                 buffer,&len,&index),"Unable to query header\n");
1879     ok(index == 1, "Index was not incremented\n");
1880     ok(strcmp(buffer,"test2")==0, "incorrect string was returned(%s)\n",buffer);
1881     len = sizeof(buffer);
1882     strcpy(buffer,"Warning");
1883     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1884                 buffer,&len,&index),"Failed to get second header\n");
1885     ok(index == 2, "Index was not incremented\n");
1886     ok(strcmp(buffer,"test3")==0, "incorrect string was returned(%s)\n",buffer);
1887     len = sizeof(buffer);
1888     strcpy(buffer,"Warning");
1889     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1890                 buffer,&len,&index)==0,"Third Header Should Not Exist\n");
1891 
1892     ok(HttpAddRequestHeadersA(hRequest,"Warning:test4",-1,HTTP_ADDREQ_FLAG_ADD_IF_NEW)==0, "HTTP_ADDREQ_FLAG_ADD_IF_NEW replaced existing header\n");
1893 
1894     index = 0;
1895     len = sizeof(buffer);
1896     strcpy(buffer,"Warning");
1897     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1898                 buffer,&len,&index),"Unable to query header\n");
1899     ok(index == 1, "Index was not incremented\n");
1900     ok(strcmp(buffer,"test2")==0, "incorrect string was returned(%s)\n",buffer);
1901     len = sizeof(buffer);
1902     strcpy(buffer,"Warning");
1903     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1904                 buffer,&len,&index),"Failed to get second header\n");
1905     ok(index == 2, "Index was not incremented\n");
1906     ok(strcmp(buffer,"test3")==0, "incorrect string was returned(%s)\n",buffer);
1907     len = sizeof(buffer);
1908     strcpy(buffer,"Warning");
1909     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1910                 buffer,&len,&index)==0,"Third Header Should Not Exist\n");
1911 
1912     ok(HttpAddRequestHeadersA(hRequest,"Warning:test4",-1, HTTP_ADDREQ_FLAG_COALESCE), "HTTP_ADDREQ_FLAG_COALESCE Did not work\n");
1913 
1914     index = 0;
1915     len = sizeof(buffer);
1916     strcpy(buffer,"Warning");
1917     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1918                 buffer,&len,&index),"Unable to query header\n");
1919     ok(index == 1, "Index was not incremented\n");
1920     ok(strcmp(buffer,"test2, test4")==0, "incorrect string was returned(%s)\n", buffer);
1921     len = sizeof(buffer);
1922     strcpy(buffer,"Warning");
1923     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Failed to get second header\n");
1924     ok(index == 2, "Index was not incremented\n");
1925     ok(strcmp(buffer,"test3")==0, "incorrect string was returned(%s)\n",buffer);
1926     len = sizeof(buffer);
1927     strcpy(buffer,"Warning");
1928     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index)==0,"Third Header Should Not Exist\n");
1929 
1930     ok(HttpAddRequestHeadersA(hRequest,"Warning:test5",-1, HTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA), "HTTP_ADDREQ_FLAG_COALESCE Did not work\n");
1931 
1932     index = 0;
1933     len = sizeof(buffer);
1934     strcpy(buffer,"Warning");
1935     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n");
1936     ok(index == 1, "Index was not incremented\n");
1937     ok(strcmp(buffer,"test2, test4, test5")==0, "incorrect string was returned(%s)\n",buffer);
1938     len = sizeof(buffer);
1939     strcpy(buffer,"Warning");
1940     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Failed to get second header\n");
1941     ok(index == 2, "Index was not incremented\n");
1942     ok(strcmp(buffer,"test3")==0, "incorrect string was returned(%s)\n",buffer);
1943     len = sizeof(buffer);
1944     strcpy(buffer,"Warning");
1945     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index)==0,"Third Header Should Not Exist\n");
1946 
1947     ok(HttpAddRequestHeadersA(hRequest,"Warning:test6",-1, HTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON), "HTTP_ADDREQ_FLAG_COALESCE Did not work\n");
1948 
1949     index = 0;
1950     len = sizeof(buffer);
1951     strcpy(buffer,"Warning");
1952     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n");
1953     ok(index == 1, "Index was not incremented\n");
1954     ok(strcmp(buffer,"test2, test4, test5; test6")==0, "incorrect string was returned(%s)\n",buffer);
1955     len = sizeof(buffer);
1956     strcpy(buffer,"Warning");
1957     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Failed to get second header\n");
1958     ok(index == 2, "Index was not incremented\n");
1959     ok(strcmp(buffer,"test3")==0, "incorrect string was returned(%s)\n",buffer);
1960     len = sizeof(buffer);
1961     strcpy(buffer,"Warning");
1962     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index)==0,"Third Header Should Not Exist\n");
1963 
1964     ok(HttpAddRequestHeadersA(hRequest,"Warning:test7",-1, HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE), "HTTP_ADDREQ_FLAG_ADD with HTTP_ADDREQ_FLAG_REPALCE Did not work\n");
1965 
1966     index = 0;
1967     len = sizeof(buffer);
1968     strcpy(buffer,"Warning");
1969     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n");
1970     ok(index == 1, "Index was not incremented\n");
1971     ok(strcmp(buffer,"test3")==0, "incorrect string was returned(%s)\n",buffer);
1972     len = sizeof(buffer);
1973     strcpy(buffer,"Warning");
1974     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Failed to get second header\n");
1975     ok(index == 2, "Index was not incremented\n");
1976     ok(strcmp(buffer,"test7")==0, "incorrect string was returned(%s)\n",buffer);
1977     len = sizeof(buffer);
1978     strcpy(buffer,"Warning");
1979     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index)==0,"Third Header Should Not Exist\n");
1980 
1981     /* Ensure that blank headers are ignored and don't cause a failure */
1982     ok(HttpAddRequestHeadersA(hRequest,"\r\nBlankTest:value\r\n\r\n",-1, HTTP_ADDREQ_FLAG_ADD_IF_NEW), "Failed to add header with blank entries in list\n");
1983 
1984     index = 0;
1985     len = sizeof(buffer);
1986     strcpy(buffer,"BlankTest");
1987     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n");
1988     ok(index == 1, "Index was not incremented\n");
1989     ok(strcmp(buffer,"value")==0, "incorrect string was returned(%s)\n",buffer);
1990 
1991     /* Ensure that malformed header separators are ignored and don't cause a failure */
1992     ok(HttpAddRequestHeadersA(hRequest,"\r\rMalformedTest:value\n\nMalformedTestTwo: value2\rMalformedTestThree: value3\n\n\r\r\n",-1, HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE),
1993         "Failed to add header with malformed entries in list\n");
1994 
1995     index = 0;
1996     len = sizeof(buffer);
1997     strcpy(buffer,"MalformedTest");
1998     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n");
1999     ok(index == 1, "Index was not incremented\n");
2000     ok(strcmp(buffer,"value")==0, "incorrect string was returned(%s)\n",buffer);
2001     index = 0;
2002     len = sizeof(buffer);
2003     strcpy(buffer,"MalformedTestTwo");
2004     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n");
2005     ok(index == 1, "Index was not incremented\n");
2006     ok(strcmp(buffer,"value2")==0, "incorrect string was returned(%s)\n",buffer);
2007     index = 0;
2008     len = sizeof(buffer);
2009     strcpy(buffer,"MalformedTestThree");
2010     ok(HttpQueryInfoA(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n");
2011     ok(index == 1, "Index was not incremented\n");
2012     ok(strcmp(buffer,"value3")==0, "incorrect string was returned(%s)\n",buffer);
2013 
2014     ret = HttpAddRequestHeadersA(hRequest, "Authorization: Basic\r\n", -1, HTTP_ADDREQ_FLAG_ADD);
2015     ok(ret, "unable to add header %u\n", GetLastError());
2016 
2017     index = 0;
2018     buffer[0] = 0;
2019     len = sizeof(buffer);
2020     ret = HttpQueryInfoA(hRequest, HTTP_QUERY_AUTHORIZATION|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &len, &index);
2021     ok(ret, "unable to query header %u\n", GetLastError());
2022     ok(index == 1, "index was not incremented\n");
2023     ok(!strcmp(buffer, "Basic"), "incorrect string was returned (%s)\n", buffer);
2024 
2025     ret = HttpAddRequestHeadersA(hRequest, "Authorization:\r\n", -1, HTTP_ADDREQ_FLAG_REPLACE);
2026     ok(ret, "unable to remove header %u\n", GetLastError());
2027 
2028     index = 0;
2029     len = sizeof(buffer);
2030     SetLastError(0xdeadbeef);
2031     ok(!HttpQueryInfoA(hRequest, HTTP_QUERY_AUTHORIZATION|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &len, &index),
2032        "header still present\n");
2033     ok(GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND, "got %u\n", GetLastError());
2034 
2035     ok(InternetCloseHandle(hRequest), "Close request handle failed\n");
2036 done:
2037     ok(InternetCloseHandle(hConnect), "Close connect handle failed\n");
2038     ok(InternetCloseHandle(hSession), "Close session handle failed\n");
2039 }
2040 
2041 static const char garbagemsg[] =
2042 "Garbage: Header\r\n";
2043 
2044 static const char contmsg[] =
2045 "HTTP/1.1 100 Continue\r\n";
2046 
2047 static const char expandcontmsg[] =
2048 "HTTP/1.1 100 Continue\r\n"
2049 "Server: winecontinue\r\n"
2050 "Tag: something witty\r\n";
2051 
2052 static const char okmsg[] =
2053 "HTTP/1.1 200 OK\r\n"
2054 "Server: winetest\r\n"
2055 "\r\n";
2056 
2057 static const char okmsg201[] =
2058 "HTTP/1.1 201 OK\r\n"
2059 "Server: winetest\r\n"
2060 "\r\n";
2061 
2062 static const char okmsg2[] =
2063 "HTTP/1.1 200 OK\r\n"
2064 "Date: Mon, 01 Dec 2008 13:44:34 GMT\r\n"
2065 "Server: winetest\r\n"
2066 "Content-Length: 0\r\n"
2067 "Set-Cookie: one\r\n"
2068 "Set-Cookie: two\r\n"
2069 "\r\n";
2070 
2071 static DWORD64 content_length;
2072 static const char largemsg[] =
2073 "HTTP/1.1 200 OK\r\n"
2074 "Content-Length: %I64u\r\n"
2075 "\r\n";
2076 
2077 static const char okmsg_cookie_path[] =
2078 "HTTP/1.1 200 OK\r\n"
2079 "Date: Mon, 01 Dec 2008 13:44:34 GMT\r\n"
2080 "Server: winetest\r\n"
2081 "Content-Length: 0\r\n"
2082 "Set-Cookie: subcookie2=data; path=/test_cookie_set_path\r\n"
2083 "\r\n";
2084 
2085 static const char okmsg_cookie[] =
2086 "HTTP/1.1 200 OK\r\n"
2087 "Date: Mon, 01 Dec 2008 13:44:34 GMT\r\n"
2088 "Server: winetest\r\n"
2089 "Content-Length: 0\r\n"
2090 "Set-Cookie: testcookie=testvalue\r\n"
2091 "\r\n";
2092 
2093 static const char notokmsg[] =
2094 "HTTP/1.1 400 Bad Request\r\n"
2095 "Server: winetest\r\n"
2096 "\r\n";
2097 
2098 static const char noauthmsg[] =
2099 "HTTP/1.1 401 Unauthorized\r\n"
2100 "Server: winetest\r\n"
2101 "Connection: close\r\n"
2102 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
2103 "\r\n";
2104 
2105 static const char noauthmsg2[] =
2106 "HTTP/1.0 401 Anonymous requests or requests on unsecure channel are not allowed\r\n"
2107 "HTTP/1.0 401 Anonymous requests or requests on unsecure channel are not allowed"
2108 "\0d`0|6\n"
2109 "Server: winetest\r\n";
2110 
2111 static const char proxymsg[] =
2112 "HTTP/1.1 407 Proxy Authentication Required\r\n"
2113 "Server: winetest\r\n"
2114 "Proxy-Connection: close\r\n"
2115 "Proxy-Authenticate: Basic realm=\"placebo\"\r\n"
2116 "\r\n";
2117 
2118 static const char page1[] =
2119 "<HTML>\r\n"
2120 "<HEAD><TITLE>wininet test page</TITLE></HEAD>\r\n"
2121 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
2122 "</HTML>\r\n\r\n";
2123 
2124 static const char ok_with_length[] =
2125 "HTTP/1.1 200 OK\r\n"
2126 "Connection: Keep-Alive\r\n"
2127 "Content-Length: 18\r\n\r\n"
2128 "HTTP/1.1 211 OK\r\n\r\n";
2129 
2130 static const char ok_with_length2[] =
2131 "HTTP/1.1 210 OK\r\n"
2132 "Connection: Keep-Alive\r\n"
2133 "Content-Length: 19\r\n\r\n"
2134 "HTTP/1.1 211 OK\r\n\r\n";
2135 
2136 struct server_info {
2137     HANDLE hEvent;
2138     int port;
2139 };
2140 
2141 static int test_cache_gzip;
2142 static const char *send_buffer;
2143 static int server_socket;
2144 
2145 static DWORD CALLBACK server_thread(LPVOID param)
2146 {
2147     struct server_info *si = param;
2148     int r, c = -1, i, on, count = 0;
2149     SOCKET s;
2150     struct sockaddr_in sa;
2151     char *buffer;
2152     size_t buffer_size;
2153     WSADATA wsaData;
2154     int last_request = 0;
2155     char host_header[22];
2156     char host_header_override[30];
2157     static int test_no_cache = 0;
2158 
2159     WSAStartup(MAKEWORD(1,1), &wsaData);
2160 
2161     s = socket(AF_INET, SOCK_STREAM, 0);
2162     if (s == INVALID_SOCKET)
2163         return 1;
2164 
2165     on = 1;
2166     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof on);
2167 
2168     memset(&sa, 0, sizeof sa);
2169     sa.sin_family = AF_INET;
2170     sa.sin_port = htons(si->port);
2171     sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
2172 
2173     r = bind(s, (struct sockaddr*) &sa, sizeof sa);
2174     if (r<0)
2175         return 1;
2176 
2177     listen(s, 0);
2178 
2179     SetEvent(si->hEvent);
2180 
2181     sprintf(host_header, "Host: localhost:%d", si->port);
2182     sprintf(host_header_override, "Host: test.local:%d\r\n", si->port);
2183     buffer = HeapAlloc(GetProcessHeap(), 0, buffer_size = 1000);
2184 
2185     do
2186     {
2187         if(c == -1)
2188             c = accept(s, NULL, NULL);
2189 
2190         memset(buffer, 0, buffer_size);
2191         for(i=0;; i++)
2192         {
2193             if(i == buffer_size)
2194                 buffer = HeapReAlloc(GetProcessHeap(), 0, buffer, buffer_size *= 2);
2195 
2196             r = recv(c, buffer+i, 1, 0);
2197             if (r != 1)
2198                 break;
2199             if (i<4) continue;
2200             if (buffer[i-2] == '\n' && buffer[i] == '\n' &&
2201                 buffer[i-3] == '\r' && buffer[i-1] == '\r')
2202                 break;
2203         }
2204         if (strstr(buffer, "GET /test1"))
2205         {
2206             if (!strstr(buffer, "Content-Length: 0"))
2207             {
2208                 send(c, okmsg, sizeof okmsg-1, 0);
2209                 send(c, page1, sizeof page1-1, 0);
2210             }
2211             else
2212                 send(c, notokmsg, sizeof notokmsg-1, 0);
2213         }
2214         if (strstr(buffer, "CONNECT "))
2215         {
2216             if (!strstr(buffer, "Content-Length: 0"))
2217                 send(c, notokmsg, sizeof notokmsg-1, 0);
2218             else
2219                 send(c, proxymsg, sizeof proxymsg-1, 0);
2220         }
2221         if (strstr(buffer, "/test2"))
2222         {
2223             if (strstr(buffer, "Proxy-Authorization: Basic bWlrZToxMTAx"))
2224             {
2225                 send(c, okmsg, sizeof okmsg-1, 0);
2226                 send(c, page1, sizeof page1-1, 0);
2227             }
2228             else
2229                 send(c, proxymsg, sizeof proxymsg-1, 0);
2230         }
2231         if (strstr(buffer, "/test3"))
2232         {
2233             if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2234                 send(c, okmsg, sizeof okmsg-1, 0);
2235             else
2236                 send(c, noauthmsg, sizeof noauthmsg-1, 0);
2237         }
2238         if (strstr(buffer, "/test4"))
2239         {
2240             if (strstr(buffer, "Connection: Close"))
2241                 send(c, okmsg, sizeof okmsg-1, 0);
2242             else
2243                 send(c, notokmsg, sizeof notokmsg-1, 0);
2244         }
2245         if (strstr(buffer, "POST /test5") ||
2246             strstr(buffer, "RPC_IN_DATA /test5") ||
2247             strstr(buffer, "RPC_OUT_DATA /test5"))
2248         {
2249             if (strstr(buffer, "Content-Length: 0"))
2250             {
2251                 send(c, okmsg, sizeof okmsg-1, 0);
2252                 send(c, page1, sizeof page1-1, 0);
2253             }
2254             else
2255                 send(c, notokmsg, sizeof notokmsg-1, 0);
2256         }
2257         if (strstr(buffer, "GET /test6"))
2258         {
2259             send(c, contmsg, sizeof contmsg-1, 0);
2260             send(c, contmsg, sizeof contmsg-1, 0);
2261             send(c, okmsg, sizeof okmsg-1, 0);
2262             send(c, page1, sizeof page1-1, 0);
2263         }
2264         if (strstr(buffer, "POST /test7"))
2265         {
2266             if (strstr(buffer, "Content-Length: 100"))
2267             {
2268                 if (strstr(buffer, "POST /test7b"))
2269                     recvfrom(c, buffer, buffer_size, 0, NULL, NULL);
2270                 send(c, okmsg, sizeof okmsg-1, 0);
2271                 send(c, page1, sizeof page1-1, 0);
2272             }
2273             else
2274                 send(c, notokmsg, sizeof notokmsg-1, 0);
2275         }
2276         if (strstr(buffer, "/test8"))
2277         {
2278             if (!strstr(buffer, "Connection: Close") &&
2279                  strstr(buffer, "Connection: Keep-Alive") &&
2280                 !strstr(buffer, "Cache-Control: no-cache") &&
2281                 !strstr(buffer, "Pragma: no-cache") &&
2282                  strstr(buffer, host_header))
2283                 send(c, okmsg, sizeof okmsg-1, 0);
2284             else
2285                 send(c, notokmsg, sizeof notokmsg-1, 0);
2286         }
2287         if (strstr(buffer, "/test9"))
2288         {
2289             if (!strstr(buffer, "Connection: Close") &&
2290                 !strstr(buffer, "Connection: Keep-Alive") &&
2291                 !strstr(buffer, "Cache-Control: no-cache") &&
2292                 !strstr(buffer, "Pragma: no-cache") &&
2293                  strstr(buffer, host_header))
2294                 send(c, okmsg, sizeof okmsg-1, 0);
2295             else
2296                 send(c, notokmsg, sizeof notokmsg-1, 0);
2297         }
2298         if (strstr(buffer, "/testA"))
2299         {
2300             if (!strstr(buffer, "Connection: Close") &&
2301                 !strstr(buffer, "Connection: Keep-Alive") &&
2302                 (strstr(buffer, "Cache-Control: no-cache") ||
2303                  strstr(buffer, "Pragma: no-cache")) &&
2304                  strstr(buffer, host_header))
2305                 send(c, okmsg, sizeof okmsg-1, 0);
2306             else
2307                 send(c, notokmsg, sizeof notokmsg-1, 0);
2308         }
2309         if (strstr(buffer, "/testC"))
2310         {
2311             if (strstr(buffer, "cookie=biscuit"))
2312                 send(c, okmsg, sizeof okmsg-1, 0);
2313             else
2314                 send(c, notokmsg, sizeof notokmsg-1, 0);
2315         }
2316         if (strstr(buffer, "/testD"))
2317         {
2318             send(c, okmsg2, sizeof okmsg2-1, 0);
2319         }
2320         if (strstr(buffer, "/testE"))
2321         {
2322             send(c, noauthmsg2, sizeof noauthmsg2-1, 0);
2323         }
2324         if (strstr(buffer, "GET /quit"))
2325         {
2326             send(c, okmsg, sizeof okmsg-1, 0);
2327             send(c, page1, sizeof page1-1, 0);
2328             last_request = 1;
2329         }
2330         if (strstr(buffer, "GET /testF"))
2331         {
2332             send(c, expandcontmsg, sizeof expandcontmsg-1, 0);
2333             send(c, garbagemsg, sizeof garbagemsg-1, 0);
2334             send(c, contmsg, sizeof contmsg-1, 0);
2335             send(c, garbagemsg, sizeof garbagemsg-1, 0);
2336             send(c, okmsg, sizeof okmsg-1, 0);
2337             send(c, page1, sizeof page1-1, 0);
2338         }
2339         if (strstr(buffer, "GET /testG"))
2340         {
2341             send(c, page1, sizeof page1-1, 0);
2342         }
2343 
2344         if (strstr(buffer, "GET /testJ"))
2345         {
2346             if (count == 0)
2347             {
2348                 count++;
2349                 send(c, ok_with_length, sizeof(ok_with_length)-1, 0);
2350             }
2351             else
2352             {
2353                 send(c, ok_with_length2, sizeof(ok_with_length2)-1, 0);
2354                 count = 0;
2355             }
2356         }
2357         if (strstr(buffer, "GET /testH"))
2358         {
2359             send(c, ok_with_length2, sizeof(ok_with_length2)-1, 0);
2360             recvfrom(c, buffer, buffer_size, 0, NULL, NULL);
2361             send(c, ok_with_length, sizeof(ok_with_length)-1, 0);
2362         }
2363 
2364         if (strstr(buffer, "GET /test_no_content"))
2365         {
2366             static const char nocontentmsg[] = "HTTP/1.1 204 No Content\r\nConnection: close\r\n\r\n";
2367             send(c, nocontentmsg, sizeof(nocontentmsg)-1, 0);
2368         }
2369         if (strstr(buffer, "GET /test_conn_close"))
2370         {
2371             static const char conn_close_response[] = "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\nsome content";
2372             send(c, conn_close_response, sizeof(conn_close_response)-1, 0);
2373             WaitForSingleObject(conn_close_event, INFINITE);
2374             trace("closing connection\n");
2375         }
2376         if (strstr(buffer, "GET /test_cache_control_no_cache"))
2377         {
2378             static const char no_cache_response[] = "HTTP/1.1 200 OK\r\nCache-Control: no-cache\r\n\r\nsome content";
2379             if(!test_no_cache++)
2380                 send(c, no_cache_response, sizeof(no_cache_response)-1, 0);
2381             else
2382                 send(c, okmsg, sizeof(okmsg)-1, 0);
2383         }
2384         if (strstr(buffer, "GET /test_cache_control_no_store"))
2385         {
2386             static const char no_cache_response[] = "HTTP/1.1 200 OK\r\nCache-Control: junk, \t No-StOrE\r\n\r\nsome content";
2387             send(c, no_cache_response, sizeof(no_cache_response)-1, 0);
2388         }
2389         if (strstr(buffer, "GET /test_cache_gzip"))
2390         {
2391             static const char gzip_response[] = "HTTP/1.1 200 OK\r\nContent-Encoding: gzip\r\nContent-Type: text/html\r\n\r\n"
2392                 "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\x4b\xaf\xca\x2c\x50\x28"
2393                 "\x49\x2d\x2e\xe1\x02\x00\x62\x92\xc7\x6c\x0a\x00\x00\x00";
2394             if(!test_cache_gzip++)
2395                 send(c, gzip_response, sizeof(gzip_response), 0);
2396             else
2397                 send(c, notokmsg, sizeof(notokmsg)-1, 0);
2398         }
2399         if (strstr(buffer, "HEAD /test_head")) {
2400             static const char head_response[] =
2401                 "HTTP/1.1 200 OK\r\n"
2402                 "Connection: Keep-Alive\r\n"
2403                 "Content-Length: 100\r\n"
2404                 "\r\n";
2405 
2406             send(c, head_response, sizeof(head_response), 0);
2407             continue;
2408         }
2409         if (strstr(buffer, "GET /send_from_buffer"))
2410             send(c, send_buffer, strlen(send_buffer), 0);
2411         if (strstr(buffer, "/test_cache_control_verb"))
2412         {
2413             if (!memcmp(buffer, "GET ", sizeof("GET ")-1) &&
2414                 !strstr(buffer, "Cache-Control: no-cache\r\n")) send(c, okmsg, sizeof(okmsg)-1, 0);
2415             else if (strstr(buffer, "Cache-Control: no-cache\r\n")) send(c, okmsg, sizeof(okmsg)-1, 0);
2416             else send(c, notokmsg, sizeof(notokmsg)-1, 0);
2417         }
2418         if (strstr(buffer, "/test_request_content_length"))
2419         {
2420             static char msg[] = "HTTP/1.1 200 OK\r\nConnection: Keep-Alive\r\n\r\n";
2421             static int seen_content_length;
2422 
2423             if (!seen_content_length)
2424             {
2425                 if (strstr(buffer, "Content-Length: 0"))
2426                 {
2427                     seen_content_length = 1;
2428                     send(c, msg, sizeof msg-1, 0);
2429                 }
2430                 else send(c, notokmsg, sizeof notokmsg-1, 0);
2431                 WaitForSingleObject(complete_event, 5000);
2432             }
2433             else
2434             {
2435                 if (strstr(buffer, "Content-Length: 0")) send(c, msg, sizeof msg-1, 0);
2436                 else send(c, notokmsg, sizeof notokmsg-1, 0);
2437                 WaitForSingleObject(complete_event, 5000);
2438             }
2439         }
2440         if (strstr(buffer, "GET /test_premature_disconnect"))
2441             trace("closing connection\n");
2442         if (strstr(buffer, "HEAD /upload.txt"))
2443         {
2444             if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2445                 send(c, okmsg, sizeof okmsg-1, 0);
2446             else
2447                 send(c, noauthmsg, sizeof noauthmsg-1, 0);
2448         }
2449         if (strstr(buffer, "PUT /upload2.txt"))
2450         {
2451             if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2452                 send(c, okmsg, sizeof okmsg-1, 0);
2453             else
2454                 send(c, notokmsg, sizeof notokmsg-1, 0);
2455         }
2456         if (strstr(buffer, "HEAD /upload3.txt"))
2457         {
2458             if (strstr(buffer, "Authorization: Basic dXNlcjE6cHdkMQ=="))
2459                 send(c, okmsg, sizeof okmsg-1, 0);
2460             else
2461                 send(c, noauthmsg, sizeof noauthmsg-1, 0);
2462         }
2463         if (strstr(buffer, "HEAD /upload4.txt"))
2464         {
2465             if (strstr(buffer, "Authorization: Bearer dXNlcjE6cHdkMQ=="))
2466                 send(c, okmsg, sizeof okmsg-1, 0);
2467             else if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
2468                 send(c, okmsg201, sizeof okmsg-1, 0);
2469             else
2470                 send(c, noauthmsg, sizeof noauthmsg-1, 0);
2471         }
2472         if (strstr(buffer, "/test_cookie_path1"))
2473         {
2474             if (strstr(buffer, "subcookie=data"))
2475                  send(c, okmsg, sizeof okmsg-1, 0);
2476              else
2477                  send(c, notokmsg, sizeof notokmsg-1, 0);
2478         }
2479         if (strstr(buffer, "/test_cookie_path2"))
2480         {
2481             if (strstr(buffer, "subcookie2=data"))
2482                  send(c, okmsg, sizeof okmsg-1, 0);
2483              else
2484                  send(c, notokmsg, sizeof notokmsg-1, 0);
2485         }
2486         if (strstr(buffer, "/test_cookie_set_path"))
2487         {
2488             send(c, okmsg_cookie_path, sizeof okmsg_cookie_path-1, 0);
2489         }
2490         if (strstr(buffer, "/test_cookie_merge"))
2491         {
2492             if (strstr(buffer, "subcookie=data") &&
2493                 !strstr(buffer, "manual_cookie=test"))
2494                  send(c, okmsg, sizeof okmsg-1, 0);
2495              else
2496                  send(c, notokmsg, sizeof notokmsg-1, 0);
2497         }
2498         if (strstr(buffer, "/test_cookie_set_host_override"))
2499         {
2500             send(c, okmsg_cookie, sizeof okmsg_cookie-1, 0);
2501         }
2502         if (strstr(buffer, "/test_cookie_check_host_override"))
2503         {
2504             if (strstr(buffer, "Cookie:") && strstr(buffer, "testcookie=testvalue"))
2505                 send(c, okmsg, sizeof okmsg-1, 0);
2506             else
2507                 send(c, notokmsg, sizeof notokmsg-1, 0);
2508         }
2509         if (strstr(buffer, "/test_cookie_check_different_host"))
2510         {
2511             if (!strstr(buffer, "foo") &&
2512                 strstr(buffer, "cookie=biscuit"))
2513                 send(c, okmsg, sizeof okmsg-1, 0);
2514             else
2515                 send(c, notokmsg, sizeof notokmsg-1, 0);
2516         }
2517         if (strstr(buffer, "/test_host_override"))
2518         {
2519             if (strstr(buffer, host_header_override))
2520                 send(c, okmsg, sizeof okmsg-1, 0);
2521             else
2522                 send(c, notokmsg, sizeof notokmsg-1, 0);
2523         }
2524         if (strstr(buffer, "/async_read"))
2525         {
2526             const char *page1_mid = page1 + (sizeof page1 - 1)/2;
2527             const char *page1_end = page1 + sizeof page1 - 1;
2528             send(c, okmsg, sizeof okmsg-1, 0);
2529             send(c, page1, page1_mid - page1, 0);
2530             WaitForSingleObject(conn_wait_event, INFINITE);
2531             send(c, page1_mid, page1_end - page1_mid, 0);
2532         }
2533         if (strstr(buffer, "/socket"))
2534         {
2535             server_socket = c;
2536             SetEvent(server_req_rec_event);
2537             WaitForSingleObject(conn_wait_event, INFINITE);
2538         }
2539         if (strstr(buffer, "/echo_request"))
2540         {
2541             send(c, okmsg, sizeof(okmsg)-1, 0);
2542             send(c, buffer, strlen(buffer), 0);
2543         }
2544         if (strstr(buffer, "GET /test_remove_dot_segments"))
2545         {
2546             send(c, okmsg, sizeof(okmsg)-1, 0);
2547         }
2548 
2549         if (strstr(buffer, "HEAD /test_large_content"))
2550         {
2551             char msg[sizeof(largemsg) + 16];
2552             sprintf(msg, largemsg, content_length);
2553             send(c, msg, strlen(msg), 0);
2554         }
2555         if (strstr(buffer, "HEAD /test_auth_host1"))
2556         {
2557             if (strstr(buffer, "Authorization: Basic dGVzdDE6cGFzcw=="))
2558                 send(c, okmsg, sizeof okmsg-1, 0);
2559             else
2560                 send(c, noauthmsg, sizeof noauthmsg-1, 0);
2561         }
2562         if (strstr(buffer, "HEAD /test_auth_host2"))
2563         {
2564             if (strstr(buffer, "Authorization: Basic dGVzdDE6cGFzczI="))
2565                 send(c, okmsg, sizeof okmsg-1, 0);
2566             else
2567                 send(c, noauthmsg, sizeof noauthmsg-1, 0);
2568         }
2569         shutdown(c, 2);
2570         closesocket(c);
2571         c = -1;
2572     } while (!last_request);
2573 
2574     closesocket(s);
2575     HeapFree(GetProcessHeap(), 0, buffer);
2576 
2577     return 0;
2578 }
2579 
2580 static void test_basic_request(int port, const char *verb, const char *url)
2581 {
2582     test_request_t req;
2583     DWORD r, count, error;
2584     char buffer[0x100];
2585 
2586     trace("basic request %s %s\n", verb, url);
2587 
2588     open_simple_request(&req, "localhost", port, verb, url);
2589 
2590     SetLastError(0xdeadbeef);
2591     r = HttpSendRequestA(req.request, NULL, 0, NULL, 0);
2592     error = GetLastError();
2593     ok(error == ERROR_SUCCESS || broken(error != ERROR_SUCCESS), "expected ERROR_SUCCESS, got %u\n", error);
2594     ok(r, "HttpSendRequest failed: %u\n", GetLastError());
2595 
2596     count = 0;
2597     memset(buffer, 0, sizeof buffer);
2598     SetLastError(0xdeadbeef);
2599     r = InternetReadFile(req.request, buffer, sizeof buffer, &count);
2600     ok(r, "InternetReadFile failed %u\n", GetLastError());
2601     ok(count == sizeof page1 - 1, "count was wrong\n");
2602     ok(!memcmp(buffer, page1, sizeof page1), "http data wrong, got: %s\n", buffer);
2603 
2604     close_request(&req);
2605 }
2606 
2607 static void test_proxy_indirect(int port)
2608 {
2609     test_request_t req;
2610     DWORD r, sz;
2611     char buffer[0x40];
2612 
2613     open_simple_request(&req, "localhost", port, NULL, "/test2");
2614 
2615     r = HttpSendRequestA(req.request, NULL, 0, NULL, 0);
2616     ok(r, "HttpSendRequest failed %u\n", GetLastError());
2617 
2618     sz = sizeof buffer;
2619     r = HttpQueryInfoA(req.request, HTTP_QUERY_PROXY_AUTHENTICATE, buffer, &sz, NULL);
2620     ok(r || GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND, "HttpQueryInfo failed: %d\n", GetLastError());
2621     if (!r)
2622     {
2623         skip("missing proxy header, not testing remaining proxy headers\n");
2624         goto out;
2625     }
2626     ok(!strcmp(buffer, "Basic realm=\"placebo\""), "proxy auth info wrong\n");
2627 
2628     test_status_code(req.request, 407);
2629     test_request_flags(req.request, 0);
2630 
2631     sz = sizeof buffer;
2632     r = HttpQueryInfoA(req.request, HTTP_QUERY_STATUS_TEXT, buffer, &sz, NULL);
2633     ok(r, "HttpQueryInfo failed\n");
2634     ok(!strcmp(buffer, "Proxy Authentication Required"), "proxy text wrong\n");
2635 
2636     sz = sizeof buffer;
2637     r = HttpQueryInfoA(req.request, HTTP_QUERY_VERSION, buffer, &sz, NULL);
2638     ok(r, "HttpQueryInfo failed\n");
2639     ok(!strcmp(buffer, "HTTP/1.1"), "http version wrong\n");
2640 
2641     sz = sizeof buffer;
2642     r = HttpQueryInfoA(req.request, HTTP_QUERY_SERVER, buffer, &sz, NULL);
2643     ok(r, "HttpQueryInfo failed\n");
2644     ok(!strcmp(buffer, "winetest"), "http server wrong\n");
2645 
2646     sz = sizeof buffer;
2647     r = HttpQueryInfoA(req.request, HTTP_QUERY_CONTENT_ENCODING, buffer, &sz, NULL);
2648     ok(GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND, "HttpQueryInfo should fail\n");
2649     ok(r == FALSE, "HttpQueryInfo failed\n");
2650 
2651 out:
2652     close_request(&req);
2653 }
2654 
2655 static void test_proxy_direct(int port)
2656 {
2657     HINTERNET hi, hc, hr;
2658     DWORD r, sz, error;
2659     char buffer[0x40], *url;
2660     WCHAR bufferW[0x40];
2661     static const char url_fmt[] = "http://test.winehq.org:%u/test2";
2662     static CHAR username[] = "mike",
2663                 password[] = "1101",
2664                 useragent[] = "winetest";
2665     static const WCHAR usernameW[]  = {'m','i','k','e',0},
2666                        passwordW[]  = {'1','1','0','1',0},
2667                        useragentW[] = {'w','i','n','e','t','e','s','t',0};
2668 
2669     /* specify proxy type without the proxy and bypass */
2670     SetLastError(0xdeadbeef);
2671     hi = InternetOpenW(NULL, INTERNET_OPEN_TYPE_PROXY, NULL, NULL, 0);
2672     error = GetLastError();
2673     ok(error == ERROR_INVALID_PARAMETER ||
2674         broken(error == ERROR_SUCCESS) /* WinXPProSP2 */, "got %u\n", error);
2675     ok(hi == NULL || broken(!!hi) /* WinXPProSP2 */, "open should have failed\n");
2676 
2677     sprintf(buffer, "localhost:%d\n", port);
2678     hi = InternetOpenA(NULL, INTERNET_OPEN_TYPE_PROXY, buffer, NULL, 0);
2679     ok(hi != NULL, "open failed\n");
2680 
2681     /* try connect without authorization */
2682     hc = InternetConnectA(hi, "test.winehq.org", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
2683     ok(hc != NULL, "connect failed\n");
2684 
2685     hr = HttpOpenRequestA(hc, NULL, "/test2", NULL, NULL, NULL, 0, 0);
2686     ok(hr != NULL, "HttpOpenRequest failed\n");
2687 
2688     sz = 0;
2689     SetLastError(0xdeadbeef);
2690     r = InternetQueryOptionA(hr, INTERNET_OPTION_PROXY_PASSWORD, NULL, &sz);
2691     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2692     ok(!r, "unexpected success\n");
2693     ok(sz == 1, "got %u\n", sz);
2694 
2695     sz = 0;
2696     SetLastError(0xdeadbeef);
2697     r = InternetQueryOptionA(hr, INTERNET_OPTION_PROXY_USERNAME, NULL, &sz);
2698     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2699     ok(!r, "unexpected success\n");
2700     ok(sz == 1, "got %u\n", sz);
2701 
2702     sz = sizeof(buffer);
2703     SetLastError(0xdeadbeef);
2704     r = InternetQueryOptionA(hr, INTERNET_OPTION_PROXY_PASSWORD, buffer, &sz);
2705     ok(r, "unexpected failure %u\n", GetLastError());
2706     ok(!sz, "got %u\n", sz);
2707 
2708     sz = sizeof(buffer);
2709     SetLastError(0xdeadbeef);
2710     r = InternetQueryOptionA(hr, INTERNET_OPTION_PROXY_USERNAME, buffer, &sz);
2711     ok(r, "unexpected failure %u\n", GetLastError());
2712     ok(!sz, "got %u\n", sz);
2713 
2714     sz = 0;
2715     SetLastError(0xdeadbeef);
2716     r = InternetQueryOptionA(hr, INTERNET_OPTION_PASSWORD, NULL, &sz);
2717     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2718     ok(!r, "unexpected success\n");
2719     ok(sz == 1, "got %u\n", sz);
2720 
2721     sz = 0;
2722     SetLastError(0xdeadbeef);
2723     r = InternetQueryOptionA(hr, INTERNET_OPTION_USERNAME, NULL, &sz);
2724     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2725     ok(!r, "unexpected success\n");
2726     ok(sz == 1, "got %u\n", sz);
2727 
2728     sz = sizeof(buffer);
2729     SetLastError(0xdeadbeef);
2730     r = InternetQueryOptionA(hr, INTERNET_OPTION_PASSWORD, buffer, &sz);
2731     ok(r, "unexpected failure %u\n", GetLastError());
2732     ok(!sz, "got %u\n", sz);
2733 
2734     sz = sizeof(buffer);
2735     SetLastError(0xdeadbeef);
2736     r = InternetQueryOptionA(hr, INTERNET_OPTION_USERNAME, buffer, &sz);
2737     ok(r, "unexpected failure %u\n", GetLastError());
2738     ok(!sz, "got %u\n", sz);
2739 
2740     sz = 0;
2741     SetLastError(0xdeadbeef);
2742     r = InternetQueryOptionA(hr, INTERNET_OPTION_URL, NULL, &sz);
2743     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2744     ok(!r, "unexpected success\n");
2745     ok(sz == 34, "got %u\n", sz);
2746 
2747     sz = sizeof(buffer);
2748     SetLastError(0xdeadbeef);
2749     r = InternetQueryOptionA(hr, INTERNET_OPTION_URL, buffer, &sz);
2750     ok(r, "unexpected failure %u\n", GetLastError());
2751     ok(sz == 33, "got %u\n", sz);
2752 
2753     r = HttpSendRequestW(hr, NULL, 0, NULL, 0);
2754     ok(r || broken(!r), "HttpSendRequest failed %u\n", GetLastError());
2755     if (!r)
2756     {
2757         win_skip("skipping proxy tests on broken wininet\n");
2758         goto done;
2759     }
2760 
2761     test_status_code(hr, 407);
2762 
2763     /* set the user + password then try again */
2764     r = InternetSetOptionA(hi, INTERNET_OPTION_PROXY_USERNAME, username, 4);
2765     ok(!r, "unexpected success\n");
2766 
2767     r = InternetSetOptionA(hc, INTERNET_OPTION_PROXY_USERNAME, username, 4);
2768     ok(r, "failed to set user\n");
2769 
2770     r = InternetSetOptionA(hr, INTERNET_OPTION_PROXY_USERNAME, username, 4);
2771     ok(r, "failed to set user\n");
2772 
2773     buffer[0] = 0;
2774     sz = 3;
2775     SetLastError(0xdeadbeef);
2776     r = InternetQueryOptionA(hr, INTERNET_OPTION_PROXY_USERNAME, buffer, &sz);
2777     ok(!r, "unexpected failure %u\n", GetLastError());
2778     ok(!buffer[0], "got %s\n", buffer);
2779     ok(sz == strlen(username) + 1, "got %u\n", sz);
2780 
2781     buffer[0] = 0;
2782     sz = 0;
2783     SetLastError(0xdeadbeef);
2784     r = InternetQueryOptionA(hr, INTERNET_OPTION_PROXY_USERNAME, buffer, &sz);
2785     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2786     ok(!r, "unexpected success\n");
2787     ok(sz == strlen(username) + 1, "got %u\n", sz);
2788 
2789     bufferW[0] = 0;
2790     sz = 0;
2791     SetLastError(0xdeadbeef);
2792     r = InternetQueryOptionW(hr, INTERNET_OPTION_PROXY_USERNAME, bufferW, &sz);
2793     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2794     ok(!r, "unexpected success\n");
2795     ok(sz == (lstrlenW(usernameW) + 1) * sizeof(WCHAR), "got %u\n", sz);
2796 
2797     buffer[0] = 0;
2798     sz = sizeof(buffer);
2799     r = InternetQueryOptionA(hr, INTERNET_OPTION_PROXY_USERNAME, buffer, &sz);
2800     ok(r, "failed to get username\n");
2801     ok(!strcmp(buffer, username), "got %s\n", buffer);
2802     ok(sz == strlen(username), "got %u\n", sz);
2803 
2804     buffer[0] = 0;
2805     sz = sizeof(bufferW);
2806     r = InternetQueryOptionW(hr, INTERNET_OPTION_PROXY_USERNAME, bufferW, &sz);
2807     ok(r, "failed to get username\n");
2808     ok(!lstrcmpW(bufferW, usernameW), "wrong username\n");
2809     ok(sz == lstrlenW(usernameW), "got %u\n", sz);
2810 
2811     r = InternetSetOptionA(hr, INTERNET_OPTION_PROXY_USERNAME, username, 1);
2812     ok(r, "failed to set user\n");
2813 
2814     buffer[0] = 0;
2815     sz = sizeof(buffer);
2816     r = InternetQueryOptionA(hr, INTERNET_OPTION_PROXY_USERNAME, buffer, &sz);
2817     ok(r, "failed to get username\n");
2818     ok(!strcmp(buffer, username), "got %s\n", buffer);
2819     ok(sz == strlen(username), "got %u\n", sz);
2820 
2821     r = InternetSetOptionA(hi, INTERNET_OPTION_USER_AGENT, useragent, 1);
2822     ok(r, "failed to set useragent\n");
2823 
2824     buffer[0] = 0;
2825     sz = 0;
2826     SetLastError(0xdeadbeef);
2827     r = InternetQueryOptionA(hi, INTERNET_OPTION_USER_AGENT, buffer, &sz);
2828     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2829     ok(!r, "unexpected success\n");
2830     ok(sz == strlen(useragent) + 1, "got %u\n", sz);
2831 
2832     buffer[0] = 0;
2833     sz = sizeof(buffer);
2834     r = InternetQueryOptionA(hi, INTERNET_OPTION_USER_AGENT, buffer, &sz);
2835     ok(r, "failed to get user agent\n");
2836     ok(!strcmp(buffer, useragent), "got %s\n", buffer);
2837     ok(sz == strlen(useragent), "got %u\n", sz);
2838 
2839     bufferW[0] = 0;
2840     sz = 0;
2841     SetLastError(0xdeadbeef);
2842     r = InternetQueryOptionW(hi, INTERNET_OPTION_USER_AGENT, bufferW, &sz);
2843     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2844     ok(!r, "unexpected success\n");
2845     ok(sz == (lstrlenW(useragentW) + 1) * sizeof(WCHAR), "got %u\n", sz);
2846 
2847     bufferW[0] = 0;
2848     sz = sizeof(bufferW);
2849     r = InternetQueryOptionW(hi, INTERNET_OPTION_USER_AGENT, bufferW, &sz);
2850     ok(r, "failed to get user agent\n");
2851     ok(!lstrcmpW(bufferW, useragentW), "wrong user agent\n");
2852     ok(sz == lstrlenW(useragentW), "got %u\n", sz);
2853 
2854     r = InternetSetOptionA(hr, INTERNET_OPTION_USERNAME, username, 1);
2855     ok(r, "failed to set user\n");
2856 
2857     buffer[0] = 0;
2858     sz = 0;
2859     SetLastError(0xdeadbeef);
2860     r = InternetQueryOptionA(hr, INTERNET_OPTION_USERNAME, buffer, &sz);
2861     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2862     ok(!r, "unexpected success\n");
2863     ok(sz == strlen(username) + 1, "got %u\n", sz);
2864 
2865     buffer[0] = 0;
2866     sz = sizeof(buffer);
2867     r = InternetQueryOptionA(hr, INTERNET_OPTION_USERNAME, buffer, &sz);
2868     ok(r, "failed to get user\n");
2869     ok(!strcmp(buffer, username), "got %s\n", buffer);
2870     ok(sz == strlen(username), "got %u\n", sz);
2871 
2872     bufferW[0] = 0;
2873     sz = 0;
2874     SetLastError(0xdeadbeef);
2875     r = InternetQueryOptionW(hr, INTERNET_OPTION_USERNAME, bufferW, &sz);
2876     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2877     ok(!r, "unexpected success\n");
2878     ok(sz == (lstrlenW(usernameW) + 1) * sizeof(WCHAR), "got %u\n", sz);
2879 
2880     bufferW[0] = 0;
2881     sz = sizeof(bufferW);
2882     r = InternetQueryOptionW(hr, INTERNET_OPTION_USERNAME, bufferW, &sz);
2883     ok(r, "failed to get user\n");
2884     ok(!lstrcmpW(bufferW, usernameW), "wrong user\n");
2885     ok(sz == lstrlenW(usernameW), "got %u\n", sz);
2886 
2887     r = InternetSetOptionA(hr, INTERNET_OPTION_PASSWORD, password, 1);
2888     ok(r, "failed to set password\n");
2889 
2890     buffer[0] = 0;
2891     sz = 0;
2892     SetLastError(0xdeadbeef);
2893     r = InternetQueryOptionA(hr, INTERNET_OPTION_PASSWORD, buffer, &sz);
2894     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2895     ok(!r, "unexpected success\n");
2896     ok(sz == strlen(password) + 1, "got %u\n", sz);
2897 
2898     buffer[0] = 0;
2899     sz = sizeof(buffer);
2900     r = InternetQueryOptionA(hr, INTERNET_OPTION_PASSWORD, buffer, &sz);
2901     ok(r, "failed to get password\n");
2902     ok(!strcmp(buffer, password), "got %s\n", buffer);
2903     ok(sz == strlen(password), "got %u\n", sz);
2904 
2905     bufferW[0] = 0;
2906     sz = 0;
2907     SetLastError(0xdeadbeef);
2908     r = InternetQueryOptionW(hr, INTERNET_OPTION_PASSWORD, bufferW, &sz);
2909     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2910     ok(!r, "unexpected success\n");
2911     ok(sz == (lstrlenW(passwordW) + 1) * sizeof(WCHAR), "got %u\n", sz);
2912 
2913     bufferW[0] = 0;
2914     sz = sizeof(bufferW);
2915     r = InternetQueryOptionW(hr, INTERNET_OPTION_PASSWORD, bufferW, &sz);
2916     ok(r, "failed to get password\n");
2917     ok(!lstrcmpW(bufferW, passwordW), "wrong password\n");
2918     ok(sz == lstrlenW(passwordW), "got %u\n", sz);
2919 
2920     url = HeapAlloc(GetProcessHeap(), 0, strlen(url_fmt) + 11);
2921     sprintf(url, url_fmt, port);
2922     buffer[0] = 0;
2923     sz = 0;
2924     SetLastError(0xdeadbeef);
2925     r = InternetQueryOptionA(hr, INTERNET_OPTION_URL, buffer, &sz);
2926     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2927     ok(!r, "unexpected success\n");
2928     ok(sz == strlen(url) + 1, "got %u\n", sz);
2929 
2930     buffer[0] = 0;
2931     sz = sizeof(buffer);
2932     r = InternetQueryOptionA(hr, INTERNET_OPTION_URL, buffer, &sz);
2933     ok(r, "failed to get url\n");
2934     ok(!strcmp(buffer, url), "got %s\n", buffer);
2935     ok(sz == strlen(url), "got %u\n", sz);
2936 
2937     bufferW[0] = 0;
2938     sz = 0;
2939     SetLastError(0xdeadbeef);
2940     r = InternetQueryOptionW(hr, INTERNET_OPTION_URL, bufferW, &sz);
2941     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2942     ok(!r, "unexpected success\n");
2943     ok(sz == (strlen(url) + 1) * sizeof(WCHAR), "got %u\n", sz);
2944 
2945     bufferW[0] = 0;
2946     sz = sizeof(bufferW);
2947     r = InternetQueryOptionW(hr, INTERNET_OPTION_URL, bufferW, &sz);
2948     ok(r, "failed to get url\n");
2949     ok(!strcmp_wa(bufferW, url), "wrong url\n");
2950     ok(sz == strlen(url), "got %u\n", sz);
2951     HeapFree(GetProcessHeap(), 0, url);
2952 
2953     r = InternetSetOptionA(hr, INTERNET_OPTION_PROXY_PASSWORD, password, 4);
2954     ok(r, "failed to set password\n");
2955 
2956     buffer[0] = 0;
2957     sz = 0;
2958     SetLastError(0xdeadbeef);
2959     r = InternetQueryOptionA(hr, INTERNET_OPTION_PROXY_PASSWORD, buffer, &sz);
2960     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2961     ok(!r, "unexpected success\n");
2962     ok(sz == strlen(password) + 1, "got %u\n", sz);
2963 
2964     buffer[0] = 0;
2965     sz = sizeof(buffer);
2966     r = InternetQueryOptionA(hr, INTERNET_OPTION_PROXY_PASSWORD, buffer, &sz);
2967     ok(r, "failed to get password\n");
2968     ok(!strcmp(buffer, password), "got %s\n", buffer);
2969     ok(sz == strlen(password), "got %u\n", sz);
2970 
2971     bufferW[0] = 0;
2972     sz = 0;
2973     SetLastError(0xdeadbeef);
2974     r = InternetQueryOptionW(hr, INTERNET_OPTION_PROXY_PASSWORD, bufferW, &sz);
2975     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %u\n", GetLastError());
2976     ok(!r, "unexpected success\n");
2977     ok(sz == (lstrlenW(passwordW) + 1) * sizeof(WCHAR), "got %u\n", sz);
2978 
2979     bufferW[0] = 0;
2980     sz = sizeof(bufferW);
2981     r = InternetQueryOptionW(hr, INTERNET_OPTION_PROXY_PASSWORD, bufferW, &sz);
2982     ok(r, "failed to get password\n");
2983     ok(!lstrcmpW(bufferW, passwordW), "wrong password\n");
2984     ok(sz == lstrlenW(passwordW), "got %u\n", sz);
2985 
2986     r = HttpSendRequestW(hr, NULL, 0, NULL, 0);
2987     if (!r)
2988     {
2989         win_skip("skipping proxy tests on broken wininet\n");
2990         goto done;
2991     }
2992     ok(r, "HttpSendRequest failed %u\n", GetLastError());
2993     sz = sizeof buffer;
2994     r = HttpQueryInfoA(hr, HTTP_QUERY_STATUS_CODE, buffer, &sz, NULL);
2995     ok(r, "HttpQueryInfo failed\n");
2996     ok(!strcmp(buffer, "200"), "proxy code wrong\n");
2997 
2998     InternetCloseHandle(hr);
2999     InternetCloseHandle(hc);
3000     InternetCloseHandle(hi);
3001 
3002     sprintf(buffer, "localhost:%d\n", port);
3003     hi = InternetOpenA("winetest", INTERNET_OPEN_TYPE_PROXY, buffer, NULL, 0);
3004     ok(hi != NULL, "InternetOpen failed\n");
3005 
3006     hc = InternetConnectA(hi, "test.winehq.org", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
3007     ok(hc != NULL, "InternetConnect failed\n");
3008 
3009     hr = HttpOpenRequestA(hc, "POST", "/test2", NULL, NULL, NULL, INTERNET_FLAG_SECURE, 0);
3010     ok(hr != NULL, "HttpOpenRequest failed\n");
3011 
3012     r = HttpSendRequestA(hr, NULL, 0, (char *)"data", sizeof("data"));
3013     ok(r, "HttpSendRequest failed %u\n", GetLastError());
3014 
3015     test_status_code(hr, 407);
3016 
3017 done:
3018     InternetCloseHandle(hr);
3019     InternetCloseHandle(hc);
3020     InternetCloseHandle(hi);
3021 }
3022 
3023 static void test_header_handling_order(int port)
3024 {
3025     static const char authorization[] = "Authorization: Basic dXNlcjpwd2Q=";
3026     static const char connection[]    = "Connection: Close";
3027     static const char *types[2] = { "*", NULL };
3028     char data[32];
3029     HINTERNET session, connect, request;
3030     DWORD size, status, data_len;
3031     BOOL ret;
3032 
3033     session = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
3034     ok(session != NULL, "InternetOpen failed\n");
3035 
3036     connect = InternetConnectA(session, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
3037     ok(connect != NULL, "InternetConnect failed\n");
3038 
3039     request = HttpOpenRequestA(connect, NULL, "/test3", NULL, NULL, types, INTERNET_FLAG_KEEP_CONNECTION, 0);
3040     ok(request != NULL, "HttpOpenRequest failed\n");
3041 
3042     ret = HttpAddRequestHeadersA(request, authorization, ~0u, HTTP_ADDREQ_FLAG_ADD);
3043     ok(ret, "HttpAddRequestHeaders failed\n");
3044 
3045     ret = HttpSendRequestA(request, NULL, 0, NULL, 0);
3046     ok(ret, "HttpSendRequest failed\n");
3047 
3048     test_status_code(request, 200);
3049     test_request_flags(request, 0);
3050 
3051     InternetCloseHandle(request);
3052 
3053     request = HttpOpenRequestA(connect, NULL, "/test4", NULL, NULL, types, INTERNET_FLAG_KEEP_CONNECTION, 0);
3054     ok(request != NULL, "HttpOpenRequest failed\n");
3055 
3056     ret = HttpSendRequestA(request, connection, ~0u, NULL, 0);
3057     ok(ret, "HttpSendRequest failed\n");
3058 
3059     status = 0;
3060     size = sizeof(status);
3061     ret = HttpQueryInfoA( request, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
3062     ok(ret, "HttpQueryInfo failed\n");
3063     ok(status == 200 || status == 400 /* IE6 */, "got status %u, expected 200 or 400\n", status);
3064 
3065     InternetCloseHandle(request);
3066     InternetCloseHandle(connect);
3067 
3068     connect = InternetConnectA(session, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
3069     ok(connect != NULL, "InternetConnect failed\n");
3070 
3071     request = HttpOpenRequestA(connect, "POST", "/test7", NULL, NULL, types, INTERNET_FLAG_KEEP_CONNECTION, 0);
3072     ok(request != NULL, "HttpOpenRequest failed\n");
3073 
3074     ret = HttpAddRequestHeadersA(request, "Content-Length: 100\r\n", ~0u, HTTP_ADDREQ_FLAG_ADD_IF_NEW);
3075     ok(ret, "HttpAddRequestHeaders failed\n");
3076 
3077     ret = HttpSendRequestA(request, connection, ~0u, NULL, 0);
3078     ok(ret, "HttpSendRequest failed\n");
3079 
3080     status = 0;
3081     size = sizeof(status);
3082     ret = HttpQueryInfoA( request, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
3083     ok(ret, "HttpQueryInfo failed\n");
3084     ok(status == 200, "got status %u, expected 200\n", status);
3085 
3086     InternetCloseHandle(request);
3087     InternetCloseHandle(connect);
3088 
3089     connect = InternetConnectA(session, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
3090     ok(connect != NULL, "InternetConnect failed\n");
3091 
3092     request = HttpOpenRequestA(connect, "POST", "/test7b", NULL, NULL, types, INTERNET_FLAG_KEEP_CONNECTION, 0);
3093     ok(request != NULL, "HttpOpenRequest failed\n");
3094 
3095     ret = HttpAddRequestHeadersA(request, "Content-Length: 100\r\n", ~0u, HTTP_ADDREQ_FLAG_ADD_IF_NEW);
3096     ok(ret, "HttpAddRequestHeaders failed\n");
3097 
3098     data_len = sizeof(data);
3099     memset(data, 'a', sizeof(data));
3100     ret = HttpSendRequestA(request, NULL, 0, data, data_len);
3101     ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
3102 
3103     status = 0;
3104     size = sizeof(status);
3105     ret = HttpQueryInfoA( request, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
3106     ok(ret, "HttpQueryInfo failed\n");
3107     ok(status == 200, "got status %u, expected 200\n", status);
3108 
3109     InternetCloseHandle(request);
3110     InternetCloseHandle(connect);
3111     InternetCloseHandle(session);
3112 }
3113 
3114 static void test_connection_header(int port)
3115 {
3116     HINTERNET ses, con, req;
3117     BOOL ret;
3118 
3119     ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
3120     ok(ses != NULL, "InternetOpen failed\n");
3121 
3122     con = InternetConnectA(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
3123     ok(con != NULL, "InternetConnect failed\n");
3124 
3125     req = HttpOpenRequestA(con, NULL, "/test8", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
3126     ok(req != NULL, "HttpOpenRequest failed\n");
3127 
3128     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3129     ok(ret, "HttpSendRequest failed\n");
3130 
3131     test_status_code(req, 200);
3132 
3133     InternetCloseHandle(req);
3134 
3135     req = HttpOpenRequestA(con, NULL, "/test9", NULL, NULL, NULL, 0, 0);
3136     ok(req != NULL, "HttpOpenRequest failed\n");
3137 
3138     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3139     ok(ret, "HttpSendRequest failed\n");
3140 
3141     test_status_code(req, 200);
3142 
3143     InternetCloseHandle(req);
3144 
3145     req = HttpOpenRequestA(con, NULL, "/test9", NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
3146     ok(req != NULL, "HttpOpenRequest failed\n");
3147 
3148     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3149     ok(ret, "HttpSendRequest failed\n");
3150 
3151     test_status_code(req, 200);
3152 
3153     InternetCloseHandle(req);
3154 
3155     req = HttpOpenRequestA(con, "POST", "/testA", NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
3156     ok(req != NULL, "HttpOpenRequest failed\n");
3157 
3158     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3159     ok(ret, "HttpSendRequest failed\n");
3160 
3161     test_status_code(req, 200);
3162 
3163     InternetCloseHandle(req);
3164     InternetCloseHandle(con);
3165     InternetCloseHandle(ses);
3166 }
3167 
3168 static void test_header_override(int port)
3169 {
3170     char buffer[128], host_header_override[30], full_url[128];
3171     HINTERNET ses, con, req;
3172     DWORD size, count, err;
3173     BOOL ret;
3174 
3175     sprintf(host_header_override, "Host: test.local:%d\r\n", port);
3176     sprintf(full_url, "http://localhost:%d/test_host_override", port);
3177 
3178     ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
3179     ok(ses != NULL, "InternetOpen failed\n");
3180 
3181     con = InternetConnectA(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
3182     ok(con != NULL, "InternetConnect failed\n");
3183 
3184     req = HttpOpenRequestA(con, NULL, "/test_host_override", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
3185     ok(req != NULL, "HttpOpenRequest failed\n");
3186 
3187     size = sizeof(buffer) - 1;
3188     count = 0;
3189     memset(buffer, 0, sizeof(buffer));
3190     ret = HttpQueryInfoA(req, HTTP_QUERY_HOST | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, &count);
3191     err = GetLastError();
3192     ok(!ret, "HttpQueryInfo succeeded\n");
3193     ok(err == ERROR_HTTP_HEADER_NOT_FOUND, "Expected error ERROR_HTTP_HEADER_NOT_FOUND, got %d\n", err);
3194 
3195     test_request_url(req, full_url);
3196 
3197     ret = HttpAddRequestHeadersA(req, host_header_override, ~0u, HTTP_ADDREQ_FLAG_COALESCE);
3198     ok(ret, "HttpAddRequestHeaders failed\n");
3199 
3200     size = sizeof(buffer) - 1;
3201     count = 0;
3202     memset(buffer, 0, sizeof(buffer));
3203     ret = HttpQueryInfoA(req, HTTP_QUERY_HOST | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, &count);
3204     ok(ret, "HttpQueryInfo failed\n");
3205 
3206     test_request_url(req, full_url);
3207 
3208     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3209     ok(ret, "HttpSendRequest failed\n");
3210 
3211     test_status_code(req, 200);
3212 
3213     InternetCloseHandle(req);
3214     req = HttpOpenRequestA(con, NULL, "/test_host_override", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
3215     ok(req != NULL, "HttpOpenRequest failed\n");
3216 
3217     ret = HttpAddRequestHeadersA(req, host_header_override, ~0u, HTTP_ADDREQ_FLAG_COALESCE);
3218     ok(ret, "HttpAddRequestHeaders failed\n");
3219 
3220     ret = HttpAddRequestHeadersA(req, host_header_override, ~0u, HTTP_ADDREQ_FLAG_COALESCE);
3221     ok(ret, "HttpAddRequestHeaders failed\n");
3222 
3223     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3224     ok(ret, "HttpSendRequest failed\n");
3225 
3226     test_status_code(req, 400);
3227 
3228     InternetCloseHandle(req);
3229     req = HttpOpenRequestA(con, NULL, "/test_host_override", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
3230     ok(req != NULL, "HttpOpenRequest failed\n");
3231 
3232     ret = HttpAddRequestHeadersA(req, host_header_override, ~0u, HTTP_ADDREQ_FLAG_ADD);
3233     ok(ret, "HttpAddRequestHeaders failed\n");
3234 
3235     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3236     ok(ret, "HttpSendRequest failed\n");
3237 
3238     test_status_code(req, 200);
3239 
3240     InternetCloseHandle(req);
3241     req = HttpOpenRequestA(con, NULL, "/test_host_override", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
3242     ok(req != NULL, "HttpOpenRequest failed\n");
3243 
3244     ret = HttpAddRequestHeadersA(req, host_header_override, ~0u, HTTP_ADDREQ_FLAG_REPLACE);
3245     if(ret) { /* win10 returns success */
3246         trace("replacing host header is supported.\n");
3247 
3248         ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3249         ok(ret, "HttpSendRequest failed\n");
3250 
3251         test_status_code(req, 200);
3252     }else {
3253         trace("replacing host header is not supported.\n");
3254 
3255         err = GetLastError();
3256         ok(err == ERROR_HTTP_HEADER_NOT_FOUND, "Expected error ERROR_HTTP_HEADER_NOT_FOUND, got %d\n", err);
3257 
3258         ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3259         ok(ret, "HttpSendRequest failed\n");
3260 
3261         test_status_code(req, 400);
3262     }
3263 
3264     InternetCloseHandle(req);
3265     InternetSetCookieA("http://localhost", "cookie", "biscuit");
3266     req = HttpOpenRequestA(con, NULL, "/testC", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
3267     ok(req != NULL, "HttpOpenRequest failed\n");
3268 
3269     ret = HttpAddRequestHeadersA(req, host_header_override, ~0u, HTTP_ADDREQ_FLAG_ADD);
3270     ok(ret, "HttpAddRequestHeaders failed\n");
3271 
3272     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3273     ok(ret, "HttpSendRequest failed\n");
3274 
3275     test_status_code(req, 200);
3276 
3277     InternetCloseHandle(req);
3278     req = HttpOpenRequestA(con, NULL, "/test_cookie_set_host_override", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
3279     ok(req != NULL, "HttpOpenRequest failed\n");
3280 
3281     ret = HttpAddRequestHeadersA(req, host_header_override, ~0u, HTTP_ADDREQ_FLAG_ADD);
3282     ok(ret, "HttpAddRequestHeaders failed\n");
3283 
3284     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3285     ok(ret, "HttpSendRequest failed\n");
3286 
3287     test_status_code(req, 200);
3288 
3289     InternetCloseHandle(req);
3290     req = HttpOpenRequestA(con, NULL, "/test_cookie_check_host_override", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
3291     ok(req != NULL, "HttpOpenRequest failed\n");
3292 
3293     ret = HttpAddRequestHeadersA(req, host_header_override, ~0u, HTTP_ADDREQ_FLAG_ADD);
3294     ok(ret, "HttpAddRequestHeaders failed\n");
3295 
3296     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3297     ok(ret, "HttpSendRequest failed\n");
3298 
3299     test_status_code(req, 200);
3300 
3301     InternetCloseHandle(req);
3302     req = HttpOpenRequestA(con, NULL, "/test_cookie_check_host_override", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
3303     ok(req != NULL, "HttpOpenRequest failed\n");
3304 
3305     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3306     ok(ret, "HttpSendRequest failed\n");
3307 
3308     test_status_code(req, 200);
3309 
3310     InternetCloseHandle(req);
3311     InternetSetCookieA("http://test.local", "foo", "bar");
3312     req = HttpOpenRequestA(con, NULL, "/test_cookie_check_different_host", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
3313     ok(req != NULL, "HttpOpenRequest failed\n");
3314 
3315     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3316     ok(ret, "HttpSendRequest failed\n");
3317 
3318     test_status_code(req, 200);
3319 
3320     InternetCloseHandle(req);
3321     req = HttpOpenRequestA(con, NULL, "/test_cookie_check_different_host", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
3322     ok(req != NULL, "HttpOpenRequest failed\n");
3323 
3324     ret = HttpAddRequestHeadersA(req, host_header_override, ~0u, HTTP_ADDREQ_FLAG_ADD);
3325     ok(ret, "HttpAddRequestHeaders failed\n");
3326 
3327     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3328     ok(ret, "HttpSendRequest failed\n");
3329 
3330     test_status_code(req, 200);
3331 
3332     InternetCloseHandle(req);
3333     InternetCloseHandle(con);
3334     InternetCloseHandle(ses);
3335 
3336     ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
3337     ok(ses != NULL, "InternetOpenA failed\n");
3338 
3339     con = InternetConnectA(ses, "localhost", port, "test1", "pass", INTERNET_SERVICE_HTTP, 0, 0);
3340     ok(con != NULL, "InternetConnectA failed %u\n", GetLastError());
3341 
3342     req = HttpOpenRequestA( con, "HEAD", "/test_auth_host1", NULL, NULL, NULL, 0, 0);
3343     ok(req != NULL, "HttpOpenRequestA failed %u\n", GetLastError());
3344 
3345     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3346     ok(ret, "HttpSendRequestA failed %u\n", GetLastError());
3347 
3348     test_status_code(req, 200);
3349 
3350     InternetCloseHandle(req);
3351     InternetCloseHandle(con);
3352     InternetCloseHandle(ses);
3353 
3354     ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
3355     ok(ses != NULL, "InternetOpenA failed\n");
3356 
3357     con = InternetConnectA( ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
3358     ok(con != NULL, "InternetConnectA failed %u\n", GetLastError());
3359 
3360     req = HttpOpenRequestA(con, "HEAD", "/test_auth_host1", NULL, NULL, NULL, 0, 0);
3361     ok(req != NULL, "HttpOpenRequestA failed %u\n", GetLastError());
3362 
3363     ret = HttpAddRequestHeadersA(req, host_header_override, ~0u, HTTP_ADDREQ_FLAG_ADD);
3364     ok(ret, "HttpAddRequestHeaders failed\n");
3365 
3366     ret = HttpSendRequestA( req, NULL, 0, NULL, 0 );
3367     ok( ret, "HttpSendRequestA failed %u\n", GetLastError() );
3368 
3369     test_status_code(req, 200);
3370 
3371     InternetCloseHandle(req);
3372     InternetCloseHandle(con);
3373     InternetCloseHandle(ses);
3374 
3375     ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
3376     ok(ses != NULL, "InternetOpenA failed\n");
3377 
3378     con = InternetConnectA(ses, "localhost", port, "test1", "pass2", INTERNET_SERVICE_HTTP, 0, 0);
3379     ok(con != NULL, "InternetConnectA failed %u\n", GetLastError());
3380 
3381     req = HttpOpenRequestA(con, "HEAD", "/test_auth_host2", NULL, NULL, NULL, 0, 0);
3382     ok(req != NULL, "HttpOpenRequestA failed %u\n", GetLastError());
3383 
3384     ret = HttpAddRequestHeadersA(req, host_header_override, ~0u, HTTP_ADDREQ_FLAG_ADD);
3385     ok(ret, "HttpAddRequestHeaders failed\n");
3386 
3387     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3388     ok(ret, "HttpSendRequestA failed %u\n", GetLastError());
3389 
3390     test_status_code(req, 200);
3391 
3392     InternetCloseHandle(req);
3393     InternetCloseHandle(con);
3394     InternetCloseHandle(ses);
3395 
3396     ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
3397     ok(ses != NULL, "InternetOpenA failed\n");
3398 
3399     con = InternetConnectA(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
3400     ok(con != NULL, "InternetConnectA failed %u\n", GetLastError());
3401 
3402     req = HttpOpenRequestA(con, "HEAD", "/test_auth_host2", NULL, NULL, NULL, 0, 0);
3403     ok(req != NULL, "HttpOpenRequestA failed %u\n", GetLastError());
3404 
3405     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3406     ok(ret, "HttpSendRequestA failed %u\n", GetLastError());
3407 
3408     test_status_code(req, 200);
3409 
3410     InternetCloseHandle(req);
3411     InternetCloseHandle(con);
3412     InternetCloseHandle(ses);
3413 }
3414 
3415 static void test_connection_closing(int port)
3416 {
3417     HINTERNET session, connection, req;
3418     DWORD res;
3419 
3420     reset_events();
3421 
3422     session = InternetOpenA("", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, INTERNET_FLAG_ASYNC);
3423     ok(session != NULL,"InternetOpen failed with error %u\n", GetLastError());
3424 
3425     pInternetSetStatusCallbackA(session, callback);
3426 
3427     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
3428     connection = InternetConnectA(session, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0x0, 0xdeadbeef);
3429     ok(connection != NULL,"InternetConnect failed with error %u\n", GetLastError());
3430     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
3431 
3432     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
3433     req = HttpOpenRequestA(connection, "GET", "/testJ", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0xdeadbeaf);
3434     ok(req != NULL, "HttpOpenRequest failed: %u\n", GetLastError());
3435     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
3436 
3437     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
3438     SET_OPTIONAL(INTERNET_STATUS_DETECTING_PROXY);
3439     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
3440     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
3441     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
3442     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
3443     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
3444     SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
3445     SET_OPTIONAL(INTERNET_STATUS_CLOSING_CONNECTION);
3446     SET_OPTIONAL(INTERNET_STATUS_CONNECTION_CLOSED);
3447     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
3448 
3449     res = HttpSendRequestA(req, NULL, 0, NULL, 0);
3450     ok(!res && (GetLastError() == ERROR_IO_PENDING),
3451        "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n");
3452     WaitForSingleObject(complete_event, INFINITE);
3453     ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error);
3454 
3455     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
3456     CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
3457     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
3458     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
3459     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
3460     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
3461     CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
3462     CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
3463     CLEAR_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
3464     CLEAR_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
3465     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
3466 
3467     test_status_code(req, 200);
3468 
3469     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
3470     SET_OPTIONAL(INTERNET_STATUS_DETECTING_PROXY);
3471     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
3472     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
3473     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
3474     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
3475     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
3476     SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
3477     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
3478 
3479     res = HttpSendRequestA(req, NULL, 0, NULL, 0);
3480     ok(!res && (GetLastError() == ERROR_IO_PENDING),
3481             "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n");
3482     WaitForSingleObject(complete_event, INFINITE);
3483     ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error);
3484 
3485     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
3486     CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
3487     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
3488     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
3489     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
3490     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
3491     CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
3492     CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
3493     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
3494 
3495     test_status_code(req, 210);
3496 
3497     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
3498     SET_OPTIONAL(INTERNET_STATUS_DETECTING_PROXY);
3499     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
3500     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
3501     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
3502     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
3503     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
3504     SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
3505     SET_OPTIONAL(INTERNET_STATUS_CLOSING_CONNECTION);
3506     SET_OPTIONAL(INTERNET_STATUS_CONNECTION_CLOSED);
3507     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
3508 
3509     res = HttpSendRequestA(req, NULL, 0, NULL, 0);
3510     ok(!res && (GetLastError() == ERROR_IO_PENDING),
3511        "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n");
3512     WaitForSingleObject(complete_event, INFINITE);
3513     ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error);
3514 
3515     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
3516     CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
3517     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
3518     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
3519     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
3520     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
3521     CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
3522     CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
3523     CLEAR_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
3524     CLEAR_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
3525     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
3526 
3527     test_status_code(req, 200);
3528 
3529     SET_WINE_ALLOW(INTERNET_STATUS_CLOSING_CONNECTION);
3530     SET_WINE_ALLOW(INTERNET_STATUS_CONNECTION_CLOSED);
3531 
3532     close_async_handle(session, 2);
3533 }
3534 
3535 static void test_successive_HttpSendRequest(int port)
3536 {
3537     HINTERNET session, connection, req;
3538     DWORD res;
3539 
3540     reset_events();
3541 
3542     session = InternetOpenA("", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, INTERNET_FLAG_ASYNC);
3543     ok(session != NULL,"InternetOpen failed with error %u\n", GetLastError());
3544 
3545     pInternetSetStatusCallbackA(session, callback);
3546 
3547     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
3548     connection = InternetConnectA(session, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0x0, 0xdeadbeef);
3549     ok(connection != NULL,"InternetConnect failed with error %u\n", GetLastError());
3550     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
3551 
3552     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
3553     req = HttpOpenRequestA(connection, "GET", "/testH", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0xdeadbeaf);
3554     ok(req != NULL, "HttpOpenRequest failed: %u\n", GetLastError());
3555     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
3556 
3557     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
3558     SET_OPTIONAL(INTERNET_STATUS_DETECTING_PROXY);
3559     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
3560     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
3561     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
3562     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
3563     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
3564     SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
3565     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
3566 
3567     res = HttpSendRequestA(req, NULL, 0, NULL, 0);
3568     ok(!res && (GetLastError() == ERROR_IO_PENDING),
3569             "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n");
3570     WaitForSingleObject(complete_event, INFINITE);
3571     ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error);
3572 
3573     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
3574     CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
3575     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
3576     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
3577     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
3578     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
3579     CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
3580     CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
3581     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
3582 
3583     test_status_code(req, 210);
3584 
3585     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
3586     SET_OPTIONAL(INTERNET_STATUS_DETECTING_PROXY);
3587     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
3588     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
3589     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
3590     SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
3591     SET_OPTIONAL(INTERNET_STATUS_CLOSING_CONNECTION);
3592     SET_OPTIONAL(INTERNET_STATUS_CONNECTION_CLOSED);
3593     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
3594 
3595     res = HttpSendRequestA(req, NULL, 0, NULL, 0);
3596     ok(!res && (GetLastError() == ERROR_IO_PENDING),
3597        "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n");
3598     WaitForSingleObject(complete_event, INFINITE);
3599     ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error);
3600 
3601     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
3602     CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
3603     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
3604     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
3605     CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
3606     CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
3607     CLEAR_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
3608     CLEAR_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
3609     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
3610 
3611     test_status_code(req, 200);
3612 
3613     SET_WINE_ALLOW(INTERNET_STATUS_CLOSING_CONNECTION);
3614     SET_WINE_ALLOW(INTERNET_STATUS_CONNECTION_CLOSED);
3615 
3616     close_async_handle(session, 2);
3617 }
3618 
3619 static void test_no_content(int port)
3620 {
3621     HINTERNET session, connection, req;
3622     DWORD res;
3623 
3624     trace("Testing 204 no content response...\n");
3625 
3626     reset_events();
3627 
3628     session = InternetOpenA("", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, INTERNET_FLAG_ASYNC);
3629     ok(session != NULL,"InternetOpen failed with error %u\n", GetLastError());
3630 
3631     pInternetSetStatusCallbackA(session, callback);
3632 
3633     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
3634     connection = InternetConnectA(session, "localhost", port,
3635             NULL, NULL, INTERNET_SERVICE_HTTP, 0x0, 0xdeadbeef);
3636     ok(connection != NULL,"InternetConnect failed with error %u\n", GetLastError());
3637     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
3638 
3639     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
3640     req = HttpOpenRequestA(connection, "GET", "/test_no_content", NULL, NULL, NULL,
3641             INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RESYNCHRONIZE, 0xdeadbead);
3642     ok(req != NULL, "HttpOpenRequest failed: %u\n", GetLastError());
3643     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
3644 
3645     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
3646     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
3647     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
3648     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
3649     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
3650     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
3651     SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
3652     SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION);
3653     SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED);
3654     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
3655 
3656     res = HttpSendRequestA(req, NULL, -1, NULL, 0);
3657     ok(!res && (GetLastError() == ERROR_IO_PENDING),
3658        "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n");
3659     WaitForSingleObject(complete_event, INFINITE);
3660     ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error);
3661 
3662     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
3663     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
3664     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
3665     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
3666     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
3667     CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
3668     CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
3669     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
3670 
3671     close_async_handle(session, 2);
3672 
3673     /*
3674      * The connection should be closed before closing handle. This is true for most
3675      * wininet versions (including Wine), but some old win2k versions fail to do that.
3676      */
3677     CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
3678     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
3679 }
3680 
3681 static void test_conn_close(int port)
3682 {
3683     HINTERNET session, connection, req;
3684     DWORD res, avail, size;
3685     BYTE buf[1024];
3686 
3687     trace("Testing connection close connection...\n");
3688 
3689     reset_events();
3690 
3691     session = InternetOpenA("", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, INTERNET_FLAG_ASYNC);
3692     ok(session != NULL,"InternetOpen failed with error %u\n", GetLastError());
3693 
3694     pInternetSetStatusCallbackA(session, callback);
3695 
3696     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
3697     connection = InternetConnectA(session, "localhost", port,
3698             NULL, NULL, INTERNET_SERVICE_HTTP, 0x0, 0xdeadbeef);
3699     ok(connection != NULL,"InternetConnect failed with error %u\n", GetLastError());
3700     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
3701 
3702     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
3703     req = HttpOpenRequestA(connection, "GET", "/test_conn_close", NULL, NULL, NULL,
3704             INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RESYNCHRONIZE, 0xdeadbead);
3705     ok(req != NULL, "HttpOpenRequest failed: %u\n", GetLastError());
3706     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
3707 
3708     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
3709     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
3710     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
3711     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
3712     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
3713     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
3714     SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
3715     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
3716 
3717     res = HttpSendRequestA(req, NULL, -1, NULL, 0);
3718     ok(!res && (GetLastError() == ERROR_IO_PENDING),
3719        "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n");
3720     WaitForSingleObject(complete_event, INFINITE);
3721     ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error);
3722 
3723     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
3724     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
3725     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
3726     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
3727     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
3728     CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
3729     CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
3730     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
3731 
3732     avail = 0;
3733     res = InternetQueryDataAvailable(req, &avail, 0, 0);
3734     ok(res, "InternetQueryDataAvailable failed: %u\n", GetLastError());
3735     ok(avail != 0, "avail = 0\n");
3736 
3737     size = 0;
3738     res = InternetReadFile(req, buf, avail, &size);
3739     ok(res, "InternetReadFile failed: %u\n", GetLastError());
3740 
3741     /* IE11 calls those in InternetQueryDataAvailable call. */
3742     SET_OPTIONAL(INTERNET_STATUS_RECEIVING_RESPONSE);
3743     SET_OPTIONAL(INTERNET_STATUS_RESPONSE_RECEIVED);
3744 
3745     res = InternetQueryDataAvailable(req, &avail, 0, 0);
3746     ok(!res && (GetLastError() == ERROR_IO_PENDING),
3747        "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n");
3748     ok(!avail, "avail = %u, expected 0\n", avail);
3749 
3750     CLEAR_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
3751 
3752     SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION);
3753     SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED);
3754     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
3755     SetEvent(conn_close_event);
3756 #ifdef ROSTESTS_73_FIXED
3757     WaitForSingleObject(complete_event, INFINITE);
3758 #else /* ROSTESTS_73_FIXED */
3759     ok(WaitForSingleObject(complete_event, 5000) == WAIT_OBJECT_0, "Wait timed out\n");
3760 #endif /* ROSTESTS_73_FIXED */
3761     ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error);
3762     CLEAR_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
3763     CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
3764     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
3765     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
3766 
3767     close_async_handle(session, 2);
3768 }
3769 
3770 static void test_no_cache(int port)
3771 {
3772     static const char cache_control_no_cache[] = "/test_cache_control_no_cache";
3773     static const char cache_control_no_store[] = "/test_cache_control_no_store";
3774     static const char cache_url_fmt[] = "http://localhost:%d%s";
3775 
3776     char cache_url[256], buf[256];
3777     HINTERNET ses, con, req;
3778     DWORD read, size;
3779     BOOL ret;
3780 
3781     trace("Testing no-cache header\n");
3782 
3783     ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
3784     ok(ses != NULL,"InternetOpen failed with error %u\n", GetLastError());
3785 
3786     con = InternetConnectA(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
3787     ok(con != NULL, "InternetConnect failed with error %u\n", GetLastError());
3788 
3789     req = HttpOpenRequestA(con, NULL, cache_control_no_cache, NULL, NULL, NULL, 0, 0);
3790     ok(req != NULL, "HttpOpenRequest failed\n");
3791 
3792     sprintf(cache_url, cache_url_fmt, port, cache_control_no_cache);
3793     DeleteUrlCacheEntryA(cache_url);
3794 
3795     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3796     ok(ret, "HttpSendRequest failed with error %u\n", GetLastError());
3797     size = 0;
3798     while(InternetReadFile(req, buf, sizeof(buf), &read) && read)
3799         size += read;
3800     ok(size == 12, "read %d bytes of data\n", size);
3801     InternetCloseHandle(req);
3802 
3803     req = HttpOpenRequestA(con, NULL, cache_control_no_cache, NULL, NULL, NULL, 0, 0);
3804     ok(req != NULL, "HttpOpenRequest failed\n");
3805 
3806     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3807     ok(ret, "HttpSendRequest failed with error %u\n", GetLastError());
3808     size = 0;
3809     while(InternetReadFile(req, buf, sizeof(buf), &read) && read)
3810         size += read;
3811     ok(size == 0, "read %d bytes of data\n", size);
3812     InternetCloseHandle(req);
3813     DeleteUrlCacheEntryA(cache_url);
3814 
3815     req = HttpOpenRequestA(con, NULL, cache_control_no_store, NULL, NULL, NULL, 0, 0);
3816     ok(req != NULL, "HttpOpenRequest failed\n");
3817 
3818     sprintf(cache_url, cache_url_fmt, port, cache_control_no_store);
3819     DeleteUrlCacheEntryA(cache_url);
3820 
3821     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
3822     ok(ret, "HttpSendRequest failed with error %u\n", GetLastError());
3823     size = 0;
3824     while(InternetReadFile(req, buf, sizeof(buf), &read) && read)
3825         size += read;
3826     ok(size == 12, "read %d bytes of data\n", size);
3827     InternetCloseHandle(req);
3828 
3829     ret = DeleteUrlCacheEntryA(cache_url);
3830     ok(!ret && GetLastError()==ERROR_FILE_NOT_FOUND, "cache entry should not exist\n");
3831 
3832     InternetCloseHandle(con);
3833     InternetCloseHandle(ses);
3834 }
3835 
3836 static void test_cache_read_gzipped(int port)
3837 {
3838     static const char cache_url_fmt[] = "http://localhost:%d%s";
3839     static const char get_gzip[] = "/test_cache_gzip";
3840     static const char content[] = "gzip test\n";
3841     static const char text_html[] = "text/html";
3842     static const char raw_header[] = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
3843 
3844     HINTERNET ses, con, req;
3845     DWORD read, size;
3846     char cache_url[256], buf[256];
3847     BOOL ret;
3848 
3849     trace("Testing reading compressed content from cache\n");
3850 
3851     ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
3852     ok(ses != NULL,"InternetOpen failed with error %u\n", GetLastError());
3853 
3854     con = InternetConnectA(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
3855     ok(con != NULL, "InternetConnect failed with error %u\n", GetLastError());
3856 
3857     req = HttpOpenRequestA(con, NULL, get_gzip, NULL, NULL, NULL, 0, 0);
3858     ok(req != NULL, "HttpOpenRequest failed\n");
3859 
3860     ret = TRUE;
3861     ret = InternetSetOptionA(req, INTERNET_OPTION_HTTP_DECODING, &ret, sizeof(ret));
3862     if(!ret && GetLastError()==ERROR_INTERNET_INVALID_OPTION) {
3863         win_skip("INTERNET_OPTION_HTTP_DECODING not supported\n");
3864         InternetCloseHandle(req);
3865         InternetCloseHandle(con);
3866         InternetCloseHandle(ses);
3867         return;
3868     }
3869     ok(ret, "InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %d\n", GetLastError());
3870 
3871     ret = HttpSendRequestA(req, "Accept-Encoding: gzip", -1, NULL, 0);
3872     ok(ret, "HttpSendRequest failed with error %u\n", GetLastError());
3873     size = 0;
3874     while(InternetReadFile(req, buf+size, sizeof(buf)-size, &read) && read)
3875         size += read;
3876     ok(size == 10, "read %d bytes of data\n", size);
3877     buf[size] = 0;
3878     ok(!strncmp(buf, content, size), "incorrect page content: %s\n", buf);
3879 
3880     size = sizeof(buf)-1;
3881     ret = HttpQueryInfoA(req, HTTP_QUERY_CONTENT_TYPE, buf, &size, 0);
3882     ok(ret, "HttpQueryInfo(HTTP_QUERY_CONTENT_TYPE) failed: %d\n", GetLastError());
3883     buf[size] = 0;
3884     ok(!strncmp(text_html, buf, size), "buf = %s\n", buf);
3885 
3886     size = sizeof(buf)-1;
3887     ret = HttpQueryInfoA(req, HTTP_QUERY_RAW_HEADERS_CRLF, buf, &size, 0);
3888     ok(ret, "HttpQueryInfo(HTTP_QUERY_CONTENT_TYPE) failed: %d\n", GetLastError());
3889     buf[size] = 0;
3890     ok(!strncmp(raw_header, buf, size), "buf = %s\n", buf);
3891     InternetCloseHandle(req);
3892 
3893     req = HttpOpenRequestA(con, NULL, get_gzip, NULL, NULL, NULL, INTERNET_FLAG_FROM_CACHE, 0);
3894     ok(req != NULL, "HttpOpenRequest failed\n");
3895 
3896     ret = TRUE;
3897     ret = InternetSetOptionA(req, INTERNET_OPTION_HTTP_DECODING, &ret, sizeof(ret));
3898     ok(ret, "InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %d\n", GetLastError());
3899 
3900     ret = HttpSendRequestA(req, "Accept-Encoding: gzip", -1, NULL, 0);
3901     ok(ret, "HttpSendRequest failed with error %u\n", GetLastError());
3902     size = 0;
3903     while(InternetReadFile(req, buf+size, sizeof(buf)-1-size, &read) && read)
3904         size += read;
3905     todo_wine ok(size == 10, "read %d bytes of data\n", size);
3906     buf[size] = 0;
3907     ok(!strncmp(buf, content, size), "incorrect page content: %s\n", buf);
3908 
3909     size = sizeof(buf);
3910     ret = HttpQueryInfoA(req, HTTP_QUERY_CONTENT_ENCODING, buf, &size, 0);
3911     ok(!ret && GetLastError()==ERROR_HTTP_HEADER_NOT_FOUND,
3912             "HttpQueryInfo(HTTP_QUERY_CONTENT_ENCODING) returned %d, %d\n",
3913             ret, GetLastError());
3914 
3915     size = sizeof(buf)-1;
3916     ret = HttpQueryInfoA(req, HTTP_QUERY_CONTENT_TYPE, buf, &size, 0);
3917     todo_wine ok(ret, "HttpQueryInfo(HTTP_QUERY_CONTENT_TYPE) failed: %d\n", GetLastError());
3918     buf[size] = 0;
3919     todo_wine ok(!strncmp(text_html, buf, size), "buf = %s\n", buf);
3920     InternetCloseHandle(req);
3921 
3922     /* Decompression doesn't work while reading from cache */
3923     test_cache_gzip = 0;
3924     sprintf(cache_url, cache_url_fmt, port, get_gzip);
3925     DeleteUrlCacheEntryA(cache_url);
3926 
3927     req = HttpOpenRequestA(con, NULL, get_gzip, NULL, NULL, NULL, 0, 0);
3928     ok(req != NULL, "HttpOpenRequest failed\n");
3929 
3930     ret = HttpSendRequestA(req, "Accept-Encoding: gzip", -1, NULL, 0);
3931     ok(ret, "HttpSendRequest failed with error %u\n", GetLastError());
3932     size = 0;
3933     while(InternetReadFile(req, buf+size, sizeof(buf)-1-size, &read) && read)
3934         size += read;
3935     ok(size == 31, "read %d bytes of data\n", size);
3936     InternetCloseHandle(req);
3937 
3938     req = HttpOpenRequestA(con, NULL, get_gzip, NULL, NULL, NULL, INTERNET_FLAG_FROM_CACHE, 0);
3939     ok(req != NULL, "HttpOpenRequest failed\n");
3940 
3941     ret = TRUE;
3942     ret = InternetSetOptionA(req, INTERNET_OPTION_HTTP_DECODING, &ret, sizeof(ret));
3943     ok(ret, "InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %d\n", GetLastError());
3944 
3945     ret = HttpSendRequestA(req, "Accept-Encoding: gzip", -1, NULL, 0);
3946     ok(ret, "HttpSendRequest failed with error %u\n", GetLastError());
3947     size = 0;
3948     while(InternetReadFile(req, buf+size, sizeof(buf)-1-size, &read) && read)
3949         size += read;
3950     todo_wine ok(size == 31, "read %d bytes of data\n", size);
3951 
3952     size = sizeof(buf);
3953     ret = HttpQueryInfoA(req, HTTP_QUERY_CONTENT_ENCODING, buf, &size, 0);
3954     todo_wine ok(ret, "HttpQueryInfo(HTTP_QUERY_CONTENT_ENCODING) failed: %d\n", GetLastError());
3955     InternetCloseHandle(req);
3956 
3957     InternetCloseHandle(con);
3958     InternetCloseHandle(ses);
3959 
3960     /* Decompression doesn't work while reading from cache */
3961     test_cache_gzip = 0;
3962     sprintf(cache_url, cache_url_fmt, port, get_gzip);
3963     DeleteUrlCacheEntryA(cache_url);
3964 
3965     ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
3966     ok(ses != NULL,"InternetOpen failed with error %u\n", GetLastError());
3967 
3968     ret = TRUE;
3969     ret = InternetSetOptionA(ses, INTERNET_OPTION_HTTP_DECODING, &ret, sizeof(ret));
3970     ok(ret, "InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %d\n", GetLastError());
3971 
3972     con = InternetConnectA(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
3973     ok(con != NULL, "InternetConnect failed with error %u\n", GetLastError());
3974 
3975     req = HttpOpenRequestA(con, NULL, get_gzip, NULL, NULL, NULL, 0, 0);
3976     ok(req != NULL, "HttpOpenRequest failed\n");
3977 
3978     ret = HttpSendRequestA(req, "Accept-Encoding: gzip", -1, NULL, 0);
3979     ok(ret, "HttpSendRequest failed with error %u\n", GetLastError());
3980     size = 0;
3981     while(InternetReadFile(req, buf+size, sizeof(buf)-1-size, &read) && read)
3982         size += read;
3983     ok(size == 10, "read %d bytes of data\n", size);
3984     buf[size] = 0;
3985     ok(!strncmp(buf, content, size), "incorrect page content: %s\n", buf);
3986     InternetCloseHandle(req);
3987 
3988     InternetCloseHandle(con);
3989     InternetCloseHandle(ses);
3990 
3991     /* Decompression doesn't work while reading from cache */
3992     test_cache_gzip = 0;
3993     sprintf(cache_url, cache_url_fmt, port, get_gzip);
3994     DeleteUrlCacheEntryA(cache_url);
3995 
3996     ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
3997     ok(ses != NULL,"InternetOpen failed with error %u\n", GetLastError());
3998 
3999     con = InternetConnectA(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
4000     ok(con != NULL, "InternetConnect failed with error %u\n", GetLastError());
4001 
4002     ret = TRUE;
4003     ret = InternetSetOptionA(con, INTERNET_OPTION_HTTP_DECODING, &ret, sizeof(ret));
4004     ok(ret, "InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %d\n", GetLastError());
4005 
4006     req = HttpOpenRequestA(con, NULL, get_gzip, NULL, NULL, NULL, 0, 0);
4007     ok(req != NULL, "HttpOpenRequest failed\n");
4008 
4009     ret = HttpSendRequestA(req, "Accept-Encoding: gzip", -1, NULL, 0);
4010     ok(ret, "HttpSendRequest failed with error %u\n", GetLastError());
4011     size = 0;
4012     while(InternetReadFile(req, buf+size, sizeof(buf)-1-size, &read) && read)
4013         size += read;
4014     ok(size == 10, "read %d bytes of data\n", size);
4015     buf[size] = 0;
4016     ok(!strncmp(buf, content, size), "incorrect page content: %s\n", buf);
4017     InternetCloseHandle(req);
4018 
4019     InternetCloseHandle(con);
4020     InternetCloseHandle(ses);
4021 
4022     DeleteUrlCacheEntryA(cache_url);
4023 }
4024 
4025 static void test_HttpSendRequestW(int port)
4026 {
4027     static const WCHAR header[] = {'U','A','-','C','P','U',':',' ','x','8','6',0};
4028     HINTERNET ses, con, req;
4029     DWORD error;
4030     BOOL ret;
4031 
4032     ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, INTERNET_FLAG_ASYNC);
4033     ok(ses != NULL, "InternetOpen failed\n");
4034 
4035     con = InternetConnectA(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
4036     ok(con != NULL, "InternetConnect failed\n");
4037 
4038     req = HttpOpenRequestA(con, NULL, "/test1", NULL, NULL, NULL, 0, 0);
4039     ok(req != NULL, "HttpOpenRequest failed\n");
4040 
4041     SetLastError(0xdeadbeef);
4042     ret = HttpSendRequestW(req, header, ~0u, NULL, 0);
4043     error = GetLastError();
4044     ok(!ret, "HttpSendRequestW succeeded\n");
4045     ok(error == ERROR_IO_PENDING ||
4046        broken(error == ERROR_HTTP_HEADER_NOT_FOUND) ||  /* IE6 */
4047        broken(error == ERROR_INVALID_PARAMETER),        /* IE5 */
4048        "got %u expected ERROR_IO_PENDING\n", error);
4049 
4050     InternetCloseHandle(req);
4051     InternetCloseHandle(con);
4052     InternetCloseHandle(ses);
4053 }
4054 
4055 static void test_cookie_header(int port)
4056 {
4057     HINTERNET ses, con, req;
4058     DWORD size, error;
4059     BOOL ret;
4060     char buffer[256];
4061 
4062     ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
4063     ok(ses != NULL, "InternetOpen failed\n");
4064 
4065     con = InternetConnectA(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
4066     ok(con != NULL, "InternetConnect failed\n");
4067 
4068     InternetSetCookieA("http://localhost", "cookie", "biscuit");
4069 
4070     req = HttpOpenRequestA(con, NULL, "/testC", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
4071     ok(req != NULL, "HttpOpenRequest failed\n");
4072 
4073     buffer[0] = 0;
4074     size = sizeof(buffer);
4075     SetLastError(0xdeadbeef);
4076     ret = HttpQueryInfoA(req, HTTP_QUERY_COOKIE | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
4077     error = GetLastError();
4078     ok(!ret, "HttpQueryInfo succeeded\n");
4079     ok(error == ERROR_HTTP_HEADER_NOT_FOUND, "got %u expected ERROR_HTTP_HEADER_NOT_FOUND\n", error);
4080 
4081     ret = HttpAddRequestHeadersA(req, "Cookie: cookie=not biscuit\r\n", ~0u, HTTP_ADDREQ_FLAG_ADD);
4082     ok(ret, "HttpAddRequestHeaders failed: %u\n", GetLastError());
4083 
4084     buffer[0] = 0;
4085     size = sizeof(buffer);
4086     ret = HttpQueryInfoA(req, HTTP_QUERY_COOKIE | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
4087     ok(ret, "HttpQueryInfo failed: %u\n", GetLastError());
4088     ok(!!strstr(buffer, "cookie=not biscuit"), "got '%s' expected \'cookie=not biscuit\'\n", buffer);
4089 
4090     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
4091     ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
4092 
4093     test_status_code(req, 200);
4094 
4095     buffer[0] = 0;
4096     size = sizeof(buffer);
4097     ret = HttpQueryInfoA(req, HTTP_QUERY_COOKIE | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
4098     ok(ret, "HttpQueryInfo failed: %u\n", GetLastError());
4099     ok(!strstr(buffer, "cookie=not biscuit"), "'%s' should not contain \'cookie=not biscuit\'\n", buffer);
4100     ok(!!strstr(buffer, "cookie=biscuit"), "'%s' should contain \'cookie=biscuit\'\n", buffer);
4101 
4102     InternetCloseHandle(req);
4103 
4104     InternetSetCookieA("http://localhost/testCCCC", "subcookie", "data");
4105 
4106     req = HttpOpenRequestA(con, NULL, "/test_cookie_path1", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
4107     ok(req != NULL, "HttpOpenRequest failed\n");
4108 
4109     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
4110     ok(ret, "HttpSendRequest failed\n");
4111 
4112     test_status_code(req, 200);
4113     InternetCloseHandle(req);
4114 
4115     req = HttpOpenRequestA(con, NULL, "/test_cookie_path1/abc", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
4116     ok(req != NULL, "HttpOpenRequest failed\n");
4117 
4118     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
4119     ok(ret, "HttpSendRequest failed\n");
4120 
4121     test_status_code(req, 200);
4122     InternetCloseHandle(req);
4123 
4124     req = HttpOpenRequestA(con, NULL, "/test_cookie_set_path", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
4125     ok(req != NULL, "HttpOpenRequest failed\n");
4126 
4127     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
4128     ok(ret, "HttpSendRequest failed\n");
4129 
4130     test_status_code(req, 200);
4131     InternetCloseHandle(req);
4132 
4133     req = HttpOpenRequestA(con, NULL, "/test_cookie_path2", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
4134     ok(req != NULL, "HttpOpenRequest failed\n");
4135 
4136     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
4137     ok(ret, "HttpSendRequest failed\n");
4138 
4139     test_status_code(req, 400);
4140     InternetCloseHandle(req);
4141 
4142     req = HttpOpenRequestA(con, NULL, "/test_cookie_merge", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
4143     ok(req != NULL, "HttpOpenRequest failed\n");
4144 
4145     ret = HttpAddRequestHeadersA(req, "Cookie: manual_cookie=test\r\n", ~0u, HTTP_ADDREQ_FLAG_ADD);
4146     ok(ret, "HttpAddRequestHeaders failed: %u\n", GetLastError());
4147 
4148     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
4149     ok(ret, "HttpSendRequest failed\n");
4150 
4151     test_status_code(req, 200);
4152     InternetCloseHandle(req);
4153 
4154     InternetCloseHandle(con);
4155     InternetCloseHandle(ses);
4156 }
4157 
4158 static void test_basic_authentication(int port)
4159 {
4160     HINTERNET session, connect, request;
4161     BOOL ret;
4162 
4163     session = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
4164     ok(session != NULL, "InternetOpen failed\n");
4165 
4166     connect = InternetConnectA(session, "localhost", port, "user", "pwd", INTERNET_SERVICE_HTTP, 0, 0);
4167     ok(connect != NULL, "InternetConnect failed\n");
4168 
4169     request = HttpOpenRequestA(connect, NULL, "/test3", NULL, NULL, NULL, 0, 0);
4170     ok(request != NULL, "HttpOpenRequest failed\n");
4171 
4172     ret = HttpSendRequestA(request, NULL, 0, NULL, 0);
4173     ok(ret, "HttpSendRequest failed %u\n", GetLastError());
4174 
4175     test_status_code(request, 200);
4176     test_request_flags(request, 0);
4177 
4178     InternetCloseHandle(request);
4179     InternetCloseHandle(connect);
4180     InternetCloseHandle(session);
4181 }
4182 
4183 static void test_premature_disconnect(int port)
4184 {
4185     test_request_t req;
4186     DWORD err;
4187     BOOL ret;
4188 
4189     open_simple_request(&req, "localhost", port, NULL, "/premature_disconnect");
4190 
4191     SetLastError(0xdeadbeef);
4192     ret = HttpSendRequestA(req.request, NULL, 0, NULL, 0);
4193     err = GetLastError();
4194     todo_wine ok(!ret, "HttpSendRequest succeeded\n");
4195     todo_wine ok(err == ERROR_HTTP_INVALID_SERVER_RESPONSE, "got %u\n", err);
4196 
4197     close_request(&req);
4198 }
4199 
4200 static void test_invalid_response_headers(int port)
4201 {
4202     test_request_t req;
4203     DWORD size;
4204     BOOL ret;
4205     char buffer[256];
4206 
4207     open_simple_request(&req, "localhost", port, NULL, "/testE");
4208 
4209     ret = HttpSendRequestA(req.request, NULL, 0, NULL, 0);
4210     ok(ret, "HttpSendRequest failed %u\n", GetLastError());
4211 
4212     test_status_code(req.request, 401);
4213     test_request_flags(req.request, 0);
4214 
4215     buffer[0] = 0;
4216     size = sizeof(buffer);
4217     ret = HttpQueryInfoA(req.request, HTTP_QUERY_RAW_HEADERS, buffer, &size, NULL);
4218     ok(ret, "HttpQueryInfo failed\n");
4219     ok(!strcmp(buffer, "HTTP/1.0 401 Anonymous requests or requests on unsecure channel are not allowed"),
4220        "headers wrong \"%s\"\n", buffer);
4221 
4222     buffer[0] = 0;
4223     size = sizeof(buffer);
4224     ret = HttpQueryInfoA(req.request, HTTP_QUERY_SERVER, buffer, &size, NULL);
4225     ok(ret, "HttpQueryInfo failed\n");
4226     ok(!strcmp(buffer, "winetest"), "server wrong \"%s\"\n", buffer);
4227 
4228     close_request(&req);
4229 }
4230 
4231 static void test_response_without_headers(int port)
4232 {
4233     test_request_t req;
4234     DWORD r, count, size;
4235     char buffer[1024];
4236 
4237     open_simple_request(&req, "localhost", port, NULL, "/testG");
4238 
4239     test_request_flags(req.request, INTERNET_REQFLAG_NO_HEADERS);
4240 
4241     r = HttpSendRequestA(req.request, NULL, 0, NULL, 0);
4242     ok(r, "HttpSendRequest failed %u\n", GetLastError());
4243 
4244     test_request_flags_todo(req.request, INTERNET_REQFLAG_NO_HEADERS);
4245 
4246     count = 0;
4247     memset(buffer, 0, sizeof buffer);
4248     r = InternetReadFile(req.request, buffer, sizeof buffer, &count);
4249     ok(r, "InternetReadFile failed %u\n", GetLastError());
4250     todo_wine ok(count == sizeof page1 - 1, "count was wrong\n");
4251     todo_wine ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
4252 
4253     test_status_code(req.request, 200);
4254     test_request_flags_todo(req.request, INTERNET_REQFLAG_NO_HEADERS);
4255 
4256     buffer[0] = 0;
4257     size = sizeof(buffer);
4258     r = HttpQueryInfoA(req.request, HTTP_QUERY_STATUS_TEXT, buffer, &size, NULL );
4259     ok(r, "HttpQueryInfo failed %u\n", GetLastError());
4260     ok(!strcmp(buffer, "OK"), "expected OK got: \"%s\"\n", buffer);
4261 
4262     buffer[0] = 0;
4263     size = sizeof(buffer);
4264     r = HttpQueryInfoA(req.request, HTTP_QUERY_VERSION, buffer, &size, NULL);
4265     ok(r, "HttpQueryInfo failed %u\n", GetLastError());
4266     ok(!strcmp(buffer, "HTTP/1.0"), "expected HTTP/1.0 got: \"%s\"\n", buffer);
4267 
4268     buffer[0] = 0;
4269     size = sizeof(buffer);
4270     r = HttpQueryInfoA(req.request, HTTP_QUERY_RAW_HEADERS, buffer, &size, NULL);
4271     ok(r, "HttpQueryInfo failed %u\n", GetLastError());
4272     ok(!strcmp(buffer, "HTTP/1.0 200 OK"), "raw headers wrong: \"%s\"\n", buffer);
4273 
4274     close_request(&req);
4275 }
4276 
4277 static void test_head_request(int port)
4278 {
4279     DWORD len, content_length;
4280     test_request_t req;
4281     BYTE buf[100];
4282     BOOL ret;
4283 
4284     open_simple_request(&req, "localhost", port, "HEAD", "/test_head");
4285 
4286     ret = HttpSendRequestA(req.request, NULL, 0, NULL, 0);
4287     ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
4288 
4289     len = sizeof(content_length);
4290     content_length = -1;
4291     ret = HttpQueryInfoA(req.request, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH, &content_length, &len, 0);
4292     ok(ret, "HttpQueryInfo failed: %u\n", GetLastError());
4293     ok(len == sizeof(DWORD), "len = %u\n", len);
4294     ok(content_length == 100, "content_length = %u\n", content_length);
4295 
4296     len = -1;
4297     ret = InternetReadFile(req.request, buf, sizeof(buf), &len);
4298     ok(ret, "InternetReadFile failed: %u\n", GetLastError());
4299 
4300     len = -1;
4301     ret = InternetReadFile(req.request, buf, sizeof(buf), &len);
4302     ok(ret, "InternetReadFile failed: %u\n", GetLastError());
4303 
4304     close_request(&req);
4305 }
4306 
4307 static void test_HttpQueryInfo(int port)
4308 {
4309     test_request_t req;
4310     DWORD size, index, error;
4311     char buffer[1024];
4312     BOOL ret;
4313 
4314     open_simple_request(&req, "localhost", port, NULL, "/testD");
4315 
4316     size = sizeof(buffer);
4317     ret = HttpQueryInfoA(req.request, HTTP_QUERY_STATUS_TEXT, buffer, &size, &index);
4318     error = GetLastError();
4319     ok(!ret || broken(ret), "HttpQueryInfo succeeded\n");
4320     if (!ret) ok(error == ERROR_HTTP_HEADER_NOT_FOUND, "got %u expected ERROR_HTTP_HEADER_NOT_FOUND\n", error);
4321 
4322     ret = HttpSendRequestA(req.request, NULL, 0, NULL, 0);
4323     ok(ret, "HttpSendRequest failed\n");
4324 
4325     index = 0;
4326     size = sizeof(buffer);
4327     ret = HttpQueryInfoA(req.request, HTTP_QUERY_HOST | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, &index);
4328     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
4329     ok(index == 1, "expected 1 got %u\n", index);
4330 
4331     index = 0;
4332     size = sizeof(buffer);
4333     ret = HttpQueryInfoA(req.request, HTTP_QUERY_DATE | HTTP_QUERY_FLAG_SYSTEMTIME, buffer, &size, &index);
4334     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
4335     ok(index == 1, "expected 1 got %u\n", index);
4336 
4337     index = 0;
4338     size = sizeof(buffer);
4339     ret = HttpQueryInfoA(req.request, HTTP_QUERY_RAW_HEADERS, buffer, &size, &index);
4340     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
4341     ok(index == 0, "expected 0 got %u\n", index);
4342 
4343     size = sizeof(buffer);
4344     ret = HttpQueryInfoA(req.request, HTTP_QUERY_RAW_HEADERS, buffer, &size, &index);
4345     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
4346     ok(index == 0, "expected 0 got %u\n", index);
4347 
4348     index = 0xdeadbeef; /* invalid start index */
4349     size = sizeof(buffer);
4350     ret = HttpQueryInfoA(req.request, HTTP_QUERY_RAW_HEADERS, buffer, &size, &index);
4351     todo_wine ok(!ret, "HttpQueryInfo should have failed\n");
4352     todo_wine ok(GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND,
4353        "Expected ERROR_HTTP_HEADER_NOT_FOUND, got %u\n", GetLastError());
4354 
4355     index = 0;
4356     size = sizeof(buffer);
4357     ret = HttpQueryInfoA(req.request, HTTP_QUERY_RAW_HEADERS_CRLF, buffer, &size, &index);
4358     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
4359     ok(index == 0, "expected 0 got %u\n", index);
4360 
4361     size = sizeof(buffer);
4362     ret = HttpQueryInfoA(req.request, HTTP_QUERY_STATUS_TEXT, buffer, &size, &index);
4363     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
4364     ok(index == 0, "expected 0 got %u\n", index);
4365 
4366     size = sizeof(buffer);
4367     ret = HttpQueryInfoA(req.request, HTTP_QUERY_VERSION, buffer, &size, &index);
4368     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
4369     ok(index == 0, "expected 0 got %u\n", index);
4370 
4371     test_status_code(req.request, 200);
4372 
4373     index = 0xdeadbeef;
4374     size = sizeof(buffer);
4375     ret = HttpQueryInfoA(req.request, HTTP_QUERY_FORWARDED, buffer, &size, &index);
4376     ok(!ret, "HttpQueryInfo succeeded\n");
4377     ok(index == 0xdeadbeef, "expected 0xdeadbeef got %u\n", index);
4378 
4379     index = 0;
4380     size = sizeof(buffer);
4381     ret = HttpQueryInfoA(req.request, HTTP_QUERY_SERVER, buffer, &size, &index);
4382     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
4383     ok(index == 1, "expected 1 got %u\n", index);
4384 
4385     index = 0;
4386     size = sizeof(buffer);
4387     strcpy(buffer, "Server");
4388     ret = HttpQueryInfoA(req.request, HTTP_QUERY_CUSTOM, buffer, &size, &index);
4389     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
4390     ok(index == 1, "expected 1 got %u\n", index);
4391 
4392     index = 0;
4393     size = sizeof(buffer);
4394     ret = HttpQueryInfoA(req.request, HTTP_QUERY_SET_COOKIE, buffer, &size, &index);
4395     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
4396     ok(index == 1, "expected 1 got %u\n", index);
4397 
4398     size = sizeof(buffer);
4399     ret = HttpQueryInfoA(req.request, HTTP_QUERY_SET_COOKIE, buffer, &size, &index);
4400     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
4401     ok(index == 2, "expected 2 got %u\n", index);
4402 
4403     close_request(&req);
4404 }
4405 
4406 static void test_options(int port)
4407 {
4408     INTERNET_DIAGNOSTIC_SOCKET_INFO idsi;
4409     HINTERNET ses, con, req;
4410     DWORD size, error;
4411     DWORD_PTR ctx;
4412     BOOL ret;
4413 
4414     ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
4415     ok(ses != NULL, "InternetOpen failed\n");
4416 
4417     SetLastError(0xdeadbeef);
4418     ret = InternetSetOptionA(ses, INTERNET_OPTION_CONTEXT_VALUE, NULL, 0);
4419     error = GetLastError();
4420     ok(!ret, "InternetSetOption succeeded\n");
4421     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
4422 
4423     SetLastError(0xdeadbeef);
4424     ret = InternetSetOptionA(ses, INTERNET_OPTION_CONTEXT_VALUE, NULL, sizeof(ctx));
4425     ok(!ret, "InternetSetOption succeeded\n");
4426     error = GetLastError();
4427     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
4428 
4429     SetLastError(0xdeadbeef);
4430     ret = InternetSetOptionA(ses, INTERNET_OPTION_CONTEXT_VALUE, &ctx, 0);
4431     ok(!ret, "InternetSetOption succeeded\n");
4432     error = GetLastError();
4433     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
4434 
4435     ctx = 1;
4436     ret = InternetSetOptionA(ses, INTERNET_OPTION_CONTEXT_VALUE, &ctx, sizeof(ctx));
4437     ok(ret, "InternetSetOption failed %u\n", GetLastError());
4438 
4439     SetLastError(0xdeadbeef);
4440     ret = InternetQueryOptionA(ses, INTERNET_OPTION_CONTEXT_VALUE, NULL, NULL);
4441     error = GetLastError();
4442     ok(!ret, "InternetQueryOption succeeded\n");
4443     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
4444 
4445     SetLastError(0xdeadbeef);
4446     ret = InternetQueryOptionA(ses, INTERNET_OPTION_CONTEXT_VALUE, &ctx, NULL);
4447     error = GetLastError();
4448     ok(!ret, "InternetQueryOption succeeded\n");
4449     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
4450 
4451     size = 0;
4452     SetLastError(0xdeadbeef);
4453     ret = InternetQueryOptionA(ses, INTERNET_OPTION_CONTEXT_VALUE, NULL, &size);
4454     error = GetLastError();
4455     ok(!ret, "InternetQueryOption succeeded\n");
4456     ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
4457 
4458     size = sizeof(ctx);
4459     SetLastError(0xdeadbeef);
4460     ret = InternetQueryOptionA(NULL, INTERNET_OPTION_CONTEXT_VALUE, &ctx, &size);
4461     error = GetLastError();
4462     ok(!ret, "InternetQueryOption succeeded\n");
4463     ok(error == ERROR_INTERNET_INCORRECT_HANDLE_TYPE, "expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %u\n", error);
4464 
4465     ctx = 0xdeadbeef;
4466     size = sizeof(ctx);
4467     ret = InternetQueryOptionA(ses, INTERNET_OPTION_CONTEXT_VALUE, &ctx, &size);
4468     ok(ret, "InternetQueryOption failed %u\n", GetLastError());
4469     ok(ctx == 1, "expected 1 got %lu\n", ctx);
4470 
4471     con = InternetConnectA(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
4472     ok(con != NULL, "InternetConnect failed\n");
4473 
4474     ctx = 0xdeadbeef;
4475     size = sizeof(ctx);
4476     ret = InternetQueryOptionA(con, INTERNET_OPTION_CONTEXT_VALUE, &ctx, &size);
4477     ok(ret, "InternetQueryOption failed %u\n", GetLastError());
4478     ok(ctx == 0, "expected 0 got %lu\n", ctx);
4479 
4480     ctx = 2;
4481     ret = InternetSetOptionA(con, INTERNET_OPTION_CONTEXT_VALUE, &ctx, sizeof(ctx));
4482     ok(ret, "InternetSetOption failed %u\n", GetLastError());
4483 
4484     ctx = 0xdeadbeef;
4485     size = sizeof(ctx);
4486     ret = InternetQueryOptionA(con, INTERNET_OPTION_CONTEXT_VALUE, &ctx, &size);
4487     ok(ret, "InternetQueryOption failed %u\n", GetLastError());
4488     ok(ctx == 2, "expected 2 got %lu\n", ctx);
4489 
4490     req = HttpOpenRequestA(con, NULL, "/test1", NULL, NULL, NULL, 0, 0);
4491     ok(req != NULL, "HttpOpenRequest failed\n");
4492 
4493     ctx = 0xdeadbeef;
4494     size = sizeof(ctx);
4495     ret = InternetQueryOptionA(req, INTERNET_OPTION_CONTEXT_VALUE, &ctx, &size);
4496     ok(ret, "InternetQueryOption failed %u\n", GetLastError());
4497     ok(ctx == 0, "expected 0 got %lu\n", ctx);
4498 
4499     ctx = 3;
4500     ret = InternetSetOptionA(req, INTERNET_OPTION_CONTEXT_VALUE, &ctx, sizeof(ctx));
4501     ok(ret, "InternetSetOption failed %u\n", GetLastError());
4502 
4503     ctx = 0xdeadbeef;
4504     size = sizeof(ctx);
4505     ret = InternetQueryOptionA(req, INTERNET_OPTION_CONTEXT_VALUE, &ctx, &size);
4506     ok(ret, "InternetQueryOption failed %u\n", GetLastError());
4507     ok(ctx == 3, "expected 3 got %lu\n", ctx);
4508 
4509     size = sizeof(idsi);
4510     ret = InternetQueryOptionA(req, INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO, &idsi, &size);
4511     ok(ret, "InternetQueryOption failed %u\n", GetLastError());
4512 
4513     size = 0;
4514     SetLastError(0xdeadbeef);
4515     ret = InternetQueryOptionA(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT, NULL, &size);
4516     error = GetLastError();
4517     ok(!ret, "InternetQueryOption succeeded\n");
4518     ok(error == ERROR_INTERNET_INVALID_OPERATION, "expected ERROR_INTERNET_INVALID_OPERATION, got %u\n", error);
4519 
4520     /* INTERNET_OPTION_PROXY */
4521     SetLastError(0xdeadbeef);
4522     ret = InternetQueryOptionA(ses, INTERNET_OPTION_PROXY, NULL, NULL);
4523     error = GetLastError();
4524     ok(!ret, "InternetQueryOption succeeded\n");
4525     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
4526 
4527     SetLastError(0xdeadbeef);
4528     ret = InternetQueryOptionA(ses, INTERNET_OPTION_PROXY, &ctx, NULL);
4529     error = GetLastError();
4530     ok(!ret, "InternetQueryOption succeeded\n");
4531     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
4532 
4533     size = 0;
4534     SetLastError(0xdeadbeef);
4535     ret = InternetQueryOptionA(ses, INTERNET_OPTION_PROXY, NULL, &size);
4536     error = GetLastError();
4537     ok(!ret, "InternetQueryOption succeeded\n");
4538     ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
4539     ok(size >= sizeof(INTERNET_PROXY_INFOA), "expected size to be greater or equal to the struct size\n");
4540 
4541     InternetCloseHandle(req);
4542     InternetCloseHandle(con);
4543     InternetCloseHandle(ses);
4544 }
4545 
4546 typedef struct {
4547     const char *response_text;
4548     int status_code;
4549     const char *status_text;
4550     const char *raw_headers;
4551 } http_status_test_t;
4552 
4553 static const http_status_test_t http_status_tests[] = {
4554     {
4555         "HTTP/1.1 200 OK\r\n"
4556         "Content-Length: 1\r\n"
4557         "\r\nx",
4558         200,
4559         "OK"
4560     },
4561     {
4562         "HTTP/1.1 404 Fail\r\n"
4563         "Content-Length: 1\r\n"
4564         "\r\nx",
4565         404,
4566         "Fail"
4567     },
4568     {
4569         "HTTP/1.1 200\r\n"
4570         "Content-Length: 1\r\n"
4571         "\r\nx",
4572         200,
4573         ""
4574     },
4575     {
4576         "HTTP/1.1 410 \r\n"
4577         "Content-Length: 1\r\n"
4578         "\r\nx",
4579         410,
4580         ""
4581     }
4582 };
4583 
4584 static void test_http_status(int port)
4585 {
4586     test_request_t req;
4587     char buf[1000];
4588     DWORD i, size;
4589     BOOL res;
4590 
4591     for(i = 0; i < ARRAY_SIZE(http_status_tests); i++) {
4592         send_buffer = http_status_tests[i].response_text;
4593 
4594         open_simple_request(&req, "localhost", port, NULL, "/send_from_buffer");
4595 
4596         res = HttpSendRequestA(req.request, NULL, 0, NULL, 0);
4597         ok(res, "HttpSendRequest failed\n");
4598 
4599         test_status_code(req.request, http_status_tests[i].status_code);
4600 
4601         size = sizeof(buf);
4602         res = HttpQueryInfoA(req.request, HTTP_QUERY_STATUS_TEXT, buf, &size, NULL);
4603         ok(res, "HttpQueryInfo failed: %u\n", GetLastError());
4604         ok(!strcmp(buf, http_status_tests[i].status_text), "[%u] Unexpected status text \"%s\", expected \"%s\"\n",
4605            i, buf, http_status_tests[i].status_text);
4606 
4607         close_request(&req);
4608     }
4609 }
4610 
4611 static void test_cache_control_verb(int port)
4612 {
4613     HINTERNET session, connect, request;
4614     BOOL ret;
4615 
4616     session = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
4617     ok(session != NULL, "InternetOpen failed\n");
4618 
4619     connect = InternetConnectA(session, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
4620     ok(connect != NULL, "InternetConnect failed\n");
4621 
4622     request = HttpOpenRequestA(connect, "RPC_OUT_DATA", "/test_cache_control_verb", NULL, NULL, NULL,
4623                               INTERNET_FLAG_NO_CACHE_WRITE, 0);
4624     ok(request != NULL, "HttpOpenRequest failed\n");
4625     ret = HttpSendRequestA(request, NULL, 0, NULL, 0);
4626     ok(ret, "HttpSendRequest failed %u\n", GetLastError());
4627     test_status_code(request, 200);
4628     InternetCloseHandle(request);
4629 
4630     request = HttpOpenRequestA(connect, "POST", "/test_cache_control_verb", NULL, NULL, NULL,
4631                               INTERNET_FLAG_NO_CACHE_WRITE, 0);
4632     ok(request != NULL, "HttpOpenRequest failed\n");
4633     ret = HttpSendRequestA(request, NULL, 0, NULL, 0);
4634     ok(ret, "HttpSendRequest failed %u\n", GetLastError());
4635     test_status_code(request, 200);
4636     InternetCloseHandle(request);
4637 
4638     request = HttpOpenRequestA(connect, "HEAD", "/test_cache_control_verb", NULL, NULL, NULL,
4639                               INTERNET_FLAG_NO_CACHE_WRITE, 0);
4640     ok(request != NULL, "HttpOpenRequest failed\n");
4641     ret = HttpSendRequestA(request, NULL, 0, NULL, 0);
4642     ok(ret, "HttpSendRequest failed %u\n", GetLastError());
4643     test_status_code(request, 200);
4644     InternetCloseHandle(request);
4645 
4646     request = HttpOpenRequestA(connect, "GET", "/test_cache_control_verb", NULL, NULL, NULL,
4647                               INTERNET_FLAG_NO_CACHE_WRITE, 0);
4648     ok(request != NULL, "HttpOpenRequest failed\n");
4649     ret = HttpSendRequestA(request, NULL, 0, NULL, 0);
4650     ok(ret, "HttpSendRequest failed %u\n", GetLastError());
4651     test_status_code(request, 200);
4652     InternetCloseHandle(request);
4653 
4654     InternetCloseHandle(connect);
4655     InternetCloseHandle(session);
4656 }
4657 
4658 static void test_request_content_length(int port)
4659 {
4660     char data[] = {'t','e','s','t'};
4661     test_request_t req;
4662     BOOL ret;
4663 
4664     reset_events();
4665     open_simple_request(&req, "localhost", port, "POST", "/test_request_content_length");
4666 
4667     ret = HttpSendRequestA(req.request, NULL, 0, NULL, 0);
4668     ok(ret, "HttpSendRequest failed %u\n", GetLastError());
4669     test_status_code(req.request, 200);
4670 
4671     SetEvent(complete_event);
4672 
4673     ret = HttpSendRequestA(req.request, NULL, 0, data, sizeof(data));
4674     ok(ret, "HttpSendRequest failed %u\n", GetLastError());
4675     test_status_code(req.request, 200);
4676 
4677     SetEvent(complete_event);
4678     close_request(&req);
4679 }
4680 
4681 static void test_accept_encoding(int port)
4682 {
4683     HINTERNET ses, con, req;
4684     char buf[1000];
4685     BOOL ret;
4686 
4687     ses = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
4688     ok(ses != NULL, "InternetOpen failed\n");
4689 
4690     con = InternetConnectA(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
4691     ok(con != NULL, "InternetConnect failed\n");
4692 
4693     req = HttpOpenRequestA(con, "GET", "/echo_request", "HTTP/1.0", NULL, NULL, 0, 0);
4694     ok(req != NULL, "HttpOpenRequest failed\n");
4695 
4696     ret = HttpAddRequestHeadersA(req, "Accept-Encoding: gzip\r\n", ~0u, HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD);
4697     ok(ret, "HttpAddRequestHeaders failed\n");
4698 
4699     ret = HttpSendRequestA(req, NULL,  0, NULL, 0);
4700     ok(ret, "HttpSendRequestA failed\n");
4701 
4702     test_status_code(req, 200);
4703     receive_simple_request(req, buf, sizeof(buf));
4704     ok(strstr(buf, "Accept-Encoding: gzip") != NULL, "Accept-Encoding header not found in %s\n", buf);
4705 
4706     InternetCloseHandle(req);
4707 
4708     req = HttpOpenRequestA(con, "GET", "/echo_request", "HTTP/1.0", NULL, NULL, 0, 0);
4709     ok(req != NULL, "HttpOpenRequest failed\n");
4710 
4711     ret = HttpSendRequestA(req, "Accept-Encoding: gzip", ~0u, NULL, 0);
4712     ok(ret, "HttpSendRequestA failed\n");
4713 
4714     test_status_code(req, 200);
4715     receive_simple_request(req, buf, sizeof(buf));
4716     ok(strstr(buf, "Accept-Encoding: gzip") != NULL, "Accept-Encoding header not found in %s\n", buf);
4717 
4718     InternetCloseHandle(req);
4719     InternetCloseHandle(con);
4720     InternetCloseHandle(ses);
4721 }
4722 
4723 static void test_basic_auth_credentials_reuse(int port)
4724 {
4725     HINTERNET ses, con, req;
4726     DWORD status, size;
4727     BOOL ret;
4728     char buffer[0x40];
4729 
4730     ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 );
4731     ok( ses != NULL, "InternetOpenA failed\n" );
4732 
4733     con = InternetConnectA( ses, "localhost", port, "user", "pwd",
4734                             INTERNET_SERVICE_HTTP, 0, 0 );
4735     ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
4736 
4737     req = HttpOpenRequestA( con, "HEAD", "/upload.txt", NULL, NULL, NULL, 0, 0 );
4738     ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
4739 
4740     ret = HttpSendRequestA( req, NULL, 0, NULL, 0 );
4741     ok( ret, "HttpSendRequestA failed %u\n", GetLastError() );
4742 
4743     size = sizeof(buffer);
4744     SetLastError(0xdeadbeef);
4745     ret = InternetQueryOptionA(req, INTERNET_OPTION_USERNAME, buffer, &size);
4746     ok(ret, "unexpected failure %u\n", GetLastError());
4747     ok(!strcmp(buffer, "user"), "got %s\n", buffer);
4748     ok(size == 4, "got %u\n", size);
4749 
4750     size = sizeof(buffer);
4751     SetLastError(0xdeadbeef);
4752     ret = InternetQueryOptionA(req, INTERNET_OPTION_PASSWORD, buffer, &size);
4753     ok(ret, "unexpected failure %u\n", GetLastError());
4754     ok(!strcmp(buffer, "pwd"), "got %s\n", buffer);
4755     ok(size == 3, "got %u\n", size);
4756 
4757     status = 0xdeadbeef;
4758     size = sizeof(status);
4759     ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
4760     ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() );
4761     ok( status == 200, "got %u\n", status );
4762 
4763     InternetCloseHandle( req );
4764     InternetCloseHandle( con );
4765     InternetCloseHandle( ses );
4766 
4767     ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 );
4768     ok( ses != NULL, "InternetOpenA failed\n" );
4769 
4770     con = InternetConnectA( ses, "localhost", port, NULL, NULL,
4771                             INTERNET_SERVICE_HTTP, 0, 0 );
4772     ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
4773 
4774     req = HttpOpenRequestA( con, "PUT", "/upload2.txt", NULL, NULL, NULL, 0, 0 );
4775     ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
4776 
4777     ret = HttpSendRequestA( req, NULL, 0, NULL, 0 );
4778     ok( ret, "HttpSendRequestA failed %u\n", GetLastError() );
4779 
4780     size = sizeof(buffer);
4781     SetLastError(0xdeadbeef);
4782     ret = InternetQueryOptionA(req, INTERNET_OPTION_USERNAME, buffer, &size);
4783     ok(ret, "unexpected failure %u\n", GetLastError());
4784     ok(!strcmp(buffer, "user"), "got %s\n", buffer);
4785     ok(size == 4, "got %u\n", size);
4786 
4787     size = sizeof(buffer);
4788     SetLastError(0xdeadbeef);
4789     ret = InternetQueryOptionA(req, INTERNET_OPTION_PASSWORD, buffer, &size);
4790     ok(ret, "unexpected failure %u\n", GetLastError());
4791     ok(!strcmp(buffer, "pwd"), "got %s\n", buffer);
4792     ok(size == 3, "got %u\n", size);
4793 
4794     status = 0xdeadbeef;
4795     size = sizeof(status);
4796     ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
4797     ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() );
4798     ok( status == 200, "got %u\n", status );
4799 
4800     InternetCloseHandle( req );
4801     InternetCloseHandle( con );
4802     InternetCloseHandle( ses );
4803 }
4804 
4805 static void test_basic_auth_credentials_end_session(int port)
4806 {
4807     HINTERNET ses, con, req;
4808     DWORD status, size;
4809     BOOL ret;
4810     char buffer[0x40];
4811 
4812     ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 );
4813     ok( ses != NULL, "InternetOpenA failed\n" );
4814 
4815     con = InternetConnectA( ses, "localhost", port, "user", "pwd",
4816                             INTERNET_SERVICE_HTTP, 0, 0 );
4817     ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
4818 
4819     req = HttpOpenRequestA( con, "HEAD", "/upload.txt", NULL, NULL, NULL, 0, 0 );
4820     ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
4821 
4822     ret = HttpSendRequestA( req, NULL, 0, NULL, 0 );
4823     ok( ret, "HttpSendRequestA failed %u\n", GetLastError() );
4824 
4825     size = sizeof(buffer);
4826     SetLastError(0xdeadbeef);
4827     ret = InternetQueryOptionA(req, INTERNET_OPTION_USERNAME, buffer, &size);
4828     ok(ret, "unexpected failure %u\n", GetLastError());
4829     ok(!strcmp(buffer, "user"), "got %s\n", buffer);
4830     ok(size == 4, "got %u\n", size);
4831 
4832     size = sizeof(buffer);
4833     SetLastError(0xdeadbeef);
4834     ret = InternetQueryOptionA(req, INTERNET_OPTION_PASSWORD, buffer, &size);
4835     ok(ret, "unexpected failure %u\n", GetLastError());
4836     ok(!strcmp(buffer, "pwd"), "got %s\n", buffer);
4837     ok(size == 3, "got %u\n", size);
4838 
4839     status = 0xdeadbeef;
4840     size = sizeof(status);
4841     ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
4842     ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() );
4843     ok( status == HTTP_STATUS_OK, "got %u\n", status );
4844 
4845     InternetCloseHandle( req );
4846     InternetCloseHandle( con );
4847     InternetCloseHandle( ses );
4848 
4849     ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 );
4850     ok( ses != NULL, "InternetOpenA failed\n" );
4851 
4852     /* Clear the cached credentials */
4853     ret = InternetSetOptionA(ses,  INTERNET_OPTION_END_BROWSER_SESSION, NULL, 0);
4854     ok(ret, "unexpected failure %u\n", GetLastError());
4855 
4856     con = InternetConnectA( ses, "localhost", port, NULL, NULL,
4857                             INTERNET_SERVICE_HTTP, 0, 0 );
4858     ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
4859 
4860     req = HttpOpenRequestA( con, "PUT", "/upload2.txt", NULL, NULL, NULL, 0, 0 );
4861     ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
4862 
4863     ret = HttpSendRequestA( req, NULL, 0, NULL, 0 );
4864     ok( ret, "HttpSendRequestA failed %u\n", GetLastError() );
4865 
4866     size = sizeof(buffer);
4867     SetLastError(0xdeadbeef);
4868     ret = InternetQueryOptionA(req, INTERNET_OPTION_USERNAME, buffer, &size);
4869     ok(ret, "unexpected failure %u\n", GetLastError());
4870     ok(!strcmp(buffer, ""), "got %s\n", buffer);
4871     ok(size == 0, "got %u\n", size);
4872 
4873     size = sizeof(buffer);
4874     SetLastError(0xdeadbeef);
4875     ret = InternetQueryOptionA(req, INTERNET_OPTION_PASSWORD, buffer, &size);
4876     ok(ret, "unexpected failure %u\n", GetLastError());
4877     ok(!strcmp(buffer, ""), "got %s\n", buffer);
4878     ok(size == 0, "got %u\n", size);
4879 
4880     status = 0xdeadbeef;
4881     size = sizeof(status);
4882     ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
4883     ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() );
4884     ok( status == HTTP_STATUS_BAD_REQUEST, "got %u\n", status );
4885 
4886     InternetCloseHandle( req );
4887     InternetCloseHandle( con );
4888     InternetCloseHandle( ses );
4889 }
4890 
4891 static void test_basic_auth_credentials_different(int port)
4892 {
4893     HINTERNET ses, con, req;
4894     DWORD status, size;
4895     BOOL ret;
4896     char buffer[0x40];
4897 
4898     ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 );
4899     ok( ses != NULL, "InternetOpenA failed\n" );
4900 
4901     con = InternetConnectA( ses, "localhost", port, "user", "pwd",
4902                             INTERNET_SERVICE_HTTP, 0, 0 );
4903     ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
4904 
4905     req = HttpOpenRequestA( con, "HEAD", "/upload.txt", NULL, NULL, NULL, 0, 0 );
4906     ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
4907 
4908     ret = HttpSendRequestA( req, NULL, 0, NULL, 0 );
4909     ok( ret, "HttpSendRequestA failed %u\n", GetLastError() );
4910 
4911     size = sizeof(buffer);
4912     SetLastError(0xdeadbeef);
4913     ret = InternetQueryOptionA(req, INTERNET_OPTION_USERNAME, buffer, &size);
4914     ok(ret, "unexpected failure %u\n", GetLastError());
4915     ok(!strcmp(buffer, "user"), "got %s\n", buffer);
4916     ok(size == 4, "got %u\n", size);
4917 
4918     size = sizeof(buffer);
4919     SetLastError(0xdeadbeef);
4920     ret = InternetQueryOptionA(req, INTERNET_OPTION_PASSWORD, buffer, &size);
4921     ok(ret, "unexpected failure %u\n", GetLastError());
4922     ok(!strcmp(buffer, "pwd"), "got %s\n", buffer);
4923     ok(size == 3, "got %u\n", size);
4924 
4925     status = 0xdeadbeef;
4926     size = sizeof(status);
4927     ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
4928     ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() );
4929     ok( status == 200, "got %u\n", status );
4930 
4931     InternetCloseHandle( req );
4932     InternetCloseHandle( con );
4933     InternetCloseHandle( ses );
4934 
4935     ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 );
4936     ok( ses != NULL, "InternetOpenA failed\n" );
4937 
4938     con = InternetConnectA( ses, "localhost", port, "user1", "pwd1",
4939                             INTERNET_SERVICE_HTTP, 0, 0 );
4940     ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
4941 
4942     req = HttpOpenRequestA( con, "HEAD", "/upload3.txt", NULL, NULL, NULL, 0, 0 );
4943     ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
4944 
4945     ret = HttpSendRequestA( req, NULL, 0, NULL, 0 );
4946     ok( ret, "HttpSendRequestA failed %u\n", GetLastError() );
4947 
4948     size = sizeof(buffer);
4949     SetLastError(0xdeadbeef);
4950     ret = InternetQueryOptionA(req, INTERNET_OPTION_USERNAME, buffer, &size);
4951     ok(ret, "unexpected failure %u\n", GetLastError());
4952     ok(!strcmp(buffer, "user1"), "got %s\n", buffer);
4953     ok(size == 5, "got %u\n", size);
4954 
4955     size = sizeof(buffer);
4956     SetLastError(0xdeadbeef);
4957     ret = InternetQueryOptionA(req, INTERNET_OPTION_PASSWORD, buffer, &size);
4958     ok(ret, "unexpected failure %u\n", GetLastError());
4959     ok(!strcmp(buffer, "pwd1"), "got %s\n", buffer);
4960     ok(size == 4, "got %u\n", size);
4961 
4962     status = 0xdeadbeef;
4963     size = sizeof(status);
4964     ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
4965     ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() );
4966     ok( status == 200, "got %u\n", status );
4967 
4968     InternetCloseHandle( req );
4969     InternetCloseHandle( con );
4970     InternetCloseHandle( ses );
4971 }
4972 
4973 /*
4974  * Manually set the Authorization for both calls.
4975  */
4976 static void test_basic_auth_credentials_manual(int port)
4977 {
4978     HINTERNET ses, con, req;
4979     DWORD status, size;
4980     BOOL ret;
4981 
4982     ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 );
4983     ok( ses != NULL, "InternetOpenA failed\n" );
4984 
4985     /* Clear the cached credentials */
4986     ret = InternetSetOptionA(ses,  INTERNET_OPTION_END_BROWSER_SESSION, NULL, 0);
4987     ok(ret, "unexpected failure %u\n", GetLastError());
4988 
4989     con = InternetConnectA( ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0 );
4990     ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
4991 
4992     req = HttpOpenRequestA( con, "HEAD", "/upload.txt", NULL, NULL, NULL, 0, 0 );
4993     ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
4994 
4995     /* Set Authorization Header */
4996     ret = HttpAddRequestHeadersA(req, "Authorization: Basic dXNlcjpwd2Q=\r\n", ~0u,
4997                             HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD);
4998     ok(ret, "HttpAddRequestHeaders Failed\n");
4999 
5000     ret = HttpSendRequestA( req, NULL, 0, NULL, 0 );
5001     ok( ret, "HttpSendRequestA failed %u\n", GetLastError() );
5002 
5003     status = 0xdeadbeef;
5004     size = sizeof(status);
5005     ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
5006     ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() );
5007     ok( status == 200, "got %u\n", status );
5008 
5009     InternetCloseHandle( req );
5010     InternetCloseHandle( con );
5011     InternetCloseHandle( ses );
5012 
5013     /* Show manual headers are cached. */
5014     ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 );
5015     ok( ses != NULL, "InternetOpenA failed\n" );
5016 
5017     con = InternetConnectA( ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0 );
5018     ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
5019 
5020     req = HttpOpenRequestA( con, "HEAD", "/upload.txt", NULL, NULL, NULL, 0, 0 );
5021     ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
5022 
5023     ret = HttpSendRequestA( req, NULL, 0, NULL, 0 );
5024     ok( ret, "HttpSendRequestA failed %u\n", GetLastError() );
5025 
5026     status = 0xdeadbeef;
5027     size = sizeof(status);
5028     ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
5029     ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() );
5030     ok( status == 401, "got %u\n", status );
5031 
5032     InternetCloseHandle( req );
5033     InternetCloseHandle( con );
5034     InternetCloseHandle( ses );
5035 
5036     ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 );
5037     ok( ses != NULL, "InternetOpenA failed\n" );
5038 
5039     con = InternetConnectA( ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0 );
5040     ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
5041 
5042     req = HttpOpenRequestA( con, "HEAD", "/upload4.txt", NULL, NULL, NULL, 0, 0 );
5043     ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
5044 
5045     /* Set Authorization Header */
5046     ret = HttpAddRequestHeadersA(req, "Authorization: Bearer dXNlcjE6cHdkMQ==\r\n", ~0u,
5047                             HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD);
5048     ok(ret, "HttpAddRequestHeaders Failed\n");
5049 
5050     ret = HttpSendRequestA( req, NULL, 0, NULL, 0 );
5051     ok( ret, "HttpSendRequestA failed %u\n", GetLastError() );
5052 
5053     status = 0xdeadbeef;
5054     size = sizeof(status);
5055     ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
5056     ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() );
5057     ok( status == 200, "got %u\n", status );
5058 
5059     InternetCloseHandle( req );
5060     InternetCloseHandle( con );
5061     InternetCloseHandle( ses );
5062 }
5063 
5064 /*
5065  * Manually set the Authorization for the bearer call, which shows the cached is used.
5066  */
5067 static void test_basic_auth_credentials_cached_manual(int port)
5068 {
5069     HINTERNET ses, con, req;
5070     DWORD status, size;
5071     BOOL ret;
5072 
5073     ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 );
5074     ok( ses != NULL, "InternetOpenA failed\n" );
5075 
5076     /* Clear the cached credentials */
5077     ret = InternetSetOptionA(ses,  INTERNET_OPTION_END_BROWSER_SESSION, NULL, 0);
5078     ok(ret, "unexpected failure %u\n", GetLastError());
5079 
5080      con = InternetConnectA( ses, "localhost", port, "user", "pwd",
5081                             INTERNET_SERVICE_HTTP, 0, 0 );
5082     ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
5083 
5084     req = HttpOpenRequestA( con, "HEAD", "/upload.txt", NULL, NULL, NULL, 0, 0 );
5085     ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
5086 
5087     ret = HttpSendRequestA( req, NULL, 0, NULL, 0 );
5088     ok( ret, "HttpSendRequestA failed %u\n", GetLastError() );
5089 
5090     status = 0xdeadbeef;
5091     size = sizeof(status);
5092     ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
5093     ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() );
5094     ok( status == 200, "got %u\n", status );
5095 
5096     InternetCloseHandle( req );
5097     InternetCloseHandle( con );
5098     InternetCloseHandle( ses );
5099 
5100     ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 );
5101     ok( ses != NULL, "InternetOpenA failed\n" );
5102 
5103     con = InternetConnectA( ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0 );
5104     ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
5105 
5106     req = HttpOpenRequestA( con, "HEAD", "/upload4.txt", NULL, NULL, NULL, 0, 0 );
5107     ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
5108 
5109     /* Setting an Authorization Header doesn't override the cached one. */
5110     ret = HttpAddRequestHeadersA(req, "Authorization: Bearer dXNlcjE6cHdkMQ==\r\n", ~0u,
5111                             HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD);
5112     ok(ret, "HttpAddRequestHeaders Failed\n");
5113 
5114     ret = HttpSendRequestA( req, NULL, 0, NULL, 0 );
5115     ok( ret, "HttpSendRequestA failed %u\n", GetLastError() );
5116 
5117     status = 0xdeadbeef;
5118     size = sizeof(status);
5119     ret = HttpQueryInfoA( req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
5120     ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() );
5121     ok( status == 201, "got %u\n", status );
5122 
5123     InternetCloseHandle( req );
5124     InternetCloseHandle( con );
5125     InternetCloseHandle( ses );
5126 }
5127 
5128 static void test_async_read(int port)
5129 {
5130     HINTERNET ses, con, req;
5131     INTERNET_BUFFERSA ib;
5132     char buffer[0x100];
5133     DWORD pending_reads;
5134     DWORD res, count, bytes;
5135     BOOL ret;
5136 
5137     reset_events();
5138 
5139     /* test asynchronous InternetReadFileEx */
5140     ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, INTERNET_FLAG_ASYNC );
5141     ok( ses != NULL, "InternetOpenA failed\n" );
5142     pInternetSetStatusCallbackA( ses, &callback );
5143 
5144     SET_EXPECT( INTERNET_STATUS_HANDLE_CREATED );
5145     con = InternetConnectA( ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0xdeadbeef );
5146     ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
5147     CHECK_NOTIFIED( INTERNET_STATUS_HANDLE_CREATED );
5148 
5149     SET_EXPECT( INTERNET_STATUS_HANDLE_CREATED );
5150     req = HttpOpenRequestA( con, "GET", "/async_read", NULL, NULL, NULL, INTERNET_FLAG_RELOAD, 0xdeadbeef );
5151     ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
5152     CHECK_NOTIFIED( INTERNET_STATUS_HANDLE_CREATED );
5153 
5154     SET_OPTIONAL( INTERNET_STATUS_COOKIE_SENT );
5155     SET_OPTIONAL( INTERNET_STATUS_DETECTING_PROXY );
5156     SET_EXPECT( INTERNET_STATUS_CONNECTING_TO_SERVER );
5157     SET_EXPECT( INTERNET_STATUS_CONNECTED_TO_SERVER );
5158     SET_EXPECT( INTERNET_STATUS_SENDING_REQUEST );
5159     SET_EXPECT( INTERNET_STATUS_REQUEST_SENT );
5160     SET_EXPECT( INTERNET_STATUS_RECEIVING_RESPONSE );
5161     SET_EXPECT( INTERNET_STATUS_RESPONSE_RECEIVED );
5162     SET_OPTIONAL( INTERNET_STATUS_CLOSING_CONNECTION );
5163     SET_OPTIONAL( INTERNET_STATUS_CONNECTION_CLOSED );
5164     SET_EXPECT( INTERNET_STATUS_REQUEST_COMPLETE );
5165 
5166     SetLastError( 0xdeadbeef );
5167     ret = HttpSendRequestA( req, NULL, 0, NULL, 0 );
5168     ok( !ret, "HttpSendRequestA unexpectedly succeeded\n" );
5169     ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
5170     WaitForSingleObject( complete_event, INFINITE );
5171     ok( req_error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", req_error );
5172 
5173     CLEAR_NOTIFIED( INTERNET_STATUS_COOKIE_SENT );
5174     CLEAR_NOTIFIED( INTERNET_STATUS_DETECTING_PROXY );
5175     CHECK_NOTIFIED( INTERNET_STATUS_CONNECTING_TO_SERVER );
5176     CHECK_NOTIFIED( INTERNET_STATUS_CONNECTED_TO_SERVER );
5177     CHECK_NOTIFIED( INTERNET_STATUS_SENDING_REQUEST );
5178     CHECK_NOTIFIED( INTERNET_STATUS_REQUEST_SENT );
5179     CHECK_NOTIFIED( INTERNET_STATUS_RECEIVING_RESPONSE );
5180     CHECK_NOTIFIED( INTERNET_STATUS_RESPONSE_RECEIVED );
5181     CLEAR_NOTIFIED( INTERNET_STATUS_CLOSING_CONNECTION );
5182     CLEAR_NOTIFIED( INTERNET_STATUS_CONNECTION_CLOSED );
5183     CHECK_NOTIFIED( INTERNET_STATUS_REQUEST_COMPLETE );
5184 
5185     pending_reads = 0;
5186     memset( &ib, 0, sizeof(ib) );
5187     memset( buffer, 0, sizeof(buffer) );
5188     ib.dwStructSize = sizeof(ib);
5189     for (count = 0; count < sizeof(buffer); count += ib.dwBufferLength)
5190     {
5191         ib.lpvBuffer = buffer + count;
5192         ib.dwBufferLength = min(16, sizeof(buffer) - count);
5193 
5194         SET_EXPECT( INTERNET_STATUS_RECEIVING_RESPONSE );
5195         SET_EXPECT( INTERNET_STATUS_RESPONSE_RECEIVED );
5196 
5197         ret = InternetReadFileExA( req, &ib, 0, 0xdeadbeef );
5198         if (!count) /* the first part should arrive immediately */
5199             ok( ret, "InternetReadFileExA failed %u\n", GetLastError() );
5200         ros_skip_flaky
5201         if (!ret)
5202         {
5203             ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
5204             ros_skip_flaky
5205             CHECK_NOTIFIED( INTERNET_STATUS_RECEIVING_RESPONSE );
5206             SET_EXPECT( INTERNET_STATUS_REQUEST_COMPLETE );
5207             if (!pending_reads++)
5208             {
5209                 res = WaitForSingleObject( complete_event, 0 );
5210                 ok( res == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", res );
5211                 SetEvent( conn_wait_event );
5212             }
5213             res = WaitForSingleObject( complete_event, INFINITE );
5214             ok( res == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", res );
5215             ok( req_error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", req_error );
5216             todo_wine_if( pending_reads > 1 )
5217             ok( ib.dwBufferLength != 0, "expected ib.dwBufferLength != 0\n" );
5218             CHECK_NOTIFIED( INTERNET_STATUS_RESPONSE_RECEIVED );
5219             CHECK_NOTIFIED( INTERNET_STATUS_REQUEST_COMPLETE );
5220         }
5221 
5222         CLEAR_NOTIFIED( INTERNET_STATUS_RECEIVING_RESPONSE );
5223         CLEAR_NOTIFIED( INTERNET_STATUS_RESPONSE_RECEIVED );
5224         if (!ib.dwBufferLength) break;
5225     }
5226 
5227     ok( pending_reads == 1, "expected 1 pending read, got %u\n", pending_reads );
5228     ok( !strcmp(buffer, page1), "unexpected buffer content\n" );
5229     close_async_handle( ses, 2 );
5230     ResetEvent( conn_wait_event );
5231 
5232     /* test asynchronous InternetReadFile */
5233     ses = InternetOpenA( "winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, INTERNET_FLAG_ASYNC );
5234     ok( ses != NULL, "InternetOpenA failed\n" );
5235     pInternetSetStatusCallbackA( ses, &callback );
5236 
5237     SET_EXPECT( INTERNET_STATUS_HANDLE_CREATED );
5238     con = InternetConnectA( ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0xdeadbeef );
5239     ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
5240     CHECK_NOTIFIED( INTERNET_STATUS_HANDLE_CREATED );
5241 
5242     SET_EXPECT( INTERNET_STATUS_HANDLE_CREATED );
5243     req = HttpOpenRequestA( con, "GET", "/async_read", NULL, NULL, NULL, INTERNET_FLAG_RELOAD, 0xdeadbeef );
5244     ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
5245     CHECK_NOTIFIED( INTERNET_STATUS_HANDLE_CREATED );
5246 
5247     SET_OPTIONAL( INTERNET_STATUS_COOKIE_SENT );
5248     SET_OPTIONAL( INTERNET_STATUS_DETECTING_PROXY );
5249     SET_EXPECT( INTERNET_STATUS_CONNECTING_TO_SERVER );
5250     SET_EXPECT( INTERNET_STATUS_CONNECTED_TO_SERVER );
5251     SET_EXPECT( INTERNET_STATUS_SENDING_REQUEST );
5252     SET_EXPECT( INTERNET_STATUS_REQUEST_SENT );
5253     SET_EXPECT( INTERNET_STATUS_RECEIVING_RESPONSE );
5254     SET_EXPECT( INTERNET_STATUS_RESPONSE_RECEIVED );
5255     SET_OPTIONAL( INTERNET_STATUS_CLOSING_CONNECTION );
5256     SET_OPTIONAL( INTERNET_STATUS_CONNECTION_CLOSED );
5257     SET_EXPECT( INTERNET_STATUS_REQUEST_COMPLETE );
5258 
5259     SetLastError( 0xdeadbeef );
5260     ret = HttpSendRequestA( req, NULL, 0, NULL, 0 );
5261     ok( !ret, "HttpSendRequestA unexpectedly succeeded\n" );
5262     ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
5263     WaitForSingleObject( complete_event, INFINITE );
5264     ok( req_error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", req_error );
5265 
5266     CLEAR_NOTIFIED( INTERNET_STATUS_COOKIE_SENT );
5267     CLEAR_NOTIFIED( INTERNET_STATUS_DETECTING_PROXY );
5268     CHECK_NOTIFIED( INTERNET_STATUS_CONNECTING_TO_SERVER );
5269     CHECK_NOTIFIED( INTERNET_STATUS_CONNECTED_TO_SERVER );
5270     CHECK_NOTIFIED( INTERNET_STATUS_SENDING_REQUEST );
5271     CHECK_NOTIFIED( INTERNET_STATUS_REQUEST_SENT );
5272     CHECK_NOTIFIED( INTERNET_STATUS_RECEIVING_RESPONSE );
5273     CHECK_NOTIFIED( INTERNET_STATUS_RESPONSE_RECEIVED );
5274     CLEAR_NOTIFIED( INTERNET_STATUS_CLOSING_CONNECTION );
5275     CLEAR_NOTIFIED( INTERNET_STATUS_CONNECTION_CLOSED );
5276     CHECK_NOTIFIED( INTERNET_STATUS_REQUEST_COMPLETE );
5277 
5278     pending_reads = 0;
5279     memset( buffer, 0, sizeof(buffer) );
5280     for (count = 0; count < sizeof(buffer); count += bytes)
5281     {
5282         SET_EXPECT( INTERNET_STATUS_RECEIVING_RESPONSE );
5283         SET_EXPECT( INTERNET_STATUS_RESPONSE_RECEIVED );
5284 
5285         bytes = 0xdeadbeef;
5286         ret = InternetReadFile( req, buffer + count, min(16, sizeof(buffer) - count), &bytes );
5287         if (!count) /* the first part should arrive immediately */
5288             ok( ret, "InternetReadFile failed %u\n", GetLastError() );
5289         if (!ret)
5290         {
5291             ok( GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError() );
5292             ok( bytes == 0, "expected 0, got %u\n", bytes );
5293             ros_skip_flaky
5294             CHECK_NOTIFIED( INTERNET_STATUS_RECEIVING_RESPONSE );
5295             SET_EXPECT( INTERNET_STATUS_REQUEST_COMPLETE );
5296             if (!pending_reads++)
5297             {
5298                 res = WaitForSingleObject( complete_event, 0 );
5299                 ok( res == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", res );
5300                 SetEvent( conn_wait_event );
5301             }
5302             res = WaitForSingleObject( complete_event, INFINITE );
5303             ok( res == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", res );
5304             ok( req_error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", req_error );
5305             ros_skip_flaky {
5306             todo_wine_if( pending_reads > 1 )
5307             ok( bytes != 0, "expected bytes != 0\n" );
5308             }
5309             ros_skip_flaky
5310             CHECK_NOTIFIED( INTERNET_STATUS_RESPONSE_RECEIVED );
5311             ros_skip_flaky
5312             CHECK_NOTIFIED( INTERNET_STATUS_REQUEST_COMPLETE );
5313         }
5314 
5315         CLEAR_NOTIFIED( INTERNET_STATUS_RECEIVING_RESPONSE );
5316         CLEAR_NOTIFIED( INTERNET_STATUS_RESPONSE_RECEIVED );
5317         if (!bytes) break;
5318     }
5319 
5320     ros_skip_flaky
5321     ok( pending_reads == 1, "expected 1 pending read, got %u\n", pending_reads );
5322     ok( !strcmp(buffer, page1), "unexpected buffer content\n" );
5323     close_async_handle( ses, 2 );
5324 }
5325 
5326 static void server_send_string(const char *msg)
5327 {
5328     send(server_socket, msg, strlen(msg), 0);
5329 }
5330 
5331 static size_t server_read_data(char *buf, size_t buf_size)
5332 {
5333     return recv(server_socket, buf, buf_size, 0);
5334 }
5335 
5336 #define server_read_request(a) _server_read_request(__LINE__,a)
5337 static void _server_read_request(unsigned line, const char *expected_request)
5338 {
5339     char buf[4000], *p;
5340     size_t size;
5341 
5342     size = server_read_data(buf, sizeof(buf) - 1);
5343     buf[size] = 0;
5344     p = strstr(buf, "\r\n");
5345     if(p) *p = 0;
5346     ok_(__FILE__,line)(p && !strcmp(buf, expected_request), "unexpected request %s\n", buf);
5347 }
5348 
5349 static BOOL skip_receive_notification_tests;
5350 static DWORD received_response_size;
5351 
5352 static void WINAPI readex_callback(HINTERNET handle, DWORD_PTR context, DWORD status, void *info, DWORD info_size)
5353 {
5354     switch(status) {
5355     case INTERNET_STATUS_RECEIVING_RESPONSE:
5356         if(!skip_receive_notification_tests)
5357             callback(handle, context, status, info, info_size);
5358         break;
5359     case INTERNET_STATUS_RESPONSE_RECEIVED:
5360         if(!skip_receive_notification_tests)
5361             callback(handle, context, status, info, info_size);
5362         received_response_size = *(DWORD*)info;
5363         break;
5364     case INTERNET_STATUS_REQUEST_SENT:
5365         callback(handle, context, status, info, info_size);
5366         SetEvent(request_sent_event);
5367         break;
5368     default:
5369         callback(handle, context, status, info, info_size);
5370     }
5371 }
5372 
5373 static void send_socket_request(test_request_t *req, BOOL new_connection)
5374 {
5375     BOOL ret;
5376 
5377     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
5378     SET_OPTIONAL(INTERNET_STATUS_DETECTING_PROXY);
5379     if(new_connection) {
5380         SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
5381         SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
5382     }
5383     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
5384     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
5385     if(!skip_receive_notification_tests)
5386         SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
5387 
5388     SetLastError(0xdeadbeef);
5389     ret = HttpSendRequestA(req->request, NULL, 0, NULL, 0);
5390     ok(!ret, "HttpSendRequestA unexpectedly succeeded\n");
5391     ok(GetLastError() == ERROR_IO_PENDING, "expected ERROR_IO_PENDING, got %u\n", GetLastError());
5392 
5393     if(new_connection)
5394         WaitForSingleObject(server_req_rec_event, INFINITE);
5395     WaitForSingleObject(request_sent_event, INFINITE);
5396 
5397     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
5398     CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
5399     if(new_connection) {
5400         CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
5401         CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
5402     }
5403     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
5404     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
5405 }
5406 
5407 static void open_socket_request(int port, test_request_t *req, const char *verb)
5408 {
5409     /* We're connecting to new socket */
5410     if(!verb)
5411         reset_events();
5412 
5413     req->session = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, INTERNET_FLAG_ASYNC);
5414     ok(req->session != NULL, "InternetOpenA failed\n");
5415     pInternetSetStatusCallbackA(req->session, readex_callback);
5416 
5417     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
5418     req->connection = InternetConnectA(req->session, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0xdeadbeef);
5419     ok(req->connection != NULL, "InternetConnectA failed %u\n", GetLastError());
5420     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED );
5421 
5422     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
5423     req->request = HttpOpenRequestA(req->connection, "GET", verb ? verb : "/socket",
5424                                     NULL, NULL, NULL, INTERNET_FLAG_RELOAD, 0xdeadbeef);
5425     ok(req->request != NULL, "HttpOpenRequestA failed %u\n", GetLastError());
5426     CHECK_NOTIFIED( INTERNET_STATUS_HANDLE_CREATED );
5427 
5428     send_socket_request(req, !verb);
5429 }
5430 
5431 static void open_read_test_request(int port, test_request_t *req, const char *response)
5432 {
5433     if(!skip_receive_notification_tests)
5434         SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
5435 
5436     open_socket_request(port, req, NULL);
5437 
5438     if(!skip_receive_notification_tests) {
5439         SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
5440         received_response_size = 0xdeadbeef;
5441     }
5442     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
5443 
5444     server_send_string(response);
5445     WaitForSingleObject(complete_event, INFINITE);
5446 
5447     if(!skip_receive_notification_tests) {
5448         CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
5449         CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
5450         todo_wine
5451         ok(received_response_size == strlen(response), "received_response_size = %u\n", received_response_size);
5452     }
5453     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
5454     ok(req_error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", req_error);
5455 }
5456 
5457 #define readex_expect_sync_data_len(a,b,c,d,e,f,g) _readex_expect_sync_data_len(__LINE__,a,b,c,d,e,f,g)
5458 static void _readex_expect_sync_data_len(unsigned line, HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf,
5459                                          DWORD buf_size, const char *exdata, DWORD len, DWORD expect_receive)
5460 {
5461     BOOL ret;
5462 
5463     if(!skip_receive_notification_tests && expect_receive) {
5464         SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
5465         SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
5466         received_response_size = 0xdeadbeef;
5467     }
5468 
5469     memset(buf->lpvBuffer, 0xff, buf_size);
5470     buf->dwBufferLength = buf_size;
5471     ret = InternetReadFileExW(req, buf, flags, 0xdeadbeef);
5472     ok_(__FILE__,line)(ret, "InternetReadFileExW failed: %u\n", GetLastError());
5473     ok_(__FILE__,line)(buf->dwBufferLength == len, "dwBufferLength = %u, expected %u\n", buf->dwBufferLength, len);
5474     if(len && exdata)
5475         ok_(__FILE__,line)(!memcmp(buf->lpvBuffer, exdata, len), "Unexpected data\n");
5476 
5477     if(!skip_receive_notification_tests && expect_receive) {
5478         CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
5479         CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
5480         ok_(__FILE__,line)(received_response_size == len, "received_response_size = %u\n", received_response_size);
5481     }
5482 }
5483 
5484 #define readex_expect_sync_data(a,b,c,d,e,f) _readex_expect_sync_data(__LINE__,a,b,c,d,e,f)
5485 static void _readex_expect_sync_data(unsigned line, HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf,
5486                                      DWORD buf_size, const char *exdata, DWORD expect_receive)
5487 {
5488     _readex_expect_sync_data_len(line, req, flags, buf, buf_size, exdata, strlen(exdata), expect_receive);
5489 }
5490 
5491 #define read_expect_sync_data_len(a,b,c,d,e) _read_expect_sync_data_len(__LINE__,a,b,c,d,e)
5492 static void _read_expect_sync_data_len(unsigned line, HINTERNET req, void *buf, DWORD buf_size,
5493         const char *exdata, DWORD len)
5494 {
5495     DWORD ret_size = 0xdeadbeef;
5496     BOOL ret;
5497 
5498     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
5499     SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
5500     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
5501     received_response_size = 0xdeadbeef;
5502 
5503     memset(buf, 0xff, buf_size);
5504     ret = InternetReadFile(req, buf, buf_size, &ret_size);
5505     ok_(__FILE__,line)(ret, "InternetReadFileExW failed: %u\n", GetLastError());
5506     ok_(__FILE__,line)(ret_size == len, "dwBufferLength = %u, expected %u\n", ret_size, len);
5507     if(len && exdata)
5508         ok_(__FILE__,line)(!memcmp(buf, exdata, len), "Unexpected data\n");
5509 
5510     CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
5511     CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
5512     CLEAR_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
5513     ok_(__FILE__,line)(received_response_size == len, "received_response_size = %u\n", received_response_size);
5514     ok_(__FILE__,line)(!req_error, "req_error = %u\n", req_error);
5515 }
5516 
5517 #define read_expect_sync_data(a,b,c,d) _read_expect_sync_data(__LINE__,a,b,c,d)
5518 static void _read_expect_sync_data(unsigned line, HINTERNET req, void *buf,
5519         DWORD buf_size, const char *exdata)
5520 {
5521     _read_expect_sync_data_len(line, req, buf, buf_size, exdata, strlen(exdata));
5522 }
5523 
5524 static void close_connection(void)
5525 {
5526     char c;
5527     SetEvent(conn_wait_event);
5528     recv(server_socket, &c, 1, 0);
5529 }
5530 
5531 #define send_response_and_wait(a,b,c,d,e,f,g,h) _send_response_and_wait(__LINE__,a,b,c,d,e,f,g,h)
5532 static void _send_response_and_wait(unsigned line, const char *response, BOOL do_close_connection,
5533                                     void *buf, DWORD *ret_size, const char *exdata,
5534                                     DWORD expected_size, DWORD expected_req_error, DWORD expected_receive_size)
5535 {
5536     if(!skip_receive_notification_tests)
5537         SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
5538     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
5539 
5540     if(response)
5541         server_send_string(response);
5542 
5543     if(do_close_connection)
5544         close_connection();
5545 
5546     WaitForSingleObject(complete_event, INFINITE);
5547 
5548     if(!skip_receive_notification_tests)
5549         CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
5550     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
5551     if(!skip_receive_notification_tests && expected_receive_size != -1)
5552         todo_wine_if(received_response_size != expected_receive_size) /* FIXME! remove when wine is fixed */
5553         ok_(__FILE__,line)(received_response_size == expected_receive_size,
5554                            "received_response_size = %u\n", received_response_size);
5555     ok_(__FILE__,line)(req_error == expected_req_error, "req_error = %u, expected %u\n", req_error, expected_req_error);
5556 
5557     /* If IRF_NO_WAIT is used, buffer is not changed. */
5558     ok_(__FILE__,line)(*ret_size == expected_size, "dwBufferLength = %u\n", *ret_size);
5559     if(exdata)
5560         ok_(__FILE__,line)(!memcmp(buf, exdata, strlen(exdata)), "unexpected buffer data\n");
5561     else if(buf)
5562         ok_(__FILE__,line)(!*(DWORD*)buf, "buffer data changed\n");
5563 }
5564 
5565 #define send_response_ex_and_wait(a,b,c,d,e,f) _send_response_ex_and_wait(__LINE__,a,b,c,d,e,f)
5566 static void _send_response_ex_and_wait(unsigned line, const char *response, BOOL close_connection,
5567                                        INTERNET_BUFFERSW *buf, const char *exdata, DWORD expected_req_error,
5568                                        DWORD expected_receive_size)
5569 {
5570     _send_response_and_wait(line, response, close_connection, buf->lpvBuffer, &buf->dwBufferLength,
5571                             exdata, exdata ? strlen(exdata) : buf->dwBufferLength, expected_req_error,
5572                             expected_receive_size);
5573 }
5574 
5575 static void send_response_len_and_wait(unsigned len, BOOL close_connection, INTERNET_BUFFERSW *buf)
5576 {
5577     char *response;
5578 
5579     response = HeapAlloc(GetProcessHeap(), 0, len+1);
5580     memset(response, 'x', len);
5581     response[len] = 0;
5582     send_response_ex_and_wait(response, close_connection, buf, NULL, 0, -1);
5583     HeapFree(GetProcessHeap(), 0, response);
5584 }
5585 
5586 #define readex_expect_async(a,b,c,d,e) _readex_expect_async(__LINE__,a,b,c,d,e)
5587 static void _readex_expect_async(unsigned line, HINTERNET req, DWORD flags, INTERNET_BUFFERSW *buf,
5588         DWORD buf_size, const char *exdata)
5589 {
5590     unsigned len = 0;
5591     BOOL ret;
5592 
5593     if(!skip_receive_notification_tests)
5594         SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
5595 
5596     memset(buf->lpvBuffer, 0, max(buf_size, sizeof(DWORD)));
5597     buf->dwBufferLength = buf_size;
5598     ret = InternetReadFileExW(req, buf, flags, 0xdeadbeef);
5599     ok_(__FILE__,line)(!ret && GetLastError() == ERROR_IO_PENDING, "InternetReadFileExW returned %x (%u)\n", ret, GetLastError());
5600     ok_(__FILE__,line)(buf->dwBufferLength == buf_size, "dwBufferLength = %u, expected %u\n", buf->dwBufferLength, buf_size);
5601     if(exdata) {
5602         len = strlen(exdata);
5603         ok_(__FILE__,line)(!memcmp(buf->lpvBuffer, exdata, len), "unexpected buffer data\n");
5604     }else {
5605         ok_(__FILE__,line)(!*(DWORD*)buf->lpvBuffer, "buffer data changed\n");
5606     }
5607 
5608     if(!skip_receive_notification_tests)
5609         CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
5610 }
5611 
5612 static void read_expect_async(HINTERNET req, void *buf, DWORD buf_size, DWORD *ret_size, const char *exdata)
5613 {
5614     unsigned len = 0;
5615     const char *p;
5616     BOOL ret;
5617 
5618     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
5619 
5620     *ret_size = 0xdeadbeef;
5621     memset(buf, 0, buf_size);
5622     ret = InternetReadFile(req, buf, buf_size, ret_size);
5623     ok(!ret && GetLastError() == ERROR_IO_PENDING, "InternetReadFileExW returned %x (%u)\n", ret, GetLastError());
5624     ok(*ret_size == 0, "dwBufferLength = %u\n", *ret_size);
5625     if(exdata) {
5626         len = strlen(exdata);
5627         ok(!memcmp(buf, exdata, len), "unexpected buffer data\n");
5628     }
5629     for(p = (const char*)buf + len; p < (const char*)buf + buf_size; p++) {
5630         if(*p)
5631             ok(0, "buffer data changed\n");
5632     }
5633 
5634     CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
5635 }
5636 
5637 #define expect_data_available(a,b) _expect_data_available(__LINE__,a,b)
5638 static DWORD _expect_data_available(unsigned line, HINTERNET req, int exsize)
5639 {
5640     DWORD size = 0;
5641     BOOL res;
5642 
5643     res = InternetQueryDataAvailable(req, &size, 0, 0);
5644     ok_(__FILE__,line)(res, "InternetQueryDataAvailable failed: %u\n", GetLastError());
5645     if(exsize != -1)
5646         ok_(__FILE__,line)(size  == exsize, "size = %u, expected %u\n", size, exsize);
5647 
5648     return size;
5649 }
5650 
5651 #define async_query_data_available(a,b) _async_query_data_available(__LINE__,a,b)
5652 static void _async_query_data_available(unsigned line, HINTERNET req, DWORD *size)
5653 {
5654     BOOL res;
5655 
5656     if(!skip_receive_notification_tests)
5657         SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
5658 
5659     *size = 0xdeadbeef;
5660     res = InternetQueryDataAvailable(req, size, 0, 0);
5661     ok_(__FILE__,line)(!res && GetLastError() == ERROR_IO_PENDING,
5662                        "InternetQueryDataAvailable returned: %x(%u)\n", res, GetLastError());
5663     ok_(__FILE__,line)(!*size, "size = %u\n", *size);
5664 
5665     if(!skip_receive_notification_tests)
5666         CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
5667 }
5668 
5669 static void test_http_read(int port)
5670 {
5671     INTERNET_BUFFERSW ib;
5672     test_request_t req;
5673     DWORD read_size;
5674     char buf[24000];
5675     DWORD avail, i;
5676 
5677     if(!is_ie7plus)
5678         return;
5679 
5680     memset(&ib, 0, sizeof(ib));
5681     ib.dwStructSize = sizeof(ib);
5682     ib.lpvBuffer = buf;
5683 
5684     trace("Testing InternetReadFileExW with IRF_ASYNC flag...\n");
5685 
5686     open_read_test_request(port, &req,
5687                            "HTTP/1.1 200 OK\r\n"
5688                            "Server: winetest\r\n"
5689                            "\r\n"
5690                            "xx");
5691 
5692     readex_expect_async(req.request, IRF_ASYNC, &ib, 4, "xx");
5693 
5694     send_response_ex_and_wait("yy1234567890", FALSE, &ib, "xxyy", 0, 2);
5695     readex_expect_sync_data(req.request, IRF_ASYNC, &ib, 4, "1234", 4);
5696     readex_expect_sync_data(req.request, IRF_ASYNC, &ib, 5, "56789", 5);
5697 
5698     readex_expect_async(req.request, IRF_ASYNC, &ib, sizeof(buf), "0");
5699     send_response_ex_and_wait("123", TRUE, &ib, "0123", 0, 4);
5700 
5701     close_async_handle(req.session, 2);
5702 
5703     trace("Testing InternetReadFileExW with no flags...\n");
5704 
5705     open_read_test_request(port, &req,
5706                            "HTTP/1.1 200 OK\r\n"
5707                            "Server: winetest\r\n"
5708                            "\r\n"
5709                            "xx");
5710 
5711     readex_expect_async(req.request, 0, &ib, 4, "xx");
5712 
5713     send_response_ex_and_wait("yy1234567890", FALSE, &ib, "xxyy", 0, 2);
5714     readex_expect_sync_data(req.request, 0, &ib, 4, "1234", 4);
5715     readex_expect_sync_data(req.request, 0, &ib, 5, "56789", 5);
5716 
5717     readex_expect_async(req.request, 0, &ib, sizeof(buf), "0");
5718     send_response_ex_and_wait("123", TRUE, &ib, "0123", 0, 4);
5719 
5720     close_async_handle(req.session, 2);
5721 
5722     trace("Testing InternetReadFile...\n");
5723 
5724     open_read_test_request(port, &req,
5725                            "HTTP/1.1 200 OK\r\n"
5726                            "Server: winetest\r\n"
5727                            "\r\n"
5728                            "xx");
5729 
5730     read_expect_async(req.request, buf, 4, &read_size, "xx");
5731 
5732     send_response_and_wait("yy1234567890", FALSE, buf, &read_size, "xxyy", 4, 0, 2);
5733     read_expect_sync_data(req.request, buf, 4, "1234");
5734     read_expect_sync_data(req.request, buf, 5, "56789");
5735 
5736     read_expect_async(req.request, buf, sizeof(buf), &read_size, "0");
5737     send_response_and_wait("123", TRUE, buf, &read_size, "0123", 4, 0, 4);
5738 
5739     close_async_handle(req.session, 2);
5740 
5741     trace("Testing InternetReadFileExW with IRF_NO_WAIT flag...\n");
5742 
5743     open_read_test_request(port, &req,
5744                            "HTTP/1.1 200 OK\r\n"
5745                            "Server: winetest\r\n"
5746                            "\r\n"
5747                            "xx");
5748 
5749     SET_OPTIONAL(INTERNET_STATUS_RECEIVING_RESPONSE);
5750 
5751     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "xx", 0);
5752 
5753     if(notified[INTERNET_STATUS_RECEIVING_RESPONSE]) {
5754         win_skip("Skipping receive notification tests on too old Windows.\n");
5755         skip_receive_notification_tests = TRUE;
5756     }
5757     CLEAR_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
5758 
5759     readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
5760     send_response_ex_and_wait("1234567890", FALSE, &ib, NULL, 0, 10);
5761     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, 5, "12345", 0);
5762     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "67890", 0);
5763 
5764     readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
5765     send_response_ex_and_wait("12345", TRUE, &ib, NULL, 0, 5);
5766 
5767     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "12345", 0);
5768     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "", TRUE);
5769 
5770     close_async_handle(req.session, 2);
5771 
5772     open_read_test_request(port, &req,
5773                            "HTTP/1.1 200 OK\r\n"
5774                            "Server: winetest\r\n"
5775                            "Transfer-Encoding: chunked\r\n"
5776                            "\r\n"
5777                            "9\r\n123456789");
5778     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123456789", 0);
5779     readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
5780 
5781     send_response_ex_and_wait("\r\n1\r\na\r\n1\r\nb\r", FALSE, &ib, NULL, 0, 13);
5782     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "ab", 0);
5783     readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
5784 
5785     send_response_ex_and_wait("\n3\r\nab", FALSE, &ib, NULL, 0, 6);
5786     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "ab", 0);
5787     readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
5788 
5789     send_response_ex_and_wait("c", FALSE, &ib, NULL, 0, 1);
5790     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "c", 0);
5791     readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
5792 
5793     send_response_ex_and_wait("\r\n1\r\nx\r\n0\r\n\r\n", TRUE, &ib, NULL, 0, 13);
5794     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "x", 0);
5795     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "", 0);
5796 
5797     close_async_handle(req.session, 2);
5798 
5799     open_read_test_request(port, &req,
5800                            "HTTP/1.1 200 OK\r\n"
5801                            "Server: winetest\r\n"
5802                            "Transfer-Encoding: chunked\r\n"
5803                            "\r\n"
5804                            "3\r\n123\r\n");
5805     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123", 0);
5806     readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
5807 
5808     send_response_ex_and_wait("0\r\n\r\n", TRUE, &ib, NULL, 0, 5);
5809     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "", 0);
5810 
5811     close_async_handle(req.session, 2);
5812 
5813     open_read_test_request(port, &req,
5814                            "HTTP/1.1 200 OK\r\n"
5815                            "Server: winetest\r\n"
5816                            "Connection: close\r\n"
5817                            "\r\n");
5818     readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
5819     send_response_ex_and_wait("123", TRUE, &ib, NULL, 0, 3);
5820     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123", 0);
5821 
5822     SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION);
5823     SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED);
5824     close_async_handle(req.session, 2);
5825     CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
5826     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
5827 
5828     trace("Testing InternetQueryDataAvailable...\n");
5829 
5830     open_read_test_request(port, &req,
5831                            "HTTP/1.1 200 OK\r\n"
5832                            "Server: winetest\r\n"
5833                            "\r\n"
5834                            "123");
5835     expect_data_available(req.request, 3);
5836     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "123", 0);
5837     readex_expect_async(req.request, IRF_NO_WAIT, &ib, sizeof(buf), NULL);
5838 
5839     send_response_len_and_wait(20000, TRUE, &ib);
5840     avail = expect_data_available(req.request, -1);
5841     ok(avail < 17000, "avail = %u\n", avail);
5842 
5843     SET_WINE_ALLOW(INTERNET_STATUS_CLOSING_CONNECTION);
5844     SET_WINE_ALLOW(INTERNET_STATUS_CONNECTION_CLOSED);
5845     close_async_handle(req.session, 2);
5846     todo_wine CHECK_NOT_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
5847     todo_wine CHECK_NOT_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
5848 
5849     open_read_test_request(port, &req,
5850                            "HTTP/1.1 200 OK\r\n"
5851                            "Server: winetest\r\n"
5852                            "Connection: close\r\n"
5853                            "\r\n"
5854                            "123");
5855 
5856     expect_data_available(req.request, 3);
5857     readex_expect_sync_data(req.request, 0, &ib, 3, "123", 0);
5858 
5859     async_query_data_available(req.request, &read_size);
5860     send_response_and_wait("1234567890", FALSE, NULL, &read_size, NULL, 10, 10, 10);
5861 
5862     readex_expect_sync_data(req.request, 0, &ib, 9, "123456789", 0);
5863     expect_data_available(req.request, 1);
5864     readex_expect_sync_data(req.request, 0, &ib, 1, "0", 0);
5865 
5866     async_query_data_available(req.request, &read_size);
5867     send_response_and_wait("1234567890", FALSE, NULL, &read_size, NULL, 10, 10, 10);
5868     expect_data_available(req.request, 10);
5869     for(i = 0; i < 10; i++)
5870         server_send_string("x");
5871     expect_data_available(req.request, 10);
5872 
5873     readex_expect_async(req.request, IRF_ASYNC, &ib, 21, "1234567890");
5874     send_response_ex_and_wait("X", FALSE, &ib, "1234567890xxxxxxxxxxX", 0, 11);
5875     async_query_data_available(req.request, &read_size);
5876 
5877     SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION);
5878     SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED);
5879     send_response_and_wait(NULL, TRUE, NULL, &read_size, NULL, 0, 0, 0);
5880     CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
5881     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
5882 
5883     close_async_handle(req.session, 2);
5884 
5885     skip_receive_notification_tests = FALSE;
5886 }
5887 
5888 static void test_connection_break(int port)
5889 {
5890     INTERNET_BUFFERSW ib;
5891     test_request_t req;
5892     char buf[24000];
5893 
5894     if(!is_ie7plus)
5895         return;
5896 
5897     memset(&ib, 0, sizeof(ib));
5898     ib.dwStructSize = sizeof(ib);
5899     ib.lpvBuffer = buf;
5900 
5901     trace("Testing InternetReadFileExW on broken connection...\n");
5902 
5903     open_read_test_request(port, &req,
5904                            "HTTP/1.1 200 OK\r\n"
5905                            "Server: winetest\r\n"
5906                            "Content-Length: 10000\r\n"
5907                            "\r\n"
5908                            "xx");
5909 
5910     /* close connection and make sure that it's closed on handle release. */
5911     close_connection();
5912     SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION);
5913     SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED);
5914     close_async_handle(req.session, 2);
5915     CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
5916     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
5917 }
5918 
5919 static void test_long_url(int port)
5920 {
5921     char long_path[INTERNET_MAX_PATH_LENGTH*2] = "/echo_request?";
5922     char buf[sizeof(long_path)*2], url[sizeof(buf)];
5923     test_request_t req;
5924     DWORD size, len;
5925     BOOL ret;
5926 
5927     if(!is_ie7plus)
5928         return;
5929 
5930     memset(long_path+strlen(long_path), 'x', sizeof(long_path)-strlen(long_path));
5931     long_path[sizeof(long_path)-1] = 0;
5932     open_simple_request(&req, "localhost", port, NULL, long_path);
5933 
5934     ret = HttpSendRequestA(req.request, NULL, 0, NULL, 0);
5935     ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
5936     test_status_code(req.request, 200);
5937 
5938     receive_simple_request(req.request, buf, sizeof(buf));
5939     ok(strstr(buf, long_path) != NULL, "long pathnot found in %s\n", buf);
5940 
5941     sprintf(url, "http://localhost:%u%s", port, long_path);
5942 
5943     size = sizeof(buf);
5944     ret = InternetQueryOptionA(req.request, INTERNET_OPTION_URL, buf, &size);
5945     ok(ret, "InternetQueryOptionA(INTERNET_OPTION_URL) failed: %u\n", GetLastError());
5946     len = strlen(url);
5947     ok(size == len, "size = %u, expected %u\n", size, len);
5948     ok(!strcmp(buf, url), "Wrong URL %s, expected %s\n", buf, url);
5949 
5950     close_request(&req);
5951 }
5952 
5953 static void test_persistent_connection(int port)
5954 {
5955     INTERNET_BUFFERSW ib;
5956     test_request_t req;
5957     char buf[24000];
5958 
5959     if(!is_ie7plus)
5960         return;
5961 
5962     memset(&ib, 0, sizeof(ib));
5963     ib.dwStructSize = sizeof(ib);
5964     ib.lpvBuffer = buf;
5965 
5966     skip_receive_notification_tests = TRUE;
5967 
5968     trace("Testing persistent connection...\n");
5969 
5970     open_read_test_request(port, &req,
5971                            "HTTP/1.1 200 OK\r\n"
5972                            "Server: winetest\r\n"
5973                            "Content-Length: 2\r\n"
5974                            "\r\n"
5975                            "xx");
5976     readex_expect_sync_data(req.request, IRF_ASYNC, &ib, 4, "xx", 0);
5977     close_async_handle(req.session, 2);
5978 
5979     open_socket_request(port, &req, "/test_simple_chunked");
5980     server_read_request("GET /test_simple_chunked HTTP/1.1");
5981 
5982     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
5983     server_send_string("HTTP/1.1 200 OK\r\n"
5984                        "Server: winetest\r\n"
5985                        "Transfer-Encoding: chunked\r\n"
5986                        "\r\n"
5987                        "2\r\nab\r\n");
5988     WaitForSingleObject(complete_event, INFINITE);
5989     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
5990     ok(req_error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", req_error);
5991 
5992     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "ab", 0);
5993     readex_expect_async(req.request, IRF_ASYNC, &ib, sizeof(buf), NULL);
5994     send_response_ex_and_wait("3\r\nabc\r\n0\r\n\r\n", FALSE, &ib, "abc", 0, 13);
5995     close_async_handle(req.session, 2);
5996 
5997     open_socket_request(port, &req, "/chunked");
5998     server_read_request("GET /chunked HTTP/1.1");
5999 
6000     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
6001     server_send_string("HTTP/1.1 200 OK\r\n"
6002                        "Server: winetest\r\n"
6003                        "Transfer-Encoding: chunked\r\n"
6004                        "\r\n"
6005                        "2\r\nab\r\n");
6006     WaitForSingleObject(complete_event, INFINITE);
6007     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
6008     ok(req_error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", req_error);
6009 
6010     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, 3, "ab", 0);
6011     readex_expect_async(req.request, IRF_ASYNC, &ib, 3, NULL);
6012     send_response_ex_and_wait("3\r\nabc\r\n", FALSE, &ib, "abc", 0, 13);
6013 
6014     /* send another request on the same request handle, it must drain remaining last chunk marker */
6015     server_send_string("0\r\n\r\n");
6016 
6017     send_socket_request(&req, FALSE);
6018     server_read_request("GET /chunked HTTP/1.1");
6019 
6020     ResetEvent(complete_event);
6021     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
6022     server_send_string("HTTP/1.1 201 OK\r\n"
6023                        "Server: winetest\r\n"
6024                        "Content-Length: 0\r\n"
6025                        "Connection: keep-alive\r\n"
6026                        "\r\n");
6027     WaitForSingleObject(complete_event, INFINITE);
6028     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
6029     ok(req_error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", req_error);
6030 
6031     test_status_code(req.request, 201);
6032     close_async_handle(req.session, 2);
6033 
6034     /* the connection is still valid */
6035     open_socket_request(port, &req, "/another_chunked");
6036     server_read_request("GET /another_chunked HTTP/1.1");
6037 
6038     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
6039     server_send_string("HTTP/1.1 200 OK\r\n"
6040                        "Server: winetest\r\n"
6041                        "Transfer-Encoding: chunked\r\n"
6042                        "\r\n"
6043                        "2\r\nab\r\n");
6044     WaitForSingleObject(complete_event, INFINITE);
6045     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
6046     ok(req_error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", req_error);
6047 
6048     readex_expect_sync_data(req.request, IRF_NO_WAIT, &ib, sizeof(buf), "ab", 0);
6049     readex_expect_async(req.request, IRF_ASYNC, &ib, sizeof(buf), NULL);
6050 
6051     /* we're missing trailing '\n'; the connection can't be drained without blocking,
6052      * so it will be closed */
6053     send_response_ex_and_wait("3\r\nabc\r\n0\r\n\r", FALSE, &ib, "abc", 0, 13);
6054 
6055     SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION);
6056     SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED);
6057     close_async_handle(req.session, 2);
6058     CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
6059     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
6060 
6061     close_connection();
6062     skip_receive_notification_tests = FALSE;
6063 }
6064 
6065 static void test_redirect(int port)
6066 {
6067     char buf[4000], expect_url[INTERNET_MAX_URL_LENGTH];
6068     INTERNET_BUFFERSW ib;
6069     test_request_t req;
6070 
6071     if(!is_ie7plus)
6072         return;
6073 
6074     skip_receive_notification_tests = TRUE;
6075 
6076     memset(&ib, 0, sizeof(ib));
6077     ib.dwStructSize = sizeof(ib);
6078     ib.lpvBuffer = buf;
6079 
6080     trace("Testing redirection...\n");
6081 
6082     open_socket_request(port, &req, NULL);
6083 
6084     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
6085     SET_EXPECT(INTERNET_STATUS_REDIRECT);
6086     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
6087     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
6088 
6089     server_send_string("HTTP/1.1 302 Found\r\n"
6090                        "Server: winetest\r\n"
6091                        "Location: test_redirection\r\n"
6092                        "Connection: keep-alive\r\n"
6093                        "Content-Length: 0\r\n"
6094                        "\r\n");
6095 
6096     server_read_request("GET /test_redirection HTTP/1.1");
6097 
6098     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
6099 
6100     sprintf(expect_url, "http://localhost:%u/test_redirection", port);
6101     test_request_url(req.request, expect_url);
6102 
6103     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
6104 
6105     server_send_string("HTTP/1.1 200 OK\r\n"
6106                        "Server: winetest\r\n"
6107                        "Content-Length: 3\r\n"
6108                        "\r\n"
6109                        "xxx");
6110 
6111     WaitForSingleObject(complete_event, INFINITE);
6112 
6113     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
6114     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
6115     CHECK_NOTIFIED(INTERNET_STATUS_REDIRECT);
6116     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
6117     ok(req_error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", req_error);
6118 
6119     test_status_code(req.request, 200);
6120 
6121     close_connection();
6122     close_async_handle(req.session, 2);
6123 
6124     trace("Test redirect to non-http URL...\n");
6125 
6126     open_socket_request(port, &req, NULL);
6127 
6128     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
6129 
6130     server_send_string("HTTP/1.1 302 Found\r\n"
6131                        "Server: winetest\r\n"
6132                        "Location: test:non:http/url\r\n"
6133                        "Connection: keep-alive\r\n"
6134                        "Content-Length: 0\r\n"
6135                        "\r\n");
6136 
6137     WaitForSingleObject(complete_event, INFINITE);
6138 
6139     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
6140     ok(req_error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", req_error);
6141 
6142     sprintf(expect_url, "http://localhost:%u/socket", port);
6143     test_request_url(req.request, expect_url);
6144     test_status_code(req.request, 302);
6145 
6146     close_connection();
6147     close_async_handle(req.session, 2);
6148 
6149     trace("Test redirect to http URL with no host name...\n");
6150 
6151     open_socket_request(port, &req, NULL);
6152 
6153     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
6154 
6155     server_send_string("HTTP/1.1 302 Found\r\n"
6156                        "Server: winetest\r\n"
6157                        "Location: http:///nohost\r\n"
6158                        "Connection: keep-alive\r\n"
6159                        "Content-Length: 0\r\n"
6160                        "\r\n");
6161 
6162     WaitForSingleObject(complete_event, INFINITE);
6163 
6164     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
6165     ok(req_error == ERROR_INTERNET_INVALID_URL, "expected ERROR_INTERNET_INVALID_URL, got %u\n", req_error);
6166 
6167     sprintf(expect_url, "http://localhost:%u/socket", port);
6168     test_request_url(req.request, expect_url);
6169     test_status_code(req.request, 302);
6170 
6171     close_connection();
6172     close_async_handle(req.session, 2);
6173 
6174     skip_receive_notification_tests = FALSE;
6175 }
6176 
6177 static void test_remove_dot_segments(int port)
6178 {
6179     test_request_t req;
6180     BOOL ret;
6181 
6182     open_simple_request(&req, "localhost", port, NULL, "/A/../B/./C/../../test_remove_dot_segments");
6183 
6184     ret = HttpSendRequestA(req.request, NULL, 0, NULL, 0);
6185     ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
6186     test_status_code(req.request, 200);
6187 
6188     close_request(&req);
6189 }
6190 
6191 struct large_test
6192 {
6193     DWORD64 content_length;
6194     BOOL ret;
6195 };
6196 
6197 static void test_large_content(int port)
6198 {
6199     struct large_test tests[] = {
6200         { 0,                   TRUE },
6201         { UINT_MAX-1,          TRUE },
6202         { UINT_MAX,            TRUE },
6203         { (DWORD64)UINT_MAX+1, FALSE },
6204         { ~0,                  FALSE },
6205     };
6206     test_request_t req;
6207     DWORD sizelen, len;
6208     DWORD read_size;
6209     DWORD64 len64;
6210     char buf[16];
6211     BOOL ret;
6212     size_t i;
6213 
6214     open_simple_request(&req, "localhost", port, "HEAD", "/test_large_content");
6215 
6216     for (i = 0; i < ARRAY_SIZE(tests); i++)
6217     {
6218         content_length = tests[i].content_length;
6219         ret = HttpSendRequestA(req.request, NULL, 0, NULL, 0);
6220         ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
6221 
6222         len = ~0;
6223         sizelen = sizeof(len);
6224         SetLastError(0xdeadbeef);
6225         ret = HttpQueryInfoA(req.request, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH,
6226                              &len, &sizelen, 0);
6227         if (tests[i].ret)
6228         {
6229             ok(ret, "HttpQueryInfo should have succeeded\n");
6230             ok(GetLastError() == ERROR_SUCCESS ||
6231                 broken(GetLastError() == 0xdeadbeef), /* xp, 2k8, vista */
6232                 "expected ERROR_SUCCESS, got %x\n", GetLastError());
6233             ok(len == (DWORD)tests[i].content_length, "expected %u, got %u\n",
6234                 (DWORD)tests[i].content_length, len);
6235         }
6236         else
6237         {
6238             ok(!ret, "HttpQueryInfo should have failed\n");
6239             ok(GetLastError() == ERROR_HTTP_INVALID_HEADER,
6240                 "expected ERROR_HTTP_INVALID_HEADER, got %x\n", GetLastError());
6241             ok(len == ~0, "expected ~0, got %u\n", len);
6242         }
6243         ok(sizelen == sizeof(DWORD), "sizelen %u\n", sizelen);
6244     }
6245 
6246     /* test argument size */
6247     len64 = ~0;
6248     sizelen = sizeof(len64);
6249     SetLastError(0xdeadbeef);
6250     ret = HttpQueryInfoA(req.request, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH,
6251                          &len64, &len, 0);
6252     ok(!ret, "HttpQueryInfo should have failed\n");
6253     ok(GetLastError() == ERROR_HTTP_INVALID_HEADER,
6254         "expected ERROR_HTTP_INVALID_HEADER, got %x\n", GetLastError());
6255     ok(sizelen == sizeof(DWORD64), "sizelen %u\n", sizelen);
6256     ok(len64 == ~0, "len64 %x%08x\n", (DWORD)(len64 >> 32), (DWORD)len64);
6257 
6258     close_request(&req);
6259 
6260     /* test internal use of HttpQueryInfo on large size */
6261     open_read_test_request(port, &req,
6262                            "HTTP/1.1 200 OK\r\n"
6263                            "Server: winetest\r\n"
6264                            "Content-Length: 4294967296\r\n"
6265                            "\r\n"
6266                            "xx");
6267     read_expect_async(req.request, buf, 4, &read_size, "xx");
6268     send_response_and_wait("yy1234567890", FALSE, buf, &read_size, "xxyy", 4, 0, 2);
6269     read_expect_sync_data(req.request, buf, 10, "1234567890");
6270 
6271     SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION);
6272     SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED);
6273     close_async_handle(req.session, 2);
6274     CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
6275     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
6276     close_connection();
6277 }
6278 
6279 static void test_http_connection(void)
6280 {
6281     struct server_info si;
6282     HANDLE hThread;
6283     DWORD id = 0, r;
6284 
6285     si.hEvent = CreateEventW(NULL, 0, 0, NULL);
6286     si.port = 7531;
6287 
6288     hThread = CreateThread(NULL, 0, server_thread, &si, 0, &id);
6289     ok( hThread != NULL, "create thread failed\n");
6290 
6291     r = WaitForSingleObject(si.hEvent, 10000);
6292     ok (r == WAIT_OBJECT_0, "failed to start wininet test server\n");
6293     if (r != WAIT_OBJECT_0)
6294     {
6295         CloseHandle(hThread);
6296         return;
6297     }
6298 
6299     test_basic_request(si.port, "GET", "/test1");
6300     test_proxy_indirect(si.port);
6301     test_proxy_direct(si.port);
6302     test_header_handling_order(si.port);
6303     test_basic_request(si.port, "POST", "/test5");
6304     test_basic_request(si.port, "RPC_IN_DATA", "/test5");
6305     test_basic_request(si.port, "RPC_OUT_DATA", "/test5");
6306     test_basic_request(si.port, "GET", "/test6");
6307     test_basic_request(si.port, "GET", "/testF");
6308     test_connection_header(si.port);
6309     test_header_override(si.port);
6310     test_cookie_header(si.port);
6311     test_basic_authentication(si.port);
6312     test_invalid_response_headers(si.port);
6313     test_response_without_headers(si.port);
6314     test_HttpQueryInfo(si.port);
6315     test_HttpSendRequestW(si.port);
6316     test_options(si.port);
6317     test_no_content(si.port);
6318     test_conn_close(si.port);
6319     test_no_cache(si.port);
6320     test_cache_read_gzipped(si.port);
6321     test_http_status(si.port);
6322     test_premature_disconnect(si.port);
6323     test_connection_closing(si.port);
6324     test_cache_control_verb(si.port);
6325     test_successive_HttpSendRequest(si.port);
6326     test_head_request(si.port);
6327     test_request_content_length(si.port);
6328     test_accept_encoding(si.port);
6329     test_basic_auth_credentials_reuse(si.port);
6330     test_basic_auth_credentials_end_session(si.port);
6331     test_basic_auth_credentials_different(si.port);
6332     test_basic_auth_credentials_manual(si.port);
6333     test_basic_auth_credentials_cached_manual(si.port);
6334     test_async_read(si.port);
6335     test_http_read(si.port);
6336     test_connection_break(si.port);
6337     test_long_url(si.port);
6338 #ifdef __REACTOS__
6339 if (!winetest_interactive)
6340 {
6341     skip("Skipping test_redirect and test_persistent_connection due to hang. See ROSTESTS-294.\n");
6342 }
6343 else
6344 {
6345 #endif
6346     test_redirect(si.port);
6347     test_persistent_connection(si.port);
6348 #ifdef __REACTOS__
6349 }
6350 #endif
6351     test_remove_dot_segments(si.port);
6352     test_large_content(si.port);
6353 
6354     /* send the basic request again to shutdown the server thread */
6355     test_basic_request(si.port, "GET", "/quit");
6356 
6357     r = WaitForSingleObject(hThread, 3000);
6358     ok( r == WAIT_OBJECT_0, "thread wait failed\n");
6359     CloseHandle(hThread);
6360 }
6361 
6362 static void release_cert_info(INTERNET_CERTIFICATE_INFOA *info)
6363 {
6364     LocalFree(info->lpszSubjectInfo);
6365     LocalFree(info->lpszIssuerInfo);
6366     LocalFree(info->lpszProtocolName);
6367     LocalFree(info->lpszSignatureAlgName);
6368     LocalFree(info->lpszEncryptionAlgName);
6369 }
6370 
6371 typedef struct {
6372     const char *ex_subject;
6373     const char *ex_issuer;
6374 } cert_struct_test_t;
6375 
6376 static const cert_struct_test_t test_winehq_org_cert = {
6377     "US\r\n"
6378     "55114\r\n"
6379     "MN\r\n"
6380     "Saint Paul\r\n"
6381     "Ste 120\r\n"
6382     "700 Raymond Ave\r\n"
6383     "CodeWeavers\r\n"
6384     "IT\r\n"
6385     "Secure Link SSL Wildcard\r\n"
6386     "*.winehq.org",
6387 
6388     "US\r\n"
6389     "VA\r\n"
6390     "Herndon\r\n"
6391     "Network Solutions L.L.C.\r\n"
6392     "Network Solutions OV Server CA 2"
6393 };
6394 
6395 static const cert_struct_test_t test_winehq_com_cert = {
6396     "US\r\n"
6397     "Minnesota\r\n"
6398     "Saint Paul\r\n"
6399     "WineHQ\r\n"
6400     "IT\r\n"
6401     "test.winehq.com\r\n"
6402     "webmaster@winehq.org",
6403 
6404     "US\r\n"
6405     "Minnesota\r\n"
6406     "Saint Paul\r\n"
6407     "WineHQ\r\n"
6408     "IT\r\n"
6409     "test.winehq.com\r\n"
6410     "webmaster@winehq.org"
6411 };
6412 
6413 static void test_cert_struct(HINTERNET req, const cert_struct_test_t *test)
6414 {
6415     INTERNET_CERTIFICATE_INFOA info;
6416     DWORD size;
6417     BOOL res;
6418 
6419     memset(&info, 0x5, sizeof(info));
6420 
6421     size = sizeof(info);
6422     res = InternetQueryOptionA(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT, &info, &size);
6423     if (!res)
6424     {
6425         win_skip("Querying INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT failed, skipping tests\n");
6426         return;
6427     }
6428 
6429     ok(res, "InternetQueryOption failed: %u\n", GetLastError());
6430     ok(size == sizeof(info), "size = %u\n", size);
6431 
6432     ok(!strcmp(info.lpszSubjectInfo, test->ex_subject), "lpszSubjectInfo = %s\n", info.lpszSubjectInfo);
6433     ok(!strcmp(info.lpszIssuerInfo, test->ex_issuer), "lpszIssuerInfo = %s\n", info.lpszIssuerInfo);
6434     ok(!info.lpszSignatureAlgName, "lpszSignatureAlgName = %s\n", info.lpszSignatureAlgName);
6435     ok(!info.lpszEncryptionAlgName, "lpszEncryptionAlgName = %s\n", info.lpszEncryptionAlgName);
6436     ok(!info.lpszProtocolName, "lpszProtocolName = %s\n", info.lpszProtocolName);
6437     ok(info.dwKeySize >= 128 && info.dwKeySize <= 256, "dwKeySize = %u\n", info.dwKeySize);
6438 
6439     release_cert_info(&info);
6440 }
6441 
6442 #define test_security_info(a,b,c) _test_security_info(__LINE__,a,b,c)
6443 static void _test_security_info(unsigned line, const char *urlc, DWORD error, DWORD ex_flags)
6444 {
6445     char url[INTERNET_MAX_URL_LENGTH];
6446     const CERT_CHAIN_CONTEXT *chain;
6447     DWORD flags;
6448     BOOL res;
6449 
6450     if(!pInternetGetSecurityInfoByURLA) {
6451         win_skip("pInternetGetSecurityInfoByURLA not available\n");
6452         return;
6453     }
6454 
6455     strcpy(url, urlc);
6456     chain = (void*)0xdeadbeef;
6457     flags = 0xdeadbeef;
6458     res = pInternetGetSecurityInfoByURLA(url, &chain, &flags);
6459     if(error == ERROR_SUCCESS) {
6460         ok_(__FILE__,line)(res, "InternetGetSecurityInfoByURLA failed: %u\n", GetLastError());
6461         ok_(__FILE__,line)(chain != NULL, "chain = NULL\n");
6462         ok_(__FILE__,line)(flags == ex_flags, "flags = %x\n", flags);
6463         CertFreeCertificateChain(chain);
6464 
6465         SetLastError(0xdeadbeef);
6466         res = pInternetGetSecurityInfoByURLA(url, NULL, NULL);
6467         ok_(__FILE__,line)(!res && GetLastError() == ERROR_INVALID_PARAMETER,
6468                            "InternetGetSecurityInfoByURLA returned: %x(%u)\n", res, GetLastError());
6469 
6470         res = pInternetGetSecurityInfoByURLA(url, &chain, NULL);
6471         ok_(__FILE__,line)(res, "InternetGetSecurityInfoByURLA failed: %u\n", GetLastError());
6472         CertFreeCertificateChain(chain);
6473 
6474         res = pInternetGetSecurityInfoByURLA(url, NULL, &flags);
6475         ok_(__FILE__,line)(res, "InternetGetSecurityInfoByURLA failed: %u\n", GetLastError());
6476     }else {
6477         ok_(__FILE__,line)(!res && GetLastError() == error,
6478                            "InternetGetSecurityInfoByURLA returned: %x(%u), expected %u\n", res, GetLastError(), error);
6479     }
6480 }
6481 
6482 #define test_secflags_option(a,b,c) _test_secflags_option(__LINE__,a,b,c)
6483 static void _test_secflags_option(unsigned line, HINTERNET req, DWORD ex_flags, DWORD opt_flags)
6484 {
6485     DWORD flags, size;
6486     BOOL res;
6487 
6488     flags = 0xdeadbeef;
6489     size = sizeof(flags);
6490     res = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size);
6491     ok_(__FILE__,line)(res, "InternetQueryOptionW(INTERNET_OPTION_SECURITY_FLAGS) failed: %u\n", GetLastError());
6492     ok_(__FILE__,line)((flags & ~opt_flags) == ex_flags, "INTERNET_OPTION_SECURITY_FLAGS flags = %x, expected %x\n",
6493                        flags, ex_flags);
6494 
6495     /* Option 98 is undocumented and seems to be the same as INTERNET_OPTION_SECURITY_FLAGS */
6496     flags = 0xdeadbeef;
6497     size = sizeof(flags);
6498     res = InternetQueryOptionW(req, 98, &flags, &size);
6499     ok_(__FILE__,line)(res, "InternetQueryOptionW(98) failed: %u\n", GetLastError());
6500     ok_(__FILE__,line)((flags & ~opt_flags) == ex_flags, "INTERNET_OPTION_SECURITY_FLAGS(98) flags = %x, expected %x\n",
6501                        flags, ex_flags);
6502 }
6503 
6504 #define set_secflags(a,b,c) _set_secflags(__LINE__,a,b,c)
6505 static void _set_secflags(unsigned line, HINTERNET req, BOOL use_undoc, DWORD flags)
6506 {
6507     BOOL res;
6508 
6509     res = InternetSetOptionW(req, use_undoc ? 99 : INTERNET_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
6510     ok_(__FILE__,line)(res, "InternetSetOption(INTERNET_OPTION_SECURITY_FLAGS) failed: %u\n", GetLastError());
6511 }
6512 
6513 static void test_security_flags(void)
6514 {
6515     INTERNET_CERTIFICATE_INFOA *cert;
6516     HINTERNET ses, conn, req;
6517     DWORD size, flags;
6518     char buf[100];
6519     BOOL res;
6520 
6521     trace("Testing security flags...\n");
6522     reset_events();
6523 
6524     ses = InternetOpenA("WineTest", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);
6525     ok(ses != NULL, "InternetOpen failed\n");
6526 
6527     pInternetSetStatusCallbackA(ses, &callback);
6528 
6529     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
6530     conn = InternetConnectA(ses, "test.winehq.com", INTERNET_DEFAULT_HTTPS_PORT,
6531                             NULL, NULL, INTERNET_SERVICE_HTTP, INTERNET_FLAG_SECURE, 0xdeadbeef);
6532     ok(conn != NULL, "InternetConnect failed with error %u\n", GetLastError());
6533     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
6534 
6535     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
6536     req = HttpOpenRequestA(conn, "GET", "/tests/hello.html", NULL, NULL, NULL,
6537                           INTERNET_FLAG_SECURE|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_RELOAD|INTERNET_FLAG_NO_CACHE_WRITE,
6538                           0xdeadbeef);
6539     ok(req != NULL, "HttpOpenRequest failed\n");
6540     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
6541 
6542     flags = 0xdeadbeef;
6543     size = sizeof(flags);
6544     res = InternetQueryOptionW(req, 98, &flags, &size);
6545     if(!res && GetLastError() == ERROR_INVALID_PARAMETER) {
6546         win_skip("Incomplete security flags support, skipping\n");
6547 
6548         close_async_handle(ses, 2);
6549         return;
6550     }
6551 
6552     test_secflags_option(req, 0, 0);
6553     test_security_info("https://test.winehq.com/data/some_file.html?q", ERROR_INTERNET_ITEM_NOT_FOUND, 0);
6554 
6555     set_secflags(req, TRUE, SECURITY_FLAG_IGNORE_REVOCATION);
6556     test_secflags_option(req, SECURITY_FLAG_IGNORE_REVOCATION, 0);
6557 
6558     set_secflags(req, TRUE, SECURITY_FLAG_IGNORE_CERT_CN_INVALID);
6559     test_secflags_option(req, SECURITY_FLAG_IGNORE_REVOCATION|SECURITY_FLAG_IGNORE_CERT_CN_INVALID, 0);
6560 
6561     set_secflags(req, FALSE, SECURITY_FLAG_IGNORE_UNKNOWN_CA);
6562     test_secflags_option(req, SECURITY_FLAG_IGNORE_UNKNOWN_CA|SECURITY_FLAG_IGNORE_REVOCATION|SECURITY_FLAG_IGNORE_CERT_CN_INVALID, 0);
6563 
6564     flags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID|SECURITY_FLAG_SECURE;
6565     res = InternetSetOptionW(req, 99, &flags, sizeof(flags));
6566     ok(!res && GetLastError() == ERROR_INTERNET_OPTION_NOT_SETTABLE, "InternetSetOption(99) failed: %u\n", GetLastError());
6567 
6568     SET_EXPECT(INTERNET_STATUS_RESOLVING_NAME);
6569     SET_EXPECT(INTERNET_STATUS_NAME_RESOLVED);
6570     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
6571     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
6572     SET_OPTIONAL(INTERNET_STATUS_CLOSING_CONNECTION); /* IE11 calls it, it probably reconnects. */
6573     SET_OPTIONAL(INTERNET_STATUS_CONNECTION_CLOSED); /* IE11 */
6574     SET_OPTIONAL(INTERNET_STATUS_CONNECTING_TO_SERVER); /* IE11 */
6575     SET_OPTIONAL(INTERNET_STATUS_CONNECTED_TO_SERVER); /* IE11 */
6576     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
6577     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
6578     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
6579     SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
6580     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
6581     SET_OPTIONAL(INTERNET_STATUS_DETECTING_PROXY);
6582     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
6583 
6584     res = HttpSendRequestA(req, NULL, 0, NULL, 0);
6585     ok(!res && GetLastError() == ERROR_IO_PENDING, "HttpSendRequest failed: %u\n", GetLastError());
6586 
6587     WaitForSingleObject(complete_event, INFINITE);
6588     ok(req_error == ERROR_SUCCESS, "req_error = %d\n", req_error);
6589 
6590     CHECK_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME);
6591     CHECK_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED);
6592     CHECK_NOTIFIED2(INTERNET_STATUS_CONNECTING_TO_SERVER, 2);
6593     CHECK_NOTIFIED2(INTERNET_STATUS_CONNECTED_TO_SERVER, 2);
6594     CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
6595     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
6596     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
6597     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
6598     CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
6599     CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
6600     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
6601     CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
6602     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
6603 
6604     test_request_flags(req, 0);
6605     test_secflags_option(req, SECURITY_FLAG_SECURE|SECURITY_FLAG_IGNORE_UNKNOWN_CA
6606             |SECURITY_FLAG_IGNORE_REVOCATION|SECURITY_FLAG_IGNORE_CERT_CN_INVALID|SECURITY_FLAG_STRENGTH_STRONG, 0);
6607 
6608     res = InternetReadFile(req, buf, sizeof(buf), &size);
6609     ok(res, "InternetReadFile failed: %u\n", GetLastError());
6610     ok(size, "size = 0\n");
6611 
6612     /* Collect all existing persistent connections */
6613     res = InternetSetOptionA(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0);
6614     ok(res, "InternetSetOption(INTERNET_OPTION_END_BROWSER_SESSION) failed: %u\n", GetLastError());
6615 
6616     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
6617     req = HttpOpenRequestA(conn, "GET", "/tests/hello.html", NULL, NULL, NULL,
6618                           INTERNET_FLAG_SECURE|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_RELOAD|INTERNET_FLAG_NO_CACHE_WRITE,
6619                           0xdeadbeef);
6620     ok(req != NULL, "HttpOpenRequest failed\n");
6621     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
6622 
6623     flags = INTERNET_ERROR_MASK_COMBINED_SEC_CERT|INTERNET_ERROR_MASK_LOGIN_FAILURE_DISPLAY_ENTITY_BODY;
6624     res = InternetSetOptionA(req, INTERNET_OPTION_ERROR_MASK, (void*)&flags, sizeof(flags));
6625     ok(res, "InternetQueryOption(INTERNET_OPTION_ERROR_MASK failed: %u\n", GetLastError());
6626 
6627     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
6628     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
6629     SET_OPTIONAL(INTERNET_STATUS_CLOSING_CONNECTION); /* IE11 calls it, it probably reconnects. */
6630     SET_OPTIONAL(INTERNET_STATUS_CONNECTION_CLOSED); /* IE11 */
6631     SET_OPTIONAL(INTERNET_STATUS_CONNECTING_TO_SERVER); /* IE11 */
6632     SET_OPTIONAL(INTERNET_STATUS_CONNECTED_TO_SERVER); /* IE11 */
6633     SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION);
6634     SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED);
6635     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
6636     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
6637     SET_OPTIONAL(INTERNET_STATUS_DETECTING_PROXY);
6638 
6639     res = HttpSendRequestA(req, NULL, 0, NULL, 0);
6640     ok(!res && GetLastError() == ERROR_IO_PENDING, "HttpSendRequest failed: %u\n", GetLastError());
6641 
6642     WaitForSingleObject(complete_event, INFINITE);
6643     ok(req_error == ERROR_INTERNET_SEC_CERT_ERRORS,
6644        "req_error = %d\n", req_error);
6645 
6646     size = 0;
6647     res = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT, NULL, &size);
6648     ok(res || GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InternetQueryOption failed: %d\n", GetLastError());
6649     ok(size == sizeof(INTERNET_CERTIFICATE_INFOA), "size = %u\n", size);
6650     cert = HeapAlloc(GetProcessHeap(), 0, size);
6651     cert->lpszSubjectInfo = NULL;
6652     cert->lpszIssuerInfo = NULL;
6653     cert->lpszSignatureAlgName = (char *)0xdeadbeef;
6654     cert->lpszEncryptionAlgName = (char *)0xdeadbeef;
6655     cert->lpszProtocolName = (char *)0xdeadbeef;
6656     cert->dwKeySize = 0xdeadbeef;
6657     res = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT, cert, &size);
6658     ok(res, "InternetQueryOption failed: %u\n", GetLastError());
6659     if (res)
6660     {
6661         ok(cert->lpszSubjectInfo && strlen(cert->lpszSubjectInfo) > 1, "expected a non-empty subject name\n");
6662         ok(cert->lpszIssuerInfo && strlen(cert->lpszIssuerInfo) > 1, "expected a non-empty issuer name\n");
6663         ok(!cert->lpszSignatureAlgName, "unexpected signature algorithm name\n");
6664         ok(!cert->lpszEncryptionAlgName, "unexpected encryption algorithm name\n");
6665         ok(!cert->lpszProtocolName, "unexpected protocol name\n");
6666         ok(cert->dwKeySize != 0xdeadbeef, "unexpected key size\n");
6667 
6668         LocalFree(cert->lpszSubjectInfo);
6669         LocalFree(cert->lpszIssuerInfo);
6670     }
6671     HeapFree(GetProcessHeap(), 0, cert);
6672 
6673     ros_skip_flaky
6674     CHECK_NOTIFIED2(INTERNET_STATUS_CONNECTING_TO_SERVER, 2);
6675     CHECK_NOTIFIED2(INTERNET_STATUS_CONNECTED_TO_SERVER, 2);
6676     CHECK_NOTIFIED2(INTERNET_STATUS_CLOSING_CONNECTION, 2);
6677     CHECK_NOTIFIED2(INTERNET_STATUS_CONNECTION_CLOSED, 2);
6678     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
6679     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
6680     CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
6681 
6682     if(req_error != ERROR_INTERNET_SEC_CERT_ERRORS) {
6683         win_skip("Unexpected cert errors %u, skipping security flags tests\n", req_error);
6684 
6685         close_async_handle(ses, 3);
6686         return;
6687     }
6688 
6689     size = sizeof(buf);
6690     res = HttpQueryInfoA(req, HTTP_QUERY_CONTENT_ENCODING, buf, &size, 0);
6691     ok(!res && GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND, "HttpQueryInfoA(HTTP_QUERY_CONTENT_ENCODING) failed: %u\n", GetLastError());
6692 
6693     test_request_flags(req, 8);
6694     /* IE11 finds both rev failure and invalid CA. Previous versions required rev failure
6695        to be ignored before invalid CA was reported. */
6696     test_secflags_option(req, _SECURITY_FLAG_CERT_INVALID_CA, _SECURITY_FLAG_CERT_REV_FAILED);
6697 
6698     set_secflags(req, FALSE, SECURITY_FLAG_IGNORE_REVOCATION);
6699     test_secflags_option(req, _SECURITY_FLAG_CERT_INVALID_CA|SECURITY_FLAG_IGNORE_REVOCATION, _SECURITY_FLAG_CERT_REV_FAILED);
6700 
6701     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
6702     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
6703     SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION);
6704     SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED);
6705     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
6706     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
6707     SET_OPTIONAL(INTERNET_STATUS_DETECTING_PROXY);
6708 
6709     res = HttpSendRequestA(req, NULL, 0, NULL, 0);
6710     ok(!res && GetLastError() == ERROR_IO_PENDING, "HttpSendRequest failed: %u\n", GetLastError());
6711 
6712     WaitForSingleObject(complete_event, INFINITE);
6713     ok(req_error == ERROR_INTERNET_INVALID_CA || req_error == ERROR_INTERNET_SEC_CERT_ERRORS, "req_error = %d\n", req_error);
6714 
6715     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
6716     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
6717     CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
6718     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
6719     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
6720     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
6721     CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
6722 
6723     test_request_flags(req, INTERNET_REQFLAG_NO_HEADERS);
6724     test_secflags_option(req, SECURITY_FLAG_IGNORE_REVOCATION|_SECURITY_FLAG_CERT_INVALID_CA, 0);
6725     test_security_info("https://test.winehq.com/data/some_file.html?q", ERROR_INTERNET_ITEM_NOT_FOUND, 0);
6726 
6727     set_secflags(req, FALSE, SECURITY_FLAG_IGNORE_UNKNOWN_CA);
6728     test_secflags_option(req, _SECURITY_FLAG_CERT_INVALID_CA
6729             |SECURITY_FLAG_IGNORE_REVOCATION|SECURITY_FLAG_IGNORE_UNKNOWN_CA, 0);
6730     test_http_version(req);
6731 
6732     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
6733     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
6734     SET_OPTIONAL(INTERNET_STATUS_CLOSING_CONNECTION); /* IE11 calls it, it probably reconnects. */
6735     SET_OPTIONAL(INTERNET_STATUS_CONNECTION_CLOSED); /* IE11 */
6736     SET_OPTIONAL(INTERNET_STATUS_CONNECTING_TO_SERVER); /* IE11 */
6737     SET_OPTIONAL(INTERNET_STATUS_CONNECTED_TO_SERVER); /* IE11 */
6738     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
6739     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
6740     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
6741     SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
6742     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
6743     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
6744     SET_OPTIONAL(INTERNET_STATUS_DETECTING_PROXY);
6745 
6746     res = HttpSendRequestA(req, NULL, 0, NULL, 0);
6747     ok(!res && GetLastError() == ERROR_IO_PENDING, "HttpSendRequest failed: %u\n", GetLastError());
6748 
6749     WaitForSingleObject(complete_event, INFINITE);
6750     ok(req_error == ERROR_SUCCESS, "req_error = %d\n", req_error);
6751 
6752     CHECK_NOTIFIED2(INTERNET_STATUS_CONNECTING_TO_SERVER, 2);
6753     CHECK_NOTIFIED2(INTERNET_STATUS_CONNECTED_TO_SERVER, 2);
6754     CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
6755     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
6756     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
6757     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
6758     CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
6759     CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
6760     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
6761     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
6762     CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
6763 
6764     test_request_flags(req, 0);
6765     test_secflags_option(req, SECURITY_FLAG_SECURE|SECURITY_FLAG_IGNORE_UNKNOWN_CA|SECURITY_FLAG_IGNORE_REVOCATION
6766             |SECURITY_FLAG_STRENGTH_STRONG|_SECURITY_FLAG_CERT_INVALID_CA, 0);
6767 
6768     test_cert_struct(req, &test_winehq_com_cert);
6769     test_security_info("https://test.winehq.com/data/some_file.html?q", 0,
6770             _SECURITY_FLAG_CERT_INVALID_CA);
6771 
6772     res = InternetReadFile(req, buf, sizeof(buf), &size);
6773     ok(res, "InternetReadFile failed: %u\n", GetLastError());
6774     ok(size, "size = 0\n");
6775 
6776     close_async_handle(ses, 3);
6777 
6778     /* Collect all existing persistent connections */
6779     res = InternetSetOptionA(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0);
6780     ok(res, "InternetSetOption(INTERNET_OPTION_END_BROWSER_SESSION) failed: %u\n", GetLastError());
6781 
6782     /* Make another request, without setting security flags */
6783 
6784     ses = InternetOpenA("WineTest", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);
6785     ok(ses != NULL, "InternetOpen failed\n");
6786 
6787     pInternetSetStatusCallbackA(ses, &callback);
6788 
6789     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
6790     conn = InternetConnectA(ses, "test.winehq.com", INTERNET_DEFAULT_HTTPS_PORT,
6791                             NULL, NULL, INTERNET_SERVICE_HTTP, INTERNET_FLAG_SECURE, 0xdeadbeef);
6792     ok(conn != NULL, "InternetConnect failed with error %u\n", GetLastError());
6793     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
6794 
6795     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
6796     req = HttpOpenRequestA(conn, "GET", "/tests/hello.html", NULL, NULL, NULL,
6797                           INTERNET_FLAG_SECURE|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_RELOAD|INTERNET_FLAG_NO_CACHE_WRITE,
6798                           0xdeadbeef);
6799     ok(req != NULL, "HttpOpenRequest failed\n");
6800     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
6801 
6802     test_secflags_option(req, SECURITY_FLAG_SECURE|SECURITY_FLAG_IGNORE_UNKNOWN_CA|SECURITY_FLAG_STRENGTH_STRONG
6803             |SECURITY_FLAG_IGNORE_REVOCATION|_SECURITY_FLAG_CERT_INVALID_CA, 0);
6804     test_http_version(req);
6805 
6806     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
6807     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
6808     SET_OPTIONAL(INTERNET_STATUS_CLOSING_CONNECTION); /* IE11 calls it, it probably reconnects. */
6809     SET_OPTIONAL(INTERNET_STATUS_CONNECTION_CLOSED); /* IE11 */
6810     SET_OPTIONAL(INTERNET_STATUS_CONNECTING_TO_SERVER); /* IE11 */
6811     SET_OPTIONAL(INTERNET_STATUS_CONNECTED_TO_SERVER); /* IE11 */
6812     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
6813     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
6814     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
6815     SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
6816     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
6817     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
6818 
6819     res = HttpSendRequestA(req, NULL, 0, NULL, 0);
6820     ok(!res && GetLastError() == ERROR_IO_PENDING, "HttpSendRequest failed: %u\n", GetLastError());
6821 
6822     WaitForSingleObject(complete_event, INFINITE);
6823     ok(req_error == ERROR_SUCCESS, "req_error = %d\n", req_error);
6824 
6825     CHECK_NOTIFIED2(INTERNET_STATUS_CONNECTING_TO_SERVER, 2);
6826     CHECK_NOTIFIED2(INTERNET_STATUS_CONNECTED_TO_SERVER, 2);
6827     CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
6828     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
6829     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
6830     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
6831     CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
6832     CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
6833     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
6834     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
6835 
6836     test_request_flags(req, 0);
6837     test_secflags_option(req, SECURITY_FLAG_SECURE|SECURITY_FLAG_IGNORE_UNKNOWN_CA|SECURITY_FLAG_STRENGTH_STRONG
6838             |SECURITY_FLAG_IGNORE_REVOCATION|_SECURITY_FLAG_CERT_INVALID_CA, 0);
6839 
6840     res = InternetReadFile(req, buf, sizeof(buf), &size);
6841     ok(res, "InternetReadFile failed: %u\n", GetLastError());
6842     ok(size, "size = 0\n");
6843 
6844     close_async_handle(ses, 2);
6845 
6846     test_security_info("http://test.winehq.com/data/some_file.html?q", ERROR_INTERNET_ITEM_NOT_FOUND, 0);
6847     test_security_info("file:///c:/dir/file.txt", ERROR_INTERNET_ITEM_NOT_FOUND, 0);
6848     test_security_info("xxx:///c:/dir/file.txt", ERROR_INTERNET_ITEM_NOT_FOUND, 0);
6849 }
6850 
6851 static void test_secure_connection(void)
6852 {
6853     static const WCHAR gizmo5[] = {'G','i','z','m','o','5',0};
6854     static const WCHAR testsite[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
6855     static const WCHAR get[] = {'G','E','T',0};
6856     static const WCHAR testpage[] = {'/','t','e','s','t','s','/','h','e','l','l','o','.','h','t','m','l',0};
6857     HINTERNET ses, con, req;
6858     DWORD size, flags;
6859     INTERNET_CERTIFICATE_INFOA *certificate_structA = NULL;
6860     INTERNET_CERTIFICATE_INFOW *certificate_structW = NULL;
6861     BOOL ret;
6862 
6863     ses = InternetOpenA("Gizmo5", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
6864     ok(ses != NULL, "InternetOpen failed\n");
6865 
6866     con = InternetConnectA(ses, "test.winehq.org",
6867                           INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL,
6868                           INTERNET_SERVICE_HTTP, 0, 0);
6869     ok(con != NULL, "InternetConnect failed\n");
6870 
6871     req = HttpOpenRequestA(con, "GET", "/tests/hello.html", NULL, NULL, NULL,
6872                           INTERNET_FLAG_SECURE, 0);
6873     ok(req != NULL, "HttpOpenRequest failed\n");
6874 
6875     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
6876     ok(ret || broken(GetLastError() == ERROR_INTERNET_CANNOT_CONNECT),
6877                      "HttpSendRequest failed: %d\n", GetLastError());
6878     if (!ret)
6879     {
6880         win_skip("Cannot connect to https.\n");
6881         goto done;
6882     }
6883 
6884     size = sizeof(flags);
6885     ret = InternetQueryOptionA(req, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size);
6886     ok(ret, "InternetQueryOption failed: %d\n", GetLastError());
6887     ok(flags & SECURITY_FLAG_SECURE, "expected secure flag to be set\n");
6888 
6889     test_cert_struct(req, &test_winehq_org_cert);
6890 
6891     /* Querying the same option through InternetQueryOptionW still results in
6892      * ASCII strings being returned.
6893      */
6894     size = 0;
6895     ret = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT,
6896                                NULL, &size);
6897     ok(ret || GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InternetQueryOption failed: %d\n", GetLastError());
6898     ok(size == sizeof(INTERNET_CERTIFICATE_INFOW), "size = %d\n", size);
6899     certificate_structW = HeapAlloc(GetProcessHeap(), 0, size);
6900     ret = InternetQueryOptionA(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT,
6901                               certificate_structW, &size);
6902     certificate_structA = (INTERNET_CERTIFICATE_INFOA *)certificate_structW;
6903     ok(ret, "InternetQueryOption failed: %d\n", GetLastError());
6904     if (ret)
6905     {
6906         ok(certificate_structA->lpszSubjectInfo &&
6907            strlen(certificate_structA->lpszSubjectInfo) > 1,
6908            "expected a non-empty subject name\n");
6909         ok(certificate_structA->lpszIssuerInfo &&
6910            strlen(certificate_structA->lpszIssuerInfo) > 1,
6911            "expected a non-empty issuer name\n");
6912         ok(!certificate_structA->lpszSignatureAlgName,
6913            "unexpected signature algorithm name\n");
6914         ok(!certificate_structA->lpszEncryptionAlgName,
6915            "unexpected encryption algorithm name\n");
6916         ok(!certificate_structA->lpszProtocolName,
6917            "unexpected protocol name\n");
6918         ok(certificate_structA->dwKeySize, "expected a non-zero key size\n");
6919         release_cert_info(certificate_structA);
6920     }
6921     HeapFree(GetProcessHeap(), 0, certificate_structW);
6922 
6923     InternetCloseHandle(req);
6924     InternetCloseHandle(con);
6925     InternetCloseHandle(ses);
6926 
6927     /* Repeating the tests with the W functions has the same result: */
6928     ses = InternetOpenW(gizmo5, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
6929     ok(ses != NULL, "InternetOpen failed\n");
6930 
6931     con = InternetConnectW(ses, testsite,
6932                           INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL,
6933                           INTERNET_SERVICE_HTTP, 0, 0);
6934     ok(con != NULL, "InternetConnect failed\n");
6935 
6936     req = HttpOpenRequestW(con, get, testpage, NULL, NULL, NULL,
6937                           INTERNET_FLAG_SECURE|INTERNET_FLAG_RELOAD, 0);
6938     ok(req != NULL, "HttpOpenRequest failed\n");
6939 
6940     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
6941     ok(ret, "HttpSendRequest failed: %d\n", GetLastError());
6942 
6943     size = sizeof(flags);
6944     ret = InternetQueryOptionA(req, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size);
6945     ok(ret, "InternetQueryOption failed: %d\n", GetLastError());
6946     ok(flags & SECURITY_FLAG_SECURE, "expected secure flag to be set, got %x\n", flags);
6947 
6948     ret = InternetQueryOptionA(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT,
6949                                NULL, &size);
6950     ok(ret || GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InternetQueryOption failed: %d\n", GetLastError());
6951     ok(size == sizeof(INTERNET_CERTIFICATE_INFOA), "size = %d\n", size);
6952     certificate_structA = HeapAlloc(GetProcessHeap(), 0, size);
6953     ret = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT,
6954                                certificate_structA, &size);
6955     ok(ret, "InternetQueryOption failed: %d\n", GetLastError());
6956     if (ret)
6957     {
6958         ok(certificate_structA->lpszSubjectInfo &&
6959            strlen(certificate_structA->lpszSubjectInfo) > 1,
6960            "expected a non-empty subject name\n");
6961         ok(certificate_structA->lpszIssuerInfo &&
6962            strlen(certificate_structA->lpszIssuerInfo) > 1,
6963            "expected a non-empty issuer name\n");
6964         ok(!certificate_structA->lpszSignatureAlgName,
6965            "unexpected signature algorithm name\n");
6966         ok(!certificate_structA->lpszEncryptionAlgName,
6967            "unexpected encryption algorithm name\n");
6968         ok(!certificate_structA->lpszProtocolName,
6969            "unexpected protocol name\n");
6970         ok(certificate_structA->dwKeySize, "expected a non-zero key size\n");
6971         release_cert_info(certificate_structA);
6972     }
6973     HeapFree(GetProcessHeap(), 0, certificate_structA);
6974 
6975     /* Again, querying the same option through InternetQueryOptionW still
6976      * results in ASCII strings being returned.
6977      */
6978     size = 0;
6979     ret = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT,
6980                                NULL, &size);
6981     ok(ret || GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InternetQueryOption failed: %d\n", GetLastError());
6982     ok(size == sizeof(INTERNET_CERTIFICATE_INFOW), "size = %d\n", size);
6983     certificate_structW = HeapAlloc(GetProcessHeap(), 0, size);
6984     ret = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT,
6985                                certificate_structW, &size);
6986     certificate_structA = (INTERNET_CERTIFICATE_INFOA *)certificate_structW;
6987     ok(ret, "InternetQueryOption failed: %d\n", GetLastError());
6988     if (ret)
6989     {
6990         ok(certificate_structA->lpszSubjectInfo &&
6991            strlen(certificate_structA->lpszSubjectInfo) > 1,
6992            "expected a non-empty subject name\n");
6993         ok(certificate_structA->lpszIssuerInfo &&
6994            strlen(certificate_structA->lpszIssuerInfo) > 1,
6995            "expected a non-empty issuer name\n");
6996         ok(!certificate_structA->lpszSignatureAlgName,
6997            "unexpected signature algorithm name\n");
6998         ok(!certificate_structA->lpszEncryptionAlgName,
6999            "unexpected encryption algorithm name\n");
7000         ok(!certificate_structA->lpszProtocolName,
7001            "unexpected protocol name\n");
7002         ok(certificate_structA->dwKeySize, "expected a non-zero key size\n");
7003         release_cert_info(certificate_structA);
7004     }
7005     HeapFree(GetProcessHeap(), 0, certificate_structW);
7006 
7007 done:
7008     InternetCloseHandle(req);
7009     InternetCloseHandle(con);
7010     InternetCloseHandle(ses);
7011 }
7012 
7013 static void test_user_agent_header(void)
7014 {
7015     HINTERNET ses, con, req;
7016     DWORD size, err;
7017     char buffer[64];
7018     BOOL ret;
7019 
7020     ses = InternetOpenA("Gizmo5", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
7021     ok(ses != NULL, "InternetOpen failed\n");
7022 
7023     con = InternetConnectA(ses, "test.winehq.org", 80, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
7024     ok(con != NULL, "InternetConnect failed\n");
7025 
7026     req = HttpOpenRequestA(con, "GET", "/tests/hello.html", "HTTP/1.0", NULL, NULL, 0, 0);
7027     ok(req != NULL, "HttpOpenRequest failed\n");
7028 
7029     size = sizeof(buffer);
7030     ret = HttpQueryInfoA(req, HTTP_QUERY_USER_AGENT | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
7031     err = GetLastError();
7032     ok(!ret, "HttpQueryInfo succeeded\n");
7033     ok(err == ERROR_HTTP_HEADER_NOT_FOUND, "expected ERROR_HTTP_HEADER_NOT_FOUND, got %u\n", err);
7034 
7035     ret = HttpAddRequestHeadersA(req, "User-Agent: Gizmo Project\r\n", ~0u, HTTP_ADDREQ_FLAG_ADD_IF_NEW);
7036     ok(ret, "HttpAddRequestHeaders succeeded\n");
7037 
7038     size = sizeof(buffer);
7039     ret = HttpQueryInfoA(req, HTTP_QUERY_USER_AGENT | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
7040     err = GetLastError();
7041     ok(ret, "HttpQueryInfo failed\n");
7042 
7043     InternetCloseHandle(req);
7044 
7045     req = HttpOpenRequestA(con, "GET", "/", "HTTP/1.0", NULL, NULL, 0, 0);
7046     ok(req != NULL, "HttpOpenRequest failed\n");
7047 
7048     size = sizeof(buffer);
7049     ret = HttpQueryInfoA(req, HTTP_QUERY_ACCEPT | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
7050     err = GetLastError();
7051     ok(!ret, "HttpQueryInfo succeeded\n");
7052     ok(err == ERROR_HTTP_HEADER_NOT_FOUND, "expected ERROR_HTTP_HEADER_NOT_FOUND, got %u\n", err);
7053 
7054     ret = HttpAddRequestHeadersA(req, "Accept: audio/*, image/*, text/*\r\nUser-Agent: Gizmo Project\r\n", ~0u, HTTP_ADDREQ_FLAG_ADD_IF_NEW);
7055     ok(ret, "HttpAddRequestHeaders failed\n");
7056 
7057     buffer[0] = 0;
7058     size = sizeof(buffer);
7059     ret = HttpQueryInfoA(req, HTTP_QUERY_ACCEPT | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
7060     ok(ret, "HttpQueryInfo failed: %u\n", GetLastError());
7061     ok(!strcmp(buffer, "audio/*, image/*, text/*"), "got '%s' expected 'audio/*, image/*, text/*'\n", buffer);
7062 
7063     InternetCloseHandle(req);
7064     InternetCloseHandle(con);
7065     InternetCloseHandle(ses);
7066 }
7067 
7068 static void test_bogus_accept_types_array(void)
7069 {
7070     HINTERNET ses, con, req;
7071     static const char *types[] = { (const char *)6240, "*/*", "%p", "", (const char *)0xffffffff, "*/*", NULL };
7072     DWORD size, error;
7073     char buffer[32];
7074     BOOL ret;
7075 
7076     ses = InternetOpenA("MERONG(0.9/;p)", INTERNET_OPEN_TYPE_DIRECT, "", "", 0);
7077     con = InternetConnectA(ses, "www.winehq.org", 80, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
7078     req = HttpOpenRequestA(con, "POST", "/post/post_action.php", "HTTP/1.0", "", types, INTERNET_FLAG_FORMS_SUBMIT, 0);
7079 
7080     ok(req != NULL, "HttpOpenRequest failed: %u\n", GetLastError());
7081 
7082     buffer[0] = 0;
7083     size = sizeof(buffer);
7084     SetLastError(0xdeadbeef);
7085     ret = HttpQueryInfoA(req, HTTP_QUERY_ACCEPT | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
7086     error = GetLastError();
7087     ok(!ret || broken(ret), "HttpQueryInfo succeeded\n");
7088     if (!ret) ok(error == ERROR_HTTP_HEADER_NOT_FOUND, "expected ERROR_HTTP_HEADER_NOT_FOUND, got %u\n", error);
7089     ok(broken(!strcmp(buffer, ", */*, %p, , , */*")) /* IE6 */ ||
7090        broken(!strcmp(buffer, "*/*, %p, */*")) /* IE7/8 */ ||
7091        !strcmp(buffer, ""), "got '%s' expected ''\n", buffer);
7092 
7093     InternetCloseHandle(req);
7094     InternetCloseHandle(con);
7095     InternetCloseHandle(ses);
7096 }
7097 
7098 struct context
7099 {
7100     HANDLE event;
7101     HINTERNET req;
7102 };
7103 
7104 static void WINAPI cb(HINTERNET handle, DWORD_PTR context, DWORD status, LPVOID info, DWORD size)
7105 {
7106     INTERNET_ASYNC_RESULT *result = info;
7107     struct context *ctx = (struct context *)context;
7108 
7109     if(winetest_debug > 1)
7110         trace("%p 0x%08lx %u %p 0x%08x\n", handle, context, status, info, size);
7111 
7112     switch(status) {
7113     case INTERNET_STATUS_REQUEST_COMPLETE:
7114         trace("request handle: 0x%08lx\n", result->dwResult);
7115         ctx->req = (HINTERNET)result->dwResult;
7116         SetEvent(ctx->event);
7117         break;
7118     case INTERNET_STATUS_HANDLE_CLOSING: {
7119         DWORD type = INTERNET_HANDLE_TYPE_CONNECT_HTTP, size = sizeof(type);
7120 
7121         if (InternetQueryOptionA(handle, INTERNET_OPTION_HANDLE_TYPE, &type, &size))
7122             ok(type != INTERNET_HANDLE_TYPE_CONNECT_HTTP, "unexpected callback\n");
7123         SetEvent(ctx->event);
7124         break;
7125     }
7126     case INTERNET_STATUS_NAME_RESOLVED:
7127     case INTERNET_STATUS_CONNECTING_TO_SERVER:
7128     case INTERNET_STATUS_CONNECTED_TO_SERVER: {
7129         char *str = info;
7130         ok(str[0] && str[1], "Got string: %s\n", str);
7131         ok(size == strlen(str)+1, "unexpected size %u\n", size);
7132     }
7133     }
7134 }
7135 
7136 static void test_open_url_async(void)
7137 {
7138     BOOL ret;
7139     HINTERNET ses, req;
7140     DWORD size, error;
7141     struct context ctx;
7142     ULONG type;
7143 
7144     /* Collect all existing persistent connections */
7145     ret = InternetSetOptionA(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0);
7146     ok(ret, "InternetSetOption(INTERNET_OPTION_END_BROWSER_SESSION) failed: %u\n", GetLastError());
7147 
7148     /*
7149      * Some versions of IE6 fail those tests. They pass some notification data as UNICODE string, while
7150      * other versions never do. They also hang of following tests. We disable it for everything older
7151      * than IE7.
7152      */
7153     if(!is_ie7plus)
7154         return;
7155 
7156     ctx.req = NULL;
7157     ctx.event = CreateEventA(NULL, TRUE, FALSE, "Z:_home_hans_jaman-installer.exe_ev1");
7158 
7159     ses = InternetOpenA("AdvancedInstaller", 0, NULL, NULL, INTERNET_FLAG_ASYNC);
7160     ok(ses != NULL, "InternetOpen failed\n");
7161 
7162     SetLastError(0xdeadbeef);
7163     ret = InternetSetOptionA(NULL, INTERNET_OPTION_CALLBACK, &cb, sizeof(DWORD_PTR));
7164     error = GetLastError();
7165     ok(!ret, "InternetSetOptionA succeeded\n");
7166     ok(error == ERROR_INTERNET_INCORRECT_HANDLE_TYPE, "got %u expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE\n", error);
7167 
7168     ret = InternetSetOptionA(ses, INTERNET_OPTION_CALLBACK, &cb, sizeof(DWORD_PTR));
7169     error = GetLastError();
7170     ok(!ret, "InternetSetOptionA failed\n");
7171     ok(error == ERROR_INTERNET_OPTION_NOT_SETTABLE, "got %u expected ERROR_INTERNET_OPTION_NOT_SETTABLE\n", error);
7172 
7173     pInternetSetStatusCallbackW(ses, cb);
7174     ResetEvent(ctx.event);
7175 
7176     req = InternetOpenUrlA(ses, "http://test.winehq.org", NULL, 0, 0, (DWORD_PTR)&ctx);
7177     ok(!req && GetLastError() == ERROR_IO_PENDING, "InternetOpenUrl failed\n");
7178 
7179     WaitForSingleObject(ctx.event, INFINITE);
7180 
7181     type = 0;
7182     size = sizeof(type);
7183     ret = InternetQueryOptionA(ctx.req, INTERNET_OPTION_HANDLE_TYPE, &type, &size);
7184     ok(ret, "InternetQueryOption failed: %u\n", GetLastError());
7185     ok(type == INTERNET_HANDLE_TYPE_HTTP_REQUEST,
7186        "expected INTERNET_HANDLE_TYPE_HTTP_REQUEST, got %u\n", type);
7187 
7188     size = 0;
7189     ret = HttpQueryInfoA(ctx.req, HTTP_QUERY_RAW_HEADERS_CRLF, NULL, &size, NULL);
7190     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "HttpQueryInfo failed\n");
7191     ok(size > 0, "expected size > 0\n");
7192 
7193     ResetEvent(ctx.event);
7194     InternetCloseHandle(ctx.req);
7195     WaitForSingleObject(ctx.event, INFINITE);
7196 
7197     InternetCloseHandle(ses);
7198     CloseHandle(ctx.event);
7199 }
7200 
7201 enum api
7202 {
7203     internet_connect = 1,
7204     http_open_request,
7205     http_send_request_ex,
7206     internet_writefile,
7207     http_end_request,
7208     internet_close_handle
7209 };
7210 
7211 struct notification
7212 {
7213     enum api     function; /* api responsible for notification */
7214     unsigned int status;   /* status received */
7215     BOOL         async;    /* delivered from another thread? */
7216     BOOL         todo;
7217     BOOL         optional;
7218 };
7219 
7220 struct info
7221 {
7222     enum api     function;
7223     const struct notification *test;
7224     unsigned int count;
7225     unsigned int index;
7226     HANDLE       wait;
7227     DWORD        thread;
7228     unsigned int line;
7229     DWORD        expect_result;
7230     BOOL         is_aborted;
7231 };
7232 
7233 static CRITICAL_SECTION notification_cs;
7234 
7235 static void CALLBACK check_notification( HINTERNET handle, DWORD_PTR context, DWORD status, LPVOID buffer, DWORD buflen )
7236 {
7237     BOOL status_ok, function_ok;
7238     struct info *info = (struct info *)context;
7239     unsigned int i;
7240 
7241     EnterCriticalSection( &notification_cs );
7242 
7243     if(info->is_aborted) {
7244         LeaveCriticalSection(&notification_cs);
7245         return;
7246     }
7247 
7248     if (status == INTERNET_STATUS_HANDLE_CREATED)
7249     {
7250         DWORD size = sizeof(struct info *);
7251         HttpQueryInfoA( handle, INTERNET_OPTION_CONTEXT_VALUE, &info, &size, 0 );
7252     }else if(status == INTERNET_STATUS_REQUEST_COMPLETE) {
7253         INTERNET_ASYNC_RESULT *ar = (INTERNET_ASYNC_RESULT*)buffer;
7254 
7255         ok(buflen == sizeof(*ar), "unexpected buflen = %d\n", buflen);
7256         if(info->expect_result == ERROR_SUCCESS) {
7257             ok(ar->dwResult == 1, "ar->dwResult = %ld, expected 1\n", ar->dwResult);
7258         }else {
7259             ok(!ar->dwResult, "ar->dwResult = %ld, expected 1\n", ar->dwResult);
7260             ok(ar->dwError == info->expect_result, "ar->dwError = %d, expected %d\n", ar->dwError, info->expect_result);
7261         }
7262     }
7263 
7264     i = info->index;
7265     if (i >= info->count)
7266     {
7267         LeaveCriticalSection( &notification_cs );
7268         return;
7269     }
7270 
7271     while (info->test[i].status != status &&
7272         (info->test[i].optional || info->test[i].todo) &&
7273         i < info->count - 1 &&
7274         info->test[i].function == info->test[i + 1].function)
7275     {
7276         i++;
7277     }
7278 
7279     status_ok   = (info->test[i].status == status);
7280     function_ok = (info->test[i].function == info->function);
7281 
7282     if (!info->test[i].todo)
7283     {
7284         ok( status_ok, "%u: expected status %u got %u\n", info->line, info->test[i].status, status );
7285         ok( function_ok, "%u: expected function %u got %u\n", info->line, info->test[i].function, info->function );
7286 
7287         if (info->test[i].async)
7288             ok(info->thread != GetCurrentThreadId(), "%u: expected thread %u got %u\n",
7289                info->line, info->thread, GetCurrentThreadId());
7290     }
7291     else
7292     {
7293         todo_wine ok( status_ok, "%u: expected status %u got %u\n", info->line, info->test[i].status, status );
7294         if (status_ok)
7295             todo_wine ok( function_ok, "%u: expected function %u got %u\n", info->line, info->test[i].function, info->function );
7296     }
7297     if (i == info->count - 1 || info->test[i].function != info->test[i + 1].function) SetEvent( info->wait );
7298     info->index = i+1;
7299 
7300     LeaveCriticalSection( &notification_cs );
7301 }
7302 
7303 static void setup_test( struct info *info, enum api function, unsigned int line, DWORD expect_result )
7304 {
7305     info->function = function;
7306     info->line = line;
7307     info->expect_result = expect_result;
7308 }
7309 
7310 struct notification_data
7311 {
7312     const struct notification *test;
7313     const unsigned int count;
7314     const char *method;
7315     const char *host;
7316     const char *path;
7317     const char *data;
7318     BOOL expect_conn_failure;
7319 };
7320 
7321 static const struct notification async_send_request_ex_test[] =
7322 {
7323     { internet_connect,      INTERNET_STATUS_HANDLE_CREATED, FALSE },
7324     { http_open_request,     INTERNET_STATUS_HANDLE_CREATED, FALSE },
7325     { http_send_request_ex,  INTERNET_STATUS_DETECTING_PROXY, TRUE, FALSE, TRUE },
7326     { http_send_request_ex,  INTERNET_STATUS_COOKIE_SENT, TRUE, FALSE, TRUE },
7327     { http_send_request_ex,  INTERNET_STATUS_RESOLVING_NAME, TRUE, FALSE, TRUE },
7328     { http_send_request_ex,  INTERNET_STATUS_NAME_RESOLVED, TRUE, FALSE, TRUE },
7329     { http_send_request_ex,  INTERNET_STATUS_CONNECTING_TO_SERVER, TRUE },
7330     { http_send_request_ex,  INTERNET_STATUS_CONNECTED_TO_SERVER, TRUE },
7331     { http_send_request_ex,  INTERNET_STATUS_SENDING_REQUEST, TRUE },
7332     { http_send_request_ex,  INTERNET_STATUS_REQUEST_SENT, TRUE },
7333     { http_send_request_ex,  INTERNET_STATUS_REQUEST_COMPLETE, TRUE },
7334     { internet_writefile,    INTERNET_STATUS_SENDING_REQUEST, FALSE },
7335     { internet_writefile,    INTERNET_STATUS_REQUEST_SENT, FALSE },
7336     { http_end_request,      INTERNET_STATUS_RECEIVING_RESPONSE, TRUE },
7337     { http_end_request,      INTERNET_STATUS_RESPONSE_RECEIVED, TRUE },
7338     { http_end_request,      INTERNET_STATUS_REQUEST_COMPLETE, TRUE },
7339     { internet_close_handle, INTERNET_STATUS_CLOSING_CONNECTION, FALSE, FALSE, TRUE },
7340     { internet_close_handle, INTERNET_STATUS_CONNECTION_CLOSED, FALSE, FALSE, TRUE },
7341     { internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING, FALSE, },
7342     { internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING, FALSE, }
7343 };
7344 
7345 static const struct notification async_send_request_ex_test2[] =
7346 {
7347     { internet_connect,      INTERNET_STATUS_HANDLE_CREATED, FALSE },
7348     { http_open_request,     INTERNET_STATUS_HANDLE_CREATED, FALSE },
7349     { http_send_request_ex,  INTERNET_STATUS_DETECTING_PROXY, TRUE, FALSE, TRUE },
7350     { http_send_request_ex,  INTERNET_STATUS_COOKIE_SENT, TRUE, FALSE, TRUE },
7351     { http_send_request_ex,  INTERNET_STATUS_RESOLVING_NAME, TRUE, FALSE, TRUE },
7352     { http_send_request_ex,  INTERNET_STATUS_NAME_RESOLVED, TRUE, FALSE, TRUE },
7353     { http_send_request_ex,  INTERNET_STATUS_CONNECTING_TO_SERVER, TRUE, TRUE },
7354     { http_send_request_ex,  INTERNET_STATUS_CONNECTED_TO_SERVER, TRUE, TRUE },
7355     { http_send_request_ex,  INTERNET_STATUS_SENDING_REQUEST, TRUE },
7356     { http_send_request_ex,  INTERNET_STATUS_REQUEST_SENT, TRUE },
7357     { http_send_request_ex,  INTERNET_STATUS_REQUEST_COMPLETE, TRUE },
7358     { http_end_request,      INTERNET_STATUS_RECEIVING_RESPONSE, TRUE },
7359     { http_end_request,      INTERNET_STATUS_RESPONSE_RECEIVED, TRUE },
7360     { http_end_request,      INTERNET_STATUS_REQUEST_COMPLETE, TRUE },
7361     { internet_close_handle, INTERNET_STATUS_CLOSING_CONNECTION, FALSE, FALSE, TRUE },
7362     { internet_close_handle, INTERNET_STATUS_CONNECTION_CLOSED, FALSE, FALSE, TRUE },
7363     { internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING, FALSE, },
7364     { internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING, FALSE, }
7365 };
7366 
7367 static const struct notification async_send_request_ex_resolve_failure_test[] =
7368 {
7369     { internet_connect,      INTERNET_STATUS_HANDLE_CREATED, FALSE },
7370     { http_open_request,     INTERNET_STATUS_HANDLE_CREATED, FALSE },
7371     { http_send_request_ex,  INTERNET_STATUS_DETECTING_PROXY, TRUE, FALSE, TRUE },
7372     { http_send_request_ex,  INTERNET_STATUS_RESOLVING_NAME, TRUE },
7373     { http_send_request_ex,  INTERNET_STATUS_DETECTING_PROXY, TRUE, FALSE, TRUE },
7374     { http_send_request_ex,  INTERNET_STATUS_REQUEST_COMPLETE, TRUE },
7375     { http_end_request,      INTERNET_STATUS_REQUEST_COMPLETE, TRUE },
7376     { internet_close_handle, INTERNET_STATUS_CLOSING_CONNECTION, FALSE, FALSE, TRUE },
7377     { internet_close_handle, INTERNET_STATUS_CONNECTION_CLOSED, FALSE, FALSE, TRUE },
7378     { internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING, FALSE, },
7379     { internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING, FALSE, }
7380 };
7381 
7382 static const struct notification async_send_request_ex_chunked_test[] =
7383 {
7384     { internet_connect,      INTERNET_STATUS_HANDLE_CREATED },
7385     { http_open_request,     INTERNET_STATUS_HANDLE_CREATED },
7386     { http_send_request_ex,  INTERNET_STATUS_DETECTING_PROXY, TRUE, FALSE, TRUE },
7387     { http_send_request_ex,  INTERNET_STATUS_COOKIE_SENT, TRUE, FALSE, TRUE },
7388     { http_send_request_ex,  INTERNET_STATUS_RESOLVING_NAME, TRUE, FALSE, TRUE },
7389     { http_send_request_ex,  INTERNET_STATUS_NAME_RESOLVED, TRUE, FALSE, TRUE },
7390     { http_send_request_ex,  INTERNET_STATUS_CONNECTING_TO_SERVER, TRUE },
7391     { http_send_request_ex,  INTERNET_STATUS_CONNECTED_TO_SERVER, TRUE },
7392     { http_send_request_ex,  INTERNET_STATUS_SENDING_REQUEST, TRUE },
7393     { http_send_request_ex,  INTERNET_STATUS_REQUEST_SENT, TRUE },
7394     { http_send_request_ex,  INTERNET_STATUS_REQUEST_COMPLETE, TRUE },
7395     { http_end_request,      INTERNET_STATUS_RECEIVING_RESPONSE, TRUE },
7396     { http_end_request,      INTERNET_STATUS_RESPONSE_RECEIVED, TRUE },
7397     { http_end_request,      INTERNET_STATUS_REQUEST_COMPLETE, TRUE },
7398     { internet_close_handle, INTERNET_STATUS_CLOSING_CONNECTION },
7399     { internet_close_handle, INTERNET_STATUS_CONNECTION_CLOSED },
7400     { internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING },
7401     { internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING }
7402 };
7403 
7404 static const struct notification_data notification_data[] = {
7405     {
7406         async_send_request_ex_chunked_test,
7407         ARRAY_SIZE(async_send_request_ex_chunked_test),
7408         "GET",
7409         "test.winehq.org",
7410         "tests/data.php"
7411     },
7412     {
7413         async_send_request_ex_test,
7414         ARRAY_SIZE(async_send_request_ex_test),
7415         "POST",
7416         "test.winehq.org",
7417         "tests/post.php",
7418         "Public ID=codeweavers"
7419     },
7420     {
7421         async_send_request_ex_test2,
7422         ARRAY_SIZE(async_send_request_ex_test2),
7423         "POST",
7424         "test.winehq.org",
7425         "tests/post.php"
7426     },
7427     {
7428         async_send_request_ex_resolve_failure_test,
7429         ARRAY_SIZE(async_send_request_ex_resolve_failure_test),
7430         "GET",
7431         "brokenhost",
7432         "index.html",
7433         NULL,
7434         TRUE
7435     }
7436 };
7437 
7438 static void test_async_HttpSendRequestEx(const struct notification_data *nd)
7439 {
7440     BOOL ret;
7441     HINTERNET ses, req, con;
7442     struct info info;
7443     DWORD size, written, error;
7444     INTERNET_BUFFERSA b;
7445     static const char *accept[2] = {"*/*", NULL};
7446     char buffer[32];
7447 
7448     trace("Async HttpSendRequestEx test (%s %s)\n", nd->method, nd->host);
7449 
7450     InitializeCriticalSection( &notification_cs );
7451 
7452     info.test  = nd->test;
7453     info.count = nd->count;
7454     info.index = 0;
7455     info.wait = CreateEventW( NULL, FALSE, FALSE, NULL );
7456     info.thread = GetCurrentThreadId();
7457     info.is_aborted = FALSE;
7458 
7459     ses = InternetOpenA( "winetest", 0, NULL, NULL, INTERNET_FLAG_ASYNC );
7460     ok( ses != NULL, "InternetOpen failed\n" );
7461 
7462     pInternetSetStatusCallbackA( ses, check_notification );
7463 
7464     setup_test( &info, internet_connect, __LINE__, ERROR_SUCCESS );
7465     con = InternetConnectA( ses, nd->host, 80, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)&info );
7466     ok( con != NULL, "InternetConnect failed %u\n", GetLastError() );
7467 
7468     WaitForSingleObject( info.wait, 10000 );
7469 
7470     setup_test( &info, http_open_request, __LINE__, ERROR_SUCCESS );
7471     req = HttpOpenRequestA( con, nd->method, nd->path, NULL, NULL, accept, 0, (DWORD_PTR)&info );
7472     ok( req != NULL, "HttpOpenRequest failed %u\n", GetLastError() );
7473 
7474     WaitForSingleObject( info.wait, 10000 );
7475 
7476     if(nd->data) {
7477         memset( &b, 0, sizeof(INTERNET_BUFFERSA) );
7478         b.dwStructSize = sizeof(INTERNET_BUFFERSA);
7479         b.lpcszHeader = "Content-Type: application/x-www-form-urlencoded";
7480         b.dwHeadersLength = strlen( b.lpcszHeader );
7481         b.dwBufferTotal = nd->data ? strlen( nd->data ) : 0;
7482     }
7483 
7484     setup_test( &info, http_send_request_ex, __LINE__,
7485             nd->expect_conn_failure ? ERROR_INTERNET_NAME_NOT_RESOLVED : ERROR_SUCCESS );
7486     ret = HttpSendRequestExA( req, nd->data ? &b : NULL, NULL, 0x28, 0 );
7487     ok( !ret && GetLastError() == ERROR_IO_PENDING, "HttpSendRequestExA failed %d %u\n", ret, GetLastError() );
7488 
7489     error = WaitForSingleObject( info.wait, 10000 );
7490     if(error != WAIT_OBJECT_0) {
7491         skip("WaitForSingleObject returned %d, assuming DNS problem\n", error);
7492         info.is_aborted = TRUE;
7493         goto abort;
7494     }
7495 
7496     size = sizeof(buffer);
7497     SetLastError( 0xdeadbeef );
7498     ret = HttpQueryInfoA( req, HTTP_QUERY_CONTENT_ENCODING, buffer, &size, 0 );
7499     error = GetLastError();
7500     ok( !ret, "HttpQueryInfoA failed %u\n", GetLastError() );
7501     if(nd->expect_conn_failure) {
7502         ok(error == ERROR_HTTP_HEADER_NOT_FOUND, "expected ERROR_HTTP_HEADER_NOT_FOUND got %u\n", error );
7503     }else {
7504         todo_wine
7505         ok(error == ERROR_INTERNET_INCORRECT_HANDLE_STATE,
7506             "expected ERROR_INTERNET_INCORRECT_HANDLE_STATE got %u\n", error );
7507     }
7508 
7509     if (nd->data)
7510     {
7511         written = 0;
7512         size = strlen( nd->data );
7513         setup_test( &info, internet_writefile, __LINE__, ERROR_SUCCESS );
7514         ret = InternetWriteFile( req, nd->data, size, &written );
7515         ok( ret, "InternetWriteFile failed %u\n", GetLastError() );
7516         ok( written == size, "expected %u got %u\n", written, size );
7517 
7518         WaitForSingleObject( info.wait, 10000 );
7519 
7520         SetLastError( 0xdeadbeef );
7521         ret = HttpEndRequestA( req, (void *)nd->data, 0x28, 0 );
7522         error = GetLastError();
7523         ok( !ret, "HttpEndRequestA succeeded\n" );
7524         ok( error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", error );
7525     }
7526 
7527     SetLastError( 0xdeadbeef );
7528     setup_test( &info, http_end_request, __LINE__,
7529             nd->expect_conn_failure ? ERROR_INTERNET_OPERATION_CANCELLED : ERROR_SUCCESS);
7530     ret = HttpEndRequestA( req, NULL, 0x28, 0 );
7531     error = GetLastError();
7532     ok( !ret, "HttpEndRequestA succeeded\n" );
7533     ok( error == ERROR_IO_PENDING, "expected ERROR_IO_PENDING got %u\n", error );
7534 
7535     WaitForSingleObject( info.wait, 10000 );
7536 
7537     setup_test( &info, internet_close_handle, __LINE__, ERROR_SUCCESS );
7538  abort:
7539     InternetCloseHandle( req );
7540     InternetCloseHandle( con );
7541     InternetCloseHandle( ses );
7542 
7543     WaitForSingleObject( info.wait, 10000 );
7544     Sleep(100);
7545     CloseHandle( info.wait );
7546     DeleteCriticalSection( &notification_cs );
7547 }
7548 
7549 static HINTERNET closetest_session, closetest_req, closetest_conn;
7550 static BOOL closetest_closed;
7551 
7552 static void WINAPI closetest_callback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus,
7553      LPVOID lpvStatusInformation, DWORD dwStatusInformationLength)
7554 {
7555     DWORD len, type;
7556     BOOL res;
7557 
7558     if(winetest_debug > 1)
7559         trace("closetest_callback %p: %d\n", hInternet, dwInternetStatus);
7560 
7561     ok(hInternet == closetest_session || hInternet == closetest_conn || hInternet == closetest_req,
7562        "Unexpected hInternet %p\n", hInternet);
7563     if(!closetest_closed)
7564         return;
7565 
7566     len = sizeof(type);
7567     res = InternetQueryOptionA(closetest_req, INTERNET_OPTION_HANDLE_TYPE, &type, &len);
7568     ok(!res && GetLastError() == ERROR_INVALID_HANDLE,
7569        "InternetQueryOptionA(%p INTERNET_OPTION_HANDLE_TYPE) failed: %x %u, expected TRUE ERROR_INVALID_HANDLE\n",
7570        closetest_req, res, GetLastError());
7571 }
7572 
7573 static void test_InternetCloseHandle(void)
7574 {
7575     DWORD len, flags;
7576     BOOL res;
7577 
7578     closetest_session = InternetOpenA("", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);
7579     ok(closetest_session != NULL,"InternetOpen failed with error %u\n", GetLastError());
7580 
7581     pInternetSetStatusCallbackA(closetest_session, closetest_callback);
7582 
7583     closetest_conn = InternetConnectA(closetest_session, "source.winehq.org", INTERNET_INVALID_PORT_NUMBER,
7584             NULL, NULL, INTERNET_SERVICE_HTTP, 0x0, 0xdeadbeef);
7585     ok(closetest_conn != NULL,"InternetConnect failed with error %u\n", GetLastError());
7586 
7587     closetest_req = HttpOpenRequestA(closetest_conn, "GET", "winegecko.php", NULL, NULL, NULL,
7588             INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RESYNCHRONIZE, 0xdeadbead);
7589 
7590     res = HttpSendRequestA(closetest_req, NULL, -1, NULL, 0);
7591     ok(!res && (GetLastError() == ERROR_IO_PENDING),
7592        "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n");
7593 
7594     test_request_flags(closetest_req, INTERNET_REQFLAG_NO_HEADERS);
7595 
7596     res = InternetCloseHandle(closetest_session);
7597     ok(res, "InternetCloseHandle failed: %u\n", GetLastError());
7598     closetest_closed = TRUE;
7599     trace("Closed session handle\n");
7600 
7601     res = InternetCloseHandle(closetest_conn);
7602     ok(!res && GetLastError() == ERROR_INVALID_HANDLE, "InternetCloseConnection(conn) failed: %x %u\n",
7603        res, GetLastError());
7604 
7605     res = InternetCloseHandle(closetest_req);
7606     ok(!res && GetLastError() == ERROR_INVALID_HANDLE, "InternetCloseConnection(req) failed: %x %u\n",
7607        res, GetLastError());
7608 
7609     len = sizeof(flags);
7610     res = InternetQueryOptionA(closetest_req, INTERNET_OPTION_REQUEST_FLAGS, &flags, &len);
7611     ok(!res && GetLastError() == ERROR_INVALID_HANDLE,
7612        "InternetQueryOptionA(%p INTERNET_OPTION_REQUEST_FLAGS) failed: %x %u, expected TRUE ERROR_INVALID_HANDLE\n",
7613        closetest_req, res, GetLastError());
7614 }
7615 
7616 static void test_connection_failure(void)
7617 {
7618     test_request_t req;
7619     DWORD error;
7620     BOOL ret;
7621 
7622     open_simple_request(&req, "localhost", 1, NULL, "/");
7623 
7624     SetLastError(0xdeadbeef);
7625     ret = HttpSendRequestA(req.request, NULL, 0, NULL, 0);
7626     error = GetLastError();
7627     ok(!ret, "unexpected success\n");
7628     ok(error == ERROR_INTERNET_CANNOT_CONNECT, "wrong error %u\n", error);
7629 
7630     close_request(&req);
7631 }
7632 
7633 static void test_default_service_port(void)
7634 {
7635     HINTERNET session, connect, request;
7636     DWORD size, error;
7637     char buffer[128];
7638     BOOL ret;
7639 
7640     if(!is_ie7plus)
7641         return;
7642 
7643     session = InternetOpenA("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
7644     ok(session != NULL, "InternetOpen failed\n");
7645 
7646     connect = InternetConnectA(session, "test.winehq.org", INTERNET_INVALID_PORT_NUMBER, NULL, NULL,
7647                               INTERNET_SERVICE_HTTP, 0, 0);
7648     ok(connect != NULL, "InternetConnect failed\n");
7649 
7650     request = HttpOpenRequestA(connect, NULL, "/", NULL, NULL, NULL, INTERNET_FLAG_SECURE, 0);
7651     ok(request != NULL, "HttpOpenRequest failed\n");
7652 
7653     SetLastError(0xdeadbeef);
7654     ret = HttpSendRequestA(request, NULL, 0, NULL, 0);
7655     error = GetLastError();
7656     ok(!ret, "HttpSendRequest succeeded\n");
7657     ok(error == ERROR_INTERNET_SECURITY_CHANNEL_ERROR || error == ERROR_INTERNET_CANNOT_CONNECT,
7658        "got %u\n", error);
7659 
7660     size = sizeof(buffer);
7661     memset(buffer, 0, sizeof(buffer));
7662     ret = HttpQueryInfoA(request, HTTP_QUERY_HOST | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
7663     ok(ret, "HttpQueryInfo failed with error %u\n", GetLastError());
7664     ok(!strcmp(buffer, "test.winehq.org:80"), "Expected test.winehg.org:80, got '%s'\n", buffer);
7665 
7666     InternetCloseHandle(request);
7667     InternetCloseHandle(connect);
7668 
7669     connect = InternetConnectA(session, "test.winehq.org", INTERNET_INVALID_PORT_NUMBER, NULL, NULL,
7670                                INTERNET_SERVICE_HTTP, INTERNET_FLAG_SECURE, 0);
7671     ok(connect != NULL, "InternetConnect failed\n");
7672 
7673     request = HttpOpenRequestA(connect, NULL, "/", NULL, NULL, NULL, INTERNET_FLAG_SECURE, 0);
7674     ok(request != NULL, "HttpOpenRequest failed\n");
7675 
7676     ret = HttpSendRequestA(request, NULL, 0, NULL, 0);
7677     ok(ret, "HttpSendRequest failed with error %u\n", GetLastError());
7678 
7679     size = sizeof(buffer);
7680     memset(buffer, 0, sizeof(buffer));
7681     ret = HttpQueryInfoA(request, HTTP_QUERY_HOST | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
7682     ok(ret, "HttpQueryInfo failed with error %u\n", GetLastError());
7683     ok(!strcmp(buffer, "test.winehq.org"), "Expected test.winehg.org, got '%s'\n", buffer);
7684 
7685     InternetCloseHandle(request);
7686     InternetCloseHandle(connect);
7687 
7688     connect = InternetConnectA(session, "test.winehq.org", INTERNET_INVALID_PORT_NUMBER, NULL, NULL,
7689                                INTERNET_SERVICE_HTTP, INTERNET_FLAG_SECURE, 0);
7690     ok(connect != NULL, "InternetConnect failed\n");
7691 
7692     request = HttpOpenRequestA(connect, NULL, "/", NULL, NULL, NULL, 0, 0);
7693     ok(request != NULL, "HttpOpenRequest failed\n");
7694 
7695     ret = HttpSendRequestA(request, NULL, 0, NULL, 0);
7696     ok(ret, "HttpSendRequest failed with error %u\n", GetLastError());
7697 
7698     size = sizeof(buffer);
7699     memset(buffer, 0, sizeof(buffer));
7700     ret = HttpQueryInfoA(request, HTTP_QUERY_HOST | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
7701     ok(ret, "HttpQueryInfo failed with error %u\n", GetLastError());
7702     ok(!strcmp(buffer, "test.winehq.org:443"), "Expected test.winehg.org:443, got '%s'\n", buffer);
7703 
7704     InternetCloseHandle(request);
7705     InternetCloseHandle(connect);
7706     InternetCloseHandle(session);
7707 }
7708 
7709 static void init_status_tests(void)
7710 {
7711     memset(expect, 0, sizeof(expect));
7712     memset(optional, 0, sizeof(optional));
7713     memset(wine_allow, 0, sizeof(wine_allow));
7714     memset(notified, 0, sizeof(notified));
7715     memset(status_string, 0, sizeof(status_string));
7716 
7717 #define STATUS_STRING(status) status_string[status] = #status
7718     STATUS_STRING(INTERNET_STATUS_RESOLVING_NAME);
7719     STATUS_STRING(INTERNET_STATUS_NAME_RESOLVED);
7720     STATUS_STRING(INTERNET_STATUS_CONNECTING_TO_SERVER);
7721     STATUS_STRING(INTERNET_STATUS_CONNECTED_TO_SERVER);
7722     STATUS_STRING(INTERNET_STATUS_SENDING_REQUEST);
7723     STATUS_STRING(INTERNET_STATUS_REQUEST_SENT);
7724     STATUS_STRING(INTERNET_STATUS_RECEIVING_RESPONSE);
7725     STATUS_STRING(INTERNET_STATUS_RESPONSE_RECEIVED);
7726     STATUS_STRING(INTERNET_STATUS_CTL_RESPONSE_RECEIVED);
7727     STATUS_STRING(INTERNET_STATUS_PREFETCH);
7728     STATUS_STRING(INTERNET_STATUS_CLOSING_CONNECTION);
7729     STATUS_STRING(INTERNET_STATUS_CONNECTION_CLOSED);
7730     STATUS_STRING(INTERNET_STATUS_HANDLE_CREATED);
7731     STATUS_STRING(INTERNET_STATUS_HANDLE_CLOSING);
7732     STATUS_STRING(INTERNET_STATUS_DETECTING_PROXY);
7733     STATUS_STRING(INTERNET_STATUS_REQUEST_COMPLETE);
7734     STATUS_STRING(INTERNET_STATUS_REDIRECT);
7735     STATUS_STRING(INTERNET_STATUS_INTERMEDIATE_RESPONSE);
7736     STATUS_STRING(INTERNET_STATUS_USER_INPUT_REQUIRED);
7737     STATUS_STRING(INTERNET_STATUS_STATE_CHANGE);
7738     STATUS_STRING(INTERNET_STATUS_COOKIE_SENT);
7739     STATUS_STRING(INTERNET_STATUS_COOKIE_RECEIVED);
7740     STATUS_STRING(INTERNET_STATUS_PRIVACY_IMPACTED);
7741     STATUS_STRING(INTERNET_STATUS_P3P_HEADER);
7742     STATUS_STRING(INTERNET_STATUS_P3P_POLICYREF);
7743     STATUS_STRING(INTERNET_STATUS_COOKIE_HISTORY);
7744 #undef STATUS_STRING
7745 }
7746 
7747 static void WINAPI header_cb( HINTERNET handle, DWORD_PTR ctx, DWORD status, LPVOID info, DWORD len )
7748 {
7749     BOOL ret;
7750     DWORD index, size;
7751     char buf[256];
7752 
7753     if (status == INTERNET_STATUS_SENDING_REQUEST)
7754     {
7755         ret = HttpAddRequestHeadersA( handle, "winetest: winetest", ~0u, HTTP_ADDREQ_FLAG_ADD );
7756         ok( ret, "HttpAddRequestHeadersA failed %u\n", GetLastError() );
7757         SetEvent( (HANDLE)ctx );
7758     }
7759     else if (status == INTERNET_STATUS_REQUEST_SENT)
7760     {
7761         index = 0;
7762         size = sizeof(buf);
7763         ret = HttpQueryInfoA( handle, HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS,
7764                               buf, &size, &index );
7765         ok( ret, "HttpQueryInfoA failed %u\n", GetLastError() );
7766         ok( strstr( buf, "winetest: winetest" ) != NULL, "header missing\n" );
7767         SetEvent( (HANDLE)ctx );
7768     }
7769 }
7770 
7771 static void test_concurrent_header_access(void)
7772 {
7773     HINTERNET ses, con, req;
7774     DWORD err;
7775     BOOL ret;
7776     HANDLE wait = CreateEventW( NULL, FALSE, FALSE, NULL );
7777 
7778     ses = InternetOpenA( "winetest", 0, NULL, NULL, INTERNET_FLAG_ASYNC );
7779     ok( ses != NULL, "InternetOpenA failed\n" );
7780 
7781     con = InternetConnectA( ses, "test.winehq.org", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
7782                             INTERNET_SERVICE_HTTP, 0, 0 );
7783     ok( con != NULL, "InternetConnectA failed %u\n", GetLastError() );
7784 
7785     req = HttpOpenRequestA( con, NULL, "/", NULL, NULL, NULL, 0, (DWORD_PTR)wait );
7786     ok( req != NULL, "HttpOpenRequestA failed %u\n", GetLastError() );
7787 
7788     pInternetSetStatusCallbackA( req, header_cb );
7789 
7790     SetLastError( 0xdeadbeef );
7791     ret = HttpSendRequestA( req, NULL, 0, NULL, 0 );
7792     err = GetLastError();
7793     ok( !ret, "HttpSendRequestA succeeded\n" );
7794     ok( err == ERROR_IO_PENDING, "got %u\n", ERROR_IO_PENDING );
7795 
7796     WaitForSingleObject( wait, 5000 );
7797     WaitForSingleObject( wait, 5000 );
7798 
7799     InternetCloseHandle( req );
7800     InternetCloseHandle( con );
7801     InternetCloseHandle( ses );
7802     CloseHandle( wait );
7803 }
7804 
7805 START_TEST(http)
7806 {
7807     HMODULE hdll;
7808     hdll = GetModuleHandleA("wininet.dll");
7809 
7810     if(!GetProcAddress(hdll, "InternetGetCookieExW")) {
7811         win_skip("Too old IE (older than 6.0)\n");
7812         return;
7813     }
7814 
7815     pInternetSetStatusCallbackA = (void*)GetProcAddress(hdll, "InternetSetStatusCallbackA");
7816     pInternetSetStatusCallbackW = (void*)GetProcAddress(hdll, "InternetSetStatusCallbackW");
7817     pInternetGetSecurityInfoByURLA = (void*)GetProcAddress(hdll, "InternetGetSecurityInfoByURLA");
7818 
7819     if(!pInternetGetSecurityInfoByURLA) {
7820         is_ie7plus = FALSE;
7821         win_skip("IE6 found. It's too old for some tests.\n");
7822     }
7823 
7824     init_events();
7825     init_status_tests();
7826     test_InternetCloseHandle();
7827     InternetReadFile_test(INTERNET_FLAG_ASYNC, &test_data[0]);
7828     InternetReadFile_test(INTERNET_FLAG_ASYNC, &test_data[1]);
7829     InternetReadFile_test(0, &test_data[1]);
7830     InternetReadFile_test(INTERNET_FLAG_ASYNC, &test_data[2]);
7831     test_security_flags();
7832     InternetReadFile_test(0, &test_data[2]);
7833     InternetReadFileExA_test(INTERNET_FLAG_ASYNC);
7834     test_open_url_async();
7835     test_async_HttpSendRequestEx(&notification_data[0]);
7836     test_async_HttpSendRequestEx(&notification_data[1]);
7837     test_async_HttpSendRequestEx(&notification_data[2]);
7838     test_async_HttpSendRequestEx(&notification_data[3]);
7839     InternetOpenRequest_test();
7840     test_http_cache();
7841     InternetLockRequestFile_test();
7842     InternetOpenUrlA_test();
7843     HttpHeaders_test();
7844     test_http_connection();
7845     test_secure_connection();
7846     test_user_agent_header();
7847     test_bogus_accept_types_array();
7848     InternetReadFile_chunked_test();
7849     HttpSendRequestEx_test();
7850     InternetReadFile_test(INTERNET_FLAG_ASYNC, &test_data[3]);
7851     test_connection_failure();
7852     test_default_service_port();
7853     test_concurrent_header_access();
7854     free_events();
7855 }
7856