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