winhttp: Use notification flags to explicitly mark notifications that should signal...
[wine.git] / dlls / winhttp / tests / notification.c
blobdc36b880814c8fd802b57aaf13bbb8af5f16f7c7
1 /*
2 * test status notifications
4 * Copyright 2008 Hans Leidekker for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <windef.h>
24 #include <winbase.h>
25 #include <winhttp.h>
27 #include "wine/test.h"
29 static const WCHAR user_agent[] = {'w','i','n','e','t','e','s','t',0};
30 static const WCHAR test_winehq[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
31 static const WCHAR tests_hello_html[] = {'/','t','e','s','t','s','/','h','e','l','l','o','.','h','t','m','l',0};
32 static const WCHAR tests_redirect[] = {'/','t','e','s','t','s','/','r','e','d','i','r','e','c','t',0};
34 enum api
36 winhttp_connect = 1,
37 winhttp_open_request,
38 winhttp_send_request,
39 winhttp_receive_response,
40 winhttp_query_data,
41 winhttp_read_data,
42 winhttp_write_data,
43 winhttp_close_handle
46 struct notification
48 enum api function; /* api responsible for notification */
49 unsigned int status; /* status received */
50 DWORD flags; /* a combination of NF_* flags */
53 #define NF_ALLOW 0x0001 /* notification may or may not happen */
54 #define NF_WINE_ALLOW 0x0002 /* wine sends notification when it should not */
55 #define NF_SIGNAL 0x0004 /* signal wait handle when notified */
57 struct info
59 enum api function;
60 const struct notification *test;
61 unsigned int count;
62 unsigned int index;
63 HANDLE wait;
64 unsigned int line;
67 static void CALLBACK check_notification( HINTERNET handle, DWORD_PTR context, DWORD status, LPVOID buffer, DWORD buflen )
69 BOOL status_ok, function_ok;
70 struct info *info = (struct info *)context;
72 if (status == WINHTTP_CALLBACK_STATUS_HANDLE_CREATED)
74 DWORD size = sizeof(struct info *);
75 WinHttpQueryOption( handle, WINHTTP_OPTION_CONTEXT_VALUE, &info, &size );
77 while (info->index < info->count && info->test[info->index].status != status && (info->test[info->index].flags & NF_ALLOW))
78 info->index++;
79 while (info->index < info->count && (info->test[info->index].flags & NF_WINE_ALLOW))
81 todo_wine ok(info->test[info->index].status != status, "unexpected %x notification\n", status);
82 if (info->test[info->index].status == status) break;
83 info->index++;
85 ok(info->index < info->count, "%u: unexpected notification 0x%08x\n", info->line, status);
86 if (info->index >= info->count) return;
88 status_ok = (info->test[info->index].status == status);
89 function_ok = (info->test[info->index].function == info->function);
90 ok(status_ok, "%u: expected status 0x%08x got 0x%08x\n", info->line, info->test[info->index].status, status);
91 ok(function_ok, "%u: expected function %u got %u\n", info->line, info->test[info->index].function, info->function);
93 if (status_ok && function_ok && info->test[info->index++].flags & NF_SIGNAL)
95 SetEvent( info->wait );
99 static const struct notification cache_test[] =
101 { winhttp_connect, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
102 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
103 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME },
104 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED },
105 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER },
106 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER },
107 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
108 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
109 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
110 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
111 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
112 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_WINE_ALLOW },
113 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL },
114 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
115 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, NF_WINE_ALLOW },
116 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, NF_WINE_ALLOW },
117 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
118 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
119 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
120 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
121 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
122 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_WINE_ALLOW },
123 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
124 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL },
125 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL },
126 { winhttp_connect, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
127 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
128 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, NF_WINE_ALLOW },
129 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, NF_WINE_ALLOW },
130 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, NF_WINE_ALLOW },
131 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, NF_WINE_ALLOW },
132 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
133 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
134 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
135 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
136 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
137 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_WINE_ALLOW },
138 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL },
139 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
140 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, NF_WINE_ALLOW },
141 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, NF_WINE_ALLOW },
142 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
143 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
144 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
145 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
146 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
147 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_WINE_ALLOW },
148 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
149 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL },
150 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL }
153 static void setup_test( struct info *info, enum api function, unsigned int line )
155 if (info->wait) ResetEvent( info->wait );
156 info->function = function;
157 info->line = line;
158 while (info->index < info->count && info->test[info->index].function != function
159 && (info->test[info->index].flags & (NF_ALLOW | NF_WINE_ALLOW)))
160 info->index++;
161 ok_(__FILE__,line)(info->test[info->index].function == function,
162 "unexpected function %u, expected %u. probably some notifications were missing\n",
163 info->test[info->index].function, function);
166 static void test_connection_cache( void )
168 HANDLE ses, con, req, event;
169 DWORD size, status, err;
170 BOOL ret, unload = TRUE;
171 struct info info, *context = &info;
173 info.test = cache_test;
174 info.count = sizeof(cache_test) / sizeof(cache_test[0]);
175 info.index = 0;
176 info.wait = CreateEventW( NULL, FALSE, FALSE, NULL );
178 ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 );
179 ok(ses != NULL, "failed to open session %u\n", GetLastError());
181 event = CreateEventW( NULL, FALSE, FALSE, NULL );
182 ret = WinHttpSetOption( ses, WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT, &event, sizeof(event) );
183 if (!ret)
185 win_skip("Unload event not supported\n");
186 unload = FALSE;
189 WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );
191 ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
192 ok(ret, "failed to set context value %u\n", GetLastError());
194 setup_test( &info, winhttp_connect, __LINE__ );
195 con = WinHttpConnect( ses, test_winehq, 0, 0 );
196 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
198 setup_test( &info, winhttp_open_request, __LINE__ );
199 req = WinHttpOpenRequest( con, NULL, tests_hello_html, NULL, NULL, NULL, 0 );
200 ok(req != NULL, "failed to open a request %u\n", GetLastError());
202 setup_test( &info, winhttp_send_request, __LINE__ );
203 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
204 err = GetLastError();
205 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
207 skip("connection failed, skipping\n");
208 goto done;
210 ok(ret, "failed to send request %u\n", GetLastError());
212 setup_test( &info, winhttp_receive_response, __LINE__ );
213 ret = WinHttpReceiveResponse( req, NULL );
214 ok(ret, "failed to receive response %u\n", GetLastError());
216 size = sizeof(status);
217 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
218 ok(ret, "failed unexpectedly %u\n", GetLastError());
219 ok(status == 200, "request failed unexpectedly %u\n", status);
221 ResetEvent( info.wait );
222 setup_test( &info, winhttp_close_handle, __LINE__ );
223 WinHttpCloseHandle( req );
224 WaitForSingleObject( info.wait, INFINITE );
226 setup_test( &info, winhttp_open_request, __LINE__ );
227 req = WinHttpOpenRequest( con, NULL, tests_hello_html, NULL, NULL, NULL, 0 );
228 ok(req != NULL, "failed to open a request %u\n", GetLastError());
230 ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
231 ok(ret, "failed to set context value %u\n", GetLastError());
233 setup_test( &info, winhttp_send_request, __LINE__ );
234 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
235 err = GetLastError();
236 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
238 skip("connection failed, skipping\n");
239 goto done;
241 ok(ret, "failed to send request %u\n", GetLastError());
243 setup_test( &info, winhttp_receive_response, __LINE__ );
244 ret = WinHttpReceiveResponse( req, NULL );
245 ok(ret, "failed to receive response %u\n", GetLastError());
247 size = sizeof(status);
248 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
249 ok(ret, "failed unexpectedly %u\n", GetLastError());
250 ok(status == 200, "request failed unexpectedly %u\n", status);
252 ResetEvent( info.wait );
253 setup_test( &info, winhttp_close_handle, __LINE__ );
254 WinHttpCloseHandle( req );
255 WinHttpCloseHandle( req );
256 WinHttpCloseHandle( con );
257 WaitForSingleObject( info.wait, INFINITE );
259 if (unload)
261 status = WaitForSingleObject( event, 0 );
262 ok(status == WAIT_TIMEOUT, "got %08x\n", status);
265 setup_test( &info, winhttp_close_handle, __LINE__ );
266 WinHttpCloseHandle( ses );
267 WaitForSingleObject( info.wait, INFINITE );
269 if (unload)
271 status = WaitForSingleObject( event, 100 );
272 ok(status == WAIT_OBJECT_0, "got %08x\n", status);
276 ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 );
277 ok(ses != NULL, "failed to open session %u\n", GetLastError());
279 if (unload)
281 ret = WinHttpSetOption( ses, WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT, &event, sizeof(event) );
282 ok(ret, "failed to set unload option\n");
285 WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );
287 ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
288 ok(ret, "failed to set context value %u\n", GetLastError());
290 setup_test( &info, winhttp_connect, __LINE__ );
291 con = WinHttpConnect( ses, test_winehq, 0, 0 );
292 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
294 setup_test( &info, winhttp_open_request, __LINE__ );
295 req = WinHttpOpenRequest( con, NULL, tests_hello_html, NULL, NULL, NULL, 0 );
296 ok(req != NULL, "failed to open a request %u\n", GetLastError());
298 ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
299 ok(ret, "failed to set context value %u\n", GetLastError());
301 setup_test( &info, winhttp_send_request, __LINE__ );
302 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
303 err = GetLastError();
304 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
306 skip("connection failed, skipping\n");
307 goto done;
309 ok(ret, "failed to send request %u\n", GetLastError());
311 setup_test( &info, winhttp_receive_response, __LINE__ );
312 ret = WinHttpReceiveResponse( req, NULL );
313 ok(ret, "failed to receive response %u\n", GetLastError());
315 size = sizeof(status);
316 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
317 ok(ret, "failed unexpectedly %u\n", GetLastError());
318 ok(status == 200, "request failed unexpectedly %u\n", status);
320 ResetEvent( info.wait );
321 setup_test( &info, winhttp_close_handle, __LINE__ );
322 WinHttpCloseHandle( req );
323 WaitForSingleObject( info.wait, INFINITE );
325 setup_test( &info, winhttp_open_request, __LINE__ );
326 req = WinHttpOpenRequest( con, NULL, tests_hello_html, NULL, NULL, NULL, 0 );
327 ok(req != NULL, "failed to open a request %u\n", GetLastError());
329 ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
330 ok(ret, "failed to set context value %u\n", GetLastError());
332 setup_test( &info, winhttp_send_request, __LINE__ );
333 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
334 err = GetLastError();
335 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
337 skip("connection failed, skipping\n");
338 goto done;
340 ok(ret, "failed to send request %u\n", GetLastError());
342 setup_test( &info, winhttp_receive_response, __LINE__ );
343 ret = WinHttpReceiveResponse( req, NULL );
344 ok(ret, "failed to receive response %u\n", GetLastError());
346 size = sizeof(status);
347 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
348 ok(ret, "failed unexpectedly %u\n", GetLastError());
349 ok(status == 200, "request failed unexpectedly %u\n", status);
351 setup_test( &info, winhttp_close_handle, __LINE__ );
352 done:
353 WinHttpCloseHandle( req );
354 WinHttpCloseHandle( con );
355 WaitForSingleObject( info.wait, INFINITE );
357 if (unload)
359 status = WaitForSingleObject( event, 0 );
360 ok(status == WAIT_TIMEOUT, "got %08x\n", status);
363 setup_test( &info, winhttp_close_handle, __LINE__ );
364 WinHttpCloseHandle( ses );
365 WaitForSingleObject( info.wait, INFINITE );
366 CloseHandle( info.wait );
368 if (unload)
370 status = WaitForSingleObject( event, 100 );
371 ok(status == WAIT_OBJECT_0, "got %08x\n", status);
374 CloseHandle( event );
377 static const struct notification redirect_test[] =
379 { winhttp_connect, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
380 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
381 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, NF_WINE_ALLOW },
382 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, NF_WINE_ALLOW },
383 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, NF_WINE_ALLOW },
384 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, NF_WINE_ALLOW },
385 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
386 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
387 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
388 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
389 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_REDIRECT },
390 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, NF_ALLOW },
391 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, NF_ALLOW },
392 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, NF_ALLOW },
393 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, NF_ALLOW },
394 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
395 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
396 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
397 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
398 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
399 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_WINE_ALLOW },
400 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
401 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
402 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL }
405 static void test_redirect( void )
407 HANDLE ses, con, req;
408 DWORD size, status, err;
409 BOOL ret;
410 struct info info, *context = &info;
412 info.test = redirect_test;
413 info.count = sizeof(redirect_test) / sizeof(redirect_test[0]);
414 info.index = 0;
415 info.wait = CreateEventW( NULL, FALSE, FALSE, NULL );
417 ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 );
418 ok(ses != NULL, "failed to open session %u\n", GetLastError());
420 WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );
422 ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
423 ok(ret, "failed to set context value %u\n", GetLastError());
425 setup_test( &info, winhttp_connect, __LINE__ );
426 con = WinHttpConnect( ses, test_winehq, 0, 0 );
427 ok(con != NULL, "failed to open a connection %u\n", GetLastError());
429 setup_test( &info, winhttp_open_request, __LINE__ );
430 req = WinHttpOpenRequest( con, NULL, tests_redirect, NULL, NULL, NULL, 0 );
431 ok(req != NULL, "failed to open a request %u\n", GetLastError());
433 setup_test( &info, winhttp_send_request, __LINE__ );
434 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
435 err = GetLastError();
436 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
438 skip("connection failed, skipping\n");
439 goto done;
441 ok(ret, "failed to send request %u\n", GetLastError());
443 setup_test( &info, winhttp_receive_response, __LINE__ );
444 ret = WinHttpReceiveResponse( req, NULL );
445 ok(ret, "failed to receive response %u\n", GetLastError());
447 size = sizeof(status);
448 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
449 ok(ret, "failed unexpectedly %u\n", GetLastError());
450 ok(status == 200, "request failed unexpectedly %u\n", status);
452 setup_test( &info, winhttp_close_handle, __LINE__ );
453 done:
454 WinHttpCloseHandle( req );
455 WinHttpCloseHandle( con );
456 WinHttpCloseHandle( ses );
457 WaitForSingleObject( info.wait, INFINITE );
458 CloseHandle( info.wait );
461 static const struct notification async_test[] =
463 { winhttp_connect, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
464 { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED },
465 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, NF_WINE_ALLOW },
466 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, NF_WINE_ALLOW },
467 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, NF_WINE_ALLOW },
468 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, NF_WINE_ALLOW },
469 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST },
470 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT },
471 { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE, NF_SIGNAL },
472 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE },
473 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED },
474 { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE, NF_SIGNAL },
475 { winhttp_query_data, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE, NF_SIGNAL },
476 { winhttp_read_data, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, NF_ALLOW },
477 { winhttp_read_data, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED, NF_ALLOW },
478 { winhttp_read_data, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, NF_SIGNAL },
479 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, NF_WINE_ALLOW },
480 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, NF_WINE_ALLOW },
481 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
482 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING },
483 { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, NF_SIGNAL }
486 static void test_async( void )
488 HANDLE ses, con, req, event;
489 DWORD size, status, err;
490 BOOL ret, unload = TRUE;
491 struct info info, *context = &info;
492 char buffer[1024];
494 info.test = async_test;
495 info.count = sizeof(async_test) / sizeof(async_test[0]);
496 info.index = 0;
497 info.wait = CreateEventW( NULL, FALSE, FALSE, NULL );
499 ses = WinHttpOpen( user_agent, 0, NULL, NULL, WINHTTP_FLAG_ASYNC );
500 ok(ses != NULL, "failed to open session %u\n", GetLastError());
502 event = CreateEventW( NULL, FALSE, FALSE, NULL );
503 ret = WinHttpSetOption( ses, WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT, &event, sizeof(event) );
504 if (!ret)
506 win_skip("Unload event not supported\n");
507 unload = FALSE;
510 SetLastError( 0xdeadbeef );
511 WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );
512 err = GetLastError();
513 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
515 SetLastError( 0xdeadbeef );
516 ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
517 err = GetLastError();
518 ok(ret, "failed to set context value %u\n", err);
519 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
521 setup_test( &info, winhttp_connect, __LINE__ );
522 SetLastError( 0xdeadbeef );
523 con = WinHttpConnect( ses, test_winehq, 0, 0 );
524 err = GetLastError();
525 ok(con != NULL, "failed to open a connection %u\n", err);
526 ok(err == ERROR_SUCCESS || broken(err == WSAEINVAL) /* < win7 */, "got %u\n", err);
528 setup_test( &info, winhttp_open_request, __LINE__ );
529 SetLastError( 0xdeadbeef );
530 req = WinHttpOpenRequest( con, NULL, tests_hello_html, NULL, NULL, NULL, 0 );
531 err = GetLastError();
532 ok(req != NULL, "failed to open a request %u\n", err);
533 ok(err == ERROR_SUCCESS, "got %u\n", err);
535 setup_test( &info, winhttp_send_request, __LINE__ );
536 SetLastError( 0xdeadbeef );
537 ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
538 err = GetLastError();
539 if (!ret && (err == ERROR_WINHTTP_CANNOT_CONNECT || err == ERROR_WINHTTP_TIMEOUT))
541 skip("connection failed, skipping\n");
542 WinHttpCloseHandle( req );
543 WinHttpCloseHandle( con );
544 WinHttpCloseHandle( ses );
545 CloseHandle( info.wait );
546 return;
548 ok(ret, "failed to send request %u\n", err);
549 ok(err == ERROR_SUCCESS, "got %u\n", err);
551 WaitForSingleObject( info.wait, INFINITE );
553 setup_test( &info, winhttp_receive_response, __LINE__ );
554 SetLastError( 0xdeadbeef );
555 ret = WinHttpReceiveResponse( req, NULL );
556 err = GetLastError();
557 ok(ret, "failed to receive response %u\n", err);
558 ok(err == ERROR_SUCCESS, "got %u\n", err);
560 WaitForSingleObject( info.wait, INFINITE );
562 size = sizeof(status);
563 SetLastError( 0xdeadbeef );
564 ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
565 err = GetLastError();
566 ok(ret, "failed unexpectedly %u\n", err);
567 ok(status == 200, "request failed unexpectedly %u\n", status);
568 ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
570 setup_test( &info, winhttp_query_data, __LINE__ );
571 SetLastError( 0xdeadbeef );
572 ret = WinHttpQueryDataAvailable( req, NULL );
573 err = GetLastError();
574 ok(ret, "failed to query data available %u\n", err);
575 ok(err == ERROR_SUCCESS || err == ERROR_IO_PENDING || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
577 WaitForSingleObject( info.wait, INFINITE );
579 setup_test( &info, winhttp_read_data, __LINE__ );
580 ret = WinHttpReadData( req, buffer, sizeof(buffer), NULL );
581 ok(ret, "failed to read data %u\n", err);
583 WaitForSingleObject( info.wait, INFINITE );
585 setup_test( &info, winhttp_close_handle, __LINE__ );
586 WinHttpCloseHandle( req );
587 WinHttpCloseHandle( con );
589 if (unload)
591 status = WaitForSingleObject( event, 0 );
592 ok(status == WAIT_TIMEOUT, "got %08x\n", status);
594 WinHttpCloseHandle( ses );
595 WaitForSingleObject( info.wait, INFINITE );
597 if (unload)
599 status = WaitForSingleObject( event, 2000 );
600 ok(status == WAIT_OBJECT_0, "got %08x\n", status);
602 CloseHandle( event );
603 CloseHandle( info.wait );
606 START_TEST (notification)
608 test_connection_cache();
609 test_redirect();
610 test_async();