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