jscript: Rename jsheap_t to heap_pool_t.
[wine] / dlls / wininet / tests / http.c
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
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wininet.h"
30 #include "winineti.h"
31 #include "winsock.h"
32
33 #include "wine/test.h"
34
35 #define TEST_URL "http://test.winehq.org/tests/hello.html"
36
37 static BOOL first_connection_to_test_url = TRUE;
38
39 /* Adapted from dlls/urlmon/tests/protocol.c */
40
41 #define SET_EXPECT2(status, num) \
42     expect[status] = num
43
44 #define SET_EXPECT(status) \
45     SET_EXPECT2(status, 1)
46
47 #define SET_OPTIONAL2(status, num) \
48     optional[status] = num
49
50 #define SET_OPTIONAL(status) \
51     SET_OPTIONAL2(status, 1)
52
53 /* SET_WINE_ALLOW's should be used with an appropriate
54  * todo_wine CHECK_NOTIFIED at a later point in the code */
55 #define SET_WINE_ALLOW2(status, num) \
56     wine_allow[status] = num
57
58 #define SET_WINE_ALLOW(status) \
59     SET_WINE_ALLOW2(status, 1)
60
61 #define CHECK_EXPECT(status) \
62     do { \
63         if (!expect[status] && !optional[status] && wine_allow[status]) \
64         { \
65             todo_wine ok(expect[status], "unexpected status %d (%s)\n", status, \
66                          status < MAX_INTERNET_STATUS && status_string[status] ? \
67                          status_string[status] : "unknown");            \
68             wine_allow[status]--; \
69         } \
70         else \
71         { \
72             ok(expect[status] || optional[status], "unexpected status %d (%s)\n", status,   \
73                status < MAX_INTERNET_STATUS && status_string[status] ? \
74                status_string[status] : "unknown");                      \
75             if (expect[status]) expect[status]--; \
76             else optional[status]--; \
77         } \
78         notified[status]++; \
79     }while(0)
80
81 /* CLEAR_NOTIFIED used in cases when notification behavior
82  * differs between Windows versions */
83 #define CLEAR_NOTIFIED(status) \
84     expect[status] = optional[status] = wine_allow[status] = notified[status] = 0;
85
86 #define CHECK_NOTIFIED2(status, num) \
87     do { \
88         ok(notified[status] + optional[status] == (num), \
89            "expected status %d (%s) %d times, received %d times\n", \
90            status, status < MAX_INTERNET_STATUS && status_string[status] ? \
91            status_string[status] : "unknown", (num), notified[status]); \
92         CLEAR_NOTIFIED(status);                                         \
93     }while(0)
94
95 #define CHECK_NOTIFIED(status) \
96     CHECK_NOTIFIED2(status, 1)
97
98 #define CHECK_NOT_NOTIFIED(status) \
99     CHECK_NOTIFIED2(status, 0)
100
101 #define MAX_INTERNET_STATUS (INTERNET_STATUS_COOKIE_HISTORY+1)
102 static int expect[MAX_INTERNET_STATUS], optional[MAX_INTERNET_STATUS],
103     wine_allow[MAX_INTERNET_STATUS], notified[MAX_INTERNET_STATUS];
104 static const char *status_string[MAX_INTERNET_STATUS];
105
106 static HANDLE hCompleteEvent, conn_close_event;
107 static DWORD req_error;
108
109 #define TESTF_REDIRECT      0x01
110 #define TESTF_COMPRESSED    0x02
111 #define TESTF_CHUNKED       0x04
112
113 typedef struct {
114     const char *url;
115     const char *redirected_url;
116     const char *host;
117     const char *path;
118     const char *headers;
119     DWORD flags;
120     const char *post_data;
121     const char *content;
122 } test_data_t;
123
124 static const test_data_t test_data[] = {
125     {
126         "http://test.winehq.org/tests/data.php",
127         "http://test.winehq.org/tests/data.php",
128         "test.winehq.org",
129         "/tests/data.php",
130         "",
131         TESTF_CHUNKED
132     },
133     {
134         "http://test.winehq.org/tests/redirect",
135         "http://test.winehq.org/tests/hello.html",
136         "test.winehq.org",
137         "/tests/redirect",
138         "",
139         TESTF_REDIRECT
140     },
141     {
142         "http://www.codeweavers.com/",
143         "http://www.codeweavers.com/",
144         "www.codeweavers.com",
145         "",
146         "Accept-Encoding: gzip, deflate",
147         TESTF_COMPRESSED
148     },
149     {
150         "http://test.winehq.org/tests/post.php",
151         "http://test.winehq.org/tests/post.php",
152         "test.winehq.org",
153         "/tests/post.php",
154         "Content-Type: application/x-www-form-urlencoded",
155         0,
156         "mode=Test",
157         "mode => Test\n"
158     }
159 };
160
161 static INTERNET_STATUS_CALLBACK (WINAPI *pInternetSetStatusCallbackA)(HINTERNET ,INTERNET_STATUS_CALLBACK);
162 static BOOL (WINAPI *pInternetGetSecurityInfoByURLA)(LPSTR,PCCERT_CHAIN_CONTEXT*,DWORD*);
163
164 static int strcmp_wa(LPCWSTR strw, const char *stra)
165 {
166     WCHAR buf[512];
167     MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)/sizeof(WCHAR));
168     return lstrcmpW(strw, buf);
169 }
170
171 static BOOL proxy_active(void)
172 {
173     HKEY internet_settings;
174     DWORD proxy_enable;
175     DWORD size;
176
177     if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
178                       0, KEY_QUERY_VALUE, &internet_settings) != ERROR_SUCCESS)
179         return FALSE;
180
181     size = sizeof(DWORD);
182     if (RegQueryValueExA(internet_settings, "ProxyEnable", NULL, NULL, (LPBYTE) &proxy_enable, &size) != ERROR_SUCCESS)
183         proxy_enable = 0;
184
185     RegCloseKey(internet_settings);
186
187     return proxy_enable != 0;
188 }
189
190 #define test_status_code(a,b) _test_status_code(__LINE__,a,b)
191 static void _test_status_code(unsigned line, HINTERNET req, DWORD excode)
192 {
193     DWORD code, size, index;
194     char exbuf[10], bufa[10];
195     WCHAR bufw[10];
196     BOOL res;
197
198     code = 0xdeadbeef;
199     size = sizeof(code);
200     res = HttpQueryInfoA(req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &code, &size, NULL);
201     ok_(__FILE__,line)(res, "[1] HttpQueryInfoA(HTTP_QUERY_STATUS_CODE|number) failed: %u\n", GetLastError());
202     ok_(__FILE__,line)(code == excode, "code = %d, expected %d\n", code, excode);
203     ok_(__FILE__,line)(size == sizeof(code), "size = %u\n", size);
204
205     code = 0xdeadbeef;
206     index = 0;
207     size = sizeof(code);
208     res = HttpQueryInfoA(req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &code, &size, &index);
209     ok_(__FILE__,line)(res, "[2] HttpQueryInfoA(HTTP_QUERY_STATUS_CODE|number index) failed: %u\n", GetLastError());
210     ok_(__FILE__,line)(code == excode, "code = %d, expected %d\n", code, excode);
211     ok_(__FILE__,line)(!index, "index = %d, expected 0\n", code);
212     ok_(__FILE__,line)(size == sizeof(code), "size = %u\n", size);
213
214     sprintf(exbuf, "%u", excode);
215
216     size = sizeof(bufa);
217     res = HttpQueryInfoA(req, HTTP_QUERY_STATUS_CODE, bufa, &size, NULL);
218     ok_(__FILE__,line)(res, "[3] HttpQueryInfoA(HTTP_QUERY_STATUS_CODE) failed: %u\n", GetLastError());
219     ok_(__FILE__,line)(!strcmp(bufa, exbuf), "unexpected status code %s, expected %s\n", bufa, exbuf);
220     ok_(__FILE__,line)(size == strlen(exbuf), "unexpected size %d for \"%s\"\n", size, exbuf);
221
222     size = 0;
223     res = HttpQueryInfoA(req, HTTP_QUERY_STATUS_CODE, NULL, &size, NULL);
224     ok_(__FILE__,line)(!res && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
225                        "[4] HttpQueryInfoA(HTTP_QUERY_STATUS_CODE) failed: %u\n", GetLastError());
226     ok_(__FILE__,line)(size == strlen(exbuf)+1, "unexpected size %d for \"%s\"\n", size, exbuf);
227
228     size = sizeof(bufw);
229     res = HttpQueryInfoW(req, HTTP_QUERY_STATUS_CODE, bufw, &size, NULL);
230     ok_(__FILE__,line)(res, "[5] HttpQueryInfoW(HTTP_QUERY_STATUS_CODE) failed: %u\n", GetLastError());
231     ok_(__FILE__,line)(!strcmp_wa(bufw, exbuf), "unexpected status code %s, expected %s\n", bufa, exbuf);
232     ok_(__FILE__,line)(size == strlen(exbuf)*sizeof(WCHAR), "unexpected size %d for \"%s\"\n", size, exbuf);
233
234     size = 0;
235     res = HttpQueryInfoW(req, HTTP_QUERY_STATUS_CODE, bufw, &size, NULL);
236     ok_(__FILE__,line)(!res && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
237                        "[6] HttpQueryInfoW(HTTP_QUERY_STATUS_CODE) failed: %u\n", GetLastError());
238     ok_(__FILE__,line)(size == (strlen(exbuf)+1)*sizeof(WCHAR), "unexpected size %d for \"%s\"\n", size, exbuf);
239
240     if(0) {
241     size = sizeof(bufw);
242     res = HttpQueryInfoW(req, HTTP_QUERY_STATUS_CODE, NULL, &size, NULL);
243     ok(!res && GetLastError() == ERROR_INVALID_PARAMETER, "HttpQueryInfo(HTTP_QUERY_STATUS_CODE) failed: %u\n", GetLastError());
244     ok(size == sizeof(bufw), "unexpected size %d\n", size);
245     }
246
247     code = 0xdeadbeef;
248     index = 1;
249     size = sizeof(code);
250     res = HttpQueryInfoA(req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &code, &size, &index);
251     ok_(__FILE__,line)(!res && GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND,
252                        "[7] HttpQueryInfoA failed: %x(%d)\n", res, GetLastError());
253
254     code = 0xdeadbeef;
255     size = sizeof(code);
256     res = HttpQueryInfoA(req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_REQUEST_HEADERS, &code, &size, NULL);
257     ok_(__FILE__,line)(!res && GetLastError() == ERROR_HTTP_INVALID_QUERY_REQUEST,
258                        "[8] HttpQueryInfoA failed: %x(%d)\n", res, GetLastError());
259 }
260
261 #define test_request_flags(a,b) _test_request_flags(__LINE__,a,b,FALSE)
262 #define test_request_flags_todo(a,b) _test_request_flags(__LINE__,a,b,TRUE)
263 static void _test_request_flags(unsigned line, HINTERNET req, DWORD exflags, BOOL is_todo)
264 {
265     DWORD flags, size;
266     BOOL res;
267
268     flags = 0xdeadbeef;
269     size = sizeof(flags);
270     res = InternetQueryOptionW(req, INTERNET_OPTION_REQUEST_FLAGS, &flags, &size);
271     ok_(__FILE__,line)(res, "InternetQueryOptionW(INTERNET_OPTION_REQUEST_FLAGS) failed: %u\n", GetLastError());
272
273     /* FIXME: Remove once we have INTERNET_REQFLAG_CACHE_WRITE_DISABLED implementation */
274     flags &= ~INTERNET_REQFLAG_CACHE_WRITE_DISABLED;
275     if(!is_todo)
276         ok_(__FILE__,line)(flags == exflags, "flags = %x, expected %x\n", flags, exflags);
277     else
278         todo_wine ok_(__FILE__,line)(flags == exflags, "flags = %x, expected %x\n", flags, exflags);
279 }
280
281 #define test_http_version(a) _test_http_version(__LINE__,a)
282 static void _test_http_version(unsigned line, HINTERNET req)
283 {
284     HTTP_VERSION_INFO v = {0xdeadbeef, 0xdeadbeef};
285     DWORD size;
286     BOOL res;
287
288     size = sizeof(v);
289     res = InternetQueryOptionW(req, INTERNET_OPTION_HTTP_VERSION, &v, &size);
290     ok_(__FILE__,line)(res, "InternetQueryOptionW(INTERNET_OPTION_HTTP_VERSION) failed: %u\n", GetLastError());
291     ok_(__FILE__,line)(v.dwMajorVersion == 1, "dwMajorVersion = %d\n", v.dwMajorVersion);
292     ok_(__FILE__,line)(v.dwMinorVersion == 1, "dwMinorVersion = %d\n", v.dwMinorVersion);
293 }
294
295 static int close_handle_cnt;
296
297 static VOID WINAPI callback(
298      HINTERNET hInternet,
299      DWORD_PTR dwContext,
300      DWORD dwInternetStatus,
301      LPVOID lpvStatusInformation,
302      DWORD dwStatusInformationLength
303 )
304 {
305     CHECK_EXPECT(dwInternetStatus);
306     switch (dwInternetStatus)
307     {
308         case INTERNET_STATUS_RESOLVING_NAME:
309             trace("%04x:Callback %p 0x%lx INTERNET_STATUS_RESOLVING_NAME \"%s\" %d\n",
310                 GetCurrentThreadId(), hInternet, dwContext,
311                 (LPCSTR)lpvStatusInformation,dwStatusInformationLength);
312             *(LPSTR)lpvStatusInformation = '\0';
313             break;
314         case INTERNET_STATUS_NAME_RESOLVED:
315             trace("%04x:Callback %p 0x%lx INTERNET_STATUS_NAME_RESOLVED \"%s\" %d\n",
316                 GetCurrentThreadId(), hInternet, dwContext,
317                 (LPCSTR)lpvStatusInformation,dwStatusInformationLength);
318             *(LPSTR)lpvStatusInformation = '\0';
319             break;
320         case INTERNET_STATUS_CONNECTING_TO_SERVER:
321             trace("%04x:Callback %p 0x%lx INTERNET_STATUS_CONNECTING_TO_SERVER \"%s\" %d\n",
322                 GetCurrentThreadId(), hInternet, dwContext,
323                 (LPCSTR)lpvStatusInformation,dwStatusInformationLength);
324             *(LPSTR)lpvStatusInformation = '\0';
325             break;
326         case INTERNET_STATUS_CONNECTED_TO_SERVER:
327             trace("%04x:Callback %p 0x%lx INTERNET_STATUS_CONNECTED_TO_SERVER \"%s\" %d\n",
328                 GetCurrentThreadId(), hInternet, dwContext,
329                 (LPCSTR)lpvStatusInformation,dwStatusInformationLength);
330             *(LPSTR)lpvStatusInformation = '\0';
331             break;
332         case INTERNET_STATUS_SENDING_REQUEST:
333             trace("%04x:Callback %p 0x%lx INTERNET_STATUS_SENDING_REQUEST %p %d\n",
334                 GetCurrentThreadId(), hInternet, dwContext,
335                 lpvStatusInformation,dwStatusInformationLength);
336             break;
337         case INTERNET_STATUS_REQUEST_SENT:
338             ok(dwStatusInformationLength == sizeof(DWORD),
339                 "info length should be sizeof(DWORD) instead of %d\n",
340                 dwStatusInformationLength);
341             trace("%04x:Callback %p 0x%lx INTERNET_STATUS_REQUEST_SENT 0x%x %d\n",
342                 GetCurrentThreadId(), hInternet, dwContext,
343                 *(DWORD *)lpvStatusInformation,dwStatusInformationLength);
344             break;
345         case INTERNET_STATUS_RECEIVING_RESPONSE:
346             trace("%04x:Callback %p 0x%lx INTERNET_STATUS_RECEIVING_RESPONSE %p %d\n",
347                 GetCurrentThreadId(), hInternet, dwContext,
348                 lpvStatusInformation,dwStatusInformationLength);
349             break;
350         case INTERNET_STATUS_RESPONSE_RECEIVED:
351             ok(dwStatusInformationLength == sizeof(DWORD),
352                 "info length should be sizeof(DWORD) instead of %d\n",
353                 dwStatusInformationLength);
354             trace("%04x:Callback %p 0x%lx INTERNET_STATUS_RESPONSE_RECEIVED 0x%x %d\n",
355                 GetCurrentThreadId(), hInternet, dwContext,
356                 *(DWORD *)lpvStatusInformation,dwStatusInformationLength);
357             break;
358         case INTERNET_STATUS_CTL_RESPONSE_RECEIVED:
359             trace("%04x:Callback %p 0x%lx INTERNET_STATUS_CTL_RESPONSE_RECEIVED %p %d\n",
360                 GetCurrentThreadId(), hInternet,dwContext,
361                 lpvStatusInformation,dwStatusInformationLength);
362             break;
363         case INTERNET_STATUS_PREFETCH:
364             trace("%04x:Callback %p 0x%lx INTERNET_STATUS_PREFETCH %p %d\n",
365                 GetCurrentThreadId(), hInternet, dwContext,
366                 lpvStatusInformation,dwStatusInformationLength);
367             break;
368         case INTERNET_STATUS_CLOSING_CONNECTION:
369             trace("%04x:Callback %p 0x%lx INTERNET_STATUS_CLOSING_CONNECTION %p %d\n",
370                 GetCurrentThreadId(), hInternet, dwContext,
371                 lpvStatusInformation,dwStatusInformationLength);
372             break;
373         case INTERNET_STATUS_CONNECTION_CLOSED:
374             trace("%04x:Callback %p 0x%lx INTERNET_STATUS_CONNECTION_CLOSED %p %d\n",
375                 GetCurrentThreadId(), hInternet, dwContext,
376                 lpvStatusInformation,dwStatusInformationLength);
377             break;
378         case INTERNET_STATUS_HANDLE_CREATED:
379             ok(dwStatusInformationLength == sizeof(HINTERNET),
380                 "info length should be sizeof(HINTERNET) instead of %d\n",
381                 dwStatusInformationLength);
382             trace("%04x:Callback %p 0x%lx INTERNET_STATUS_HANDLE_CREATED %p %d\n",
383                 GetCurrentThreadId(), hInternet, dwContext,
384                 *(HINTERNET *)lpvStatusInformation,dwStatusInformationLength);
385             CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
386             SET_EXPECT(INTERNET_STATUS_DETECTING_PROXY);
387             break;
388         case INTERNET_STATUS_HANDLE_CLOSING:
389             ok(dwStatusInformationLength == sizeof(HINTERNET),
390                 "info length should be sizeof(HINTERNET) instead of %d\n",
391                 dwStatusInformationLength);
392             trace("%04x:Callback %p 0x%lx INTERNET_STATUS_HANDLE_CLOSING %p %d\n",
393                 GetCurrentThreadId(), hInternet, dwContext,
394                 *(HINTERNET *)lpvStatusInformation, dwStatusInformationLength);
395             if(!--close_handle_cnt)
396                 SetEvent(hCompleteEvent);
397             break;
398         case INTERNET_STATUS_REQUEST_COMPLETE:
399         {
400             INTERNET_ASYNC_RESULT *iar = (INTERNET_ASYNC_RESULT *)lpvStatusInformation;
401             ok(dwStatusInformationLength == sizeof(INTERNET_ASYNC_RESULT),
402                 "info length should be sizeof(INTERNET_ASYNC_RESULT) instead of %d\n",
403                 dwStatusInformationLength);
404             ok(iar->dwResult == 1 || iar->dwResult == 0, "iar->dwResult = %ld\n", iar->dwResult);
405             trace("%04x:Callback %p 0x%lx INTERNET_STATUS_REQUEST_COMPLETE {%ld,%d} %d\n",
406                 GetCurrentThreadId(), hInternet, dwContext,
407                 iar->dwResult,iar->dwError,dwStatusInformationLength);
408             req_error = iar->dwError;
409             SetEvent(hCompleteEvent);
410             break;
411         }
412         case INTERNET_STATUS_REDIRECT:
413             trace("%04x:Callback %p 0x%lx INTERNET_STATUS_REDIRECT \"%s\" %d\n",
414                 GetCurrentThreadId(), hInternet, dwContext,
415                 (LPCSTR)lpvStatusInformation, dwStatusInformationLength);
416             *(LPSTR)lpvStatusInformation = '\0';
417             CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
418             SET_EXPECT(INTERNET_STATUS_DETECTING_PROXY);
419             break;
420         case INTERNET_STATUS_INTERMEDIATE_RESPONSE:
421             trace("%04x:Callback %p 0x%lx INTERNET_STATUS_INTERMEDIATE_RESPONSE %p %d\n",
422                 GetCurrentThreadId(), hInternet, dwContext,
423                 lpvStatusInformation, dwStatusInformationLength);
424             break;
425         default:
426             trace("%04x:Callback %p 0x%lx %d %p %d\n",
427                 GetCurrentThreadId(), hInternet, dwContext, dwInternetStatus,
428                 lpvStatusInformation, dwStatusInformationLength);
429     }
430 }
431
432 static void close_async_handle(HINTERNET handle, HANDLE complete_event, int handle_cnt)
433 {
434     BOOL res;
435
436     close_handle_cnt = handle_cnt;
437
438     SET_EXPECT2(INTERNET_STATUS_HANDLE_CLOSING, handle_cnt);
439     res = InternetCloseHandle(handle);
440     ok(res, "InternetCloseHandle failed: %u\n", GetLastError());
441     WaitForSingleObject(hCompleteEvent, INFINITE);
442     CHECK_NOTIFIED2(INTERNET_STATUS_HANDLE_CLOSING, handle_cnt);
443     SET_EXPECT2(INTERNET_STATUS_HANDLE_CLOSING, handle_cnt);
444 }
445
446 static void InternetReadFile_test(int flags, const test_data_t *test)
447 {
448     char *post_data = NULL;
449     BOOL res, on_async = TRUE;
450     CHAR buffer[4000];
451     DWORD length, exlen = 0, post_len = 0;
452     const char *types[2] = { "*", NULL };
453     HINTERNET hi, hic = 0, hor = 0;
454
455     hCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
456
457     trace("Starting InternetReadFile test with flags 0x%x on url %s\n",flags,test->url);
458
459     trace("InternetOpenA <--\n");
460     hi = InternetOpenA((test->flags & TESTF_COMPRESSED) ? "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" : "",
461             INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, flags);
462     ok((hi != 0x0),"InternetOpen failed with error %u\n", GetLastError());
463     trace("InternetOpenA -->\n");
464
465     if (hi == 0x0) goto abort;
466
467     pInternetSetStatusCallbackA(hi,&callback);
468
469     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
470
471     trace("InternetConnectA <--\n");
472     hic=InternetConnectA(hi, test->host, INTERNET_INVALID_PORT_NUMBER,
473                          NULL, NULL, INTERNET_SERVICE_HTTP, 0x0, 0xdeadbeef);
474     ok((hic != 0x0),"InternetConnect failed with error %u\n", GetLastError());
475     trace("InternetConnectA -->\n");
476
477     if (hic == 0x0) goto abort;
478
479     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
480     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
481
482     trace("HttpOpenRequestA <--\n");
483     hor = HttpOpenRequestA(hic, test->post_data ? "POST" : "GET", test->path, NULL, NULL, types,
484                            INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RELOAD,
485                            0xdeadbead);
486     if (hor == 0x0 && GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED) {
487         /*
488          * If the internet name can't be resolved we are probably behind
489          * a firewall or in some other way not directly connected to the
490          * Internet. Not enough reason to fail the test. Just ignore and
491          * abort.
492          */
493     } else  {
494         ok((hor != 0x0),"HttpOpenRequest failed with error %u\n", GetLastError());
495     }
496     trace("HttpOpenRequestA -->\n");
497
498     if (hor == 0x0) goto abort;
499
500     test_request_flags(hor, INTERNET_REQFLAG_NO_HEADERS);
501
502     length = sizeof(buffer);
503     res = InternetQueryOptionA(hor, INTERNET_OPTION_URL, buffer, &length);
504     ok(res, "InternetQueryOptionA(INTERNET_OPTION_URL) failed: %u\n", GetLastError());
505     ok(!strcmp(buffer, test->url), "Wrong URL %s, expected %s\n", buffer, test->url);
506
507     length = sizeof(buffer);
508     res = HttpQueryInfoA(hor, HTTP_QUERY_RAW_HEADERS, buffer, &length, 0x0);
509     ok(res, "HttpQueryInfoA(HTTP_QUERY_RAW_HEADERS) failed with error %d\n", GetLastError());
510     ok(length == 0, "HTTP_QUERY_RAW_HEADERS: expected length 0, but got %d\n", length);
511     ok(!strcmp(buffer, ""), "HTTP_QUERY_RAW_HEADERS: expected string \"\", but got \"%s\"\n", buffer);
512
513     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
514     CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME);
515     CHECK_NOT_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED);
516     SET_OPTIONAL2(INTERNET_STATUS_COOKIE_SENT,2);
517     SET_OPTIONAL2(INTERNET_STATUS_COOKIE_RECEIVED,2);
518     if (first_connection_to_test_url)
519     {
520         SET_EXPECT(INTERNET_STATUS_RESOLVING_NAME);
521         SET_EXPECT(INTERNET_STATUS_NAME_RESOLVED);
522     }
523     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
524     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
525     SET_EXPECT2(INTERNET_STATUS_SENDING_REQUEST, (test->flags & TESTF_REDIRECT) ? 2 : 1);
526     SET_EXPECT2(INTERNET_STATUS_REQUEST_SENT, (test->flags & TESTF_REDIRECT) ? 2 : 1);
527     SET_EXPECT2(INTERNET_STATUS_RECEIVING_RESPONSE, (test->flags & TESTF_REDIRECT) ? 2 : 1);
528     SET_EXPECT2(INTERNET_STATUS_RESPONSE_RECEIVED, (test->flags & TESTF_REDIRECT) ? 2 : 1);
529     if(test->flags & TESTF_REDIRECT) {
530         SET_OPTIONAL2(INTERNET_STATUS_CLOSING_CONNECTION, 2);
531         SET_OPTIONAL2(INTERNET_STATUS_CONNECTION_CLOSED, 2);
532     }
533     SET_EXPECT(INTERNET_STATUS_REDIRECT);
534     SET_OPTIONAL(INTERNET_STATUS_CONNECTING_TO_SERVER);
535     SET_OPTIONAL(INTERNET_STATUS_CONNECTED_TO_SERVER);
536     if (flags & INTERNET_FLAG_ASYNC)
537         SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
538
539     if(test->flags & TESTF_COMPRESSED) {
540         BOOL b = TRUE;
541
542         res = InternetSetOption(hor, INTERNET_OPTION_HTTP_DECODING, &b, sizeof(b));
543         ok(res || broken(!res && GetLastError() == ERROR_INTERNET_INVALID_OPTION),
544            "InternetSetOption failed: %u\n", GetLastError());
545         if(!res)
546             goto abort;
547     }
548
549     test_status_code(hor, 0);
550
551     trace("HttpSendRequestA -->\n");
552     if(test->post_data) {
553         post_len = strlen(test->post_data);
554         post_data = HeapAlloc(GetProcessHeap(), 0, post_len);
555         memcpy(post_data, test->post_data, post_len);
556     }
557     SetLastError(0xdeadbeef);
558     res = HttpSendRequestA(hor, test->headers, -1, post_data, post_len);
559     if (flags & INTERNET_FLAG_ASYNC)
560         ok(!res && (GetLastError() == ERROR_IO_PENDING),
561             "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n");
562     else
563         ok(res || (GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED),
564            "Synchronous HttpSendRequest returning 0, error %u\n", GetLastError());
565     trace("HttpSendRequestA <--\n");
566
567     if (flags & INTERNET_FLAG_ASYNC) {
568         WaitForSingleObject(hCompleteEvent, INFINITE);
569         ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error);
570     }
571     HeapFree(GetProcessHeap(), 0, post_data);
572
573     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
574     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_RECEIVED);
575     if (first_connection_to_test_url)
576     {
577         if (! proxy_active())
578         {
579             CHECK_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME);
580             CHECK_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED);
581         }
582         else
583         {
584             CLEAR_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME);
585             CLEAR_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED);
586         }
587     }
588     else
589     {
590         CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME);
591         CHECK_NOT_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED);
592     }
593     CHECK_NOTIFIED2(INTERNET_STATUS_SENDING_REQUEST, (test->flags & TESTF_REDIRECT) ? 2 : 1);
594     CHECK_NOTIFIED2(INTERNET_STATUS_REQUEST_SENT, (test->flags & TESTF_REDIRECT) ? 2 : 1);
595     CHECK_NOTIFIED2(INTERNET_STATUS_RECEIVING_RESPONSE, (test->flags & TESTF_REDIRECT) ? 2 : 1);
596     CHECK_NOTIFIED2(INTERNET_STATUS_RESPONSE_RECEIVED, (test->flags & TESTF_REDIRECT) ? 2 : 1);
597     if(test->flags & TESTF_REDIRECT)
598         CHECK_NOTIFIED(INTERNET_STATUS_REDIRECT);
599     if (flags & INTERNET_FLAG_ASYNC)
600         CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
601     /* Sent on WinXP only if first_connection_to_test_url is TRUE, on Win98 always sent */
602     CLEAR_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
603     CLEAR_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
604
605     test_request_flags(hor, 0);
606
607     length = 100;
608     res = InternetQueryOptionA(hor,INTERNET_OPTION_URL,buffer,&length);
609     ok(res, "InternetQueryOptionA(INTERNET_OPTION_URL) failed with error %d\n", GetLastError());
610
611     length = sizeof(buffer);
612     res = HttpQueryInfoA(hor,HTTP_QUERY_RAW_HEADERS,buffer,&length,0x0);
613     ok(res, "HttpQueryInfoA(HTTP_QUERY_RAW_HEADERS) failed with error %d\n", GetLastError());
614     buffer[length]=0;
615
616     length = sizeof(buffer);
617     res = InternetQueryOptionA(hor, INTERNET_OPTION_URL, buffer, &length);
618     ok(res, "InternetQueryOptionA(INTERNET_OPTION_URL) failed: %u\n", GetLastError());
619     ok(!strcmp(buffer, test->redirected_url), "Wrong URL %s\n", buffer);
620
621     length = 16;
622     res = HttpQueryInfoA(hor,HTTP_QUERY_CONTENT_LENGTH,&buffer,&length,0x0);
623     trace("Option HTTP_QUERY_CONTENT_LENGTH -> %i  %s  (%u)\n",res,buffer,GetLastError());
624     if(test->flags & TESTF_COMPRESSED)
625         ok(!res && GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND,
626            "expected ERROR_HTTP_HEADER_NOT_FOUND, got %x (%u)\n", res, GetLastError());
627
628     length = 100;
629     res = HttpQueryInfoA(hor,HTTP_QUERY_CONTENT_TYPE,buffer,&length,0x0);
630     buffer[length]=0;
631     trace("Option HTTP_QUERY_CONTENT_TYPE -> %i  %s\n",res,buffer);
632
633     length = 100;
634     res = HttpQueryInfoA(hor,HTTP_QUERY_CONTENT_ENCODING,buffer,&length,0x0);
635     buffer[length]=0;
636     trace("Option HTTP_QUERY_CONTENT_ENCODING -> %i  %s\n",res,buffer);
637
638     SetLastError(0xdeadbeef);
639     res = InternetReadFile(NULL, buffer, 100, &length);
640     ok(!res, "InternetReadFile should have failed\n");
641     ok(GetLastError() == ERROR_INVALID_HANDLE,
642         "InternetReadFile should have set last error to ERROR_INVALID_HANDLE instead of %u\n",
643         GetLastError());
644
645     length = 100;
646     trace("Entering Query loop\n");
647
648     while (TRUE)
649     {
650         if (flags & INTERNET_FLAG_ASYNC)
651             SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
652         length = 0;
653         res = InternetQueryDataAvailable(hor,&length,0x0,0x0);
654         if (flags & INTERNET_FLAG_ASYNC)
655         {
656             if (res)
657             {
658                 CHECK_NOT_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
659                 if(exlen) {
660                     ok(length >= exlen, "length %u < exlen %u\n", length, exlen);
661                     exlen = 0;
662                 }
663             }
664             else if (GetLastError() == ERROR_IO_PENDING)
665             {
666                 trace("PENDING\n");
667                 /* on some tests, InternetQueryDataAvailable returns non-zero length and ERROR_IO_PENDING */
668                 if(!(test->flags & TESTF_CHUNKED))
669                     ok(!length, "InternetQueryDataAvailable returned ERROR_IO_PENDING and %u length\n", length);
670                 WaitForSingleObject(hCompleteEvent, INFINITE);
671                 exlen = length;
672                 ok(exlen, "length = 0\n");
673                 CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
674                 ok(req_error, "req_error = 0\n");
675                 continue;
676             }else {
677                 ok(0, "InternetQueryDataAvailable failed: %u\n", GetLastError());
678             }
679         }else {
680             ok(res, "InternetQueryDataAvailable failed: %u\n", GetLastError());
681         }
682         trace("LENGTH %d\n", length);
683         if(test->flags & TESTF_CHUNKED)
684             ok(length <= 8192, "length = %d, expected <= 8192\n", length);
685         if (length)
686         {
687             char *buffer;
688             buffer = HeapAlloc(GetProcessHeap(),0,length+1);
689
690             res = InternetReadFile(hor,buffer,length,&length);
691
692             buffer[length]=0;
693
694             trace("ReadFile -> %s %i\n",res?"TRUE":"FALSE",length);
695
696             if(test->content)
697                 ok(!strcmp(buffer, test->content), "buffer = '%s', expected '%s'\n", buffer, test->content);
698             HeapFree(GetProcessHeap(),0,buffer);
699         }else {
700             ok(!on_async, "Returned zero size in response to request complete\n");
701             break;
702         }
703         on_async = FALSE;
704     }
705     if(test->flags & TESTF_REDIRECT) {
706         CHECK_NOTIFIED2(INTERNET_STATUS_CLOSING_CONNECTION, 2);
707         CHECK_NOTIFIED2(INTERNET_STATUS_CONNECTION_CLOSED, 2);
708     }
709 abort:
710     trace("aborting\n");
711     close_async_handle(hi, hCompleteEvent, 2);
712     CloseHandle(hCompleteEvent);
713     first_connection_to_test_url = FALSE;
714 }
715
716 static void InternetReadFile_chunked_test(void)
717 {
718     BOOL res;
719     CHAR buffer[4000];
720     DWORD length;
721     const char *types[2] = { "*", NULL };
722     HINTERNET hi, hic = 0, hor = 0;
723
724     trace("Starting InternetReadFile chunked test\n");
725
726     trace("InternetOpenA <--\n");
727     hi = InternetOpenA("", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
728     ok((hi != 0x0),"InternetOpen failed with error %u\n", GetLastError());
729     trace("InternetOpenA -->\n");
730
731     if (hi == 0x0) goto abort;
732
733     trace("InternetConnectA <--\n");
734     hic=InternetConnectA(hi, "test.winehq.org", INTERNET_INVALID_PORT_NUMBER,
735                          NULL, NULL, INTERNET_SERVICE_HTTP, 0x0, 0xdeadbeef);
736     ok((hic != 0x0),"InternetConnect failed with error %u\n", GetLastError());
737     trace("InternetConnectA -->\n");
738
739     if (hic == 0x0) goto abort;
740
741     trace("HttpOpenRequestA <--\n");
742     hor = HttpOpenRequestA(hic, "GET", "/tests/chunked", NULL, NULL, types,
743                            INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RELOAD,
744                            0xdeadbead);
745     if (hor == 0x0 && GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED) {
746         /*
747          * If the internet name can't be resolved we are probably behind
748          * a firewall or in some other way not directly connected to the
749          * Internet. Not enough reason to fail the test. Just ignore and
750          * abort.
751          */
752     } else  {
753         ok((hor != 0x0),"HttpOpenRequest failed with error %u\n", GetLastError());
754     }
755     trace("HttpOpenRequestA -->\n");
756
757     if (hor == 0x0) goto abort;
758
759     trace("HttpSendRequestA -->\n");
760     SetLastError(0xdeadbeef);
761     res = HttpSendRequestA(hor, "", -1, NULL, 0);
762     ok(res || (GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED),
763        "Synchronous HttpSendRequest returning 0, error %u\n", GetLastError());
764     trace("HttpSendRequestA <--\n");
765
766     test_request_flags(hor, 0);
767
768     length = 100;
769     res = HttpQueryInfoA(hor,HTTP_QUERY_CONTENT_TYPE,buffer,&length,0x0);
770     buffer[length]=0;
771     trace("Option CONTENT_TYPE -> %i  %s\n",res,buffer);
772
773     SetLastError( 0xdeadbeef );
774     length = 100;
775     res = HttpQueryInfoA(hor,HTTP_QUERY_TRANSFER_ENCODING,buffer,&length,0x0);
776     buffer[length]=0;
777     trace("Option TRANSFER_ENCODING -> %i  %s\n",res,buffer);
778     ok( res || ( proxy_active() && GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND ),
779         "Failed to get TRANSFER_ENCODING option, error %u\n", GetLastError() );
780     ok( !strcmp( buffer, "chunked" ) || ( ! res && proxy_active() && GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND ),
781         "Wrong transfer encoding '%s'\n", buffer );
782
783     SetLastError( 0xdeadbeef );
784     length = 16;
785     res = HttpQueryInfoA(hor,HTTP_QUERY_CONTENT_LENGTH,&buffer,&length,0x0);
786     ok( !res, "Found CONTENT_LENGTH option '%s'\n", buffer );
787     ok( GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND, "Wrong error %u\n", GetLastError() );
788
789     length = 100;
790     trace("Entering Query loop\n");
791
792     while (TRUE)
793     {
794         res = InternetQueryDataAvailable(hor,&length,0x0,0x0);
795         ok(!(!res && length != 0),"InternetQueryDataAvailable failed with non-zero length\n");
796         ok(res, "InternetQueryDataAvailable failed, error %d\n", GetLastError());
797         trace("got %u available\n",length);
798         if (length)
799         {
800             DWORD got;
801             char *buffer = HeapAlloc(GetProcessHeap(),0,length+1);
802
803             res = InternetReadFile(hor,buffer,length,&got);
804
805             buffer[got]=0;
806             trace("ReadFile -> %i %i\n",res,got);
807             ok( length == got, "only got %u of %u available\n", got, length );
808             ok( buffer[got-1] == '\n', "received partial line '%s'\n", buffer );
809
810             HeapFree(GetProcessHeap(),0,buffer);
811             if (!got) break;
812         }
813         if (length == 0)
814             break;
815     }
816 abort:
817     trace("aborting\n");
818     if (hor != 0x0) {
819         res = InternetCloseHandle(hor);
820         ok (res, "InternetCloseHandle of handle opened by HttpOpenRequestA failed\n");
821     }
822     if (hi != 0x0) {
823         res = InternetCloseHandle(hi);
824         ok (res, "InternetCloseHandle of handle opened by InternetOpenA failed\n");
825     }
826 }
827
828 static void InternetReadFileExA_test(int flags)
829 {
830     DWORD rc;
831     DWORD length;
832     const char *types[2] = { "*", NULL };
833     HINTERNET hi, hic = 0, hor = 0;
834     INTERNET_BUFFERS inetbuffers;
835
836     hCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
837
838     trace("Starting InternetReadFileExA test with flags 0x%x\n",flags);
839
840     trace("InternetOpenA <--\n");
841     hi = InternetOpenA("", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, flags);
842     ok((hi != 0x0),"InternetOpen failed with error %u\n", GetLastError());
843     trace("InternetOpenA -->\n");
844
845     if (hi == 0x0) goto abort;
846
847     pInternetSetStatusCallbackA(hi,&callback);
848
849     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
850
851     trace("InternetConnectA <--\n");
852     hic=InternetConnectA(hi, "test.winehq.org", INTERNET_INVALID_PORT_NUMBER,
853                          NULL, NULL, INTERNET_SERVICE_HTTP, 0x0, 0xdeadbeef);
854     ok((hic != 0x0),"InternetConnect failed with error %u\n", GetLastError());
855     trace("InternetConnectA -->\n");
856
857     if (hic == 0x0) goto abort;
858
859     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
860     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
861
862     trace("HttpOpenRequestA <--\n");
863     hor = HttpOpenRequestA(hic, "GET", "/tests/redirect", NULL, NULL, types,
864                            INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RELOAD,
865                            0xdeadbead);
866     if (hor == 0x0 && GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED) {
867         /*
868          * If the internet name can't be resolved we are probably behind
869          * a firewall or in some other way not directly connected to the
870          * Internet. Not enough reason to fail the test. Just ignore and
871          * abort.
872          */
873     } else  {
874         ok((hor != 0x0),"HttpOpenRequest failed with error %u\n", GetLastError());
875     }
876     trace("HttpOpenRequestA -->\n");
877
878     if (hor == 0x0) goto abort;
879
880     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
881     CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME);
882     CHECK_NOT_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED);
883     if (first_connection_to_test_url)
884     {
885         SET_EXPECT(INTERNET_STATUS_RESOLVING_NAME);
886         SET_EXPECT(INTERNET_STATUS_NAME_RESOLVED);
887     }
888     SET_OPTIONAL2(INTERNET_STATUS_COOKIE_SENT, 2);
889     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
890     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
891     SET_EXPECT2(INTERNET_STATUS_SENDING_REQUEST, 2);
892     SET_EXPECT2(INTERNET_STATUS_REQUEST_SENT, 2);
893     SET_EXPECT2(INTERNET_STATUS_RECEIVING_RESPONSE, 2);
894     SET_EXPECT2(INTERNET_STATUS_RESPONSE_RECEIVED, 2);
895     SET_OPTIONAL2(INTERNET_STATUS_CLOSING_CONNECTION, 2);
896     SET_OPTIONAL2(INTERNET_STATUS_CONNECTION_CLOSED, 2);
897     SET_EXPECT(INTERNET_STATUS_REDIRECT);
898     SET_OPTIONAL(INTERNET_STATUS_CONNECTING_TO_SERVER);
899     SET_OPTIONAL(INTERNET_STATUS_CONNECTED_TO_SERVER);
900     if (flags & INTERNET_FLAG_ASYNC)
901         SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
902     else
903         SET_WINE_ALLOW(INTERNET_STATUS_REQUEST_COMPLETE);
904
905     trace("HttpSendRequestA -->\n");
906     SetLastError(0xdeadbeef);
907     rc = HttpSendRequestA(hor, "", -1, NULL, 0);
908     if (flags & INTERNET_FLAG_ASYNC)
909         ok(((rc == 0)&&(GetLastError() == ERROR_IO_PENDING)),
910             "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n");
911     else
912         ok((rc != 0) || GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED,
913            "Synchronous HttpSendRequest returning 0, error %u\n", GetLastError());
914     trace("HttpSendRequestA <--\n");
915
916     if (!rc && (GetLastError() == ERROR_IO_PENDING)) {
917         WaitForSingleObject(hCompleteEvent, INFINITE);
918         ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error);
919     }
920
921     if (first_connection_to_test_url)
922     {
923         CHECK_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME);
924         CHECK_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED);
925     }
926     else
927     {
928         CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME);
929         CHECK_NOT_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED);
930     }
931     CHECK_NOTIFIED2(INTERNET_STATUS_SENDING_REQUEST, 2);
932     CHECK_NOTIFIED2(INTERNET_STATUS_REQUEST_SENT, 2);
933     CHECK_NOTIFIED2(INTERNET_STATUS_RECEIVING_RESPONSE, 2);
934     CHECK_NOTIFIED2(INTERNET_STATUS_RESPONSE_RECEIVED, 2);
935     CHECK_NOTIFIED2(INTERNET_STATUS_CLOSING_CONNECTION, 2);
936     CHECK_NOTIFIED2(INTERNET_STATUS_CONNECTION_CLOSED, 2);
937     CHECK_NOTIFIED(INTERNET_STATUS_REDIRECT);
938     if (flags & INTERNET_FLAG_ASYNC)
939         CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
940     else
941         todo_wine CHECK_NOT_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
942     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
943     /* Sent on WinXP only if first_connection_to_test_url is TRUE, on Win98 always sent */
944     CLEAR_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
945     CLEAR_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
946
947     /* tests invalid dwStructSize */
948     inetbuffers.dwStructSize = sizeof(INTERNET_BUFFERS)+1;
949     inetbuffers.lpcszHeader = NULL;
950     inetbuffers.dwHeadersLength = 0;
951     inetbuffers.dwBufferLength = 10;
952     inetbuffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, 10);
953     inetbuffers.dwOffsetHigh = 1234;
954     inetbuffers.dwOffsetLow = 5678;
955     rc = InternetReadFileEx(hor, &inetbuffers, 0, 0xdeadcafe);
956     ok(!rc && (GetLastError() == ERROR_INVALID_PARAMETER),
957         "InternetReadFileEx should have failed with ERROR_INVALID_PARAMETER instead of %s, %u\n",
958         rc ? "TRUE" : "FALSE", GetLastError());
959     HeapFree(GetProcessHeap(), 0, inetbuffers.lpvBuffer);
960
961     test_request_flags(hor, 0);
962
963     /* tests to see whether lpcszHeader is used - it isn't */
964     inetbuffers.dwStructSize = sizeof(INTERNET_BUFFERS);
965     inetbuffers.lpcszHeader = (LPCTSTR)0xdeadbeef;
966     inetbuffers.dwHeadersLength = 255;
967     inetbuffers.dwBufferLength = 0;
968     inetbuffers.lpvBuffer = NULL;
969     inetbuffers.dwOffsetHigh = 1234;
970     inetbuffers.dwOffsetLow = 5678;
971     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
972     SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
973     rc = InternetReadFileEx(hor, &inetbuffers, 0, 0xdeadcafe);
974     ok(rc, "InternetReadFileEx failed with error %u\n", GetLastError());
975     trace("read %i bytes\n", inetbuffers.dwBufferLength);
976     todo_wine
977     {
978         CHECK_NOT_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
979         CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
980     }
981
982     rc = InternetReadFileEx(NULL, &inetbuffers, 0, 0xdeadcafe);
983     ok(!rc && (GetLastError() == ERROR_INVALID_HANDLE),
984         "InternetReadFileEx should have failed with ERROR_INVALID_HANDLE instead of %s, %u\n",
985         rc ? "TRUE" : "FALSE", GetLastError());
986
987     length = 0;
988     trace("Entering Query loop\n");
989
990     while (TRUE)
991     {
992         inetbuffers.dwStructSize = sizeof(INTERNET_BUFFERS);
993         inetbuffers.dwBufferLength = 1024;
994         inetbuffers.lpvBuffer = HeapAlloc(GetProcessHeap(), 0, inetbuffers.dwBufferLength+1);
995         inetbuffers.dwOffsetHigh = 1234;
996         inetbuffers.dwOffsetLow = 5678;
997
998         SET_WINE_ALLOW(INTERNET_STATUS_RECEIVING_RESPONSE);
999         SET_WINE_ALLOW(INTERNET_STATUS_RESPONSE_RECEIVED);
1000         SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
1001         rc = InternetReadFileExA(hor, &inetbuffers, IRF_ASYNC | IRF_USE_CONTEXT, 0xcafebabe);
1002         if (!rc)
1003         {
1004             if (GetLastError() == ERROR_IO_PENDING)
1005             {
1006                 trace("InternetReadFileEx -> PENDING\n");
1007                 ok(flags & INTERNET_FLAG_ASYNC,
1008                    "Should not get ERROR_IO_PENDING without INTERNET_FLAG_ASYNC\n");
1009                 CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
1010                 WaitForSingleObject(hCompleteEvent, INFINITE);
1011                 CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
1012                 CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
1013                 ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error);
1014             }
1015             else
1016             {
1017                 trace("InternetReadFileEx -> FAILED %u\n", GetLastError());
1018                 break;
1019             }
1020         }
1021         else
1022         {
1023             trace("InternetReadFileEx -> SUCCEEDED\n");
1024             CHECK_NOT_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
1025             if (inetbuffers.dwBufferLength)
1026             {
1027                 todo_wine {
1028                 CHECK_NOT_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
1029                 CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
1030                 }
1031             }
1032             else
1033             {
1034                 /* Win98 still sends these when 0 bytes are read, WinXP does not */
1035                 CLEAR_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
1036                 CLEAR_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
1037             }
1038         }
1039
1040         trace("read %i bytes\n", inetbuffers.dwBufferLength);
1041         ((char *)inetbuffers.lpvBuffer)[inetbuffers.dwBufferLength] = '\0';
1042
1043         ok(inetbuffers.dwOffsetHigh == 1234 && inetbuffers.dwOffsetLow == 5678,
1044             "InternetReadFileEx sets offsets to 0x%x%08x\n",
1045             inetbuffers.dwOffsetHigh, inetbuffers.dwOffsetLow);
1046
1047         HeapFree(GetProcessHeap(), 0, inetbuffers.lpvBuffer);
1048
1049         if (!inetbuffers.dwBufferLength)
1050             break;
1051
1052         length += inetbuffers.dwBufferLength;
1053     }
1054     ok(length > 0, "failed to read any of the document\n");
1055     trace("Finished. Read %d bytes\n", length);
1056
1057 abort:
1058     close_async_handle(hi, hCompleteEvent, 2);
1059     CloseHandle(hCompleteEvent);
1060     first_connection_to_test_url = FALSE;
1061 }
1062
1063 static void InternetOpenUrlA_test(void)
1064 {
1065   HINTERNET myhinternet, myhttp;
1066   char buffer[0x400];
1067   DWORD size, readbytes, totalbytes=0;
1068   BOOL ret;
1069
1070   myhinternet = InternetOpen("Winetest",0,NULL,NULL,INTERNET_FLAG_NO_CACHE_WRITE);
1071   ok((myhinternet != 0), "InternetOpen failed, error %u\n",GetLastError());
1072   size = 0x400;
1073   ret = InternetCanonicalizeUrl(TEST_URL, buffer, &size,ICU_BROWSER_MODE);
1074   ok( ret, "InternetCanonicalizeUrl failed, error %u\n",GetLastError());
1075
1076   SetLastError(0);
1077   myhttp = InternetOpenUrl(myhinternet, TEST_URL, 0, 0,
1078                            INTERNET_FLAG_RELOAD|INTERNET_FLAG_NO_CACHE_WRITE|INTERNET_FLAG_TRANSFER_BINARY,0);
1079   if (GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED)
1080     return; /* WinXP returns this when not connected to the net */
1081   ok((myhttp != 0),"InternetOpenUrl failed, error %u\n",GetLastError());
1082   ret = InternetReadFile(myhttp, buffer,0x400,&readbytes);
1083   ok( ret, "InternetReadFile failed, error %u\n",GetLastError());
1084   totalbytes += readbytes;
1085   while (readbytes && InternetReadFile(myhttp, buffer,0x400,&readbytes))
1086     totalbytes += readbytes;
1087   trace("read 0x%08x bytes\n",totalbytes);
1088
1089   InternetCloseHandle(myhttp);
1090   InternetCloseHandle(myhinternet);
1091 }
1092
1093 static void HttpSendRequestEx_test(void)
1094 {
1095     HINTERNET hSession;
1096     HINTERNET hConnect;
1097     HINTERNET hRequest;
1098
1099     INTERNET_BUFFERS BufferIn;
1100     DWORD dwBytesWritten, dwBytesRead, error;
1101     CHAR szBuffer[256];
1102     int i;
1103     BOOL ret;
1104
1105     static char szPostData[] = "mode=Test";
1106     static const char szContentType[] = "Content-Type: application/x-www-form-urlencoded";
1107
1108     hSession = InternetOpen("Wine Regression Test",
1109             INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
1110     ok( hSession != NULL ,"Unable to open Internet session\n");
1111     hConnect = InternetConnect(hSession, "crossover.codeweavers.com",
1112             INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0,
1113             0);
1114     ok( hConnect != NULL, "Unable to connect to http://crossover.codeweavers.com\n");
1115     hRequest = HttpOpenRequest(hConnect, "POST", "/posttest.php",
1116             NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
1117     if (!hRequest && GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED)
1118     {
1119         skip( "Network unreachable, skipping test\n" );
1120         goto done;
1121     }
1122     ok( hRequest != NULL, "Failed to open request handle err %u\n", GetLastError());
1123
1124     test_request_flags(hRequest, INTERNET_REQFLAG_NO_HEADERS);
1125
1126     BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS);
1127     BufferIn.Next = (LPINTERNET_BUFFERS)0xdeadcab;
1128     BufferIn.lpcszHeader = szContentType;
1129     BufferIn.dwHeadersLength = sizeof(szContentType)-1;
1130     BufferIn.dwHeadersTotal = sizeof(szContentType)-1;
1131     BufferIn.lpvBuffer = szPostData;
1132     BufferIn.dwBufferLength = 3;
1133     BufferIn.dwBufferTotal = sizeof(szPostData)-1;
1134     BufferIn.dwOffsetLow = 0;
1135     BufferIn.dwOffsetHigh = 0;
1136
1137     SetLastError(0xdeadbeef);
1138     ret = HttpSendRequestEx(hRequest, &BufferIn, NULL, 0 ,0);
1139     error = GetLastError();
1140     ok(ret, "HttpSendRequestEx Failed with error %u\n", error);
1141     ok(error == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", error);
1142
1143     test_request_flags(hRequest, INTERNET_REQFLAG_NO_HEADERS);
1144
1145     for (i = 3; szPostData[i]; i++)
1146         ok(InternetWriteFile(hRequest, &szPostData[i], 1, &dwBytesWritten),
1147                 "InternetWriteFile failed\n");
1148
1149     test_request_flags(hRequest, INTERNET_REQFLAG_NO_HEADERS);
1150
1151     ok(HttpEndRequest(hRequest, NULL, 0, 0), "HttpEndRequest Failed\n");
1152
1153     test_request_flags(hRequest, 0);
1154
1155     ok(InternetReadFile(hRequest, szBuffer, 255, &dwBytesRead),
1156             "Unable to read response\n");
1157     szBuffer[dwBytesRead] = 0;
1158
1159     ok(dwBytesRead == 13,"Read %u bytes instead of 13\n",dwBytesRead);
1160     ok(strncmp(szBuffer,"mode => Test\n",dwBytesRead)==0 || broken(proxy_active()),"Got string %s\n",szBuffer);
1161
1162     ok(InternetCloseHandle(hRequest), "Close request handle failed\n");
1163 done:
1164     ok(InternetCloseHandle(hConnect), "Close connect handle failed\n");
1165     ok(InternetCloseHandle(hSession), "Close session handle failed\n");
1166 }
1167
1168 static void InternetOpenRequest_test(void)
1169 {
1170     HINTERNET session, connect, request;
1171     static const char *types[] = { "*", "", NULL };
1172     static const WCHAR slash[] = {'/', 0}, any[] = {'*', 0}, empty[] = {0};
1173     static const WCHAR *typesW[] = { any, empty, NULL };
1174     BOOL ret;
1175
1176     session = InternetOpenA("Wine Regression Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
1177     ok(session != NULL ,"Unable to open Internet session\n");
1178
1179     connect = InternetConnectA(session, NULL, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
1180                               INTERNET_SERVICE_HTTP, 0, 0);
1181     ok(connect == NULL, "InternetConnectA should have failed\n");
1182     ok(GetLastError() == ERROR_INVALID_PARAMETER, "InternetConnectA with NULL server named should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
1183
1184     connect = InternetConnectA(session, "", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
1185                               INTERNET_SERVICE_HTTP, 0, 0);
1186     ok(connect == NULL, "InternetConnectA should have failed\n");
1187     ok(GetLastError() == ERROR_INVALID_PARAMETER, "InternetConnectA with blank server named should have failed with ERROR_INVALID_PARAMETER instead of %d\n", GetLastError());
1188
1189     connect = InternetConnectA(session, "test.winehq.org", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
1190                               INTERNET_SERVICE_HTTP, 0, 0);
1191     ok(connect != NULL, "Unable to connect to http://test.winehq.org with error %d\n", GetLastError());
1192
1193     request = HttpOpenRequestA(connect, NULL, "/", NULL, NULL, types, INTERNET_FLAG_NO_CACHE_WRITE, 0);
1194     if (!request && GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED)
1195     {
1196         skip( "Network unreachable, skipping test\n" );
1197         goto done;
1198     }
1199     ok(request != NULL, "Failed to open request handle err %u\n", GetLastError());
1200
1201     ret = HttpSendRequest(request, NULL, 0, NULL, 0);
1202     ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
1203     ok(InternetCloseHandle(request), "Close request handle failed\n");
1204
1205     request = HttpOpenRequestW(connect, NULL, slash, NULL, NULL, typesW, INTERNET_FLAG_NO_CACHE_WRITE, 0);
1206     ok(request != NULL, "Failed to open request handle err %u\n", GetLastError());
1207
1208     ret = HttpSendRequest(request, NULL, 0, NULL, 0);
1209     ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
1210     ok(InternetCloseHandle(request), "Close request handle failed\n");
1211
1212 done:
1213     ok(InternetCloseHandle(connect), "Close connect handle failed\n");
1214     ok(InternetCloseHandle(session), "Close session handle failed\n");
1215 }
1216
1217 static void test_http_cache(void)
1218 {
1219     HINTERNET session, connect, request;
1220     char file_name[MAX_PATH], url[INTERNET_MAX_URL_LENGTH];
1221     DWORD size, file_size;
1222     BYTE buf[100];
1223     HANDLE file;
1224     BOOL ret;
1225
1226     static const char *types[] = { "*", "", NULL };
1227
1228     session = InternetOpenA("Wine Regression Test", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
1229     ok(session != NULL ,"Unable to open Internet session\n");
1230
1231     connect = InternetConnectA(session, "test.winehq.org", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL,
1232                               INTERNET_SERVICE_HTTP, 0, 0);
1233     ok(connect != NULL, "Unable to connect to http://test.winehq.org with error %d\n", GetLastError());
1234
1235     request = HttpOpenRequestA(connect, NULL, "/tests/hello.html", NULL, NULL, types, INTERNET_FLAG_NEED_FILE, 0);
1236     if (!request && GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED)
1237     {
1238         skip( "Network unreachable, skipping test\n" );
1239
1240         ok(InternetCloseHandle(connect), "Close connect handle failed\n");
1241         ok(InternetCloseHandle(session), "Close session handle failed\n");
1242
1243         return;
1244     }
1245     ok(request != NULL, "Failed to open request handle err %u\n", GetLastError());
1246
1247     size = sizeof(url);
1248     ret = InternetQueryOptionA(request, INTERNET_OPTION_URL, url, &size);
1249     ok(ret, "InternetQueryOptionA(INTERNET_OPTION_URL) failed: %u\n", GetLastError());
1250     ok(!strcmp(url, "http://test.winehq.org/tests/hello.html"), "Wrong URL %s\n", url);
1251
1252     size = sizeof(file_name);
1253     ret = InternetQueryOptionA(request, INTERNET_OPTION_DATAFILE_NAME, file_name, &size);
1254     ok(!ret, "InternetQueryOptionA(INTERNET_OPTION_DATAFILE_NAME) succeeded\n");
1255     ok(GetLastError() == ERROR_INTERNET_ITEM_NOT_FOUND, "GetLastError()=%u\n", GetLastError());
1256     ok(!size, "size = %d\n", size);
1257
1258     ret = HttpSendRequest(request, NULL, 0, NULL, 0);
1259     ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
1260
1261     size = sizeof(file_name);
1262     ret = InternetQueryOptionA(request, INTERNET_OPTION_DATAFILE_NAME, file_name, &size);
1263     ok(ret, "InternetQueryOptionA(INTERNET_OPTION_DATAFILE_NAME) failed: %u\n", GetLastError());
1264
1265     file = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
1266                       FILE_ATTRIBUTE_NORMAL, NULL);
1267     ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError());
1268     file_size = GetFileSize(file, NULL);
1269     ok(file_size == 106, "file size = %u\n", file_size);
1270
1271     size = sizeof(buf);
1272     ret = InternetReadFile(request, buf, sizeof(buf), &size);
1273     ok(ret, "InternetReadFile failed: %u\n", GetLastError());
1274     ok(size == 100, "size = %u\n", size);
1275
1276     file_size = GetFileSize(file, NULL);
1277     ok(file_size == 106, "file size = %u\n", file_size);
1278     CloseHandle(file);
1279
1280     ok(InternetCloseHandle(request), "Close request handle failed\n");
1281
1282     file = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
1283                       FILE_ATTRIBUTE_NORMAL, NULL);
1284     ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError());
1285     CloseHandle(file);
1286
1287     /* Send the same request, requiring it to be retrieved from the cache */
1288     request = HttpOpenRequest(connect, "GET", "/tests/hello.html", NULL, NULL, NULL, INTERNET_FLAG_FROM_CACHE, 0);
1289
1290     ret = HttpSendRequest(request, NULL, 0, NULL, 0);
1291     ok(ret, "HttpSendRequest failed\n");
1292
1293     size = sizeof(buf);
1294     ret = InternetReadFile(request, buf, sizeof(buf), &size);
1295     ok(ret, "InternetReadFile failed: %u\n", GetLastError());
1296     ok(size == 100, "size = %u\n", size);
1297
1298     ok(InternetCloseHandle(request), "Close request handle failed\n");
1299
1300     request = HttpOpenRequestA(connect, NULL, "/", NULL, NULL, types, INTERNET_FLAG_NO_CACHE_WRITE, 0);
1301     ok(request != NULL, "Failed to open request handle err %u\n", GetLastError());
1302
1303     size = sizeof(file_name);
1304     ret = InternetQueryOptionA(request, INTERNET_OPTION_DATAFILE_NAME, file_name, &size);
1305     ok(!ret, "InternetQueryOptionA(INTERNET_OPTION_DATAFILE_NAME) succeeded\n");
1306     ok(GetLastError() == ERROR_INTERNET_ITEM_NOT_FOUND, "GetLastError()=%u\n", GetLastError());
1307     ok(!size, "size = %d\n", size);
1308
1309     ret = HttpSendRequest(request, NULL, 0, NULL, 0);
1310     ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
1311
1312     size = sizeof(file_name);
1313     file_name[0] = 0;
1314     ret = InternetQueryOptionA(request, INTERNET_OPTION_DATAFILE_NAME, file_name, &size);
1315     if (ret)
1316     {
1317         file = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
1318                       FILE_ATTRIBUTE_NORMAL, NULL);
1319         ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError());
1320         CloseHandle(file);
1321     }
1322     else
1323     {
1324         /* < IE8 */
1325         ok(file_name[0] == 0, "Didn't expect a file name\n");
1326     }
1327
1328     ok(InternetCloseHandle(request), "Close request handle failed\n");
1329     ok(InternetCloseHandle(connect), "Close connect handle failed\n");
1330     ok(InternetCloseHandle(session), "Close session handle failed\n");
1331 }
1332
1333 static void HttpHeaders_test(void)
1334 {
1335     HINTERNET hSession;
1336     HINTERNET hConnect;
1337     HINTERNET hRequest;
1338     CHAR      buffer[256];
1339     WCHAR     wbuffer[256];
1340     DWORD     len = 256;
1341     DWORD     oldlen;
1342     DWORD     index = 0;
1343
1344     hSession = InternetOpen("Wine Regression Test",
1345             INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
1346     ok( hSession != NULL ,"Unable to open Internet session\n");
1347     hConnect = InternetConnect(hSession, "crossover.codeweavers.com",
1348             INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0,
1349             0);
1350     ok( hConnect != NULL, "Unable to connect to http://crossover.codeweavers.com\n");
1351     hRequest = HttpOpenRequest(hConnect, "POST", "/posttest.php",
1352             NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
1353     if (!hRequest && GetLastError() == ERROR_INTERNET_NAME_NOT_RESOLVED)
1354     {
1355         skip( "Network unreachable, skipping test\n" );
1356         goto done;
1357     }
1358     ok( hRequest != NULL, "Failed to open request handle\n");
1359
1360     index = 0;
1361     len = sizeof(buffer);
1362     strcpy(buffer,"Warning");
1363     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1364                buffer,&len,&index)==0,"Warning hearder reported as Existing\n");
1365
1366     ok(HttpAddRequestHeaders(hRequest,"Warning:test1",-1,HTTP_ADDREQ_FLAG_ADD),
1367             "Failed to add new header\n");
1368
1369     index = 0;
1370     len = sizeof(buffer);
1371     strcpy(buffer,"Warning");
1372     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1373                 buffer,&len,&index),"Unable to query header\n");
1374     ok(index == 1, "Index was not incremented\n");
1375     ok(strcmp(buffer,"test1")==0, "incorrect string was returned(%s)\n",buffer);
1376     ok(len == 5, "Invalid length (exp. 5, got %d)\n", len);
1377     ok((len < sizeof(buffer)) && (buffer[len] == 0), "Buffer not NULL-terminated\n"); /* len show only 5 characters but the buffer is NULL-terminated*/
1378     len = sizeof(buffer);
1379     strcpy(buffer,"Warning");
1380     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1381                 buffer,&len,&index)==0,"Second Index Should Not Exist\n");
1382
1383     index = 0;
1384     len = 5; /* could store the string but not the NULL terminator */
1385     strcpy(buffer,"Warning");
1386     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1387                 buffer,&len,&index) == FALSE,"Query succeeded on a too small buffer\n");
1388     ok(strcmp(buffer,"Warning")==0, "incorrect string was returned(%s)\n",buffer); /* string not touched */
1389     ok(len == 6, "Invalid length (exp. 6, got %d)\n", len); /* unlike success, the length includes the NULL-terminator */
1390
1391     /* a call with NULL will fail but will return the length */
1392     index = 0;
1393     len = sizeof(buffer);
1394     SetLastError(0xdeadbeef);
1395     ok(HttpQueryInfo(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1396                 NULL,&len,&index) == FALSE,"Query worked\n");
1397     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected last error: %d\n", GetLastError());
1398     ok(len > 40, "Invalid length (exp. more than 40, got %d)\n", len);
1399     ok(index == 0, "Index was incremented\n");
1400
1401     /* even for a len that is too small */
1402     index = 0;
1403     len = 15;
1404     SetLastError(0xdeadbeef);
1405     ok(HttpQueryInfo(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1406                 NULL,&len,&index) == FALSE,"Query worked\n");
1407     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected last error: %d\n", GetLastError());
1408     ok(len > 40, "Invalid length (exp. more than 40, got %d)\n", len);
1409     ok(index == 0, "Index was incremented\n");
1410
1411     index = 0;
1412     len = 0;
1413     SetLastError(0xdeadbeef);
1414     ok(HttpQueryInfo(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1415                 NULL,&len,&index) == FALSE,"Query worked\n");
1416     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected last error: %d\n", GetLastError());
1417     ok(len > 40, "Invalid length (exp. more than 40, got %d)\n", len);
1418     ok(index == 0, "Index was incremented\n");
1419     oldlen = len;   /* bytes; at least long enough to hold buffer & nul */
1420
1421
1422     /* a working query */
1423     index = 0;
1424     len = sizeof(buffer);
1425     memset(buffer, 'x', sizeof(buffer));
1426     ok(HttpQueryInfo(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1427                 buffer,&len,&index),"Unable to query header\n");
1428     ok(len + sizeof(CHAR) <= oldlen, "Result longer than advertised\n");
1429     ok((len < sizeof(buffer)-sizeof(CHAR)) && (buffer[len/sizeof(CHAR)] == 0),"No NUL at end\n");
1430     ok(len == strlen(buffer) * sizeof(CHAR), "Length wrong\n");
1431     /* what's in the middle differs between Wine and Windows so currently we check only the beginning and the end */
1432     ok(strncmp(buffer, "POST /posttest.php HTTP/1", 25)==0, "Invalid beginning of headers string\n");
1433     ok(strcmp(buffer + strlen(buffer) - 4, "\r\n\r\n")==0, "Invalid end of headers string\n");
1434     ok(index == 0, "Index was incremented\n");
1435
1436     /* Like above two tests, but for W version */
1437
1438     index = 0;
1439     len = 0;
1440     SetLastError(0xdeadbeef);
1441     ok(HttpQueryInfoW(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1442                 NULL,&len,&index) == FALSE,"Query worked\n");
1443     ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Unexpected last error: %d\n", GetLastError());
1444     ok(len > 80, "Invalid length (exp. more than 80, got %d)\n", len);
1445     ok(index == 0, "Index was incremented\n");
1446     oldlen = len;   /* bytes; at least long enough to hold buffer & nul */
1447
1448     /* a working query */
1449     index = 0;
1450     len = sizeof(wbuffer);
1451     memset(wbuffer, 'x', sizeof(wbuffer));
1452     ok(HttpQueryInfoW(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1453                 wbuffer,&len,&index),"Unable to query header\n");
1454     ok(len + sizeof(WCHAR) <= oldlen, "Result longer than advertised\n");
1455     ok(len == lstrlenW(wbuffer) * sizeof(WCHAR), "Length wrong\n");
1456     ok((len < sizeof(wbuffer)-sizeof(WCHAR)) && (wbuffer[len/sizeof(WCHAR)] == 0),"No NUL at end\n");
1457     ok(index == 0, "Index was incremented\n");
1458
1459     /* end of W version tests */
1460
1461     /* Without HTTP_QUERY_FLAG_REQUEST_HEADERS */
1462     index = 0;
1463     len = sizeof(buffer);
1464     memset(buffer, 'x', sizeof(buffer));
1465     ok(HttpQueryInfo(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF,
1466                 buffer,&len,&index) == TRUE,"Query failed\n");
1467     ok(len == 2, "Expected 2, got %d\n", len);
1468     ok(strcmp(buffer, "\r\n") == 0, "Expected CRLF, got '%s'\n", buffer);
1469     ok(index == 0, "Index was incremented\n");
1470
1471     ok(HttpAddRequestHeaders(hRequest,"Warning:test2",-1,HTTP_ADDREQ_FLAG_ADD),
1472             "Failed to add duplicate header using HTTP_ADDREQ_FLAG_ADD\n");
1473
1474     index = 0;
1475     len = sizeof(buffer);
1476     strcpy(buffer,"Warning");
1477     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1478                 buffer,&len,&index),"Unable to query header\n");
1479     ok(index == 1, "Index was not incremented\n");
1480     ok(strcmp(buffer,"test1")==0, "incorrect string was returned(%s)\n",buffer);
1481     len = sizeof(buffer);
1482     strcpy(buffer,"Warning");
1483     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1484                 buffer,&len,&index),"Failed to get second header\n");
1485     ok(index == 2, "Index was not incremented\n");
1486     ok(strcmp(buffer,"test2")==0, "incorrect string was returned(%s)\n",buffer);
1487     len = sizeof(buffer);
1488     strcpy(buffer,"Warning");
1489     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1490                 buffer,&len,&index)==0,"Third Header Should Not Exist\n");
1491
1492     ok(HttpAddRequestHeaders(hRequest,"Warning:test3",-1,HTTP_ADDREQ_FLAG_REPLACE), "Failed to replace header using HTTP_ADDREQ_FLAG_REPLACE\n");
1493
1494     index = 0;
1495     len = sizeof(buffer);
1496     strcpy(buffer,"Warning");
1497     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1498                 buffer,&len,&index),"Unable to query header\n");
1499     ok(index == 1, "Index was not incremented\n");
1500     ok(strcmp(buffer,"test2")==0, "incorrect string was returned(%s)\n",buffer);
1501     len = sizeof(buffer);
1502     strcpy(buffer,"Warning");
1503     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1504                 buffer,&len,&index),"Failed to get second header\n");
1505     ok(index == 2, "Index was not incremented\n");
1506     ok(strcmp(buffer,"test3")==0, "incorrect string was returned(%s)\n",buffer);
1507     len = sizeof(buffer);
1508     strcpy(buffer,"Warning");
1509     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1510                 buffer,&len,&index)==0,"Third Header Should Not Exist\n");
1511
1512     ok(HttpAddRequestHeaders(hRequest,"Warning:test4",-1,HTTP_ADDREQ_FLAG_ADD_IF_NEW)==0, "HTTP_ADDREQ_FLAG_ADD_IF_NEW replaced existing header\n");
1513
1514     index = 0;
1515     len = sizeof(buffer);
1516     strcpy(buffer,"Warning");
1517     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1518                 buffer,&len,&index),"Unable to query header\n");
1519     ok(index == 1, "Index was not incremented\n");
1520     ok(strcmp(buffer,"test2")==0, "incorrect string was returned(%s)\n",buffer);
1521     len = sizeof(buffer);
1522     strcpy(buffer,"Warning");
1523     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1524                 buffer,&len,&index),"Failed to get second header\n");
1525     ok(index == 2, "Index was not incremented\n");
1526     ok(strcmp(buffer,"test3")==0, "incorrect string was returned(%s)\n",buffer);
1527     len = sizeof(buffer);
1528     strcpy(buffer,"Warning");
1529     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1530                 buffer,&len,&index)==0,"Third Header Should Not Exist\n");
1531
1532     ok(HttpAddRequestHeaders(hRequest,"Warning:test4",-1, HTTP_ADDREQ_FLAG_COALESCE), "HTTP_ADDREQ_FLAG_COALESCE Did not work\n");
1533
1534     index = 0;
1535     len = sizeof(buffer);
1536     strcpy(buffer,"Warning");
1537     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS,
1538                 buffer,&len,&index),"Unable to query header\n");
1539     ok(index == 1, "Index was not incremented\n");
1540     ok(strcmp(buffer,"test2, test4")==0, "incorrect string was returned(%s)\n", buffer);
1541     len = sizeof(buffer);
1542     strcpy(buffer,"Warning");
1543     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Failed to get second header\n");
1544     ok(index == 2, "Index was not incremented\n");
1545     ok(strcmp(buffer,"test3")==0, "incorrect string was returned(%s)\n",buffer);
1546     len = sizeof(buffer);
1547     strcpy(buffer,"Warning");
1548     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index)==0,"Third Header Should Not Exist\n");
1549
1550     ok(HttpAddRequestHeaders(hRequest,"Warning:test5",-1, HTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA), "HTTP_ADDREQ_FLAG_COALESCE Did not work\n");
1551
1552     index = 0;
1553     len = sizeof(buffer);
1554     strcpy(buffer,"Warning");
1555     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n");
1556     ok(index == 1, "Index was not incremented\n");
1557     ok(strcmp(buffer,"test2, test4, test5")==0, "incorrect string was returned(%s)\n",buffer);
1558     len = sizeof(buffer);
1559     strcpy(buffer,"Warning");
1560     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Failed to get second header\n");
1561     ok(index == 2, "Index was not incremented\n");
1562     ok(strcmp(buffer,"test3")==0, "incorrect string was returned(%s)\n",buffer);
1563     len = sizeof(buffer);
1564     strcpy(buffer,"Warning");
1565     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index)==0,"Third Header Should Not Exist\n");
1566
1567     ok(HttpAddRequestHeaders(hRequest,"Warning:test6",-1, HTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON), "HTTP_ADDREQ_FLAG_COALESCE Did not work\n");
1568
1569     index = 0;
1570     len = sizeof(buffer);
1571     strcpy(buffer,"Warning");
1572     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n");
1573     ok(index == 1, "Index was not incremented\n");
1574     ok(strcmp(buffer,"test2, test4, test5; test6")==0, "incorrect string was returned(%s)\n",buffer);
1575     len = sizeof(buffer);
1576     strcpy(buffer,"Warning");
1577     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Failed to get second header\n");
1578     ok(index == 2, "Index was not incremented\n");
1579     ok(strcmp(buffer,"test3")==0, "incorrect string was returned(%s)\n",buffer);
1580     len = sizeof(buffer);
1581     strcpy(buffer,"Warning");
1582     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index)==0,"Third Header Should Not Exist\n");
1583
1584     ok(HttpAddRequestHeaders(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");
1585
1586     index = 0;
1587     len = sizeof(buffer);
1588     strcpy(buffer,"Warning");
1589     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n");
1590     ok(index == 1, "Index was not incremented\n");
1591     ok(strcmp(buffer,"test3")==0, "incorrect string was returned(%s)\n",buffer);
1592     len = sizeof(buffer);
1593     strcpy(buffer,"Warning");
1594     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Failed to get second header\n");
1595     ok(index == 2, "Index was not incremented\n");
1596     ok(strcmp(buffer,"test7")==0, "incorrect string was returned(%s)\n",buffer);
1597     len = sizeof(buffer);
1598     strcpy(buffer,"Warning");
1599     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index)==0,"Third Header Should Not Exist\n");
1600
1601     /* Ensure that blank headers are ignored and don't cause a failure */
1602     ok(HttpAddRequestHeaders(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");
1603
1604     index = 0;
1605     len = sizeof(buffer);
1606     strcpy(buffer,"BlankTest");
1607     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n");
1608     ok(index == 1, "Index was not incremented\n");
1609     ok(strcmp(buffer,"value")==0, "incorrect string was returned(%s)\n",buffer);
1610
1611     /* Ensure that malformed header separators are ignored and don't cause a failure */
1612     ok(HttpAddRequestHeaders(hRequest,"\r\rMalformedTest:value\n\nMalformedTestTwo: value2\rMalformedTestThree: value3\n\n\r\r\n",-1, HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE),
1613         "Failed to add header with malformed entries in list\n");
1614
1615     index = 0;
1616     len = sizeof(buffer);
1617     strcpy(buffer,"MalformedTest");
1618     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n");
1619     ok(index == 1, "Index was not incremented\n");
1620     ok(strcmp(buffer,"value")==0, "incorrect string was returned(%s)\n",buffer);
1621     index = 0;
1622     len = sizeof(buffer);
1623     strcpy(buffer,"MalformedTestTwo");
1624     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n");
1625     ok(index == 1, "Index was not incremented\n");
1626     ok(strcmp(buffer,"value2")==0, "incorrect string was returned(%s)\n",buffer);
1627     index = 0;
1628     len = sizeof(buffer);
1629     strcpy(buffer,"MalformedTestThree");
1630     ok(HttpQueryInfo(hRequest,HTTP_QUERY_CUSTOM|HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer,&len,&index),"Unable to query header\n");
1631     ok(index == 1, "Index was not incremented\n");
1632     ok(strcmp(buffer,"value3")==0, "incorrect string was returned(%s)\n",buffer);
1633
1634     ok(InternetCloseHandle(hRequest), "Close request handle failed\n");
1635 done:
1636     ok(InternetCloseHandle(hConnect), "Close connect handle failed\n");
1637     ok(InternetCloseHandle(hSession), "Close session handle failed\n");
1638 }
1639
1640 static const char garbagemsg[] =
1641 "Garbage: Header\r\n";
1642
1643 static const char contmsg[] =
1644 "HTTP/1.1 100 Continue\r\n";
1645
1646 static const char expandcontmsg[] =
1647 "HTTP/1.1 100 Continue\r\n"
1648 "Server: winecontinue\r\n"
1649 "Tag: something witty\r\n"
1650 "\r\n";
1651
1652 static const char okmsg[] =
1653 "HTTP/1.1 200 OK\r\n"
1654 "Server: winetest\r\n"
1655 "\r\n";
1656
1657 static const char okmsg2[] =
1658 "HTTP/1.1 200 OK\r\n"
1659 "Date: Mon, 01 Dec 2008 13:44:34 GMT\r\n"
1660 "Server: winetest\r\n"
1661 "Content-Length: 0\r\n"
1662 "Set-Cookie: one\r\n"
1663 "Set-Cookie: two\r\n"
1664 "\r\n";
1665
1666 static const char notokmsg[] =
1667 "HTTP/1.1 400 Bad Request\r\n"
1668 "Server: winetest\r\n"
1669 "\r\n";
1670
1671 static const char noauthmsg[] =
1672 "HTTP/1.1 401 Unauthorized\r\n"
1673 "Server: winetest\r\n"
1674 "Connection: close\r\n"
1675 "WWW-Authenticate: Basic realm=\"placebo\"\r\n"
1676 "\r\n";
1677
1678 static const char noauthmsg2[] =
1679 "HTTP/1.0 401 Anonymous requests or requests on unsecure channel are not allowed\r\n"
1680 "HTTP/1.0 401 Anonymous requests or requests on unsecure channel are not allowed"
1681 "\0d`0|6\n"
1682 "Server: winetest\r\n";
1683
1684 static const char proxymsg[] =
1685 "HTTP/1.1 407 Proxy Authentication Required\r\n"
1686 "Server: winetest\r\n"
1687 "Proxy-Connection: close\r\n"
1688 "Proxy-Authenticate: Basic realm=\"placebo\"\r\n"
1689 "\r\n";
1690
1691 static const char page1[] =
1692 "<HTML>\r\n"
1693 "<HEAD><TITLE>wininet test page</TITLE></HEAD>\r\n"
1694 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
1695 "</HTML>\r\n\r\n";
1696
1697 struct server_info {
1698     HANDLE hEvent;
1699     int port;
1700     int num_testH_retrievals;
1701 };
1702
1703 static DWORD CALLBACK server_thread(LPVOID param)
1704 {
1705     struct server_info *si = param;
1706     int r, c, i, on;
1707     SOCKET s;
1708     struct sockaddr_in sa;
1709     char buffer[0x100];
1710     WSADATA wsaData;
1711     int last_request = 0;
1712     char host_header[22];
1713     static int test_b = 0;
1714
1715     WSAStartup(MAKEWORD(1,1), &wsaData);
1716
1717     s = socket(AF_INET, SOCK_STREAM, 0);
1718     if (s == INVALID_SOCKET)
1719         return 1;
1720
1721     on = 1;
1722     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof on);
1723
1724     memset(&sa, 0, sizeof sa);
1725     sa.sin_family = AF_INET;
1726     sa.sin_port = htons(si->port);
1727     sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
1728
1729     r = bind(s, (struct sockaddr*) &sa, sizeof sa);
1730     if (r<0)
1731         return 1;
1732
1733     listen(s, 0);
1734
1735     SetEvent(si->hEvent);
1736
1737     sprintf(host_header, "Host: localhost:%d", si->port);
1738
1739     do
1740     {
1741         c = accept(s, NULL, NULL);
1742
1743         memset(buffer, 0, sizeof buffer);
1744         for(i=0; i<(sizeof buffer-1); i++)
1745         {
1746             r = recv(c, &buffer[i], 1, 0);
1747             if (r != 1)
1748                 break;
1749             if (i<4) continue;
1750             if (buffer[i-2] == '\n' && buffer[i] == '\n' &&
1751                 buffer[i-3] == '\r' && buffer[i-1] == '\r')
1752                 break;
1753         }
1754         if (strstr(buffer, "GET /test1"))
1755         {
1756             if (!strstr(buffer, "Content-Length: 0"))
1757             {
1758                 send(c, okmsg, sizeof okmsg-1, 0);
1759                 send(c, page1, sizeof page1-1, 0);
1760             }
1761             else
1762                 send(c, notokmsg, sizeof notokmsg-1, 0);
1763         }
1764         if (strstr(buffer, "/test2"))
1765         {
1766             if (strstr(buffer, "Proxy-Authorization: Basic bWlrZToxMTAx"))
1767             {
1768                 send(c, okmsg, sizeof okmsg-1, 0);
1769                 send(c, page1, sizeof page1-1, 0);
1770             }
1771             else
1772                 send(c, proxymsg, sizeof proxymsg-1, 0);
1773         }
1774         if (strstr(buffer, "/test3"))
1775         {
1776             if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q="))
1777                 send(c, okmsg, sizeof okmsg-1, 0);
1778             else
1779                 send(c, noauthmsg, sizeof noauthmsg-1, 0);
1780         }
1781         if (strstr(buffer, "/test4"))
1782         {
1783             if (strstr(buffer, "Connection: Close"))
1784                 send(c, okmsg, sizeof okmsg-1, 0);
1785             else
1786                 send(c, notokmsg, sizeof notokmsg-1, 0);
1787         }
1788         if (strstr(buffer, "POST /test5") ||
1789             strstr(buffer, "RPC_IN_DATA /test5") ||
1790             strstr(buffer, "RPC_OUT_DATA /test5"))
1791         {
1792             if (strstr(buffer, "Content-Length: 0"))
1793             {
1794                 send(c, okmsg, sizeof okmsg-1, 0);
1795                 send(c, page1, sizeof page1-1, 0);
1796             }
1797             else
1798                 send(c, notokmsg, sizeof notokmsg-1, 0);
1799         }
1800         if (strstr(buffer, "GET /test6"))
1801         {
1802             send(c, contmsg, sizeof contmsg-1, 0);
1803             send(c, contmsg, sizeof contmsg-1, 0);
1804             send(c, okmsg, sizeof okmsg-1, 0);
1805             send(c, page1, sizeof page1-1, 0);
1806         }
1807         if (strstr(buffer, "POST /test7"))
1808         {
1809             if (strstr(buffer, "Content-Length: 100"))
1810             {
1811                 send(c, okmsg, sizeof okmsg-1, 0);
1812                 send(c, page1, sizeof page1-1, 0);
1813             }
1814             else
1815                 send(c, notokmsg, sizeof notokmsg-1, 0);
1816         }
1817         if (strstr(buffer, "/test8"))
1818         {
1819             if (!strstr(buffer, "Connection: Close") &&
1820                  strstr(buffer, "Connection: Keep-Alive") &&
1821                 !strstr(buffer, "Cache-Control: no-cache") &&
1822                 !strstr(buffer, "Pragma: no-cache") &&
1823                  strstr(buffer, host_header))
1824                 send(c, okmsg, sizeof okmsg-1, 0);
1825             else
1826                 send(c, notokmsg, sizeof notokmsg-1, 0);
1827         }
1828         if (strstr(buffer, "/test9"))
1829         {
1830             if (!strstr(buffer, "Connection: Close") &&
1831                 !strstr(buffer, "Connection: Keep-Alive") &&
1832                 !strstr(buffer, "Cache-Control: no-cache") &&
1833                 !strstr(buffer, "Pragma: no-cache") &&
1834                  strstr(buffer, host_header))
1835                 send(c, okmsg, sizeof okmsg-1, 0);
1836             else
1837                 send(c, notokmsg, sizeof notokmsg-1, 0);
1838         }
1839         if (strstr(buffer, "/testA"))
1840         {
1841             if (!strstr(buffer, "Connection: Close") &&
1842                 !strstr(buffer, "Connection: Keep-Alive") &&
1843                 (strstr(buffer, "Cache-Control: no-cache") ||
1844                  strstr(buffer, "Pragma: no-cache")) &&
1845                  strstr(buffer, host_header))
1846                 send(c, okmsg, sizeof okmsg-1, 0);
1847             else
1848                 send(c, notokmsg, sizeof notokmsg-1, 0);
1849         }
1850         if (!test_b && strstr(buffer, "/testB HTTP/1.1"))
1851         {
1852             test_b = 1;
1853             send(c, okmsg, sizeof okmsg-1, 0);
1854             recvfrom(c, buffer, sizeof buffer, 0, NULL, NULL);
1855             send(c, okmsg, sizeof okmsg-1, 0);
1856         }
1857         if (strstr(buffer, "/testC"))
1858         {
1859             if (strstr(buffer, "Cookie: cookie=biscuit"))
1860                 send(c, okmsg, sizeof okmsg-1, 0);
1861             else
1862                 send(c, notokmsg, sizeof notokmsg-1, 0);
1863         }
1864         if (strstr(buffer, "/testD"))
1865         {
1866             send(c, okmsg2, sizeof okmsg2-1, 0);
1867         }
1868         if (strstr(buffer, "/testE"))
1869         {
1870             send(c, noauthmsg2, sizeof noauthmsg2-1, 0);
1871         }
1872         if (strstr(buffer, "GET /quit"))
1873         {
1874             send(c, okmsg, sizeof okmsg-1, 0);
1875             send(c, page1, sizeof page1-1, 0);
1876             last_request = 1;
1877         }
1878         if (strstr(buffer, "GET /testF"))
1879         {
1880             send(c, expandcontmsg, sizeof expandcontmsg-1, 0);
1881             send(c, garbagemsg, sizeof garbagemsg-1, 0);
1882             send(c, contmsg, sizeof contmsg-1, 0);
1883             send(c, garbagemsg, sizeof garbagemsg-1, 0);
1884             send(c, okmsg, sizeof okmsg-1, 0);
1885             send(c, page1, sizeof page1-1, 0);
1886         }
1887         if (strstr(buffer, "GET /testG"))
1888         {
1889             send(c, page1, sizeof page1-1, 0);
1890         }
1891         if (strstr(buffer, "GET /testH"))
1892         {
1893             si->num_testH_retrievals++;
1894             if (!strstr(buffer, "Content-Length: 0"))
1895             {
1896                 send(c, okmsg, sizeof okmsg-1, 0);
1897                 send(c, page1, sizeof page1-1, 0);
1898             }
1899             else
1900                 send(c, notokmsg, sizeof notokmsg-1, 0);
1901         }
1902         if (strstr(buffer, "GET /test_no_content"))
1903         {
1904             static const char nocontentmsg[] = "HTTP/1.1 204 No Content\r\nConnection: close\r\n\r\n";
1905             send(c, nocontentmsg, sizeof(nocontentmsg)-1, 0);
1906         }
1907         if (strstr(buffer, "GET /test_conn_close"))
1908         {
1909             static const char conn_close_response[] = "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\nsome content";
1910             send(c, conn_close_response, sizeof(conn_close_response)-1, 0);
1911             WaitForSingleObject(conn_close_event, INFINITE);
1912             trace("closing connection\n");
1913         }
1914
1915         shutdown(c, 2);
1916         closesocket(c);
1917     } while (!last_request);
1918
1919     closesocket(s);
1920
1921     return 0;
1922 }
1923
1924 static void test_basic_request(int port, const char *verb, const char *url)
1925 {
1926     HINTERNET hi, hc, hr;
1927     DWORD r, count;
1928     char buffer[0x100];
1929
1930     hi = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
1931     ok(hi != NULL, "open failed\n");
1932
1933     hc = InternetConnect(hi, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
1934     ok(hc != NULL, "connect failed\n");
1935
1936     hr = HttpOpenRequest(hc, verb, url, NULL, NULL, NULL, 0, 0);
1937     ok(hr != NULL, "HttpOpenRequest failed\n");
1938
1939     r = HttpSendRequest(hr, NULL, 0, NULL, 0);
1940     ok(r, "HttpSendRequest failed\n");
1941
1942     count = 0;
1943     memset(buffer, 0, sizeof buffer);
1944     SetLastError(0xdeadbeef);
1945     r = InternetReadFile(hr, buffer, sizeof buffer, &count);
1946     ok(r, "InternetReadFile failed %u\n", GetLastError());
1947     ok(count == sizeof page1 - 1, "count was wrong\n");
1948     ok(!memcmp(buffer, page1, sizeof page1), "http data wrong, got: %s\n", buffer);
1949
1950     InternetCloseHandle(hr);
1951     InternetCloseHandle(hc);
1952     InternetCloseHandle(hi);
1953 }
1954
1955 static void test_last_error(int port)
1956 {
1957     HINTERNET hi, hc, hr;
1958     DWORD error;
1959     BOOL r;
1960
1961     hi = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
1962     ok(hi != NULL, "open failed\n");
1963
1964     hc = InternetConnect(hi, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
1965     ok(hc != NULL, "connect failed\n");
1966
1967     hr = HttpOpenRequest(hc, NULL, "/test1", NULL, NULL, NULL, 0, 0);
1968     ok(hr != NULL, "HttpOpenRequest failed\n");
1969
1970     SetLastError(0xdeadbeef);
1971     r = HttpSendRequest(hr, NULL, 0, NULL, 0);
1972     error = GetLastError();
1973     ok(r, "HttpSendRequest failed\n");
1974     ok(error == ERROR_SUCCESS || broken(error != ERROR_SUCCESS), "expected ERROR_SUCCESS, got %u\n", error);
1975
1976     InternetCloseHandle(hr);
1977     InternetCloseHandle(hc);
1978     InternetCloseHandle(hi);
1979 }
1980
1981 static void test_proxy_indirect(int port)
1982 {
1983     HINTERNET hi, hc, hr;
1984     DWORD r, sz;
1985     char buffer[0x40];
1986
1987     hi = InternetOpen(NULL, 0, NULL, NULL, 0);
1988     ok(hi != NULL, "open failed\n");
1989
1990     hc = InternetConnect(hi, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
1991     ok(hc != NULL, "connect failed\n");
1992
1993     hr = HttpOpenRequest(hc, NULL, "/test2", NULL, NULL, NULL, 0, 0);
1994     ok(hr != NULL, "HttpOpenRequest failed\n");
1995
1996     r = HttpSendRequest(hr, NULL, 0, NULL, 0);
1997     ok(r, "HttpSendRequest failed\n");
1998
1999     sz = sizeof buffer;
2000     r = HttpQueryInfo(hr, HTTP_QUERY_PROXY_AUTHENTICATE, buffer, &sz, NULL);
2001     ok(r || GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND, "HttpQueryInfo failed: %d\n", GetLastError());
2002     if (!r)
2003     {
2004         skip("missing proxy header, not testing remaining proxy headers\n");
2005         goto out;
2006     }
2007     ok(!strcmp(buffer, "Basic realm=\"placebo\""), "proxy auth info wrong\n");
2008
2009     test_status_code(hr, 407);
2010     test_request_flags(hr, 0);
2011
2012     sz = sizeof buffer;
2013     r = HttpQueryInfo(hr, HTTP_QUERY_STATUS_TEXT, buffer, &sz, NULL);
2014     ok(r, "HttpQueryInfo failed\n");
2015     ok(!strcmp(buffer, "Proxy Authentication Required"), "proxy text wrong\n");
2016
2017     sz = sizeof buffer;
2018     r = HttpQueryInfo(hr, HTTP_QUERY_VERSION, buffer, &sz, NULL);
2019     ok(r, "HttpQueryInfo failed\n");
2020     ok(!strcmp(buffer, "HTTP/1.1"), "http version wrong\n");
2021
2022     sz = sizeof buffer;
2023     r = HttpQueryInfo(hr, HTTP_QUERY_SERVER, buffer, &sz, NULL);
2024     ok(r, "HttpQueryInfo failed\n");
2025     ok(!strcmp(buffer, "winetest"), "http server wrong\n");
2026
2027     sz = sizeof buffer;
2028     r = HttpQueryInfo(hr, HTTP_QUERY_CONTENT_ENCODING, buffer, &sz, NULL);
2029     ok(GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND, "HttpQueryInfo should fail\n");
2030     ok(r == FALSE, "HttpQueryInfo failed\n");
2031
2032 out:
2033     InternetCloseHandle(hr);
2034     InternetCloseHandle(hc);
2035     InternetCloseHandle(hi);
2036 }
2037
2038 static void test_proxy_direct(int port)
2039 {
2040     HINTERNET hi, hc, hr;
2041     DWORD r, sz;
2042     char buffer[0x40];
2043     static CHAR username[] = "mike",
2044                 password[] = "1101";
2045
2046     sprintf(buffer, "localhost:%d\n", port);
2047     hi = InternetOpen(NULL, INTERNET_OPEN_TYPE_PROXY, buffer, NULL, 0);
2048     ok(hi != NULL, "open failed\n");
2049
2050     /* try connect without authorization */
2051     hc = InternetConnect(hi, "test.winehq.org/", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
2052     ok(hc != NULL, "connect failed\n");
2053
2054     hr = HttpOpenRequest(hc, NULL, "/test2", NULL, NULL, NULL, 0, 0);
2055     ok(hr != NULL, "HttpOpenRequest failed\n");
2056
2057     r = HttpSendRequest(hr, NULL, 0, NULL, 0);
2058     ok(r, "HttpSendRequest failed\n");
2059
2060     test_status_code(hr, 407);
2061
2062     /* set the user + password then try again */
2063     todo_wine {
2064     r = InternetSetOption(hr, INTERNET_OPTION_PROXY_USERNAME, username, 4);
2065     ok(r, "failed to set user\n");
2066
2067     r = InternetSetOption(hr, INTERNET_OPTION_PROXY_PASSWORD, password, 4);
2068     ok(r, "failed to set password\n");
2069     }
2070
2071     r = HttpSendRequest(hr, NULL, 0, NULL, 0);
2072     ok(r, "HttpSendRequest failed\n");
2073     sz = sizeof buffer;
2074     r = HttpQueryInfo(hr, HTTP_QUERY_STATUS_CODE, buffer, &sz, NULL);
2075     ok(r, "HttpQueryInfo failed\n");
2076     todo_wine {
2077     ok(!strcmp(buffer, "200"), "proxy code wrong\n");
2078     }
2079
2080
2081     InternetCloseHandle(hr);
2082     InternetCloseHandle(hc);
2083     InternetCloseHandle(hi);
2084 }
2085
2086 static void test_header_handling_order(int port)
2087 {
2088     static char authorization[] = "Authorization: Basic dXNlcjpwd2Q=";
2089     static char connection[]    = "Connection: Close";
2090
2091     static const char *types[2] = { "*", NULL };
2092     HINTERNET session, connect, request;
2093     DWORD size, status;
2094     BOOL ret;
2095
2096     session = InternetOpen("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
2097     ok(session != NULL, "InternetOpen failed\n");
2098
2099     connect = InternetConnect(session, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
2100     ok(connect != NULL, "InternetConnect failed\n");
2101
2102     request = HttpOpenRequest(connect, NULL, "/test3", NULL, NULL, types, INTERNET_FLAG_KEEP_CONNECTION, 0);
2103     ok(request != NULL, "HttpOpenRequest failed\n");
2104
2105     ret = HttpAddRequestHeaders(request, authorization, ~0u, HTTP_ADDREQ_FLAG_ADD);
2106     ok(ret, "HttpAddRequestHeaders failed\n");
2107
2108     ret = HttpSendRequest(request, NULL, 0, NULL, 0);
2109     ok(ret, "HttpSendRequest failed\n");
2110
2111     test_status_code(request, 200);
2112     test_request_flags(request, 0);
2113
2114     InternetCloseHandle(request);
2115
2116     request = HttpOpenRequest(connect, NULL, "/test4", NULL, NULL, types, INTERNET_FLAG_KEEP_CONNECTION, 0);
2117     ok(request != NULL, "HttpOpenRequest failed\n");
2118
2119     ret = HttpSendRequest(request, connection, ~0u, NULL, 0);
2120     ok(ret, "HttpSendRequest failed\n");
2121
2122     status = 0;
2123     size = sizeof(status);
2124     ret = HttpQueryInfo( request, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
2125     ok(ret, "HttpQueryInfo failed\n");
2126     ok(status == 200 || status == 400 /* IE6 */, "got status %u, expected 200 or 400\n", status);
2127
2128     InternetCloseHandle(request);
2129
2130     request = HttpOpenRequest(connect, "POST", "/test7", NULL, NULL, types, INTERNET_FLAG_KEEP_CONNECTION, 0);
2131     ok(request != NULL, "HttpOpenRequest failed\n");
2132
2133     ret = HttpAddRequestHeaders(request, "Content-Length: 100\r\n", ~0u, HTTP_ADDREQ_FLAG_ADD_IF_NEW);
2134     ok(ret, "HttpAddRequestHeaders failed\n");
2135
2136     ret = HttpSendRequest(request, connection, ~0u, NULL, 0);
2137     ok(ret, "HttpSendRequest failed\n");
2138
2139     status = 0;
2140     size = sizeof(status);
2141     ret = HttpQueryInfo( request, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &status, &size, NULL );
2142     ok(ret, "HttpQueryInfo failed\n");
2143     ok(status == 200 || status == 400 /* IE6 */, "got status %u, expected 200 or 400\n", status);
2144
2145     InternetCloseHandle(request);
2146     InternetCloseHandle(connect);
2147     InternetCloseHandle(session);
2148 }
2149
2150 static void test_connection_header(int port)
2151 {
2152     HINTERNET ses, con, req;
2153     BOOL ret;
2154
2155     ses = InternetOpen("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
2156     ok(ses != NULL, "InternetOpen failed\n");
2157
2158     con = InternetConnect(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
2159     ok(con != NULL, "InternetConnect failed\n");
2160
2161     req = HttpOpenRequest(con, NULL, "/test8", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
2162     ok(req != NULL, "HttpOpenRequest failed\n");
2163
2164     ret = HttpSendRequest(req, NULL, 0, NULL, 0);
2165     ok(ret, "HttpSendRequest failed\n");
2166
2167     test_status_code(req, 200);
2168
2169     InternetCloseHandle(req);
2170
2171     req = HttpOpenRequest(con, NULL, "/test9", NULL, NULL, NULL, 0, 0);
2172     ok(req != NULL, "HttpOpenRequest failed\n");
2173
2174     ret = HttpSendRequest(req, NULL, 0, NULL, 0);
2175     ok(ret, "HttpSendRequest failed\n");
2176
2177     test_status_code(req, 200);
2178
2179     InternetCloseHandle(req);
2180
2181     req = HttpOpenRequest(con, NULL, "/test9", NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
2182     ok(req != NULL, "HttpOpenRequest failed\n");
2183
2184     ret = HttpSendRequest(req, NULL, 0, NULL, 0);
2185     ok(ret, "HttpSendRequest failed\n");
2186
2187     test_status_code(req, 200);
2188
2189     InternetCloseHandle(req);
2190
2191     req = HttpOpenRequest(con, "POST", "/testA", NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
2192     ok(req != NULL, "HttpOpenRequest failed\n");
2193
2194     ret = HttpSendRequest(req, NULL, 0, NULL, 0);
2195     ok(ret, "HttpSendRequest failed\n");
2196
2197     test_status_code(req, 200);
2198
2199     InternetCloseHandle(req);
2200     InternetCloseHandle(con);
2201     InternetCloseHandle(ses);
2202 }
2203
2204 static void test_http1_1(int port)
2205 {
2206     HINTERNET ses, con, req;
2207     BOOL ret;
2208
2209     ses = InternetOpen("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
2210     ok(ses != NULL, "InternetOpen failed\n");
2211
2212     con = InternetConnect(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
2213     ok(con != NULL, "InternetConnect failed\n");
2214
2215     req = HttpOpenRequest(con, NULL, "/testB", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
2216     ok(req != NULL, "HttpOpenRequest failed\n");
2217
2218     ret = HttpSendRequest(req, NULL, 0, NULL, 0);
2219     if (ret)
2220     {
2221         InternetCloseHandle(req);
2222
2223         req = HttpOpenRequest(con, NULL, "/testB", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
2224         ok(req != NULL, "HttpOpenRequest failed\n");
2225
2226         ret = HttpSendRequest(req, NULL, 0, NULL, 0);
2227         ok(ret, "HttpSendRequest failed\n");
2228     }
2229
2230     InternetCloseHandle(req);
2231     InternetCloseHandle(con);
2232     InternetCloseHandle(ses);
2233 }
2234
2235 static void test_no_content(int port)
2236 {
2237     HINTERNET session, connection, req;
2238     DWORD res;
2239
2240     trace("Testing 204 no content response...\n");
2241
2242     hCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
2243
2244     session = InternetOpenA("", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);
2245     ok(session != NULL,"InternetOpen failed with error %u\n", GetLastError());
2246
2247     pInternetSetStatusCallbackA(session, callback);
2248
2249     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
2250     connection = InternetConnectA(session, "localhost", port,
2251             NULL, NULL, INTERNET_SERVICE_HTTP, 0x0, 0xdeadbeef);
2252     ok(connection != NULL,"InternetConnect failed with error %u\n", GetLastError());
2253     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
2254
2255     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
2256     req = HttpOpenRequestA(connection, "GET", "/test_no_content", NULL, NULL, NULL,
2257             INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RESYNCHRONIZE, 0xdeadbead);
2258     ok(req != NULL, "HttpOpenRequest failed: %u\n", GetLastError());
2259     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
2260
2261     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
2262     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
2263     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
2264     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
2265     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
2266     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
2267     SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
2268     SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION);
2269     SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED);
2270     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
2271
2272     res = HttpSendRequestA(req, NULL, -1, NULL, 0);
2273     ok(!res && (GetLastError() == ERROR_IO_PENDING),
2274        "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n");
2275     WaitForSingleObject(hCompleteEvent, INFINITE);
2276     ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error);
2277
2278     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
2279     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
2280     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
2281     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
2282     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
2283     CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
2284     CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
2285     CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
2286     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
2287     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
2288
2289     close_async_handle(session, hCompleteEvent, 2);
2290     CloseHandle(hCompleteEvent);
2291 }
2292
2293 static void test_conn_close(int port)
2294 {
2295     HINTERNET session, connection, req;
2296     DWORD res, avail, size;
2297     BYTE buf[1024];
2298
2299     trace("Testing connection close connection...\n");
2300
2301     hCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
2302     conn_close_event = CreateEvent(NULL, FALSE, FALSE, NULL);
2303
2304     session = InternetOpenA("", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);
2305     ok(session != NULL,"InternetOpen failed with error %u\n", GetLastError());
2306
2307     pInternetSetStatusCallbackA(session, callback);
2308
2309     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
2310     connection = InternetConnectA(session, "localhost", port,
2311             NULL, NULL, INTERNET_SERVICE_HTTP, 0x0, 0xdeadbeef);
2312     ok(connection != NULL,"InternetConnect failed with error %u\n", GetLastError());
2313     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
2314
2315     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
2316     req = HttpOpenRequestA(connection, "GET", "/test_conn_close", NULL, NULL, NULL,
2317             INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RESYNCHRONIZE, 0xdeadbead);
2318     ok(req != NULL, "HttpOpenRequest failed: %u\n", GetLastError());
2319     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
2320
2321     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
2322     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
2323     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
2324     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
2325     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
2326     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
2327     SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
2328     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
2329
2330     res = HttpSendRequestA(req, NULL, -1, NULL, 0);
2331     ok(!res && (GetLastError() == ERROR_IO_PENDING),
2332        "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n");
2333     WaitForSingleObject(hCompleteEvent, INFINITE);
2334     ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error);
2335
2336     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
2337     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
2338     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
2339     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
2340     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
2341     CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
2342     CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
2343     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
2344
2345     avail = 0;
2346     res = InternetQueryDataAvailable(req, &avail, 0, 0);
2347     ok(res, "InternetQueryDataAvailable failed: %u\n", GetLastError());
2348     ok(avail != 0, "avail = 0\n");
2349
2350     size = 0;
2351     res = InternetReadFile(req, buf, avail, &size);
2352     ok(res, "InternetReadFile failed: %u\n", GetLastError());
2353
2354     res = InternetQueryDataAvailable(req, &avail, 0, 0);
2355     ok(!res && (GetLastError() == ERROR_IO_PENDING),
2356        "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n");
2357     ok(!avail, "avail = %u, expected 0\n", avail);
2358
2359     SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION);
2360     SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED);
2361     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
2362     SetEvent(conn_close_event);
2363     WaitForSingleObject(hCompleteEvent, INFINITE);
2364     ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error);
2365     CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
2366     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
2367     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
2368
2369     close_async_handle(session, hCompleteEvent, 2);
2370     CloseHandle(hCompleteEvent);
2371 }
2372
2373 static void test_HttpSendRequestW(int port)
2374 {
2375     static const WCHAR header[] = {'U','A','-','C','P','U',':',' ','x','8','6',0};
2376     HINTERNET ses, con, req;
2377     DWORD error;
2378     BOOL ret;
2379
2380     ses = InternetOpen("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, INTERNET_FLAG_ASYNC);
2381     ok(ses != NULL, "InternetOpen failed\n");
2382
2383     con = InternetConnect(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
2384     ok(con != NULL, "InternetConnect failed\n");
2385
2386     req = HttpOpenRequest(con, NULL, "/test1", NULL, NULL, NULL, 0, 0);
2387     ok(req != NULL, "HttpOpenRequest failed\n");
2388
2389     SetLastError(0xdeadbeef);
2390     ret = HttpSendRequestW(req, header, ~0u, NULL, 0);
2391     error = GetLastError();
2392     ok(!ret, "HttpSendRequestW succeeded\n");
2393     ok(error == ERROR_IO_PENDING ||
2394        broken(error == ERROR_HTTP_HEADER_NOT_FOUND) ||  /* IE6 */
2395        broken(error == ERROR_INVALID_PARAMETER),        /* IE5 */
2396        "got %u expected ERROR_IO_PENDING\n", error);
2397
2398     InternetCloseHandle(req);
2399     InternetCloseHandle(con);
2400     InternetCloseHandle(ses);
2401 }
2402
2403 static void test_cookie_header(int port)
2404 {
2405     HINTERNET ses, con, req;
2406     DWORD size, error;
2407     BOOL ret;
2408     char buffer[64];
2409
2410     ses = InternetOpen("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
2411     ok(ses != NULL, "InternetOpen failed\n");
2412
2413     con = InternetConnect(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
2414     ok(con != NULL, "InternetConnect failed\n");
2415
2416     InternetSetCookie("http://localhost", "cookie", "biscuit");
2417
2418     req = HttpOpenRequest(con, NULL, "/testC", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
2419     ok(req != NULL, "HttpOpenRequest failed\n");
2420
2421     buffer[0] = 0;
2422     size = sizeof(buffer);
2423     SetLastError(0xdeadbeef);
2424     ret = HttpQueryInfo(req, HTTP_QUERY_COOKIE | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
2425     error = GetLastError();
2426     ok(!ret, "HttpQueryInfo succeeded\n");
2427     ok(error == ERROR_HTTP_HEADER_NOT_FOUND, "got %u expected ERROR_HTTP_HEADER_NOT_FOUND\n", error);
2428
2429     ret = HttpAddRequestHeaders(req, "Cookie: cookie=not biscuit\r\n", ~0u, HTTP_ADDREQ_FLAG_ADD);
2430     ok(ret, "HttpAddRequestHeaders failed: %u\n", GetLastError());
2431
2432     buffer[0] = 0;
2433     size = sizeof(buffer);
2434     ret = HttpQueryInfo(req, HTTP_QUERY_COOKIE | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
2435     ok(ret, "HttpQueryInfo failed: %u\n", GetLastError());
2436     ok(!strcmp(buffer, "cookie=not biscuit"), "got '%s' expected \'cookie=not biscuit\'\n", buffer);
2437
2438     ret = HttpSendRequest(req, NULL, 0, NULL, 0);
2439     ok(ret, "HttpSendRequest failed: %u\n", GetLastError());
2440
2441     test_status_code(req, 200);
2442
2443     buffer[0] = 0;
2444     size = sizeof(buffer);
2445     ret = HttpQueryInfo(req, HTTP_QUERY_COOKIE | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
2446     ok(ret, "HttpQueryInfo failed: %u\n", GetLastError());
2447     ok(!strcmp(buffer, "cookie=biscuit"), "got '%s' expected \'cookie=biscuit\'\n", buffer);
2448
2449     InternetCloseHandle(req);
2450     InternetCloseHandle(con);
2451     InternetCloseHandle(ses);
2452 }
2453
2454 static void test_basic_authentication(int port)
2455 {
2456     HINTERNET session, connect, request;
2457     BOOL ret;
2458
2459     session = InternetOpen("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
2460     ok(session != NULL, "InternetOpen failed\n");
2461
2462     connect = InternetConnect(session, "localhost", port, "user", "pwd", INTERNET_SERVICE_HTTP, 0, 0);
2463     ok(connect != NULL, "InternetConnect failed\n");
2464
2465     request = HttpOpenRequest(connect, NULL, "/test3", NULL, NULL, NULL, 0, 0);
2466     ok(request != NULL, "HttpOpenRequest failed\n");
2467
2468     ret = HttpSendRequest(request, NULL, 0, NULL, 0);
2469     ok(ret, "HttpSendRequest failed %u\n", GetLastError());
2470
2471     test_status_code(request, 200);
2472     test_request_flags(request, 0);
2473
2474     InternetCloseHandle(request);
2475     InternetCloseHandle(connect);
2476     InternetCloseHandle(session);
2477 }
2478
2479 static void test_invalid_response_headers(int port)
2480 {
2481     HINTERNET session, connect, request;
2482     DWORD size;
2483     BOOL ret;
2484     char buffer[256];
2485
2486     session = InternetOpen("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
2487     ok(session != NULL, "InternetOpen failed\n");
2488
2489     connect = InternetConnect(session, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
2490     ok(connect != NULL, "InternetConnect failed\n");
2491
2492     request = HttpOpenRequest(connect, NULL, "/testE", NULL, NULL, NULL, 0, 0);
2493     ok(request != NULL, "HttpOpenRequest failed\n");
2494
2495     ret = HttpSendRequest(request, NULL, 0, NULL, 0);
2496     ok(ret, "HttpSendRequest failed %u\n", GetLastError());
2497
2498     test_status_code(request, 401);
2499     test_request_flags(request, 0);
2500
2501     buffer[0] = 0;
2502     size = sizeof(buffer);
2503     ret = HttpQueryInfo( request, HTTP_QUERY_RAW_HEADERS, buffer, &size, NULL);
2504     ok(ret, "HttpQueryInfo failed\n");
2505     ok(!strcmp(buffer, "HTTP/1.0 401 Anonymous requests or requests on unsecure channel are not allowed"),
2506        "headers wrong \"%s\"\n", buffer);
2507
2508     buffer[0] = 0;
2509     size = sizeof(buffer);
2510     ret = HttpQueryInfo( request, HTTP_QUERY_SERVER, buffer, &size, NULL);
2511     ok(ret, "HttpQueryInfo failed\n");
2512     ok(!strcmp(buffer, "winetest"), "server wrong \"%s\"\n", buffer);
2513
2514     InternetCloseHandle(request);
2515     InternetCloseHandle(connect);
2516     InternetCloseHandle(session);
2517 }
2518
2519 static void test_response_without_headers(int port)
2520 {
2521     HINTERNET hi, hc, hr;
2522     DWORD r, count, size;
2523     char buffer[1024];
2524
2525     SetLastError(0xdeadbeef);
2526     hi = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
2527     ok(hi != NULL, "open failed %u\n", GetLastError());
2528
2529     SetLastError(0xdeadbeef);
2530     hc = InternetConnect(hi, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
2531     ok(hc != NULL, "connect failed %u\n", GetLastError());
2532
2533     SetLastError(0xdeadbeef);
2534     hr = HttpOpenRequest(hc, NULL, "/testG", NULL, NULL, NULL, 0, 0);
2535     ok(hr != NULL, "HttpOpenRequest failed %u\n", GetLastError());
2536
2537     test_request_flags(hr, INTERNET_REQFLAG_NO_HEADERS);
2538
2539     SetLastError(0xdeadbeef);
2540     r = HttpSendRequest(hr, NULL, 0, NULL, 0);
2541     ok(r, "HttpSendRequest failed %u\n", GetLastError());
2542
2543     test_request_flags_todo(hr, INTERNET_REQFLAG_NO_HEADERS);
2544
2545     count = 0;
2546     memset(buffer, 0, sizeof buffer);
2547     SetLastError(0xdeadbeef);
2548     r = InternetReadFile(hr, buffer, sizeof buffer, &count);
2549     ok(r, "InternetReadFile failed %u\n", GetLastError());
2550     todo_wine ok(count == sizeof page1 - 1, "count was wrong\n");
2551     todo_wine ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
2552
2553     test_status_code(hr, 200);
2554     test_request_flags_todo(hr, INTERNET_REQFLAG_NO_HEADERS);
2555
2556     buffer[0] = 0;
2557     size = sizeof(buffer);
2558     SetLastError(0xdeadbeef);
2559     r = HttpQueryInfo(hr, HTTP_QUERY_STATUS_TEXT, buffer, &size, NULL );
2560     ok(r, "HttpQueryInfo failed %u\n", GetLastError());
2561     ok(!strcmp(buffer, "OK"), "expected OK got: \"%s\"\n", buffer);
2562
2563     buffer[0] = 0;
2564     size = sizeof(buffer);
2565     SetLastError(0xdeadbeef);
2566     r = HttpQueryInfo(hr, HTTP_QUERY_VERSION, buffer, &size, NULL);
2567     ok(r, "HttpQueryInfo failed %u\n", GetLastError());
2568     ok(!strcmp(buffer, "HTTP/1.0"), "expected HTTP/1.0 got: \"%s\"\n", buffer);
2569
2570     buffer[0] = 0;
2571     size = sizeof(buffer);
2572     SetLastError(0xdeadbeef);
2573     r = HttpQueryInfo(hr, HTTP_QUERY_RAW_HEADERS, buffer, &size, NULL);
2574     ok(r, "HttpQueryInfo failed %u\n", GetLastError());
2575     ok(!strcmp(buffer, "HTTP/1.0 200 OK"), "raw headers wrong: \"%s\"\n", buffer);
2576
2577     InternetCloseHandle(hr);
2578     InternetCloseHandle(hc);
2579     InternetCloseHandle(hi);
2580 }
2581
2582 static void test_HttpQueryInfo(int port)
2583 {
2584     HINTERNET hi, hc, hr;
2585     DWORD size, index;
2586     char buffer[1024];
2587     BOOL ret;
2588
2589     hi = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
2590     ok(hi != NULL, "InternetOpen failed\n");
2591
2592     hc = InternetConnect(hi, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
2593     ok(hc != NULL, "InternetConnect failed\n");
2594
2595     hr = HttpOpenRequest(hc, NULL, "/testD", NULL, NULL, NULL, 0, 0);
2596     ok(hr != NULL, "HttpOpenRequest failed\n");
2597
2598     ret = HttpSendRequest(hr, NULL, 0, NULL, 0);
2599     ok(ret, "HttpSendRequest failed\n");
2600
2601     index = 0;
2602     size = sizeof(buffer);
2603     ret = HttpQueryInfo(hr, HTTP_QUERY_HOST | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, &index);
2604     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
2605     ok(index == 1, "expected 1 got %u\n", index);
2606
2607     index = 0;
2608     size = sizeof(buffer);
2609     ret = HttpQueryInfo(hr, HTTP_QUERY_DATE | HTTP_QUERY_FLAG_SYSTEMTIME, buffer, &size, &index);
2610     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
2611     ok(index == 1, "expected 1 got %u\n", index);
2612
2613     index = 0;
2614     size = sizeof(buffer);
2615     ret = HttpQueryInfo(hr, HTTP_QUERY_RAW_HEADERS, buffer, &size, &index);
2616     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
2617     ok(index == 0, "expected 0 got %u\n", index);
2618
2619     size = sizeof(buffer);
2620     ret = HttpQueryInfo(hr, HTTP_QUERY_RAW_HEADERS, buffer, &size, &index);
2621     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
2622     ok(index == 0, "expected 0 got %u\n", index);
2623
2624     index = 0xdeadbeef; /* invalid start index */
2625     size = sizeof(buffer);
2626     ret = HttpQueryInfo(hr, HTTP_QUERY_RAW_HEADERS, buffer, &size, &index);
2627     todo_wine ok(!ret, "HttpQueryInfo should have failed\n");
2628     todo_wine ok(GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND,
2629        "Expected ERROR_HTTP_HEADER_NOT_FOUND, got %u\n", GetLastError());
2630
2631     index = 0;
2632     size = sizeof(buffer);
2633     ret = HttpQueryInfo(hr, HTTP_QUERY_RAW_HEADERS_CRLF, buffer, &size, &index);
2634     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
2635     ok(index == 0, "expected 0 got %u\n", index);
2636
2637     size = sizeof(buffer);
2638     ret = HttpQueryInfo(hr, HTTP_QUERY_STATUS_TEXT, buffer, &size, &index);
2639     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
2640     ok(index == 0, "expected 0 got %u\n", index);
2641
2642     size = sizeof(buffer);
2643     ret = HttpQueryInfo(hr, HTTP_QUERY_VERSION, buffer, &size, &index);
2644     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
2645     ok(index == 0, "expected 0 got %u\n", index);
2646
2647     test_status_code(hr, 200);
2648
2649     index = 0xdeadbeef;
2650     size = sizeof(buffer);
2651     ret = HttpQueryInfo(hr, HTTP_QUERY_FORWARDED, buffer, &size, &index);
2652     ok(!ret, "HttpQueryInfo succeeded\n");
2653     ok(index == 0xdeadbeef, "expected 0xdeadbeef got %u\n", index);
2654
2655     index = 0;
2656     size = sizeof(buffer);
2657     ret = HttpQueryInfo(hr, HTTP_QUERY_SERVER, buffer, &size, &index);
2658     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
2659     ok(index == 1, "expected 1 got %u\n", index);
2660
2661     index = 0;
2662     size = sizeof(buffer);
2663     strcpy(buffer, "Server");
2664     ret = HttpQueryInfo(hr, HTTP_QUERY_CUSTOM, buffer, &size, &index);
2665     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
2666     ok(index == 1, "expected 1 got %u\n", index);
2667
2668     index = 0;
2669     size = sizeof(buffer);
2670     ret = HttpQueryInfo(hr, HTTP_QUERY_SET_COOKIE, buffer, &size, &index);
2671     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
2672     ok(index == 1, "expected 1 got %u\n", index);
2673
2674     size = sizeof(buffer);
2675     ret = HttpQueryInfo(hr, HTTP_QUERY_SET_COOKIE, buffer, &size, &index);
2676     ok(ret, "HttpQueryInfo failed %u\n", GetLastError());
2677     ok(index == 2, "expected 2 got %u\n", index);
2678
2679     InternetCloseHandle(hr);
2680     InternetCloseHandle(hc);
2681     InternetCloseHandle(hi);
2682 }
2683
2684 static void test_options(int port)
2685 {
2686     HINTERNET ses, con, req;
2687     DWORD size, error;
2688     DWORD_PTR ctx;
2689     BOOL ret;
2690
2691     ses = InternetOpen("winetest", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
2692     ok(ses != NULL, "InternetOpen failed\n");
2693
2694     SetLastError(0xdeadbeef);
2695     ret = InternetSetOption(ses, INTERNET_OPTION_CONTEXT_VALUE, NULL, 0);
2696     error = GetLastError();
2697     ok(!ret, "InternetSetOption succeeded\n");
2698     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2699
2700     SetLastError(0xdeadbeef);
2701     ret = InternetSetOption(ses, INTERNET_OPTION_CONTEXT_VALUE, NULL, sizeof(ctx));
2702     ok(!ret, "InternetSetOption succeeded\n");
2703     error = GetLastError();
2704     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2705
2706     SetLastError(0xdeadbeef);
2707     ret = InternetSetOption(ses, INTERNET_OPTION_CONTEXT_VALUE, &ctx, 0);
2708     ok(!ret, "InternetSetOption succeeded\n");
2709     error = GetLastError();
2710     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2711
2712     ctx = 1;
2713     ret = InternetSetOption(ses, INTERNET_OPTION_CONTEXT_VALUE, &ctx, sizeof(ctx));
2714     ok(ret, "InternetSetOption failed %u\n", GetLastError());
2715
2716     SetLastError(0xdeadbeef);
2717     ret = InternetQueryOption(ses, INTERNET_OPTION_CONTEXT_VALUE, NULL, NULL);
2718     error = GetLastError();
2719     ok(!ret, "InternetQueryOption succeeded\n");
2720     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2721
2722     SetLastError(0xdeadbeef);
2723     ret = InternetQueryOption(ses, INTERNET_OPTION_CONTEXT_VALUE, &ctx, NULL);
2724     error = GetLastError();
2725     ok(!ret, "InternetQueryOption succeeded\n");
2726     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2727
2728     size = 0;
2729     SetLastError(0xdeadbeef);
2730     ret = InternetQueryOption(ses, INTERNET_OPTION_CONTEXT_VALUE, NULL, &size);
2731     error = GetLastError();
2732     ok(!ret, "InternetQueryOption succeeded\n");
2733     ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
2734
2735     size = sizeof(ctx);
2736     SetLastError(0xdeadbeef);
2737     ret = InternetQueryOption(NULL, INTERNET_OPTION_CONTEXT_VALUE, &ctx, &size);
2738     error = GetLastError();
2739     ok(!ret, "InternetQueryOption succeeded\n");
2740     ok(error == ERROR_INTERNET_INCORRECT_HANDLE_TYPE, "expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE, got %u\n", error);
2741
2742     ctx = 0xdeadbeef;
2743     size = sizeof(ctx);
2744     ret = InternetQueryOption(ses, INTERNET_OPTION_CONTEXT_VALUE, &ctx, &size);
2745     ok(ret, "InternetQueryOption failed %u\n", GetLastError());
2746     ok(ctx == 1, "expected 1 got %lu\n", ctx);
2747
2748     con = InternetConnect(ses, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
2749     ok(con != NULL, "InternetConnect failed\n");
2750
2751     ctx = 0xdeadbeef;
2752     size = sizeof(ctx);
2753     ret = InternetQueryOption(con, INTERNET_OPTION_CONTEXT_VALUE, &ctx, &size);
2754     ok(ret, "InternetQueryOption failed %u\n", GetLastError());
2755     ok(ctx == 0, "expected 0 got %lu\n", ctx);
2756
2757     ctx = 2;
2758     ret = InternetSetOption(con, INTERNET_OPTION_CONTEXT_VALUE, &ctx, sizeof(ctx));
2759     ok(ret, "InternetSetOption failed %u\n", GetLastError());
2760
2761     ctx = 0xdeadbeef;
2762     size = sizeof(ctx);
2763     ret = InternetQueryOption(con, INTERNET_OPTION_CONTEXT_VALUE, &ctx, &size);
2764     ok(ret, "InternetQueryOption failed %u\n", GetLastError());
2765     ok(ctx == 2, "expected 2 got %lu\n", ctx);
2766
2767     req = HttpOpenRequest(con, NULL, "/test1", NULL, NULL, NULL, 0, 0);
2768     ok(req != NULL, "HttpOpenRequest failed\n");
2769
2770     ctx = 0xdeadbeef;
2771     size = sizeof(ctx);
2772     ret = InternetQueryOption(req, INTERNET_OPTION_CONTEXT_VALUE, &ctx, &size);
2773     ok(ret, "InternetQueryOption failed %u\n", GetLastError());
2774     ok(ctx == 0, "expected 0 got %lu\n", ctx);
2775
2776     ctx = 3;
2777     ret = InternetSetOption(req, INTERNET_OPTION_CONTEXT_VALUE, &ctx, sizeof(ctx));
2778     ok(ret, "InternetSetOption failed %u\n", GetLastError());
2779
2780     ctx = 0xdeadbeef;
2781     size = sizeof(ctx);
2782     ret = InternetQueryOption(req, INTERNET_OPTION_CONTEXT_VALUE, &ctx, &size);
2783     ok(ret, "InternetQueryOption failed %u\n", GetLastError());
2784     ok(ctx == 3, "expected 3 got %lu\n", ctx);
2785
2786     /* INTERNET_OPTION_PROXY */
2787     SetLastError(0xdeadbeef);
2788     ret = InternetQueryOptionA(ses, INTERNET_OPTION_PROXY, NULL, NULL);
2789     error = GetLastError();
2790     ok(!ret, "InternetQueryOption succeeded\n");
2791     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2792
2793     SetLastError(0xdeadbeef);
2794     ret = InternetQueryOptionA(ses, INTERNET_OPTION_PROXY, &ctx, NULL);
2795     error = GetLastError();
2796     ok(!ret, "InternetQueryOption succeeded\n");
2797     ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", error);
2798
2799     size = 0;
2800     SetLastError(0xdeadbeef);
2801     ret = InternetQueryOptionA(ses, INTERNET_OPTION_PROXY, NULL, &size);
2802     error = GetLastError();
2803     ok(!ret, "InternetQueryOption succeeded\n");
2804     ok(error == ERROR_INSUFFICIENT_BUFFER, "expected ERROR_INSUFFICIENT_BUFFER, got %u\n", error);
2805     ok(size >= sizeof(INTERNET_PROXY_INFOA), "expected size to be greater or equal to the struct size\n");
2806
2807     InternetCloseHandle(req);
2808     InternetCloseHandle(con);
2809     InternetCloseHandle(ses);
2810 }
2811
2812 static void test_url_caching(int port, int *num_retrievals)
2813 {
2814     HINTERNET hi, hc, hr;
2815     DWORD r, count;
2816     char buffer[0x100];
2817
2818     ok(*num_retrievals == 0, "expected 0 retrievals prior to test\n");
2819
2820     hi = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
2821     ok(hi != NULL, "open failed\n");
2822
2823     hc = InternetConnect(hi, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
2824     ok(hc != NULL, "connect failed\n");
2825
2826     /* Pre-load the cache: */
2827     hr = HttpOpenRequest(hc, "GET", "/testH", NULL, NULL, NULL, 0, 0);
2828     ok(hr != NULL, "HttpOpenRequest failed\n");
2829
2830     r = HttpSendRequest(hr, NULL, 0, NULL, 0);
2831     ok(r, "HttpSendRequest failed\n");
2832
2833     ok(*num_retrievals == 1, "expected 1 retrievals, got %d\n", *num_retrievals);
2834
2835     count = 0;
2836     memset(buffer, 0, sizeof buffer);
2837     SetLastError(0xdeadbeef);
2838     r = InternetReadFile(hr, buffer, sizeof buffer, &count);
2839     ok(r, "InternetReadFile failed %u\n", GetLastError());
2840     ok(count == sizeof page1 - 1, "count was wrong\n");
2841     ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
2842
2843     InternetCloseHandle(hr);
2844
2845     /* Send the same request, requiring it to be retrieved from the cache */
2846     hr = HttpOpenRequest(hc, "GET", "/testH", NULL, NULL, NULL, INTERNET_FLAG_FROM_CACHE, 0);
2847     ok(hr != NULL, "HttpOpenRequest failed\n");
2848
2849     r = HttpSendRequest(hr, NULL, 0, NULL, 0);
2850     /* Older Windows versions succeed with this request, newer ones fail with
2851      * ERROR_FILE_NOT_FOUND.  Accept either, as the older version allows us
2852      * to verify that the server isn't contacted.
2853      */
2854     if (!r)
2855         ok(GetLastError() == ERROR_FILE_NOT_FOUND,
2856            "expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
2857     else
2858     {
2859         /* The server shouldn't be contacted for this request. */
2860         todo_wine
2861         ok(*num_retrievals == 1, "expected 1 retrievals\n");
2862
2863         count = 0;
2864         memset(buffer, 0, sizeof buffer);
2865         SetLastError(0xdeadbeef);
2866         r = InternetReadFile(hr, buffer, sizeof buffer, &count);
2867         ok(r, "InternetReadFile failed %u\n", GetLastError());
2868         ok(count == sizeof page1 - 1, "count was wrong\n");
2869         ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
2870     }
2871
2872     InternetCloseHandle(hc);
2873     InternetCloseHandle(hi);
2874 }
2875
2876 static void test_http_connection(void)
2877 {
2878     struct server_info si;
2879     HANDLE hThread;
2880     DWORD id = 0, r;
2881
2882     si.hEvent = CreateEvent(NULL, 0, 0, NULL);
2883     si.port = 7531;
2884     si.num_testH_retrievals = 0;
2885
2886     hThread = CreateThread(NULL, 0, server_thread, (LPVOID) &si, 0, &id);
2887     ok( hThread != NULL, "create thread failed\n");
2888
2889     r = WaitForSingleObject(si.hEvent, 10000);
2890     ok (r == WAIT_OBJECT_0, "failed to start wininet test server\n");
2891     if (r != WAIT_OBJECT_0)
2892         return;
2893
2894     test_basic_request(si.port, "GET", "/test1");
2895     test_proxy_indirect(si.port);
2896     test_proxy_direct(si.port);
2897     test_header_handling_order(si.port);
2898     test_basic_request(si.port, "POST", "/test5");
2899     test_basic_request(si.port, "RPC_IN_DATA", "/test5");
2900     test_basic_request(si.port, "RPC_OUT_DATA", "/test5");
2901     test_basic_request(si.port, "GET", "/test6");
2902     test_basic_request(si.port, "GET", "/testF");
2903     test_connection_header(si.port);
2904     test_http1_1(si.port);
2905     test_cookie_header(si.port);
2906     test_basic_authentication(si.port);
2907     test_invalid_response_headers(si.port);
2908     test_response_without_headers(si.port);
2909     test_HttpQueryInfo(si.port);
2910     test_HttpSendRequestW(si.port);
2911     test_last_error(si.port);
2912     test_options(si.port);
2913     test_url_caching(si.port, &si.num_testH_retrievals);
2914     test_no_content(si.port);
2915     test_conn_close(si.port);
2916
2917     /* send the basic request again to shutdown the server thread */
2918     test_basic_request(si.port, "GET", "/quit");
2919
2920     r = WaitForSingleObject(hThread, 3000);
2921     ok( r == WAIT_OBJECT_0, "thread wait failed\n");
2922     CloseHandle(hThread);
2923 }
2924
2925 static void release_cert_info(INTERNET_CERTIFICATE_INFOA *info)
2926 {
2927     LocalFree(info->lpszSubjectInfo);
2928     LocalFree(info->lpszIssuerInfo);
2929     LocalFree(info->lpszProtocolName);
2930     LocalFree(info->lpszSignatureAlgName);
2931     LocalFree(info->lpszEncryptionAlgName);
2932 }
2933
2934 static void test_cert_struct(HINTERNET req)
2935 {
2936     INTERNET_CERTIFICATE_INFOA info;
2937     DWORD size;
2938     BOOL res;
2939
2940     static const char ex_subject[] =
2941         "US\r\n"
2942         "Minnesota\r\n"
2943         "Saint Paul\r\n"
2944         "WineHQ\r\n"
2945         "test.winehq.org\r\n"
2946         "webmaster@winehq.org";
2947
2948     static const char ex_issuer[] =
2949         "US\r\n"
2950         "Minnesota\r\n"
2951         "WineHQ\r\n"
2952         "test.winehq.org\r\n"
2953         "webmaster@winehq.org";
2954
2955     memset(&info, 0x5, sizeof(info));
2956
2957     size = sizeof(info);
2958     res = InternetQueryOption(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT, &info, &size);
2959     ok(res, "InternetQueryOption failed: %u\n", GetLastError());
2960     ok(size == sizeof(info), "size = %u\n", size);
2961
2962     ok(!strcmp(info.lpszSubjectInfo, ex_subject), "lpszSubjectInfo = %s\n", info.lpszSubjectInfo);
2963     ok(!strcmp(info.lpszIssuerInfo, ex_issuer), "lpszIssuerInfo = %s\n", info.lpszIssuerInfo);
2964     ok(!info.lpszSignatureAlgName, "lpszSignatureAlgName = %s\n", info.lpszSignatureAlgName);
2965     ok(!info.lpszEncryptionAlgName, "lpszEncryptionAlgName = %s\n", info.lpszEncryptionAlgName);
2966     ok(!info.lpszProtocolName, "lpszProtocolName = %s\n", info.lpszProtocolName);
2967     todo_wine
2968     ok(info.dwKeySize == 128, "dwKeySize = %u\n", info.dwKeySize);
2969
2970     release_cert_info(&info);
2971 }
2972
2973 #define test_security_info(a,b,c) _test_security_info(__LINE__,a,b,c)
2974 static void _test_security_info(unsigned line, const char *urlc, DWORD error, DWORD ex_flags)
2975 {
2976     char url[INTERNET_MAX_URL_LENGTH];
2977     const CERT_CHAIN_CONTEXT *chain;
2978     DWORD flags;
2979     BOOL res;
2980
2981     if(!pInternetGetSecurityInfoByURLA) {
2982         win_skip("pInternetGetSecurityInfoByURLA not available\n");
2983         return;
2984     }
2985
2986     strcpy(url, urlc);
2987     chain = (void*)0xdeadbeef;
2988     flags = 0xdeadbeef;
2989     res = pInternetGetSecurityInfoByURLA(url, &chain, &flags);
2990     if(error == ERROR_SUCCESS) {
2991         ok_(__FILE__,line)(res, "InternetGetSecurityInfoByURLA failed: %u\n", GetLastError());
2992         ok_(__FILE__,line)(chain != NULL, "chain = NULL\n");
2993         ok_(__FILE__,line)(flags == ex_flags, "flags = %x\n", flags);
2994         CertFreeCertificateChain(chain);
2995     }else {
2996         ok_(__FILE__,line)(!res && GetLastError() == error,
2997                            "InternetGetSecurityInfoByURLA returned: %x(%u), exected %u\n", res, GetLastError(), error);
2998     }
2999 }
3000
3001 #define test_secflags_option(a,b) _test_secflags_option(__LINE__,a,b)
3002 static void _test_secflags_option(unsigned line, HINTERNET req, DWORD ex_flags)
3003 {
3004     DWORD flags, size;
3005     BOOL res;
3006
3007     flags = 0xdeadbeef;
3008     size = sizeof(flags);
3009     res = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size);
3010     ok_(__FILE__,line)(res, "InternetQueryOptionW(INTERNET_OPTION_SECURITY_FLAGS) failed: %u\n", GetLastError());
3011     ok_(__FILE__,line)(flags == ex_flags, "INTERNET_OPTION_SECURITY_FLAGS flags = %x, expected %x\n", flags, ex_flags);
3012
3013     /* Option 98 is undocumented and seems to be the same as INTERNET_OPTION_SECURITY_FLAGS */
3014     flags = 0xdeadbeef;
3015     size = sizeof(flags);
3016     res = InternetQueryOptionW(req, 98, &flags, &size);
3017     ok_(__FILE__,line)(res, "InternetQueryOptionW(98) failed: %u\n", GetLastError());
3018     ok_(__FILE__,line)(flags == ex_flags, "INTERNET_OPTION_SECURITY_FLAGS(98) flags = %x, expected %x\n", flags, ex_flags);
3019 }
3020
3021 #define set_secflags(a,b,c) _set_secflags(__LINE__,a,b,c)
3022 static void _set_secflags(unsigned line, HINTERNET req, BOOL use_undoc, DWORD flags)
3023 {
3024     BOOL res;
3025
3026     res = InternetSetOptionW(req, use_undoc ? 99 : INTERNET_OPTION_SECURITY_FLAGS, &flags, sizeof(flags));
3027     ok_(__FILE__,line)(res, "InternetSetOption(INTERNET_OPTION_SECURITY_FLAGS) failed: %u\n", GetLastError());
3028 }
3029
3030 static void test_security_flags(void)
3031 {
3032     HINTERNET ses, conn, req;
3033     DWORD size, flags;
3034     char buf[100];
3035     BOOL res;
3036
3037     trace("Testing security flags...\n");
3038
3039     hCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
3040
3041     ses = InternetOpen("WineTest", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);
3042     ok(ses != NULL, "InternetOpen failed\n");
3043
3044     pInternetSetStatusCallbackA(ses, &callback);
3045
3046     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
3047     conn = InternetConnectA(ses, "test.winehq.org", INTERNET_DEFAULT_HTTPS_PORT,
3048                             NULL, NULL, INTERNET_SERVICE_HTTP, INTERNET_FLAG_SECURE, 0xdeadbeef);
3049     ok(conn != NULL, "InternetConnect failed with error %u\n", GetLastError());
3050     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
3051
3052     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
3053     req = HttpOpenRequest(conn, "GET", "/tests/hello.html", NULL, NULL, NULL,
3054                           INTERNET_FLAG_SECURE|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_RELOAD|INTERNET_FLAG_NO_CACHE_WRITE,
3055                           0xdeadbeef);
3056     ok(req != NULL, "HttpOpenRequest failed\n");
3057     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
3058
3059     flags = 0xdeadbeef;
3060     size = sizeof(flags);
3061     res = InternetQueryOptionW(req, 98, &flags, &size);
3062     if(!res && GetLastError() == ERROR_INVALID_PARAMETER) {
3063         win_skip("Incomplete security flags support, skipping\n");
3064
3065         close_async_handle(ses, hCompleteEvent, 2);
3066         CloseHandle(hCompleteEvent);
3067         return;
3068     }
3069
3070     test_secflags_option(req, 0);
3071     test_security_info("https://test.winehq.org/data/some_file.html?q", ERROR_INTERNET_ITEM_NOT_FOUND, 0);
3072
3073     set_secflags(req, TRUE, SECURITY_FLAG_IGNORE_REVOCATION);
3074     test_secflags_option(req, SECURITY_FLAG_IGNORE_REVOCATION);
3075
3076     set_secflags(req, TRUE, SECURITY_FLAG_IGNORE_CERT_CN_INVALID);
3077     test_secflags_option(req, SECURITY_FLAG_IGNORE_REVOCATION|SECURITY_FLAG_IGNORE_CERT_CN_INVALID);
3078
3079     set_secflags(req, FALSE, SECURITY_FLAG_IGNORE_UNKNOWN_CA);
3080     test_secflags_option(req, SECURITY_FLAG_IGNORE_UNKNOWN_CA|SECURITY_FLAG_IGNORE_REVOCATION|SECURITY_FLAG_IGNORE_CERT_CN_INVALID);
3081
3082     flags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID|SECURITY_FLAG_SECURE;
3083     res = InternetSetOptionW(req, 99, &flags, sizeof(flags));
3084     ok(!res && GetLastError() == ERROR_INTERNET_OPTION_NOT_SETTABLE, "InternetSetOption(99) failed: %u\n", GetLastError());
3085
3086     SET_EXPECT(INTERNET_STATUS_RESOLVING_NAME);
3087     SET_EXPECT(INTERNET_STATUS_NAME_RESOLVED);
3088     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
3089     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
3090     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
3091     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
3092     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
3093     SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
3094     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
3095     SET_OPTIONAL(INTERNET_STATUS_DETECTING_PROXY);
3096     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
3097
3098     res = HttpSendRequest(req, NULL, 0, NULL, 0);
3099     ok(!res && GetLastError() == ERROR_IO_PENDING, "HttpSendRequest failed: %u\n", GetLastError());
3100
3101     WaitForSingleObject(hCompleteEvent, INFINITE);
3102     ok(req_error == ERROR_SUCCESS, "req_error = %d\n", req_error);
3103
3104     todo_wine CHECK_NOT_NOTIFIED(INTERNET_STATUS_RESOLVING_NAME);
3105     todo_wine CHECK_NOT_NOTIFIED(INTERNET_STATUS_NAME_RESOLVED);
3106     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
3107     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
3108     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
3109     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
3110     CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
3111     CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
3112     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
3113     CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
3114     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
3115
3116     test_request_flags(req, 0);
3117     test_secflags_option(req, SECURITY_FLAG_SECURE|SECURITY_FLAG_IGNORE_UNKNOWN_CA
3118             |SECURITY_FLAG_IGNORE_REVOCATION|SECURITY_FLAG_IGNORE_CERT_CN_INVALID|SECURITY_FLAG_STRENGTH_STRONG);
3119
3120     res = InternetReadFile(req, buf, sizeof(buf), &size);
3121     ok(res, "InternetReadFile failed: %u\n", GetLastError());
3122     ok(size, "size = 0\n");
3123
3124     /* Collect all existing persistent connections */
3125     res = InternetSetOptionA(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0);
3126     ok(res, "InternetSetOption(INTERNET_OPTION_END_BROWSER_SESSION) failed: %u\n", GetLastError());
3127
3128     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
3129     req = HttpOpenRequest(conn, "GET", "/tests/hello.html", NULL, NULL, NULL,
3130                           INTERNET_FLAG_SECURE|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_RELOAD|INTERNET_FLAG_NO_CACHE_WRITE,
3131                           0xdeadbeef);
3132     ok(req != NULL, "HttpOpenRequest failed\n");
3133     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
3134
3135     flags = INTERNET_ERROR_MASK_COMBINED_SEC_CERT|INTERNET_ERROR_MASK_LOGIN_FAILURE_DISPLAY_ENTITY_BODY;
3136     res = InternetSetOption(req, INTERNET_OPTION_ERROR_MASK, (void*)&flags, sizeof(flags));
3137     ok(res, "InternetQueryOption(INTERNET_OPTION_ERROR_MASK failed: %u\n", GetLastError());
3138
3139     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
3140     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
3141     SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION);
3142     SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED);
3143     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
3144     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
3145     SET_OPTIONAL(INTERNET_STATUS_DETECTING_PROXY);
3146
3147     res = HttpSendRequest(req, NULL, 0, NULL, 0);
3148     ok(!res && GetLastError() == ERROR_IO_PENDING, "HttpSendRequest failed: %u\n", GetLastError());
3149
3150     WaitForSingleObject(hCompleteEvent, INFINITE);
3151     ok(req_error == ERROR_INTERNET_SEC_CERT_REV_FAILED || broken(req_error == ERROR_INTERNET_SEC_CERT_ERRORS),
3152        "req_error = %d\n", req_error);
3153
3154     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
3155     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
3156     CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
3157     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
3158     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
3159     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
3160     CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
3161
3162     if(req_error != ERROR_INTERNET_SEC_CERT_REV_FAILED) {
3163         win_skip("Unexpected cert errors, skipping security flags tests\n");
3164
3165         close_async_handle(ses, hCompleteEvent, 3);
3166         CloseHandle(hCompleteEvent);
3167         return;
3168     }
3169
3170     size = sizeof(buf);
3171     res = HttpQueryInfoA(req, HTTP_QUERY_CONTENT_ENCODING, buf, &size, 0);
3172     ok(!res && GetLastError() == ERROR_HTTP_HEADER_NOT_FOUND, "HttpQueryInfoA(HTTP_QUERY_CONTENT_ENCODING) failed: %u\n", GetLastError());
3173
3174     test_request_flags(req, 8);
3175     test_secflags_option(req, 0x800000);
3176
3177     set_secflags(req, FALSE, SECURITY_FLAG_IGNORE_REVOCATION);
3178     test_secflags_option(req, 0x800000|SECURITY_FLAG_IGNORE_REVOCATION);
3179
3180     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
3181     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
3182     SET_EXPECT(INTERNET_STATUS_CLOSING_CONNECTION);
3183     SET_EXPECT(INTERNET_STATUS_CONNECTION_CLOSED);
3184     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
3185     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
3186     SET_OPTIONAL(INTERNET_STATUS_DETECTING_PROXY);
3187
3188     res = HttpSendRequest(req, NULL, 0, NULL, 0);
3189     ok(!res && GetLastError() == ERROR_IO_PENDING, "HttpSendRequest failed: %u\n", GetLastError());
3190
3191     WaitForSingleObject(hCompleteEvent, INFINITE);
3192     ok(req_error == ERROR_INTERNET_SEC_CERT_ERRORS, "req_error = %d\n", req_error);
3193
3194     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
3195     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
3196     CHECK_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION);
3197     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED);
3198     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
3199     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
3200     CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
3201
3202     test_request_flags(req, INTERNET_REQFLAG_NO_HEADERS);
3203     test_secflags_option(req, SECURITY_FLAG_IGNORE_REVOCATION|0x1800000);
3204     test_security_info("https://test.winehq.org/data/some_file.html?q", ERROR_INTERNET_ITEM_NOT_FOUND, 0);
3205
3206     set_secflags(req, FALSE, SECURITY_FLAG_IGNORE_UNKNOWN_CA);
3207     test_secflags_option(req, 0x1800000|SECURITY_FLAG_IGNORE_REVOCATION|SECURITY_FLAG_IGNORE_UNKNOWN_CA
3208             |SECURITY_FLAG_IGNORE_REVOCATION);
3209     test_http_version(req);
3210
3211     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
3212     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
3213     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
3214     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
3215     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
3216     SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
3217     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
3218     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
3219     SET_OPTIONAL(INTERNET_STATUS_DETECTING_PROXY);
3220
3221     res = HttpSendRequest(req, NULL, 0, NULL, 0);
3222     ok(!res && GetLastError() == ERROR_IO_PENDING, "HttpSendRequest failed: %u\n", GetLastError());
3223
3224     WaitForSingleObject(hCompleteEvent, INFINITE);
3225     ok(req_error == ERROR_SUCCESS, "req_error = %d\n", req_error);
3226
3227     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
3228     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
3229     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
3230     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
3231     CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
3232     CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
3233     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
3234     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
3235     CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY);
3236
3237     test_request_flags(req, 0);
3238     test_secflags_option(req, SECURITY_FLAG_SECURE|SECURITY_FLAG_IGNORE_UNKNOWN_CA|SECURITY_FLAG_IGNORE_REVOCATION
3239             |SECURITY_FLAG_STRENGTH_STRONG|0x1800000);
3240
3241     test_cert_struct(req);
3242     test_security_info("https://test.winehq.org/data/some_file.html?q", 0, 0x1800000);
3243
3244     res = InternetReadFile(req, buf, sizeof(buf), &size);
3245     ok(res, "InternetReadFile failed: %u\n", GetLastError());
3246     ok(size, "size = 0\n");
3247
3248     close_async_handle(ses, hCompleteEvent, 3);
3249
3250     /* Collect all existing persistent connections */
3251     res = InternetSetOptionA(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0);
3252     ok(res, "InternetSetOption(INTERNET_OPTION_END_BROWSER_SESSION) failed: %u\n", GetLastError());
3253
3254     /* Make another request, without setting security flags */
3255
3256     ses = InternetOpen("WineTest", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);
3257     ok(ses != NULL, "InternetOpen failed\n");
3258
3259     pInternetSetStatusCallbackA(ses, &callback);
3260
3261     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
3262     conn = InternetConnectA(ses, "test.winehq.org", INTERNET_DEFAULT_HTTPS_PORT,
3263                             NULL, NULL, INTERNET_SERVICE_HTTP, INTERNET_FLAG_SECURE, 0xdeadbeef);
3264     ok(conn != NULL, "InternetConnect failed with error %u\n", GetLastError());
3265     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
3266
3267     SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED);
3268     req = HttpOpenRequest(conn, "GET", "/tests/hello.html", NULL, NULL, NULL,
3269                           INTERNET_FLAG_SECURE|INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_RELOAD|INTERNET_FLAG_NO_CACHE_WRITE,
3270                           0xdeadbeef);
3271     ok(req != NULL, "HttpOpenRequest failed\n");
3272     CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED);
3273
3274     test_secflags_option(req, SECURITY_FLAG_SECURE|SECURITY_FLAG_IGNORE_UNKNOWN_CA|SECURITY_FLAG_STRENGTH_STRONG
3275            |SECURITY_FLAG_IGNORE_REVOCATION|0x1800000);
3276     test_http_version(req);
3277
3278     SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER);
3279     SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER);
3280     SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST);
3281     SET_EXPECT(INTERNET_STATUS_REQUEST_SENT);
3282     SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE);
3283     SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED);
3284     SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE);
3285     SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT);
3286
3287     res = HttpSendRequest(req, NULL, 0, NULL, 0);
3288     ok(!res && GetLastError() == ERROR_IO_PENDING, "HttpSendRequest failed: %u\n", GetLastError());
3289
3290     WaitForSingleObject(hCompleteEvent, INFINITE);
3291     ok(req_error == ERROR_SUCCESS, "req_error = %d\n", req_error);
3292
3293     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER);
3294     CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER);
3295     CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST);
3296     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT);
3297     CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE);
3298     CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED);
3299     CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE);
3300     CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT);
3301
3302     test_request_flags(req, 0);
3303     test_secflags_option(req, SECURITY_FLAG_SECURE|SECURITY_FLAG_IGNORE_UNKNOWN_CA|SECURITY_FLAG_STRENGTH_STRONG
3304             |SECURITY_FLAG_IGNORE_REVOCATION|0x1800000);
3305
3306     res = InternetReadFile(req, buf, sizeof(buf), &size);
3307     ok(res, "InternetReadFile failed: %u\n", GetLastError());
3308     ok(size, "size = 0\n");
3309
3310     close_async_handle(ses, hCompleteEvent, 2);
3311
3312     CloseHandle(hCompleteEvent);
3313
3314     test_security_info("http://test.winehq.org/data/some_file.html?q", ERROR_INTERNET_ITEM_NOT_FOUND, 0);
3315     test_security_info("file:///c:/dir/file.txt", ERROR_INTERNET_ITEM_NOT_FOUND, 0);
3316     test_security_info("xxx:///c:/dir/file.txt", ERROR_INTERNET_ITEM_NOT_FOUND, 0);
3317 }
3318
3319 static void test_secure_connection(void)
3320 {
3321     static const WCHAR gizmo5[] = {'G','i','z','m','o','5',0};
3322     static const WCHAR testbot[] = {'t','e','s','t','b','o','t','.','w','i','n','e','h','q','.','o','r','g',0};
3323     static const WCHAR get[] = {'G','E','T',0};
3324     static const WCHAR slash[] = {'/',0};
3325     HINTERNET ses, con, req;
3326     DWORD size, flags;
3327     INTERNET_CERTIFICATE_INFOA *certificate_structA = NULL;
3328     INTERNET_CERTIFICATE_INFOW *certificate_structW = NULL;
3329     BOOL ret;
3330
3331     ses = InternetOpen("Gizmo5", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
3332     ok(ses != NULL, "InternetOpen failed\n");
3333
3334     con = InternetConnect(ses, "testbot.winehq.org",
3335                           INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL,
3336                           INTERNET_SERVICE_HTTP, 0, 0);
3337     ok(con != NULL, "InternetConnect failed\n");
3338
3339     req = HttpOpenRequest(con, "GET", "/", NULL, NULL, NULL,
3340                           INTERNET_FLAG_SECURE, 0);
3341     ok(req != NULL, "HttpOpenRequest failed\n");
3342
3343     ret = HttpSendRequest(req, NULL, 0, NULL, 0);
3344     ok(ret, "HttpSendRequest failed: %d\n", GetLastError());
3345
3346     size = sizeof(flags);
3347     ret = InternetQueryOption(req, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size);
3348     ok(ret, "InternetQueryOption failed: %d\n", GetLastError());
3349     ok(flags & SECURITY_FLAG_SECURE, "expected secure flag to be set\n");
3350
3351     ret = InternetQueryOptionA(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT,
3352                                NULL, &size);
3353     ok(ret || GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InternetQueryOption failed: %d\n", GetLastError());
3354     ok(size == sizeof(INTERNET_CERTIFICATE_INFOA), "size = %d\n", size);
3355     certificate_structA = HeapAlloc(GetProcessHeap(), 0, size);
3356     ret = InternetQueryOption(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT,
3357                               certificate_structA, &size);
3358     ok(ret, "InternetQueryOption failed: %d\n", GetLastError());
3359     if (ret)
3360     {
3361         ok(certificate_structA->lpszSubjectInfo &&
3362            strlen(certificate_structA->lpszSubjectInfo) > 1,
3363            "expected a non-empty subject name\n");
3364         ok(certificate_structA->lpszIssuerInfo &&
3365            strlen(certificate_structA->lpszIssuerInfo) > 1,
3366            "expected a non-empty issuer name\n");
3367         ok(!certificate_structA->lpszSignatureAlgName,
3368            "unexpected signature algorithm name\n");
3369         ok(!certificate_structA->lpszEncryptionAlgName,
3370            "unexpected encryption algorithm name\n");
3371         ok(!certificate_structA->lpszProtocolName,
3372            "unexpected protocol name\n");
3373         ok(certificate_structA->dwKeySize, "expected a non-zero key size\n");
3374         release_cert_info(certificate_structA);
3375     }
3376     HeapFree(GetProcessHeap(), 0, certificate_structA);
3377
3378     /* Querying the same option through InternetQueryOptionW still results in
3379      * ASCII strings being returned.
3380      */
3381     size = 0;
3382     ret = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT,
3383                                NULL, &size);
3384     ok(ret || GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InternetQueryOption failed: %d\n", GetLastError());
3385     ok(size == sizeof(INTERNET_CERTIFICATE_INFOW), "size = %d\n", size);
3386     certificate_structW = HeapAlloc(GetProcessHeap(), 0, size);
3387     ret = InternetQueryOption(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT,
3388                               certificate_structW, &size);
3389     certificate_structA = (INTERNET_CERTIFICATE_INFOA *)certificate_structW;
3390     ok(ret, "InternetQueryOption failed: %d\n", GetLastError());
3391     if (ret)
3392     {
3393         ok(certificate_structA->lpszSubjectInfo &&
3394            strlen(certificate_structA->lpszSubjectInfo) > 1,
3395            "expected a non-empty subject name\n");
3396         ok(certificate_structA->lpszIssuerInfo &&
3397            strlen(certificate_structA->lpszIssuerInfo) > 1,
3398            "expected a non-empty issuer name\n");
3399         ok(!certificate_structA->lpszSignatureAlgName,
3400            "unexpected signature algorithm name\n");
3401         ok(!certificate_structA->lpszEncryptionAlgName,
3402            "unexpected encryption algorithm name\n");
3403         ok(!certificate_structA->lpszProtocolName,
3404            "unexpected protocol name\n");
3405         ok(certificate_structA->dwKeySize, "expected a non-zero key size\n");
3406         release_cert_info(certificate_structA);
3407     }
3408     HeapFree(GetProcessHeap(), 0, certificate_structW);
3409
3410     InternetCloseHandle(req);
3411     InternetCloseHandle(con);
3412     InternetCloseHandle(ses);
3413
3414     /* Repeating the tests with the W functions has the same result: */
3415     ses = InternetOpenW(gizmo5, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
3416     ok(ses != NULL, "InternetOpen failed\n");
3417
3418     con = InternetConnectW(ses, testbot,
3419                           INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL,
3420                           INTERNET_SERVICE_HTTP, 0, 0);
3421     ok(con != NULL, "InternetConnect failed\n");
3422
3423     req = HttpOpenRequestW(con, get, slash, NULL, NULL, NULL,
3424                           INTERNET_FLAG_SECURE, 0);
3425     ok(req != NULL, "HttpOpenRequest failed\n");
3426
3427     ret = HttpSendRequest(req, NULL, 0, NULL, 0);
3428     ok(ret, "HttpSendRequest failed: %d\n", GetLastError());
3429
3430     size = sizeof(flags);
3431     ret = InternetQueryOption(req, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size);
3432     ok(ret, "InternetQueryOption failed: %d\n", GetLastError());
3433     ok(flags & SECURITY_FLAG_SECURE, "expected secure flag to be set\n");
3434
3435     ret = InternetQueryOptionA(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT,
3436                                NULL, &size);
3437     ok(ret || GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InternetQueryOption failed: %d\n", GetLastError());
3438     ok(size == sizeof(INTERNET_CERTIFICATE_INFOA), "size = %d\n", size);
3439     certificate_structA = HeapAlloc(GetProcessHeap(), 0, size);
3440     ret = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT,
3441                                certificate_structA, &size);
3442     ok(ret, "InternetQueryOption failed: %d\n", GetLastError());
3443     if (ret)
3444     {
3445         ok(certificate_structA->lpszSubjectInfo &&
3446            strlen(certificate_structA->lpszSubjectInfo) > 1,
3447            "expected a non-empty subject name\n");
3448         ok(certificate_structA->lpszIssuerInfo &&
3449            strlen(certificate_structA->lpszIssuerInfo) > 1,
3450            "expected a non-empty issuer name\n");
3451         ok(!certificate_structA->lpszSignatureAlgName,
3452            "unexpected signature algorithm name\n");
3453         ok(!certificate_structA->lpszEncryptionAlgName,
3454            "unexpected encryption algorithm name\n");
3455         ok(!certificate_structA->lpszProtocolName,
3456            "unexpected protocol name\n");
3457         ok(certificate_structA->dwKeySize, "expected a non-zero key size\n");
3458         release_cert_info(certificate_structA);
3459     }
3460     HeapFree(GetProcessHeap(), 0, certificate_structA);
3461
3462     /* Again, querying the same option through InternetQueryOptionW still
3463      * results in ASCII strings being returned.
3464      */
3465     size = 0;
3466     ret = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT,
3467                                NULL, &size);
3468     ok(ret || GetLastError() == ERROR_INSUFFICIENT_BUFFER, "InternetQueryOption failed: %d\n", GetLastError());
3469     ok(size == sizeof(INTERNET_CERTIFICATE_INFOW), "size = %d\n", size);
3470     certificate_structW = HeapAlloc(GetProcessHeap(), 0, size);
3471     ret = InternetQueryOptionW(req, INTERNET_OPTION_SECURITY_CERTIFICATE_STRUCT,
3472                                certificate_structW, &size);
3473     certificate_structA = (INTERNET_CERTIFICATE_INFOA *)certificate_structW;
3474     ok(ret, "InternetQueryOption failed: %d\n", GetLastError());
3475     if (ret)
3476     {
3477         ok(certificate_structA->lpszSubjectInfo &&
3478            strlen(certificate_structA->lpszSubjectInfo) > 1,
3479            "expected a non-empty subject name\n");
3480         ok(certificate_structA->lpszIssuerInfo &&
3481            strlen(certificate_structA->lpszIssuerInfo) > 1,
3482            "expected a non-empty issuer name\n");
3483         ok(!certificate_structA->lpszSignatureAlgName,
3484            "unexpected signature algorithm name\n");
3485         ok(!certificate_structA->lpszEncryptionAlgName,
3486            "unexpected encryption algorithm name\n");
3487         ok(!certificate_structA->lpszProtocolName,
3488            "unexpected protocol name\n");
3489         ok(certificate_structA->dwKeySize, "expected a non-zero key size\n");
3490         release_cert_info(certificate_structA);
3491     }
3492     HeapFree(GetProcessHeap(), 0, certificate_structW);
3493
3494     InternetCloseHandle(req);
3495     InternetCloseHandle(con);
3496     InternetCloseHandle(ses);
3497 }
3498
3499 static void test_user_agent_header(void)
3500 {
3501     HINTERNET ses, con, req;
3502     DWORD size, err;
3503     char buffer[64];
3504     BOOL ret;
3505
3506     ses = InternetOpen("Gizmo5", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
3507     ok(ses != NULL, "InternetOpen failed\n");
3508
3509     con = InternetConnect(ses, "test.winehq.org", 80, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
3510     ok(con != NULL, "InternetConnect failed\n");
3511
3512     req = HttpOpenRequest(con, "GET", "/tests/hello.html", "HTTP/1.0", NULL, NULL, 0, 0);
3513     ok(req != NULL, "HttpOpenRequest failed\n");
3514
3515     size = sizeof(buffer);
3516     ret = HttpQueryInfo(req, HTTP_QUERY_USER_AGENT | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
3517     err = GetLastError();
3518     ok(!ret, "HttpQueryInfo succeeded\n");
3519     ok(err == ERROR_HTTP_HEADER_NOT_FOUND, "expected ERROR_HTTP_HEADER_NOT_FOUND, got %u\n", err);
3520
3521     ret = HttpAddRequestHeaders(req, "User-Agent: Gizmo Project\r\n", ~0u, HTTP_ADDREQ_FLAG_ADD_IF_NEW);
3522     ok(ret, "HttpAddRequestHeaders succeeded\n");
3523
3524     size = sizeof(buffer);
3525     ret = HttpQueryInfo(req, HTTP_QUERY_USER_AGENT | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
3526     err = GetLastError();
3527     ok(ret, "HttpQueryInfo failed\n");
3528     ok(err == ERROR_HTTP_HEADER_NOT_FOUND, "expected ERROR_HTTP_HEADER_NOT_FOUND, got %u\n", err);
3529
3530     InternetCloseHandle(req);
3531
3532     req = HttpOpenRequest(con, "GET", "/", "HTTP/1.0", NULL, NULL, 0, 0);
3533     ok(req != NULL, "HttpOpenRequest failed\n");
3534
3535     size = sizeof(buffer);
3536     ret = HttpQueryInfo(req, HTTP_QUERY_ACCEPT | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
3537     err = GetLastError();
3538     ok(!ret, "HttpQueryInfo succeeded\n");
3539     ok(err == ERROR_HTTP_HEADER_NOT_FOUND, "expected ERROR_HTTP_HEADER_NOT_FOUND, got %u\n", err);
3540
3541     ret = HttpAddRequestHeaders(req, "Accept: audio/*, image/*, text/*\r\nUser-Agent: Gizmo Project\r\n", ~0u, HTTP_ADDREQ_FLAG_ADD_IF_NEW);
3542     ok(ret, "HttpAddRequestHeaders failed\n");
3543
3544     buffer[0] = 0;
3545     size = sizeof(buffer);
3546     ret = HttpQueryInfo(req, HTTP_QUERY_ACCEPT | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
3547     ok(ret, "HttpQueryInfo failed: %u\n", GetLastError());
3548     ok(!strcmp(buffer, "audio/*, image/*, text/*"), "got '%s' expected 'audio/*, image/*, text/*'\n", buffer);
3549
3550     InternetCloseHandle(req);
3551     InternetCloseHandle(con);
3552     InternetCloseHandle(ses);
3553 }
3554
3555 static void test_bogus_accept_types_array(void)
3556 {
3557     HINTERNET ses, con, req;
3558     static const char *types[] = { (const char *)6240, "*/*", "%p", "", (const char *)0xffffffff, "*/*", NULL };
3559     DWORD size, error;
3560     char buffer[32];
3561     BOOL ret;
3562
3563     ses = InternetOpen("MERONG(0.9/;p)", INTERNET_OPEN_TYPE_DIRECT, "", "", 0);
3564     con = InternetConnect(ses, "www.winehq.org", 80, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
3565     req = HttpOpenRequest(con, "POST", "/post/post_action.php", "HTTP/1.0", "", types, INTERNET_FLAG_FORMS_SUBMIT, 0);
3566
3567     ok(req != NULL, "HttpOpenRequest failed: %u\n", GetLastError());
3568
3569     buffer[0] = 0;
3570     size = sizeof(buffer);
3571     SetLastError(0xdeadbeef);
3572     ret = HttpQueryInfo(req, HTTP_QUERY_ACCEPT | HTTP_QUERY_FLAG_REQUEST_HEADERS, buffer, &size, NULL);
3573     error = GetLastError();
3574     ok(!ret || broken(ret), "HttpQueryInfo succeeded\n");
3575     if (!ret) ok(error == ERROR_HTTP_HEADER_NOT_FOUND, "expected ERROR_HTTP_HEADER_NOT_FOUND, got %u\n", error);
3576     ok(broken(!strcmp(buffer, ", */*, %p, , , */*")) /* IE6 */ ||
3577        broken(!strcmp(buffer, "*/*, %p, */*")) /* IE7/8 */ ||
3578        !strcmp(buffer, ""), "got '%s' expected ''\n", buffer);
3579
3580     InternetCloseHandle(req);
3581     InternetCloseHandle(con);
3582     InternetCloseHandle(ses);
3583 }
3584
3585 struct context
3586 {
3587     HANDLE event;
3588     HINTERNET req;
3589 };
3590
3591 static void WINAPI cb(HINTERNET handle, DWORD_PTR context, DWORD status, LPVOID info, DWORD size)
3592 {
3593     INTERNET_ASYNC_RESULT *result = info;
3594     struct context *ctx = (struct context *)context;
3595
3596     trace("%p 0x%08lx %u %p 0x%08x\n", handle, context, status, info, size);
3597
3598     if (status == INTERNET_STATUS_REQUEST_COMPLETE)
3599     {
3600         trace("request handle: 0x%08lx\n", result->dwResult);
3601         ctx->req = (HINTERNET)result->dwResult;
3602         SetEvent(ctx->event);
3603     }
3604     if (status == INTERNET_STATUS_HANDLE_CLOSING)
3605     {
3606         DWORD type = INTERNET_HANDLE_TYPE_CONNECT_HTTP, size = sizeof(type);
3607
3608         if (InternetQueryOption(handle, INTERNET_OPTION_HANDLE_TYPE, &type, &size))
3609             ok(type != INTERNET_HANDLE_TYPE_CONNECT_HTTP, "unexpected callback\n");
3610         SetEvent(ctx->event);
3611     }
3612 }
3613
3614 static void test_open_url_async(void)
3615 {
3616     BOOL ret;
3617     HINTERNET ses, req;
3618     DWORD size, error;
3619     struct context ctx;
3620     ULONG type;
3621
3622     ctx.req = NULL;
3623     ctx.event = CreateEvent(NULL, TRUE, FALSE, "Z:_home_hans_jaman-installer.exe_ev1");
3624
3625     ses = InternetOpen("AdvancedInstaller", 0, NULL, NULL, INTERNET_FLAG_ASYNC);
3626     ok(ses != NULL, "InternetOpen failed\n");
3627
3628     SetLastError(0xdeadbeef);
3629     ret = InternetSetOptionA(NULL, INTERNET_OPTION_CALLBACK, &cb, sizeof(DWORD_PTR));
3630     error = GetLastError();
3631     ok(!ret, "InternetSetOptionA succeeded\n");
3632     ok(error == ERROR_INTERNET_INCORRECT_HANDLE_TYPE, "got %u expected ERROR_INTERNET_INCORRECT_HANDLE_TYPE\n", error);
3633
3634     ret = InternetSetOptionA(ses, INTERNET_OPTION_CALLBACK, &cb, sizeof(DWORD_PTR));
3635     error = GetLastError();
3636     ok(!ret, "InternetSetOptionA failed\n");
3637     ok(error == ERROR_INTERNET_OPTION_NOT_SETTABLE, "got %u expected ERROR_INTERNET_OPTION_NOT_SETTABLE\n", error);
3638
3639     pInternetSetStatusCallbackA(ses, cb);
3640     ResetEvent(ctx.event);
3641
3642     req = InternetOpenUrl(ses, "http://test.winehq.org", NULL, 0, 0, (DWORD_PTR)&ctx);
3643     ok(!req && GetLastError() == ERROR_IO_PENDING, "InternetOpenUrl failed\n");
3644
3645     WaitForSingleObject(ctx.event, INFINITE);
3646
3647     type = 0;
3648     size = sizeof(type);
3649     ret = InternetQueryOption(ctx.req, INTERNET_OPTION_HANDLE_TYPE, &type, &size);
3650     ok(ret, "InternetQueryOption failed: %u\n", GetLastError());
3651     ok(type == INTERNET_HANDLE_TYPE_HTTP_REQUEST,
3652        "expected INTERNET_HANDLE_TYPE_HTTP_REQUEST, got %u\n", type);
3653
3654     size = 0;
3655     ret = HttpQueryInfo(ctx.req, HTTP_QUERY_RAW_HEADERS_CRLF, NULL, &size, NULL);
3656     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "HttpQueryInfo failed\n");
3657     ok(size > 0, "expected size > 0\n");
3658
3659     ResetEvent(ctx.event);
3660     InternetCloseHandle(ctx.req);
3661     WaitForSingleObject(ctx.event, INFINITE);
3662
3663     InternetCloseHandle(ses);
3664     CloseHandle(ctx.event);
3665 }
3666
3667 enum api
3668 {
3669     internet_connect = 1,
3670     http_open_request,
3671     http_send_request_ex,
3672     internet_writefile,
3673     http_end_request,
3674     internet_close_handle
3675 };
3676
3677 struct notification
3678 {
3679     enum api     function; /* api responsible for notification */
3680     unsigned int status;   /* status received */
3681     int          async;    /* delivered from another thread? */
3682     int          todo;
3683     int          optional;
3684 };
3685
3686 struct info
3687 {
3688     enum api     function;
3689     const struct notification *test;
3690     unsigned int count;
3691     unsigned int index;
3692     HANDLE       wait;
3693     DWORD        thread;
3694     unsigned int line;
3695     DWORD        expect_result;
3696     BOOL         is_aborted;
3697 };
3698
3699 static CRITICAL_SECTION notification_cs;
3700
3701 static void CALLBACK check_notification( HINTERNET handle, DWORD_PTR context, DWORD status, LPVOID buffer, DWORD buflen )
3702 {
3703     BOOL status_ok, function_ok;
3704     struct info *info = (struct info *)context;
3705     unsigned int i;
3706
3707     EnterCriticalSection( &notification_cs );
3708
3709     if(info->is_aborted) {
3710         LeaveCriticalSection(&notification_cs);
3711         return;
3712     }
3713
3714     if (status == INTERNET_STATUS_HANDLE_CREATED)
3715     {
3716         DWORD size = sizeof(struct info *);
3717         HttpQueryInfoA( handle, INTERNET_OPTION_CONTEXT_VALUE, &info, &size, 0 );
3718     }else if(status == INTERNET_STATUS_REQUEST_COMPLETE) {
3719         INTERNET_ASYNC_RESULT *ar = (INTERNET_ASYNC_RESULT*)buffer;
3720
3721         ok(buflen == sizeof(*ar), "unexpected buflen = %d\n", buflen);
3722         if(info->expect_result == ERROR_SUCCESS) {
3723             ok(ar->dwResult == 1, "ar->dwResult = %ld, expected 1\n", ar->dwResult);
3724         }else {
3725             ok(!ar->dwResult, "ar->dwResult = %ld, expected 1\n", ar->dwResult);
3726             ok(ar->dwError == info->expect_result, "ar->dwError = %d, expected %d\n", ar->dwError, info->expect_result);
3727         }
3728     }
3729
3730     i = info->index;
3731     if (i >= info->count)
3732     {
3733         LeaveCriticalSection( &notification_cs );
3734         return;
3735     }
3736
3737     while (info->test[i].status != status &&
3738         (info->test[i].optional || info->test[i].todo) &&
3739         i < info->count - 1 &&
3740         info->test[i].function == info->test[i + 1].function)
3741     {
3742         i++;
3743     }
3744
3745     status_ok   = (info->test[i].status == status);
3746     function_ok = (info->test[i].function == info->function);
3747
3748     if (!info->test[i].todo)
3749     {
3750         ok( status_ok, "%u: expected status %u got %u\n", info->line, info->test[i].status, status );
3751         ok( function_ok, "%u: expected function %u got %u\n", info->line, info->test[i].function, info->function );
3752
3753         if (info->test[i].async)
3754             ok(info->thread != GetCurrentThreadId(), "%u: expected thread %u got %u\n",
3755                info->line, info->thread, GetCurrentThreadId());
3756     }
3757     else
3758     {
3759         todo_wine ok( status_ok, "%u: expected status %u got %u\n", info->line, info->test[i].status, status );
3760         if (status_ok)
3761             todo_wine ok( function_ok, "%u: expected function %u got %u\n", info->line, info->test[i].function, info->function );
3762     }
3763     if (i == info->count - 1 || info->test[i].function != info->test[i + 1].function) SetEvent( info->wait );
3764     info->index = i+1;
3765
3766     LeaveCriticalSection( &notification_cs );
3767 }
3768
3769 static void setup_test( struct info *info, enum api function, unsigned int line, DWORD expect_result )
3770 {
3771     info->function = function;
3772     info->line = line;
3773     info->expect_result = expect_result;
3774 }
3775
3776 struct notification_data
3777 {
3778     const struct notification *test;
3779     const unsigned int count;
3780     const char *method;
3781     const char *host;
3782     const char *path;
3783     const char *data;
3784     BOOL expect_conn_failure;
3785 };
3786
3787 static const struct notification async_send_request_ex_test[] =
3788 {
3789     { internet_connect,      INTERNET_STATUS_HANDLE_CREATED, 0 },
3790     { http_open_request,     INTERNET_STATUS_HANDLE_CREATED, 0 },
3791     { http_send_request_ex,  INTERNET_STATUS_DETECTING_PROXY, 1, 0, 1 },
3792     { http_send_request_ex,  INTERNET_STATUS_COOKIE_SENT, 1, 0, 1 },
3793     { http_send_request_ex,  INTERNET_STATUS_RESOLVING_NAME, 1, 0, 1 },
3794     { http_send_request_ex,  INTERNET_STATUS_NAME_RESOLVED, 1, 0, 1 },
3795     { http_send_request_ex,  INTERNET_STATUS_CONNECTING_TO_SERVER, 1 },
3796     { http_send_request_ex,  INTERNET_STATUS_CONNECTED_TO_SERVER, 1 },
3797     { http_send_request_ex,  INTERNET_STATUS_SENDING_REQUEST, 1 },
3798     { http_send_request_ex,  INTERNET_STATUS_REQUEST_SENT, 1 },
3799     { http_send_request_ex,  INTERNET_STATUS_REQUEST_COMPLETE, 1 },
3800     { internet_writefile,    INTERNET_STATUS_SENDING_REQUEST, 0 },
3801     { internet_writefile,    INTERNET_STATUS_REQUEST_SENT, 0 },
3802     { http_end_request,      INTERNET_STATUS_RECEIVING_RESPONSE, 1 },
3803     { http_end_request,      INTERNET_STATUS_RESPONSE_RECEIVED, 1 },
3804     { http_end_request,      INTERNET_STATUS_REQUEST_COMPLETE, 1 },
3805     { internet_close_handle, INTERNET_STATUS_CLOSING_CONNECTION, 0, 0, 1 },
3806     { internet_close_handle, INTERNET_STATUS_CONNECTION_CLOSED, 0, 0, 1 },
3807     { internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING, 0, },
3808     { internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING, 0, }
3809 };
3810
3811 static const struct notification async_send_request_ex_test2[] =
3812 {
3813     { internet_connect,      INTERNET_STATUS_HANDLE_CREATED, 0 },
3814     { http_open_request,     INTERNET_STATUS_HANDLE_CREATED, 0 },
3815     { http_send_request_ex,  INTERNET_STATUS_DETECTING_PROXY, 1, 0, 1 },
3816     { http_send_request_ex,  INTERNET_STATUS_COOKIE_SENT, 1, 0, 1 },
3817     { http_send_request_ex,  INTERNET_STATUS_RESOLVING_NAME, 1, 0, 1 },
3818     { http_send_request_ex,  INTERNET_STATUS_NAME_RESOLVED, 1, 0, 1 },
3819     { http_send_request_ex,  INTERNET_STATUS_CONNECTING_TO_SERVER, 1, 1 },
3820     { http_send_request_ex,  INTERNET_STATUS_CONNECTED_TO_SERVER, 1, 1 },
3821     { http_send_request_ex,  INTERNET_STATUS_SENDING_REQUEST, 1 },
3822     { http_send_request_ex,  INTERNET_STATUS_REQUEST_SENT, 1 },
3823     { http_send_request_ex,  INTERNET_STATUS_REQUEST_COMPLETE, 1 },
3824     { http_end_request,      INTERNET_STATUS_RECEIVING_RESPONSE, 1 },
3825     { http_end_request,      INTERNET_STATUS_RESPONSE_RECEIVED, 1 },
3826     { http_end_request,      INTERNET_STATUS_REQUEST_COMPLETE, 1 },
3827     { internet_close_handle, INTERNET_STATUS_CLOSING_CONNECTION, 0, 0, 1 },
3828     { internet_close_handle, INTERNET_STATUS_CONNECTION_CLOSED, 0, 0, 1 },
3829     { internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING, 0, },
3830     { internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING, 0, }
3831 };
3832
3833 static const struct notification async_send_request_ex_resolve_failure_test[] =
3834 {
3835     { internet_connect,      INTERNET_STATUS_HANDLE_CREATED, 0 },
3836     { http_open_request,     INTERNET_STATUS_HANDLE_CREATED, 0 },
3837     { http_send_request_ex,  INTERNET_STATUS_DETECTING_PROXY, 1, 0, 1 },
3838     { http_send_request_ex,  INTERNET_STATUS_RESOLVING_NAME, 1 },
3839     { http_send_request_ex,  INTERNET_STATUS_DETECTING_PROXY, 1, 0, 1 },
3840     { http_send_request_ex,  INTERNET_STATUS_REQUEST_COMPLETE, 1 },
3841     { http_end_request,      INTERNET_STATUS_REQUEST_COMPLETE, 1 },
3842     { internet_close_handle, INTERNET_STATUS_CLOSING_CONNECTION, 0, 0, 1 },
3843     { internet_close_handle, INTERNET_STATUS_CONNECTION_CLOSED, 0, 0, 1 },
3844     { internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING, 0, },
3845     { internet_close_handle, INTERNET_STATUS_HANDLE_CLOSING, 0, }
3846 };
3847
3848 static const struct notification_data notification_data[] = {
3849     {
3850         async_send_request_ex_test,
3851         sizeof(async_send_request_ex_test)/sizeof(async_send_request_ex_test[0]),
3852         "POST",
3853         "test.winehq.org",
3854         "tests/posttest.php",
3855         "Public ID=codeweavers"
3856     },
3857     {
3858         async_send_request_ex_test2,
3859         sizeof(async_send_request_ex_test)/sizeof(async_send_request_ex_test[0]),
3860         "POST",
3861         "test.winehq.org",
3862         "tests/posttest.php"
3863     },
3864     {
3865         async_send_request_ex_resolve_failure_test,
3866         sizeof(async_send_request_ex_resolve_failure_test)/sizeof(async_send_request_ex_resolve_failure_test[0]),
3867         "GET",
3868         "brokenhost",
3869         "index.html",
3870         NULL,
3871         TRUE
3872     }
3873 };
3874
3875 static void test_async_HttpSendRequestEx(const struct notification_data *nd)
3876 {
3877     BOOL ret;
3878     HINTERNET ses, req, con;
3879     struct info info;
3880     DWORD size, written, error;
3881     INTERNET_BUFFERSA b;
3882     static const char *accept[2] = {"*/*", NULL};
3883     char buffer[32];
3884
3885     trace("Async HttpSendRequestEx test (%s %s)\n", nd->method, nd->host);
3886
3887     InitializeCriticalSection( &notification_cs );
3888
3889     info.test  = nd->test;
3890     info.count = nd->count;
3891     info.index = 0;
3892     info.wait = CreateEvent( NULL, FALSE, FALSE, NULL );
3893     info.thread = GetCurrentThreadId();
3894     info.is_aborted = FALSE;
3895
3896     ses = InternetOpen( "winetest", 0, NULL, NULL, INTERNET_FLAG_ASYNC );
3897     ok( ses != NULL, "InternetOpen failed\n" );
3898
3899     pInternetSetStatusCallbackA( ses, check_notification );
3900
3901     setup_test( &info, internet_connect, __LINE__, ERROR_SUCCESS );
3902     con = InternetConnect( ses, nd->host, 80, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)&info );
3903     ok( con != NULL, "InternetConnect failed %u\n", GetLastError() );
3904
3905     WaitForSingleObject( info.wait, 10000 );
3906
3907     setup_test( &info, http_open_request, __LINE__, ERROR_SUCCESS );
3908     req = HttpOpenRequest( con, nd->method, nd->path, NULL, NULL, accept, 0, (DWORD_PTR)&info );
3909     ok( req != NULL, "HttpOpenRequest failed %u\n", GetLastError() );
3910
3911     WaitForSingleObject( info.wait, 10000 );
3912
3913     if(nd->data) {
3914         memset( &b, 0, sizeof(INTERNET_BUFFERSA) );
3915         b.dwStructSize = sizeof(INTERNET_BUFFERSA);
3916         b.lpcszHeader = "Content-Type: application/x-www-form-urlencoded";
3917         b.dwHeadersLength = strlen( b.lpcszHeader );
3918         b.dwBufferTotal = nd->data ? strlen( nd->data ) : 0;
3919     }
3920
3921     setup_test( &info, http_send_request_ex, __LINE__,
3922             nd->expect_conn_failure ? ERROR_INTERNET_NAME_NOT_RESOLVED : ERROR_SUCCESS );
3923     ret = HttpSendRequestExA( req, nd->data ? &b : NULL, NULL, 0x28, 0 );
3924     ok( !ret && GetLastError() == ERROR_IO_PENDING, "HttpSendRequestExA failed %d %u\n", ret, GetLastError() );
3925
3926     error = WaitForSingleObject( info.wait, 10000 );
3927     if(error != WAIT_OBJECT_0) {
3928         skip("WaitForSingleObject returned %d, assuming DNS problem\n", error);
3929         info.is_aborted = TRUE;
3930         goto abort;
3931     }
3932
3933     size = sizeof(buffer);
3934     SetLastError( 0xdeadbeef );
3935     ret = HttpQueryInfoA( req, HTTP_QUERY_CONTENT_ENCODING, buffer, &size, 0 );
3936     error = GetLastError();
3937     ok( !ret, "HttpQueryInfoA failed %u\n", GetLastError() );
3938     if(nd->expect_conn_failure) {
3939         ok(error == ERROR_HTTP_HEADER_NOT_FOUND, "expected ERROR_HTTP_HEADER_NOT_FOUND got %u\n", error );
3940     }else {
3941         todo_wine
3942         ok(error == ERROR_INTERNET_INCORRECT_HANDLE_STATE,
3943             "expected ERROR_INTERNET_INCORRECT_HANDLE_STATE got %u\n", error );
3944     }
3945
3946     if (nd->data)
3947     {
3948         written = 0;
3949         size = strlen( nd->data );
3950         setup_test( &info, internet_writefile, __LINE__, ERROR_SUCCESS );
3951         ret = InternetWriteFile( req, nd->data, size, &written );
3952         ok( ret, "InternetWriteFile failed %u\n", GetLastError() );
3953         ok( written == size, "expected %u got %u\n", written, size );
3954
3955         WaitForSingleObject( info.wait, 10000 );
3956
3957         SetLastError( 0xdeadbeef );
3958         ret = HttpEndRequestA( req, (void *)nd->data, 0x28, 0 );
3959         error = GetLastError();
3960         ok( !ret, "HttpEndRequestA succeeded\n" );
3961         ok( error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", error );
3962     }
3963
3964     SetLastError( 0xdeadbeef );
3965     setup_test( &info, http_end_request, __LINE__,
3966             nd->expect_conn_failure ? ERROR_INTERNET_OPERATION_CANCELLED : ERROR_SUCCESS);
3967     ret = HttpEndRequestA( req, NULL, 0x28, 0 );
3968     error = GetLastError();
3969     ok( !ret, "HttpEndRequestA succeeded\n" );
3970     ok( error == ERROR_IO_PENDING, "expected ERROR_IO_PENDING got %u\n", error );
3971
3972     WaitForSingleObject( info.wait, 10000 );
3973
3974     setup_test( &info, internet_close_handle, __LINE__, ERROR_SUCCESS );
3975  abort:
3976     InternetCloseHandle( req );
3977     InternetCloseHandle( con );
3978     InternetCloseHandle( ses );
3979
3980     WaitForSingleObject( info.wait, 10000 );
3981     Sleep(100);
3982     CloseHandle( info.wait );
3983 }
3984
3985 static HINTERNET closetest_session, closetest_req, closetest_conn;
3986 static BOOL closetest_closed;
3987
3988 static void WINAPI closetest_callback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus,
3989      LPVOID lpvStatusInformation, DWORD dwStatusInformationLength)
3990 {
3991     DWORD len, type;
3992     BOOL res;
3993
3994     trace("closetest_callback %p: %d\n", hInternet, dwInternetStatus);
3995
3996     ok(hInternet == closetest_session || hInternet == closetest_conn || hInternet == closetest_req,
3997        "Unexpected hInternet %p\n", hInternet);
3998     if(!closetest_closed)
3999         return;
4000
4001     len = sizeof(type);
4002     res = InternetQueryOptionA(closetest_req, INTERNET_OPTION_HANDLE_TYPE, &type, &len);
4003     ok(!res && GetLastError() == ERROR_INVALID_HANDLE,
4004        "InternetQueryOptionA(%p INTERNET_OPTION_HANDLE_TYPE) failed: %x %u, expected TRUE ERROR_INVALID_HANDLE\n",
4005        closetest_req, res, GetLastError());
4006 }
4007
4008 static void test_InternetCloseHandle(void)
4009 {
4010     DWORD len, flags;
4011     BOOL res;
4012
4013     closetest_session = InternetOpenA("", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);
4014     ok(closetest_session != NULL,"InternetOpen failed with error %u\n", GetLastError());
4015
4016     pInternetSetStatusCallbackA(closetest_session, closetest_callback);
4017
4018     closetest_conn = InternetConnectA(closetest_session, "source.winehq.org", INTERNET_INVALID_PORT_NUMBER,
4019             NULL, NULL, INTERNET_SERVICE_HTTP, 0x0, 0xdeadbeef);
4020     ok(closetest_conn != NULL,"InternetConnect failed with error %u\n", GetLastError());
4021
4022     closetest_req = HttpOpenRequestA(closetest_conn, "GET", "winegecko.php", NULL, NULL, NULL,
4023             INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_RESYNCHRONIZE, 0xdeadbead);
4024
4025     res = HttpSendRequestA(closetest_req, NULL, -1, NULL, 0);
4026     ok(!res && (GetLastError() == ERROR_IO_PENDING),
4027        "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n");
4028
4029     test_request_flags(closetest_req, INTERNET_REQFLAG_NO_HEADERS);
4030
4031     res = InternetCloseHandle(closetest_session);
4032     ok(res, "InternetCloseHandle failed: %u\n", GetLastError());
4033     closetest_closed = TRUE;
4034     trace("Closed session handle\n");
4035
4036     res = InternetCloseHandle(closetest_conn);
4037     ok(!res && GetLastError() == ERROR_INVALID_HANDLE, "InternetCloseConnection(conn) failed: %x %u\n",
4038        res, GetLastError());
4039
4040     res = InternetCloseHandle(closetest_req);
4041     ok(!res && GetLastError() == ERROR_INVALID_HANDLE, "InternetCloseConnection(req) failed: %x %u\n",
4042        res, GetLastError());
4043
4044     len = sizeof(flags);
4045     res = InternetQueryOptionA(closetest_req, INTERNET_OPTION_REQUEST_FLAGS, &flags, &len);
4046     ok(!res && GetLastError() == ERROR_INVALID_HANDLE,
4047        "InternetQueryOptionA(%p INTERNET_OPTION_URL) failed: %x %u, expected TRUE ERROR_INVALID_HANDLE\n",
4048        closetest_req, res, GetLastError());
4049 }
4050
4051 static void test_connection_failure(void)
4052 {
4053     HINTERNET session, connect, request;
4054     DWORD error;
4055     BOOL ret;
4056
4057     session = InternetOpenA("winetest", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
4058     ok(session != NULL, "failed to get session handle\n");
4059
4060     connect = InternetConnectA(session, "localhost", 1, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
4061     ok(connect != NULL, "failed to get connection handle\n");
4062
4063     request = HttpOpenRequestA(connect, NULL, "/", NULL, NULL, NULL, 0, 0);
4064     ok(request != NULL, "failed to get request handle\n");
4065
4066     SetLastError(0xdeadbeef);
4067     ret = HttpSendRequest(request, NULL, 0, NULL, 0);
4068     error = GetLastError();
4069     ok(!ret, "unexpected success\n");
4070     ok(error == ERROR_INTERNET_CANNOT_CONNECT, "wrong error %u\n", error);
4071
4072     InternetCloseHandle(request);
4073     InternetCloseHandle(connect);
4074     InternetCloseHandle(session);
4075 }
4076
4077 static void init_status_tests(void)
4078 {
4079     memset(expect, 0, sizeof(expect));
4080     memset(optional, 0, sizeof(optional));
4081     memset(wine_allow, 0, sizeof(wine_allow));
4082     memset(notified, 0, sizeof(notified));
4083     memset(status_string, 0, sizeof(status_string));
4084
4085 #define STATUS_STRING(status) status_string[status] = #status
4086     STATUS_STRING(INTERNET_STATUS_RESOLVING_NAME);
4087     STATUS_STRING(INTERNET_STATUS_NAME_RESOLVED);
4088     STATUS_STRING(INTERNET_STATUS_CONNECTING_TO_SERVER);
4089     STATUS_STRING(INTERNET_STATUS_CONNECTED_TO_SERVER);
4090     STATUS_STRING(INTERNET_STATUS_SENDING_REQUEST);
4091     STATUS_STRING(INTERNET_STATUS_REQUEST_SENT);
4092     STATUS_STRING(INTERNET_STATUS_RECEIVING_RESPONSE);
4093     STATUS_STRING(INTERNET_STATUS_RESPONSE_RECEIVED);
4094     STATUS_STRING(INTERNET_STATUS_CTL_RESPONSE_RECEIVED);
4095     STATUS_STRING(INTERNET_STATUS_PREFETCH);
4096     STATUS_STRING(INTERNET_STATUS_CLOSING_CONNECTION);
4097     STATUS_STRING(INTERNET_STATUS_CONNECTION_CLOSED);
4098     STATUS_STRING(INTERNET_STATUS_HANDLE_CREATED);
4099     STATUS_STRING(INTERNET_STATUS_HANDLE_CLOSING);
4100     STATUS_STRING(INTERNET_STATUS_DETECTING_PROXY);
4101     STATUS_STRING(INTERNET_STATUS_REQUEST_COMPLETE);
4102     STATUS_STRING(INTERNET_STATUS_REDIRECT);
4103     STATUS_STRING(INTERNET_STATUS_INTERMEDIATE_RESPONSE);
4104     STATUS_STRING(INTERNET_STATUS_USER_INPUT_REQUIRED);
4105     STATUS_STRING(INTERNET_STATUS_STATE_CHANGE);
4106     STATUS_STRING(INTERNET_STATUS_COOKIE_SENT);
4107     STATUS_STRING(INTERNET_STATUS_COOKIE_RECEIVED);
4108     STATUS_STRING(INTERNET_STATUS_PRIVACY_IMPACTED);
4109     STATUS_STRING(INTERNET_STATUS_P3P_HEADER);
4110     STATUS_STRING(INTERNET_STATUS_P3P_POLICYREF);
4111     STATUS_STRING(INTERNET_STATUS_COOKIE_HISTORY);
4112 #undef STATUS_STRING
4113 }
4114
4115 START_TEST(http)
4116 {
4117     HMODULE hdll;
4118     hdll = GetModuleHandleA("wininet.dll");
4119
4120     if(!GetProcAddress(hdll, "InternetGetCookieExW")) {
4121         win_skip("Too old IE (older than 6.0)\n");
4122         return;
4123     }
4124
4125     pInternetSetStatusCallbackA = (void*)GetProcAddress(hdll, "InternetSetStatusCallbackA");
4126     pInternetGetSecurityInfoByURLA = (void*)GetProcAddress(hdll, "InternetGetSecurityInfoByURLA");
4127
4128     init_status_tests();
4129     test_InternetCloseHandle();
4130     InternetReadFile_test(INTERNET_FLAG_ASYNC, &test_data[0]);
4131     InternetReadFile_test(INTERNET_FLAG_ASYNC, &test_data[1]);
4132     InternetReadFile_test(0, &test_data[1]);
4133     first_connection_to_test_url = TRUE;
4134     InternetReadFile_test(INTERNET_FLAG_ASYNC, &test_data[2]);
4135     test_security_flags();
4136     InternetReadFile_test(0, &test_data[2]);
4137     InternetReadFileExA_test(INTERNET_FLAG_ASYNC);
4138     test_open_url_async();
4139     test_async_HttpSendRequestEx(&notification_data[0]);
4140     test_async_HttpSendRequestEx(&notification_data[1]);
4141     test_async_HttpSendRequestEx(&notification_data[2]);
4142     InternetOpenRequest_test();
4143     test_http_cache();
4144     InternetOpenUrlA_test();
4145     HttpHeaders_test();
4146     test_http_connection();
4147     test_secure_connection();
4148     test_user_agent_header();
4149     test_bogus_accept_types_array();
4150     InternetReadFile_chunked_test();
4151     HttpSendRequestEx_test();
4152     InternetReadFile_test(INTERNET_FLAG_ASYNC, &test_data[3]);
4153     test_connection_failure();
4154 }