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
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};
39 winhttp_receive_response
,
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 */
60 const struct notification
*test
;
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
))
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;
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
;
158 while (info
->index
< info
->count
&& info
->test
[info
->index
].function
!= function
159 && (info
->test
[info
->index
].flags
& (NF_ALLOW
| NF_WINE_ALLOW
)))
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]);
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
) );
185 win_skip("Unload event not supported\n");
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");
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");
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
);
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
);
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());
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");
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");
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__
);
353 WinHttpCloseHandle( req
);
354 WinHttpCloseHandle( con
);
355 WaitForSingleObject( info
.wait
, INFINITE
);
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
);
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
;
410 struct info info
, *context
= &info
;
412 info
.test
= redirect_test
;
413 info
.count
= sizeof(redirect_test
) / sizeof(redirect_test
[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");
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__
);
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
;
494 info
.test
= async_test
;
495 info
.count
= sizeof(async_test
) / sizeof(async_test
[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
) );
506 win_skip("Unload event not supported\n");
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
);
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
);
591 status
= WaitForSingleObject( event
, 0 );
592 ok(status
== WAIT_TIMEOUT
, "got %08x\n", status
);
594 WinHttpCloseHandle( ses
);
595 WaitForSingleObject( info
.wait
, INFINITE
);
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();