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