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
29 #include "wine/test.h"
31 static DWORD (WINAPI
*pWinHttpWebSocketClose
)(HINTERNET
,USHORT
,void*,DWORD
);
32 static HINTERNET (WINAPI
*pWinHttpWebSocketCompleteUpgrade
)(HINTERNET
,DWORD_PTR
);
33 static DWORD (WINAPI
*pWinHttpWebSocketQueryCloseStatus
)(HINTERNET
,USHORT
*,void*,DWORD
,DWORD
*);
34 static DWORD (WINAPI
*pWinHttpWebSocketReceive
)(HINTERNET
,void*,DWORD
,DWORD
*,WINHTTP_WEB_SOCKET_BUFFER_TYPE
*);
35 static DWORD (WINAPI
*pWinHttpWebSocketSend
)(HINTERNET
,WINHTTP_WEB_SOCKET_BUFFER_TYPE
,void*,DWORD
);
36 static DWORD (WINAPI
*pWinHttpWebSocketShutdown
)(HINTERNET
,USHORT
,void*,DWORD
);
43 winhttp_receive_response
,
44 winhttp_websocket_complete_upgrade
,
45 winhttp_websocket_send
,
46 winhttp_websocket_receive
,
47 winhttp_websocket_shutdown
,
48 winhttp_websocket_close
,
57 enum api function
; /* api responsible for notification */
58 unsigned int status
; /* status received */
59 DWORD flags
; /* a combination of NF_* flags */
62 #define NF_ALLOW 0x0001 /* notification may or may not happen */
63 #define NF_WINE_ALLOW 0x0002 /* wine sends notification when it should not */
64 #define NF_SIGNAL 0x0004 /* signal wait handle when notified */
65 #define NF_MAIN_THREAD 0x0008 /* the operation completes synchronously and callback is called from the main thread */
70 const struct notification
*test
;
87 static void CALLBACK
check_notification( HINTERNET handle
, DWORD_PTR context
, DWORD status
, LPVOID buffer
, DWORD buflen
)
89 BOOL status_ok
, function_ok
;
90 struct info
*info
= (struct info
*)context
;
92 info
->last_status
= status
;
93 info
->last_thread_id
= GetCurrentThreadId();
95 if (status
== WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
)
97 DWORD size
= sizeof(struct info
*);
98 WinHttpQueryOption( handle
, WINHTTP_OPTION_CONTEXT_VALUE
, &info
, &size
);
100 while (info
->index
< info
->count
&& info
->test
[info
->index
].status
!= status
&& (info
->test
[info
->index
].flags
& NF_ALLOW
))
102 while (info
->index
< info
->count
&& (info
->test
[info
->index
].flags
& NF_WINE_ALLOW
))
104 todo_wine
ok(info
->test
[info
->index
].status
!= status
, "unexpected %x notification\n", status
);
105 if (info
->test
[info
->index
].status
== status
) break;
108 ok(info
->index
< info
->count
, "%u: unexpected notification 0x%08x\n", info
->line
, status
);
109 if (info
->index
>= info
->count
) return;
111 status_ok
= (info
->test
[info
->index
].status
== status
);
112 function_ok
= (info
->test
[info
->index
].function
== info
->function
);
113 ok(status_ok
, "%u: expected status 0x%08x got 0x%08x\n", info
->line
, info
->test
[info
->index
].status
, status
);
114 ok(function_ok
, "%u: expected function %u got %u\n", info
->line
, info
->test
[info
->index
].function
, info
->function
);
116 if (info
->test
[info
->index
].flags
& NF_MAIN_THREAD
)
118 ok(GetCurrentThreadId() == info
->main_thread_id
, "%u: expected callback to be called from the same thread\n",
122 if (status_ok
&& function_ok
&& info
->test
[info
->index
++].flags
& NF_SIGNAL
)
124 SetEvent( info
->wait
);
128 static const struct notification cache_test
[] =
130 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
131 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
132 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
},
133 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
},
134 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
},
135 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
},
136 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
137 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
138 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
},
139 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
},
140 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, NF_WINE_ALLOW
},
141 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, NF_WINE_ALLOW
},
142 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
},
143 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
144 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, NF_WINE_ALLOW
},
145 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, NF_WINE_ALLOW
},
146 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
147 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
148 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
},
149 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
},
150 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, NF_WINE_ALLOW
},
151 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, NF_WINE_ALLOW
},
152 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
153 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
},
154 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
},
155 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
156 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
157 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, NF_WINE_ALLOW
},
158 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, NF_WINE_ALLOW
},
159 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, NF_WINE_ALLOW
},
160 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, NF_WINE_ALLOW
},
161 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
162 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
163 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
},
164 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
},
165 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, NF_WINE_ALLOW
},
166 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, NF_WINE_ALLOW
},
167 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
},
168 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
169 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, NF_WINE_ALLOW
},
170 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, NF_WINE_ALLOW
},
171 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
172 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
173 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
},
174 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
},
175 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, NF_WINE_ALLOW
},
176 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, NF_WINE_ALLOW
},
177 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
178 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
},
179 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
}
182 static void setup_test( struct info
*info
, enum api function
, unsigned int line
)
184 if (info
->wait
) ResetEvent( info
->wait
);
185 info
->function
= function
;
187 while (info
->index
< info
->count
&& info
->test
[info
->index
].function
!= function
188 && (info
->test
[info
->index
].flags
& (NF_ALLOW
| NF_WINE_ALLOW
)))
190 ok_(__FILE__
,line
)(info
->test
[info
->index
].function
== function
,
191 "unexpected function %u, expected %u. probably some notifications were missing\n",
192 info
->test
[info
->index
].function
, function
);
193 info
->last_thread_id
= 0xdeadbeef;
194 info
->last_status
= 0xdeadbeef;
195 info
->main_thread_id
= GetCurrentThreadId();
198 static void end_test( struct info
*info
, unsigned int line
)
200 ok_(__FILE__
,line
)(info
->index
== info
->count
, "some notifications were missing: %x\n",
201 info
->test
[info
->index
].status
);
204 static void test_connection_cache( void )
206 HANDLE ses
, con
, req
, event
;
207 DWORD size
, status
, err
;
208 BOOL ret
, unload
= TRUE
;
209 struct info info
, *context
= &info
;
211 info
.test
= cache_test
;
212 info
.count
= ARRAY_SIZE( cache_test
);
214 info
.wait
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
216 ses
= WinHttpOpen( L
"winetest", 0, NULL
, NULL
, 0 );
217 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
219 event
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
220 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT
, &event
, sizeof(event
) );
223 win_skip("Unload event not supported\n");
227 WinHttpSetStatusCallback( ses
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
229 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
230 ok(ret
, "failed to set context value %u\n", GetLastError());
232 setup_test( &info
, winhttp_connect
, __LINE__
);
233 con
= WinHttpConnect( ses
, L
"test.winehq.org", 0, 0 );
234 ok(con
!= NULL
, "failed to open a connection %u\n", GetLastError());
236 setup_test( &info
, winhttp_open_request
, __LINE__
);
237 req
= WinHttpOpenRequest( con
, NULL
, L
"/tests/hello.html", NULL
, NULL
, NULL
, 0 );
238 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
240 setup_test( &info
, winhttp_send_request
, __LINE__
);
241 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
242 err
= GetLastError();
243 if (!ret
&& (err
== ERROR_WINHTTP_CANNOT_CONNECT
|| err
== ERROR_WINHTTP_TIMEOUT
))
245 skip("connection failed, skipping\n");
248 ok(ret
, "failed to send request %u\n", GetLastError());
250 setup_test( &info
, winhttp_receive_response
, __LINE__
);
251 ret
= WinHttpReceiveResponse( req
, NULL
);
252 ok(ret
, "failed to receive response %u\n", GetLastError());
254 size
= sizeof(status
);
255 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
256 ok(ret
, "failed unexpectedly %u\n", GetLastError());
257 ok(status
== 200, "request failed unexpectedly %u\n", status
);
259 ResetEvent( info
.wait
);
260 setup_test( &info
, winhttp_close_handle
, __LINE__
);
261 WinHttpCloseHandle( req
);
262 WaitForSingleObject( info
.wait
, INFINITE
);
264 setup_test( &info
, winhttp_open_request
, __LINE__
);
265 req
= WinHttpOpenRequest( con
, NULL
, L
"/tests/hello.html", NULL
, NULL
, NULL
, 0 );
266 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
268 ret
= WinHttpSetOption( req
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
269 ok(ret
, "failed to set context value %u\n", GetLastError());
271 setup_test( &info
, winhttp_send_request
, __LINE__
);
272 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
273 err
= GetLastError();
274 if (!ret
&& (err
== ERROR_WINHTTP_CANNOT_CONNECT
|| err
== ERROR_WINHTTP_TIMEOUT
))
276 skip("connection failed, skipping\n");
279 ok(ret
, "failed to send request %u\n", GetLastError());
281 setup_test( &info
, winhttp_receive_response
, __LINE__
);
282 ret
= WinHttpReceiveResponse( req
, NULL
);
283 ok(ret
, "failed to receive response %u\n", GetLastError());
285 size
= sizeof(status
);
286 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
287 ok(ret
, "failed unexpectedly %u\n", GetLastError());
288 ok(status
== 200, "request failed unexpectedly %u\n", status
);
290 ResetEvent( info
.wait
);
291 setup_test( &info
, winhttp_close_handle
, __LINE__
);
292 WinHttpCloseHandle( req
);
293 WinHttpCloseHandle( req
);
294 WinHttpCloseHandle( con
);
295 WaitForSingleObject( info
.wait
, INFINITE
);
299 status
= WaitForSingleObject( event
, 0 );
300 ok(status
== WAIT_TIMEOUT
, "got %08x\n", status
);
303 setup_test( &info
, winhttp_close_handle
, __LINE__
);
304 WinHttpCloseHandle( ses
);
305 WaitForSingleObject( info
.wait
, INFINITE
);
309 status
= WaitForSingleObject( event
, 100 );
310 ok(status
== WAIT_OBJECT_0
, "got %08x\n", status
);
314 ses
= WinHttpOpen( L
"winetest", 0, NULL
, NULL
, 0 );
315 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
319 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT
, &event
, sizeof(event
) );
320 ok(ret
, "failed to set unload option\n");
323 WinHttpSetStatusCallback( ses
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
325 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
326 ok(ret
, "failed to set context value %u\n", GetLastError());
328 setup_test( &info
, winhttp_connect
, __LINE__
);
329 con
= WinHttpConnect( ses
, L
"test.winehq.org", 0, 0 );
330 ok(con
!= NULL
, "failed to open a connection %u\n", GetLastError());
332 setup_test( &info
, winhttp_open_request
, __LINE__
);
333 req
= WinHttpOpenRequest( con
, NULL
, L
"/tests/hello.html", NULL
, NULL
, NULL
, 0 );
334 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
336 ret
= WinHttpSetOption( req
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
337 ok(ret
, "failed to set context value %u\n", GetLastError());
339 setup_test( &info
, winhttp_send_request
, __LINE__
);
340 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
341 err
= GetLastError();
342 if (!ret
&& (err
== ERROR_WINHTTP_CANNOT_CONNECT
|| err
== ERROR_WINHTTP_TIMEOUT
))
344 skip("connection failed, skipping\n");
347 ok(ret
, "failed to send request %u\n", GetLastError());
349 setup_test( &info
, winhttp_receive_response
, __LINE__
);
350 ret
= WinHttpReceiveResponse( req
, NULL
);
351 ok(ret
, "failed to receive response %u\n", GetLastError());
353 size
= sizeof(status
);
354 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
355 ok(ret
, "failed unexpectedly %u\n", GetLastError());
356 ok(status
== 200, "request failed unexpectedly %u\n", status
);
358 ResetEvent( info
.wait
);
359 setup_test( &info
, winhttp_close_handle
, __LINE__
);
360 WinHttpCloseHandle( req
);
361 WaitForSingleObject( info
.wait
, INFINITE
);
363 setup_test( &info
, winhttp_open_request
, __LINE__
);
364 req
= WinHttpOpenRequest( con
, NULL
, L
"/tests/hello.html", NULL
, NULL
, NULL
, 0 );
365 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
367 ret
= WinHttpSetOption( req
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
368 ok(ret
, "failed to set context value %u\n", GetLastError());
370 setup_test( &info
, winhttp_send_request
, __LINE__
);
371 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
372 err
= GetLastError();
373 if (!ret
&& (err
== ERROR_WINHTTP_CANNOT_CONNECT
|| err
== ERROR_WINHTTP_TIMEOUT
))
375 skip("connection failed, skipping\n");
378 ok(ret
, "failed to send request %u\n", GetLastError());
380 setup_test( &info
, winhttp_receive_response
, __LINE__
);
381 ret
= WinHttpReceiveResponse( req
, NULL
);
382 ok(ret
, "failed to receive response %u\n", GetLastError());
384 size
= sizeof(status
);
385 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
386 ok(ret
, "failed unexpectedly %u\n", GetLastError());
387 ok(status
== 200, "request failed unexpectedly %u\n", status
);
389 setup_test( &info
, winhttp_close_handle
, __LINE__
);
391 WinHttpCloseHandle( req
);
392 WinHttpCloseHandle( con
);
393 WaitForSingleObject( info
.wait
, INFINITE
);
397 status
= WaitForSingleObject( event
, 0 );
398 ok(status
== WAIT_TIMEOUT
, "got %08x\n", status
);
401 setup_test( &info
, winhttp_close_handle
, __LINE__
);
402 WinHttpCloseHandle( ses
);
403 WaitForSingleObject( info
.wait
, INFINITE
);
404 CloseHandle( info
.wait
);
405 end_test( &info
, __LINE__
);
409 status
= WaitForSingleObject( event
, 100 );
410 ok(status
== WAIT_OBJECT_0
, "got %08x\n", status
);
413 CloseHandle( event
);
416 static const struct notification redirect_test
[] =
418 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
419 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
420 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, NF_WINE_ALLOW
},
421 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, NF_WINE_ALLOW
},
422 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, NF_WINE_ALLOW
},
423 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, NF_WINE_ALLOW
},
424 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
425 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
426 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
},
427 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
},
428 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_REDIRECT
},
429 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, NF_ALLOW
},
430 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, NF_ALLOW
},
431 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, NF_ALLOW
},
432 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, NF_ALLOW
},
433 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
434 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
435 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
},
436 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
},
437 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, NF_WINE_ALLOW
},
438 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, NF_WINE_ALLOW
},
439 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
440 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
441 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
}
444 static void test_redirect( void )
446 HANDLE ses
, con
, req
;
447 DWORD size
, status
, err
;
449 struct info info
, *context
= &info
;
451 info
.test
= redirect_test
;
452 info
.count
= ARRAY_SIZE( redirect_test
);
454 info
.wait
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
456 ses
= WinHttpOpen( L
"winetest", 0, NULL
, NULL
, 0 );
457 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
459 WinHttpSetStatusCallback( ses
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
461 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
462 ok(ret
, "failed to set context value %u\n", GetLastError());
464 setup_test( &info
, winhttp_connect
, __LINE__
);
465 con
= WinHttpConnect( ses
, L
"test.winehq.org", 0, 0 );
466 ok(con
!= NULL
, "failed to open a connection %u\n", GetLastError());
468 setup_test( &info
, winhttp_open_request
, __LINE__
);
469 req
= WinHttpOpenRequest( con
, NULL
, L
"/tests/redirect", NULL
, NULL
, NULL
, 0 );
470 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
472 setup_test( &info
, winhttp_send_request
, __LINE__
);
473 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
474 err
= GetLastError();
475 if (!ret
&& (err
== ERROR_WINHTTP_CANNOT_CONNECT
|| err
== ERROR_WINHTTP_TIMEOUT
))
477 skip("connection failed, skipping\n");
480 ok(ret
, "failed to send request %u\n", GetLastError());
482 setup_test( &info
, winhttp_receive_response
, __LINE__
);
483 ret
= WinHttpReceiveResponse( req
, NULL
);
484 ok(ret
, "failed to receive response %u\n", GetLastError());
486 size
= sizeof(status
);
487 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
488 ok(ret
, "failed unexpectedly %u\n", GetLastError());
489 ok(status
== 200, "request failed unexpectedly %u\n", status
);
491 setup_test( &info
, winhttp_close_handle
, __LINE__
);
493 WinHttpCloseHandle( req
);
494 WinHttpCloseHandle( con
);
495 WinHttpCloseHandle( ses
);
496 WaitForSingleObject( info
.wait
, INFINITE
);
497 CloseHandle( info
.wait
);
498 end_test( &info
, __LINE__
);
501 static const struct notification async_test
[] =
503 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
504 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
505 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
, NF_WINE_ALLOW
},
506 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
, NF_WINE_ALLOW
},
507 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, NF_WINE_ALLOW
},
508 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
, NF_WINE_ALLOW
},
509 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
510 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
511 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
, NF_SIGNAL
},
512 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
},
513 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
},
514 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
, NF_SIGNAL
},
515 { winhttp_query_data
, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE
, NF_SIGNAL
},
516 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, NF_ALLOW
},
517 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, NF_ALLOW
},
518 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_READ_COMPLETE
, NF_SIGNAL
},
519 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
520 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
521 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
}
524 static void test_async( void )
526 HANDLE ses
, con
, req
, event
;
527 DWORD size
, status
, err
;
528 BOOL ret
, unload
= TRUE
;
529 struct info info
, *context
= &info
;
532 info
.test
= async_test
;
533 info
.count
= ARRAY_SIZE( async_test
);
535 info
.wait
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
537 ses
= WinHttpOpen( L
"winetest", 0, NULL
, NULL
, WINHTTP_FLAG_ASYNC
);
538 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
540 event
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
541 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT
, &event
, sizeof(event
) );
544 win_skip("Unload event not supported\n");
548 SetLastError( 0xdeadbeef );
549 WinHttpSetStatusCallback( ses
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
550 err
= GetLastError();
551 ok(err
== ERROR_SUCCESS
|| broken(err
== 0xdeadbeef) /* < win7 */, "got %u\n", err
);
553 SetLastError( 0xdeadbeef );
554 ret
= WinHttpSetOption( ses
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(struct info
*) );
555 err
= GetLastError();
556 ok(ret
, "failed to set context value %u\n", err
);
557 ok(err
== ERROR_SUCCESS
|| broken(err
== 0xdeadbeef) /* < win7 */, "got %u\n", err
);
559 setup_test( &info
, winhttp_connect
, __LINE__
);
560 SetLastError( 0xdeadbeef );
561 con
= WinHttpConnect( ses
, L
"test.winehq.org", 0, 0 );
562 err
= GetLastError();
563 ok(con
!= NULL
, "failed to open a connection %u\n", err
);
564 ok(err
== ERROR_SUCCESS
|| broken(err
== WSAEINVAL
) /* < win7 */, "got %u\n", err
);
566 setup_test( &info
, winhttp_open_request
, __LINE__
);
567 SetLastError( 0xdeadbeef );
568 req
= WinHttpOpenRequest( con
, NULL
, L
"/tests/hello.html", NULL
, NULL
, NULL
, 0 );
569 err
= GetLastError();
570 ok(req
!= NULL
, "failed to open a request %u\n", err
);
571 ok(err
== ERROR_SUCCESS
, "got %u\n", err
);
573 setup_test( &info
, winhttp_send_request
, __LINE__
);
574 SetLastError( 0xdeadbeef );
575 ret
= WinHttpSendRequest( req
, NULL
, 0, NULL
, 0, 0, 0 );
576 err
= GetLastError();
577 if (!ret
&& (err
== ERROR_WINHTTP_CANNOT_CONNECT
|| err
== ERROR_WINHTTP_TIMEOUT
))
579 skip("connection failed, skipping\n");
580 WinHttpCloseHandle( req
);
581 WinHttpCloseHandle( con
);
582 WinHttpCloseHandle( ses
);
583 CloseHandle( info
.wait
);
586 ok(ret
, "failed to send request %u\n", err
);
587 ok(err
== ERROR_SUCCESS
, "got %u\n", err
);
589 WaitForSingleObject( info
.wait
, INFINITE
);
591 setup_test( &info
, winhttp_receive_response
, __LINE__
);
592 SetLastError( 0xdeadbeef );
593 ret
= WinHttpReceiveResponse( req
, NULL
);
594 err
= GetLastError();
595 ok(ret
, "failed to receive response %u\n", err
);
596 ok(err
== ERROR_SUCCESS
, "got %u\n", err
);
598 WaitForSingleObject( info
.wait
, INFINITE
);
600 size
= sizeof(status
);
601 SetLastError( 0xdeadbeef );
602 ret
= WinHttpQueryHeaders( req
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
603 err
= GetLastError();
604 ok(ret
, "failed unexpectedly %u\n", err
);
605 ok(status
== 200, "request failed unexpectedly %u\n", status
);
606 ok(err
== ERROR_SUCCESS
|| broken(err
== 0xdeadbeef) /* < win7 */, "got %u\n", err
);
608 setup_test( &info
, winhttp_query_data
, __LINE__
);
609 SetLastError( 0xdeadbeef );
610 ret
= WinHttpQueryDataAvailable( req
, NULL
);
611 err
= GetLastError();
612 ok(ret
, "failed to query data available %u\n", err
);
613 ok(err
== ERROR_SUCCESS
|| err
== ERROR_IO_PENDING
|| broken(err
== 0xdeadbeef) /* < win7 */, "got %u\n", err
);
615 WaitForSingleObject( info
.wait
, INFINITE
);
616 ok(info
.last_status
== WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE
, "got status %#x.\n", status
);
617 ok((err
== ERROR_SUCCESS
&& info
.last_thread_id
== GetCurrentThreadId())
618 || (err
== ERROR_IO_PENDING
&& info
.last_thread_id
!= GetCurrentThreadId()),
619 "Got unexpected thread %#x, err %#x.\n", info
.last_thread_id
, err
);
621 setup_test( &info
, winhttp_read_data
, __LINE__
);
622 ret
= WinHttpReadData( req
, buffer
, sizeof(buffer
), NULL
);
623 ok(ret
, "failed to read data %u\n", err
);
625 WaitForSingleObject( info
.wait
, INFINITE
);
627 ok(info
.last_status
== WINHTTP_CALLBACK_STATUS_READ_COMPLETE
, "got status %#x.\n", status
);
628 ok((err
== ERROR_SUCCESS
&& info
.last_thread_id
== GetCurrentThreadId())
629 || (err
== ERROR_IO_PENDING
&& info
.last_thread_id
!= GetCurrentThreadId()),
630 "Got unexpected thread %#x, err %#x.\n", info
.last_thread_id
, err
);
632 setup_test( &info
, winhttp_close_handle
, __LINE__
);
633 WinHttpCloseHandle( req
);
634 WinHttpCloseHandle( con
);
638 status
= WaitForSingleObject( event
, 0 );
639 ok(status
== WAIT_TIMEOUT
, "got %08x\n", status
);
641 WinHttpCloseHandle( ses
);
642 WaitForSingleObject( info
.wait
, INFINITE
);
643 end_test( &info
, __LINE__
);
647 status
= WaitForSingleObject( event
, 2000 );
648 ok(status
== WAIT_OBJECT_0
, "got %08x\n", status
);
650 CloseHandle( event
);
651 CloseHandle( info
.wait
);
652 end_test( &info
, __LINE__
);
655 static const struct notification websocket_test
[] =
657 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
658 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
659 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
},
660 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
},
661 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
},
662 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
},
663 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
664 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
665 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
, NF_SIGNAL
},
666 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
},
667 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
},
668 { winhttp_receive_response
, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
, NF_SIGNAL
},
669 { winhttp_websocket_complete_upgrade
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
, NF_SIGNAL
},
670 { winhttp_websocket_send
, WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE
, NF_MAIN_THREAD
| NF_SIGNAL
},
671 { winhttp_websocket_send
, WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE
, NF_MAIN_THREAD
| NF_SIGNAL
},
672 { winhttp_websocket_shutdown
, WINHTTP_CALLBACK_STATUS_SHUTDOWN_COMPLETE
, NF_SIGNAL
},
673 { winhttp_websocket_receive
, WINHTTP_CALLBACK_STATUS_READ_COMPLETE
, NF_SIGNAL
},
674 { winhttp_websocket_receive
, WINHTTP_CALLBACK_STATUS_READ_COMPLETE
, NF_SIGNAL
},
675 { winhttp_websocket_close
, WINHTTP_CALLBACK_STATUS_CLOSE_COMPLETE
, NF_SIGNAL
},
676 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
677 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, NF_WINE_ALLOW
},
678 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, NF_WINE_ALLOW
},
679 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
680 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
681 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
}
684 static void test_websocket(BOOL secure
)
686 HANDLE session
, connection
, request
, socket
, event
;
687 WINHTTP_WEB_SOCKET_BUFFER_TYPE type
;
688 DWORD size
, status
, err
;
689 BOOL ret
, unload
= TRUE
;
690 struct info info
, *context
= &info
;
693 DWORD protocols
, flags
;
696 if (!pWinHttpWebSocketCompleteUpgrade
)
698 win_skip( "WinHttpWebSocketCompleteUpgrade not supported\n" );
702 info
.test
= websocket_test
;
703 info
.count
= ARRAY_SIZE( websocket_test
);
705 info
.wait
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
707 session
= WinHttpOpen( L
"winetest", 0, NULL
, NULL
, WINHTTP_FLAG_ASYNC
);
708 ok( session
!= NULL
, "got %u\n", GetLastError() );
710 event
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
711 ret
= WinHttpSetOption( session
, WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT
, &event
, sizeof(event
) );
714 win_skip( "Unload event not supported\n" );
720 protocols
= WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2
;
721 ret
= WinHttpSetOption(session
, WINHTTP_OPTION_SECURE_PROTOCOLS
, &protocols
, sizeof(protocols
));
722 ok(ret
, "failed to set protocols %u\n", GetLastError());
725 SetLastError( 0xdeadbeef );
726 WinHttpSetStatusCallback( session
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
727 err
= GetLastError();
728 ok( err
== ERROR_SUCCESS
|| broken(err
== 0xdeadbeef) /* < win7 */, "got %u\n", err
);
730 SetLastError( 0xdeadbeef );
731 ret
= WinHttpSetOption( session
, WINHTTP_OPTION_CONTEXT_VALUE
, &context
, sizeof(context
) );
732 err
= GetLastError();
733 ok( ret
, "got %u\n", err
);
734 ok( err
== ERROR_SUCCESS
|| broken(err
== 0xdeadbeef) /* < win7 */, "got %u\n", err
);
736 setup_test( &info
, winhttp_connect
, __LINE__
);
737 SetLastError( 0xdeadbeef );
738 connection
= WinHttpConnect( session
, L
"ws.ifelse.io", 0, 0 );
739 err
= GetLastError();
740 ok( connection
!= NULL
, "got %u\n", err
);
741 ok( err
== ERROR_SUCCESS
|| broken(err
== WSAEINVAL
) /* < win7 */, "got %u\n", err
);
743 setup_test( &info
, winhttp_open_request
, __LINE__
);
744 SetLastError( 0xdeadbeef );
745 request
= WinHttpOpenRequest( connection
, NULL
, L
"/", NULL
, NULL
, NULL
, secure
? WINHTTP_FLAG_SECURE
: 0);
746 err
= GetLastError();
747 ok( request
!= NULL
, "got %u\n", err
);
748 ok( err
== ERROR_SUCCESS
, "got %u\n", err
);
752 flags
= SECURITY_FLAG_IGNORE_UNKNOWN_CA
| SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
|
753 SECURITY_FLAG_IGNORE_CERT_CN_INVALID
;
754 ret
= WinHttpSetOption(request
, WINHTTP_OPTION_SECURITY_FLAGS
, &flags
, sizeof(flags
));
755 ok(ret
, "failed to set security flags %u\n", GetLastError());
758 ret
= WinHttpSetOption( request
, WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET
, NULL
, 0 );
759 ok( ret
, "got %u\n", GetLastError() );
761 setup_test( &info
, winhttp_send_request
, __LINE__
);
762 SetLastError( 0xdeadbeef );
763 ret
= WinHttpSendRequest( request
, NULL
, 0, NULL
, 0, 0, 0 );
764 err
= GetLastError();
765 if (!ret
&& (err
== ERROR_WINHTTP_CANNOT_CONNECT
|| err
== ERROR_WINHTTP_TIMEOUT
))
767 skip( "connection failed, skipping\n" );
768 WinHttpCloseHandle( request
);
769 WinHttpCloseHandle( connection
);
770 WinHttpCloseHandle( session
);
771 CloseHandle( info
.wait
);
774 ok( ret
, "got %u\n", err
);
775 ok( err
== ERROR_SUCCESS
, "got %u\n", err
);
776 WaitForSingleObject( info
.wait
, INFINITE
);
778 setup_test( &info
, winhttp_receive_response
, __LINE__
);
779 SetLastError( 0xdeadbeef );
780 ret
= WinHttpReceiveResponse( request
, NULL
);
781 err
= GetLastError();
782 ok( ret
, "got %u\n", err
);
783 ok( err
== ERROR_SUCCESS
, "got %u\n", err
);
784 WaitForSingleObject( info
.wait
, INFINITE
);
786 size
= sizeof(status
);
787 SetLastError( 0xdeadbeef );
788 ret
= WinHttpQueryHeaders( request
, WINHTTP_QUERY_STATUS_CODE
|WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
789 err
= GetLastError();
790 ok( ret
, "failed unexpectedly %u\n", err
);
791 ok( status
== 101, "got %u\n", status
);
792 ok( err
== ERROR_SUCCESS
|| broken(err
== 0xdeadbeef) /* < win7 */, "got %u\n", err
);
794 setup_test( &info
, winhttp_websocket_complete_upgrade
, __LINE__
);
795 SetLastError( 0xdeadbeef );
796 socket
= pWinHttpWebSocketCompleteUpgrade( request
, (DWORD_PTR
)context
);
797 err
= GetLastError();
798 ok( socket
!= NULL
, "got %u\n", err
);
799 ok( err
== ERROR_SUCCESS
, "got %u\n", err
);
800 WaitForSingleObject( info
.wait
, INFINITE
);
802 for (i
= 0; i
< 2; ++i
)
804 /* The send is executed synchronously (even if sending a reasonably big buffer exceeding SSL buffer size).
805 * It is possible to trigger queueing the send into another thread but that involves sending a considerable
806 * amount of big enough buffers. */
807 setup_test( &info
, winhttp_websocket_send
, __LINE__
);
808 err
= pWinHttpWebSocketSend( socket
, WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE
,
809 (void*)"hello", sizeof("hello") );
810 ok( err
== ERROR_SUCCESS
, "got %u\n", err
);
811 WaitForSingleObject( info
.wait
, INFINITE
);
814 setup_test( &info
, winhttp_websocket_shutdown
, __LINE__
);
815 err
= pWinHttpWebSocketShutdown( socket
, 1000, (void *)"success", sizeof("success") );
816 ok( err
== ERROR_SUCCESS
, "got %u\n", err
);
817 WaitForSingleObject( info
.wait
, INFINITE
);
819 err
= pWinHttpWebSocketShutdown( socket
, 1000, (void *)"success", sizeof("success") );
820 ok( err
== ERROR_INVALID_OPERATION
, "got %u\n", err
);
821 err
= pWinHttpWebSocketSend( socket
, WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE
,
822 (void*)"hello", sizeof("hello") );
823 ok( err
== ERROR_INVALID_OPERATION
, "got %u\n", err
);
825 setup_test( &info
, winhttp_websocket_receive
, __LINE__
);
829 err
= pWinHttpWebSocketReceive( socket
, buffer
, sizeof(buffer
), &size
, &type
);
830 ok( err
== ERROR_SUCCESS
, "got %u\n", err
);
831 WaitForSingleObject( info
.wait
, INFINITE
);
832 ok( size
== 0xdeadbeef, "got %u\n", size
);
833 ok( type
== 0xdeadbeef, "got %u\n", type
);
834 ok( buffer
[0] == 'R', "unexpected data\n" );
836 setup_test( &info
, winhttp_websocket_receive
, __LINE__
);
840 err
= pWinHttpWebSocketReceive( socket
, buffer
, sizeof(buffer
), &size
, &type
);
841 ok( err
== ERROR_SUCCESS
, "got %u\n", err
);
842 WaitForSingleObject( info
.wait
, INFINITE
);
843 ok( size
== 0xdeadbeef, "got %u\n", size
);
844 ok( type
== 0xdeadbeef, "got %u\n", type
);
845 ok( buffer
[0] == 'h', "unexpected data\n" );
847 close_status
= 0xdead;
848 size
= sizeof(buffer
) + 1;
849 err
= pWinHttpWebSocketQueryCloseStatus( socket
, &close_status
, buffer
, sizeof(buffer
), &size
);
850 ok( err
== ERROR_INVALID_OPERATION
, "got %u\n", err
);
851 ok( close_status
== 0xdead, "got %u\n", close_status
);
852 ok( size
== sizeof(buffer
) + 1, "got %u\n", size
);
854 setup_test( &info
, winhttp_websocket_close
, __LINE__
);
855 err
= pWinHttpWebSocketClose( socket
, 1000, (void *)"success", sizeof("success") );
856 ok( err
== ERROR_SUCCESS
, "got %u\n", err
);
857 WaitForSingleObject( info
.wait
, INFINITE
);
859 close_status
= 0xdead;
860 size
= sizeof(buffer
) + 1;
861 err
= pWinHttpWebSocketQueryCloseStatus( socket
, &close_status
, buffer
, sizeof(buffer
), &size
);
862 ok( err
== ERROR_SUCCESS
, "got %u\n", err
);
863 ok( close_status
== 1000, "got %u\n", close_status
);
864 ok( size
<= sizeof(buffer
), "got %u\n", size
);
866 setup_test( &info
, winhttp_close_handle
, __LINE__
);
867 WinHttpCloseHandle( socket
);
868 WinHttpCloseHandle( request
);
869 WinHttpCloseHandle( connection
);
873 status
= WaitForSingleObject( event
, 0 );
874 ok( status
== WAIT_TIMEOUT
, "got %08x\n", status
);
876 WinHttpCloseHandle( session
);
877 WaitForSingleObject( info
.wait
, INFINITE
);
878 end_test( &info
, __LINE__
);
882 status
= WaitForSingleObject( event
, 2000 );
883 ok( status
== WAIT_OBJECT_0
, "got %08x\n", status
);
885 CloseHandle( event
);
886 CloseHandle( info
.wait
);
887 end_test( &info
, __LINE__
);
890 static const char okmsg
[] =
891 "HTTP/1.1 200 OK\r\n"
892 "Server: winetest\r\n"
895 static const char page1
[] =
897 "<HEAD><TITLE>winhttp test page</TITLE></HEAD>\r\n"
898 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
907 static int server_socket
;
908 static HANDLE server_socket_available
, server_socket_done
;
910 static DWORD CALLBACK
server_thread(LPVOID param
)
912 struct server_info
*si
= param
;
913 int r
, c
= -1, i
, on
;
915 struct sockaddr_in sa
;
918 int last_request
= 0;
920 WSAStartup(MAKEWORD(1,1), &wsaData
);
922 s
= socket(AF_INET
, SOCK_STREAM
, 0);
923 if (s
== INVALID_SOCKET
)
927 setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
, (char*)&on
, sizeof on
);
929 memset(&sa
, 0, sizeof sa
);
930 sa
.sin_family
= AF_INET
;
931 sa
.sin_port
= htons(si
->port
);
932 sa
.sin_addr
.S_un
.S_addr
= inet_addr("127.0.0.1");
934 r
= bind(s
, (struct sockaddr
*)&sa
, sizeof(sa
));
942 if (c
== -1) c
= accept(s
, NULL
, NULL
);
944 memset(buffer
, 0, sizeof buffer
);
945 for(i
= 0; i
< sizeof buffer
- 1; i
++)
947 r
= recv(c
, &buffer
[i
], 1, 0);
951 if (buffer
[i
- 2] == '\n' && buffer
[i
] == '\n' &&
952 buffer
[i
- 3] == '\r' && buffer
[i
- 1] == '\r')
955 if (strstr(buffer
, "GET /quit"))
957 send(c
, okmsg
, sizeof okmsg
- 1, 0);
958 send(c
, page1
, sizeof page1
- 1, 0);
961 else if(strstr(buffer
, "GET /socket"))
964 SetEvent(server_socket_available
);
965 WaitForSingleObject(server_socket_done
, INFINITE
);
966 ResetEvent(server_socket_available
);
971 } while (!last_request
);
977 static void test_basic_request(int port
, const WCHAR
*verb
, const WCHAR
*path
)
979 HINTERNET ses
, con
, req
;
981 DWORD count
, status
, size
;
984 ses
= WinHttpOpen(NULL
, WINHTTP_ACCESS_TYPE_NO_PROXY
, NULL
, NULL
, 0);
985 ok(ses
!= NULL
, "failed to open session %u\n", GetLastError());
987 con
= WinHttpConnect(ses
, L
"localhost", port
, 0);
988 ok(con
!= NULL
, "failed to open a connection %u\n", GetLastError());
990 req
= WinHttpOpenRequest(con
, verb
, path
, NULL
, NULL
, NULL
, 0);
991 ok(req
!= NULL
, "failed to open a request %u\n", GetLastError());
993 ret
= WinHttpSendRequest(req
, NULL
, 0, NULL
, 0, 0, 0);
994 ok(ret
, "failed to send request %u\n", GetLastError());
996 ret
= WinHttpReceiveResponse(req
, NULL
);
997 ok(ret
, "failed to receive response %u\n", GetLastError());
1000 size
= sizeof(status
);
1001 ret
= WinHttpQueryHeaders(req
, WINHTTP_QUERY_STATUS_CODE
|WINHTTP_QUERY_FLAG_NUMBER
, NULL
, &status
, &size
, NULL
);
1002 ok(ret
, "failed to query status code %u\n", GetLastError());
1003 ok(status
== HTTP_STATUS_OK
, "request failed unexpectedly %u\n", status
);
1006 memset(buffer
, 0, sizeof(buffer
));
1007 ret
= WinHttpReadData(req
, buffer
, sizeof buffer
, &count
);
1008 ok(ret
, "failed to read data %u\n", GetLastError());
1009 ok(count
== sizeof page1
- 1, "count was wrong\n");
1010 ok(!memcmp(buffer
, page1
, sizeof page1
), "http data wrong\n");
1012 WinHttpCloseHandle(req
);
1013 WinHttpCloseHandle(con
);
1014 WinHttpCloseHandle(ses
);
1017 static const struct notification open_socket_request_test
[] =
1019 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
1020 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
1021 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
},
1022 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
},
1023 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
},
1024 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
, NF_ALLOW
}, /* some versions call it twice. why? */
1025 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
},
1026 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
1027 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
1028 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
, NF_SIGNAL
}
1031 static const struct notification reuse_socket_request_test
[] =
1033 { winhttp_connect
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
1034 { winhttp_open_request
, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
},
1035 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
},
1036 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_REQUEST_SENT
},
1037 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
, NF_SIGNAL
},
1040 static void open_async_request(int port
, struct test_request
*req
, struct info
*info
, const WCHAR
*path
, BOOL reuse_connection
)
1045 if (reuse_connection
)
1047 info
->test
= reuse_socket_request_test
;
1048 info
->count
= ARRAY_SIZE( reuse_socket_request_test
);
1052 info
->test
= open_socket_request_test
;
1053 info
->count
= ARRAY_SIZE( open_socket_request_test
);
1056 req
->session
= WinHttpOpen( L
"winetest", 0, NULL
, NULL
, WINHTTP_FLAG_ASYNC
);
1057 ok(req
->session
!= NULL
, "failed to open session %u\n", GetLastError());
1059 WinHttpSetOption( req
->session
, WINHTTP_OPTION_CONTEXT_VALUE
, &info
, sizeof(struct info
*) );
1060 WinHttpSetStatusCallback( req
->session
, check_notification
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
1062 setup_test( info
, winhttp_connect
, __LINE__
);
1063 req
->connection
= WinHttpConnect( req
->session
, L
"localhost", port
, 0 );
1064 ok(req
->connection
!= NULL
, "failed to open a connection %u\n", GetLastError());
1066 setup_test( info
, winhttp_open_request
, __LINE__
);
1067 req
->request
= WinHttpOpenRequest( req
->connection
, NULL
, path
, NULL
, NULL
, NULL
, 0 );
1068 ok(req
->request
!= NULL
, "failed to open a request %u\n", GetLastError());
1070 setup_test( info
, winhttp_send_request
, __LINE__
);
1071 ret
= WinHttpSendRequest( req
->request
, NULL
, 0, NULL
, 0, 0, 0 );
1072 ok(ret
, "failed to send request %u\n", GetLastError());
1075 static void open_socket_request(int port
, struct test_request
*req
, struct info
*info
)
1077 ResetEvent( server_socket_done
);
1078 open_async_request( port
, req
, info
, L
"/socket", FALSE
);
1079 WaitForSingleObject( server_socket_available
, INFINITE
);
1082 static const struct notification server_reply_test
[] =
1084 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, NF_ALLOW
},
1085 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, NF_ALLOW
},
1086 { winhttp_send_request
, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
, NF_SIGNAL
}
1089 static void server_send_reply(struct test_request
*req
, struct info
*info
, const char *msg
)
1093 send( server_socket
, msg
, strlen( msg
), 0 );
1094 WaitForSingleObject( info
->wait
, INFINITE
);
1096 info
->test
= server_reply_test
;
1097 info
->count
= ARRAY_SIZE( server_reply_test
);
1099 setup_test( info
, winhttp_send_request
, __LINE__
);
1100 ret
= WinHttpReceiveResponse( req
->request
, NULL
);
1101 ok(ret
, "failed to receive response %u\n", GetLastError());
1103 WaitForSingleObject( info
->wait
, INFINITE
);
1104 end_test( info
, __LINE__
);
1107 #define server_read_data(a) _server_read_data(a,__LINE__)
1108 static void _server_read_data(const char *expect_prefix
, unsigned int line
)
1113 size
= recv( server_socket
, buf
, sizeof(buf
), 0 );
1114 len
= strlen( expect_prefix
);
1115 ok_(__FILE__
,line
)(size
> len
, "data too short\n");
1119 ok_(__FILE__
,line
)(!strcmp( buf
, expect_prefix
), "unexpected data \"%s\"\n", buf
);
1123 static const struct notification close_request_test
[] =
1125 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
1126 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
1127 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
}
1130 static const struct notification close_allow_connection_close_request_test
[] =
1132 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
, NF_ALLOW
},
1133 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
, NF_ALLOW
},
1134 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
1135 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
},
1136 { winhttp_close_handle
, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
, NF_SIGNAL
}
1139 static void close_request(struct test_request
*req
, struct info
*info
, BOOL allow_closing_connection
)
1143 if (allow_closing_connection
)
1145 info
->test
= close_allow_connection_close_request_test
;
1146 info
->count
= ARRAY_SIZE( close_allow_connection_close_request_test
);
1150 info
->test
= close_request_test
;
1151 info
->count
= ARRAY_SIZE( close_request_test
);
1154 setup_test( info
, winhttp_close_handle
, __LINE__
);
1156 ret
= WinHttpCloseHandle( req
->request
);
1157 ok(ret
, "WinHttpCloseHandle failed: %u\n", GetLastError());
1158 ret
= WinHttpCloseHandle( req
->connection
);
1159 ok(ret
, "WinHttpCloseHandle failed: %u\n", GetLastError());
1160 ret
= WinHttpCloseHandle( req
->session
);
1161 ok(ret
, "WinHttpCloseHandle failed: %u\n", GetLastError());
1163 WaitForSingleObject( info
->wait
, INFINITE
);
1164 end_test( info
, __LINE__
);
1167 static const struct notification read_test
[] =
1169 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
, NF_ALLOW
},
1170 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
, NF_ALLOW
},
1171 { winhttp_read_data
, WINHTTP_CALLBACK_STATUS_READ_COMPLETE
, NF_SIGNAL
}
1174 #define read_request_data(a,b,c) _read_request_data(a,b,c,__LINE__)
1175 static void _read_request_data(struct test_request
*req
, struct info
*info
, const char *expected_data
, unsigned line
)
1181 info
->test
= read_test
;
1182 info
->count
= ARRAY_SIZE( read_test
);
1185 setup_test( info
, winhttp_read_data
, line
);
1186 memset(buffer
, '?', sizeof(buffer
));
1187 ret
= WinHttpReadData( req
->request
, buffer
, sizeof(buffer
), NULL
);
1188 ok(ret
, "failed to read data %u\n", GetLastError());
1190 WaitForSingleObject( info
->wait
, INFINITE
);
1192 len
= strlen(expected_data
);
1193 ok(!memcmp(buffer
, expected_data
, len
), "unexpected data\n");
1196 static void test_persistent_connection(int port
)
1198 struct test_request req
;
1201 trace("Testing persistent connection...\n");
1203 info
.wait
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
1205 open_socket_request( port
, &req
, &info
);
1206 server_send_reply( &req
, &info
,
1207 "HTTP/1.1 200 OK\r\n"
1208 "Server: winetest\r\n"
1209 "Connection: keep-alive\r\n"
1210 "Content-Length: 1\r\n"
1213 read_request_data( &req
, &info
, "X" );
1214 close_request( &req
, &info
, FALSE
);
1216 /* chunked connection test */
1217 open_async_request( port
, &req
, &info
, L
"/test", TRUE
);
1218 server_read_data( "GET /test HTTP/1.1\r\n" );
1219 server_send_reply( &req
, &info
,
1220 "HTTP/1.1 200 OK\r\n"
1221 "Server: winetest\r\n"
1222 "Transfer-Encoding: chunked\r\n"
1223 "Connection: keep-alive\r\n"
1225 "9\r\n123456789\r\n"
1227 read_request_data( &req
, &info
, "123456789" );
1228 close_request( &req
, &info
, FALSE
);
1230 /* HTTP/1.1 connections are persistent by default, no additional header is needed */
1231 open_async_request( port
, &req
, &info
, L
"/test", TRUE
);
1232 server_read_data( "GET /test HTTP/1.1\r\n" );
1233 server_send_reply( &req
, &info
,
1234 "HTTP/1.1 200 OK\r\n"
1235 "Server: winetest\r\n"
1236 "Content-Length: 2\r\n"
1239 read_request_data( &req
, &info
, "xx" );
1240 close_request( &req
, &info
, FALSE
);
1242 open_async_request( port
, &req
, &info
, L
"/test", TRUE
);
1243 server_read_data( "GET /test HTTP/1.1\r\n" );
1244 server_send_reply( &req
, &info
,
1245 "HTTP/1.1 200 OK\r\n"
1246 "Server: winetest\r\n"
1247 "Content-Length: 2\r\n"
1248 "Connection: close\r\n"
1251 read_request_data( &req
, &info
, "yy" );
1252 close_request( &req
, &info
, TRUE
);
1254 SetEvent( server_socket_done
);
1255 CloseHandle( info
.wait
);
1258 struct test_recursion_context
1262 LONG recursion_count
, max_recursion_query
, max_recursion_read
;
1263 BOOL read_from_callback
;
1264 BOOL have_sync_callback
;
1267 /* The limit is 128 before Win7 and 3 on newer Windows. */
1268 #define TEST_RECURSION_LIMIT 128
1270 static void CALLBACK
test_recursion_callback( HINTERNET handle
, DWORD_PTR context_ptr
,
1271 DWORD status
, void *buffer
, DWORD buflen
)
1273 struct test_recursion_context
*context
= (struct test_recursion_context
*)context_ptr
;
1280 case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
:
1281 case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
:
1282 SetEvent( context
->wait
);
1285 case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE
:
1286 if (!context
->read_from_callback
)
1288 SetEvent( context
->wait
);
1292 if (!*(DWORD
*)buffer
)
1294 SetEvent( context
->wait
);
1298 ok(context
->recursion_count
< TEST_RECURSION_LIMIT
,
1299 "Got unexpected context->recursion_count %u, thread %#x.\n",
1300 context
->recursion_count
, GetCurrentThreadId());
1301 context
->max_recursion_query
= max( context
->max_recursion_query
, context
->recursion_count
);
1302 InterlockedIncrement( &context
->recursion_count
);
1303 ret
= WinHttpReadData( context
->request
, &b
, 1, NULL
);
1304 err
= GetLastError();
1305 ok(ret
, "Failed to read data, GetLastError() %u.\n", err
);
1306 ok(err
== ERROR_SUCCESS
|| err
== ERROR_IO_PENDING
, "Got unexpected err %u.\n", err
);
1307 if (err
== ERROR_SUCCESS
)
1308 context
->have_sync_callback
= TRUE
;
1309 InterlockedDecrement( &context
->recursion_count
);
1312 case WINHTTP_CALLBACK_STATUS_READ_COMPLETE
:
1315 SetEvent( context
->wait
);
1318 ok(context
->recursion_count
< TEST_RECURSION_LIMIT
,
1319 "Got unexpected context->recursion_count %u, thread %#x.\n",
1320 context
->recursion_count
, GetCurrentThreadId());
1321 context
->max_recursion_read
= max( context
->max_recursion_read
, context
->recursion_count
);
1322 context
->read_from_callback
= TRUE
;
1323 InterlockedIncrement( &context
->recursion_count
);
1324 ret
= WinHttpQueryDataAvailable( context
->request
, NULL
);
1325 err
= GetLastError();
1326 ok(ret
, "Failed to query data available, GetLastError() %u.\n", err
);
1327 ok(err
== ERROR_SUCCESS
|| err
== ERROR_IO_PENDING
, "Got unexpected err %u.\n", err
);
1328 if (err
== ERROR_SUCCESS
)
1329 context
->have_sync_callback
= TRUE
;
1330 InterlockedDecrement( &context
->recursion_count
);
1335 static void test_recursion(void)
1337 struct test_recursion_context context
;
1338 HANDLE session
, connection
, request
;
1339 DWORD size
, status
, err
;
1343 memset( &context
, 0, sizeof(context
) );
1345 context
.wait
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
);
1347 session
= WinHttpOpen( L
"winetest", 0, NULL
, NULL
, WINHTTP_FLAG_ASYNC
);
1348 ok(!!session
, "Failed to open session, GetLastError() %u.\n", GetLastError());
1350 WinHttpSetStatusCallback( session
, test_recursion_callback
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
1352 connection
= WinHttpConnect( session
, L
"test.winehq.org", 0, 0 );
1353 ok(!!connection
, "Failed to open a connection, GetLastError() %u.\n", GetLastError());
1355 request
= WinHttpOpenRequest( connection
, NULL
, L
"/tests/hello.html", NULL
, NULL
, NULL
, 0 );
1356 ok(!!request
, "Failed to open a request, GetLastError() %u.\n", GetLastError());
1358 context
.request
= request
;
1359 ret
= WinHttpSendRequest( request
, NULL
, 0, NULL
, 0, 0, (DWORD_PTR
)&context
);
1360 err
= GetLastError();
1361 if (!ret
&& (err
== ERROR_WINHTTP_CANNOT_CONNECT
|| err
== ERROR_WINHTTP_TIMEOUT
))
1363 skip("Connection failed, skipping\n");
1364 WinHttpSetStatusCallback( session
, NULL
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
1365 WinHttpCloseHandle( request
);
1366 WinHttpCloseHandle( connection
);
1367 WinHttpCloseHandle( session
);
1368 CloseHandle( context
.wait
);
1371 ok(ret
, "Failed to send request, GetLastError() %u.\n", GetLastError());
1373 WaitForSingleObject( context
.wait
, INFINITE
);
1375 ret
= WinHttpReceiveResponse( request
, NULL
);
1376 ok(ret
, "Failed to receive response, GetLastError() %u.\n", GetLastError());
1378 WaitForSingleObject( context
.wait
, INFINITE
);
1380 size
= sizeof(status
);
1381 ret
= WinHttpQueryHeaders( request
, WINHTTP_QUERY_STATUS_CODE
| WINHTTP_QUERY_FLAG_NUMBER
, NULL
,
1382 &status
, &size
, NULL
);
1383 ok(ret
, "Request failed, GetLastError() %u.\n", GetLastError());
1384 ok(status
== 200, "Request failed unexpectedly, status %u.\n", status
);
1386 ret
= WinHttpQueryDataAvailable( request
, NULL
);
1387 ok(ret
, "Failed to query data available, GetLastError() %u.\n", GetLastError());
1389 WaitForSingleObject( context
.wait
, INFINITE
);
1391 ret
= WinHttpReadData( request
, &b
, 1, NULL
);
1392 ok(ret
, "Failed to read data, GetLastError() %u.\n", GetLastError());
1394 WaitForSingleObject( context
.wait
, INFINITE
);
1395 if (context
.have_sync_callback
)
1397 ok(context
.max_recursion_query
>= 2, "Got unexpected max_recursion_query %u.\n", context
.max_recursion_query
);
1398 ok(context
.max_recursion_read
>= 2, "Got unexpected max_recursion_read %u.\n", context
.max_recursion_read
);
1402 skip("No sync callbacks.\n");
1405 WinHttpSetStatusCallback( session
, NULL
, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
, 0 );
1407 WinHttpCloseHandle( request
);
1408 WinHttpCloseHandle( connection
);
1409 WinHttpCloseHandle( session
);
1410 CloseHandle( context
.wait
);
1413 START_TEST (notification
)
1415 HMODULE mod
= GetModuleHandleA( "winhttp.dll" );
1416 struct server_info si
;
1420 pWinHttpWebSocketClose
= (void *)GetProcAddress( mod
, "WinHttpWebSocketClose" );
1421 pWinHttpWebSocketCompleteUpgrade
= (void *)GetProcAddress( mod
, "WinHttpWebSocketCompleteUpgrade" );
1422 pWinHttpWebSocketQueryCloseStatus
= (void *)GetProcAddress( mod
, "WinHttpWebSocketQueryCloseStatus" );
1423 pWinHttpWebSocketReceive
= (void *)GetProcAddress( mod
, "WinHttpWebSocketReceive" );
1424 pWinHttpWebSocketSend
= (void *)GetProcAddress( mod
, "WinHttpWebSocketSend" );
1425 pWinHttpWebSocketShutdown
= (void *)GetProcAddress( mod
, "WinHttpWebSocketShutdown" );
1427 test_connection_cache();
1430 test_websocket( FALSE
);
1431 winetest_push_context( "secure" );
1432 test_websocket( TRUE
);
1433 winetest_pop_context();
1436 si
.event
= CreateEventW( NULL
, 0, 0, NULL
);
1439 thread
= CreateThread( NULL
, 0, server_thread
, &si
, 0, NULL
);
1440 ok(thread
!= NULL
, "failed to create thread %u\n", GetLastError());
1442 server_socket_available
= CreateEventW( NULL
, 0, 0, NULL
);
1443 server_socket_done
= CreateEventW( NULL
, 0, 0, NULL
);
1445 ret
= WaitForSingleObject( si
.event
, 10000 );
1446 ok(ret
== WAIT_OBJECT_0
, "failed to start winhttp test server %u\n", GetLastError());
1447 if (ret
!= WAIT_OBJECT_0
)
1449 CloseHandle(thread
);
1453 test_persistent_connection( si
.port
);
1455 /* send the basic request again to shutdown the server thread */
1456 test_basic_request( si
.port
, NULL
, L
"/quit" );
1458 WaitForSingleObject( thread
, 3000 );
1459 CloseHandle( thread
);
1460 CloseHandle( server_socket_available
);
1461 CloseHandle( server_socket_done
);