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