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