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