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