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