ReactOS  0.4.12-dev-375-g61fed54
notification.c
Go to the documentation of this file.
1 /*
2  * test status notifications
3  *
4  * Copyright 2008 Hans Leidekker for CodeWeavers
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <windef.h>
24 #include <winbase.h>
25 #include <winsock2.h>
26 #include <ws2tcpip.h>
27 #include <winhttp.h>
28 
29 #include "wine/test.h"
30 
31 static const WCHAR user_agent[] = {'w','i','n','e','t','e','s','t',0};
32 static const WCHAR test_winehq[] = {'t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',0};
33 static const WCHAR tests_hello_html[] = {'/','t','e','s','t','s','/','h','e','l','l','o','.','h','t','m','l',0};
34 static const WCHAR tests_redirect[] = {'/','t','e','s','t','s','/','r','e','d','i','r','e','c','t',0};
35 static const WCHAR localhostW[] = {'l','o','c','a','l','h','o','s','t',0};
36 
37 enum api
38 {
47 };
48 
50 {
51  enum api function; /* api responsible for notification */
52  unsigned int status; /* status received */
53  DWORD flags; /* a combination of NF_* flags */
54 };
55 
56 #define NF_ALLOW 0x0001 /* notification may or may not happen */
57 #define NF_WINE_ALLOW 0x0002 /* wine sends notification when it should not */
58 #define NF_SIGNAL 0x0004 /* signal wait handle when notified */
59 
60 struct info
61 {
62  enum api function;
63  const struct notification *test;
64  unsigned int count;
65  unsigned int index;
67  unsigned int line;
68 };
69 
71 {
75 };
76 
78 {
79  BOOL status_ok, function_ok;
80  struct info *info = (struct info *)context;
81 
83  {
84  DWORD size = sizeof(struct info *);
86  }
87  while (info->index < info->count && info->test[info->index].status != status && (info->test[info->index].flags & NF_ALLOW))
88  info->index++;
89  while (info->index < info->count && (info->test[info->index].flags & NF_WINE_ALLOW))
90  {
91  todo_wine ok(info->test[info->index].status != status, "unexpected %x notification\n", status);
92  if (info->test[info->index].status == status) break;
93  info->index++;
94  }
95  ok(info->index < info->count, "%u: unexpected notification 0x%08x\n", info->line, status);
96  if (info->index >= info->count) return;
97 
98  status_ok = (info->test[info->index].status == status);
99  function_ok = (info->test[info->index].function == info->function);
100  ok(status_ok, "%u: expected status 0x%08x got 0x%08x\n", info->line, info->test[info->index].status, status);
101  ok(function_ok, "%u: expected function %u got %u\n", info->line, info->test[info->index].function, info->function);
102 
103  if (status_ok && function_ok && info->test[info->index++].flags & NF_SIGNAL)
104  {
105  SetEvent( info->wait );
106  }
107 }
108 
109 static const struct notification cache_test[] =
110 {
161 };
162 
163 static void setup_test( struct info *info, enum api function, unsigned int line )
164 {
165  if (info->wait) ResetEvent( info->wait );
166  info->function = function;
167  info->line = line;
168  while (info->index < info->count && info->test[info->index].function != function
169  && (info->test[info->index].flags & (NF_ALLOW | NF_WINE_ALLOW)))
170  info->index++;
171  ok_(__FILE__,line)(info->test[info->index].function == function,
172  "unexpected function %u, expected %u. probably some notifications were missing\n",
173  info->test[info->index].function, function);
174 }
175 
176 static void end_test( struct info *info, unsigned int line )
177 {
178  ok_(__FILE__,line)(info->index == info->count, "some notifications were missing: %x\n",
179  info->test[info->index].status);
180 }
181 
182 static void test_connection_cache( void )
183 {
184  HANDLE ses, con, req, event;
185  DWORD size, status, err;
186  BOOL ret, unload = TRUE;
187  struct info info, *context = &info;
188 
189  info.test = cache_test;
190  info.count = sizeof(cache_test) / sizeof(cache_test[0]);
191  info.index = 0;
193 
194  ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 );
195  ok(ses != NULL, "failed to open session %u\n", GetLastError());
196 
197  event = CreateEventW( NULL, FALSE, FALSE, NULL );
199  if (!ret)
200  {
201  win_skip("Unload event not supported\n");
202  unload = FALSE;
203  }
204 
206 
207  ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
208  ok(ret, "failed to set context value %u\n", GetLastError());
209 
210  setup_test( &info, winhttp_connect, __LINE__ );
211  con = WinHttpConnect( ses, test_winehq, 0, 0 );
212  ok(con != NULL, "failed to open a connection %u\n", GetLastError());
213 
214  setup_test( &info, winhttp_open_request, __LINE__ );
215  req = WinHttpOpenRequest( con, NULL, tests_hello_html, NULL, NULL, NULL, 0 );
216  ok(req != NULL, "failed to open a request %u\n", GetLastError());
217 
218  setup_test( &info, winhttp_send_request, __LINE__ );
219  ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
220  err = GetLastError();
222  {
223  skip("connection failed, skipping\n");
224  goto done;
225  }
226  ok(ret, "failed to send request %u\n", GetLastError());
227 
229  ret = WinHttpReceiveResponse( req, NULL );
230  ok(ret, "failed to receive response %u\n", GetLastError());
231 
232  size = sizeof(status);
234  ok(ret, "failed unexpectedly %u\n", GetLastError());
235  ok(status == 200, "request failed unexpectedly %u\n", status);
236 
237  ResetEvent( info.wait );
238  setup_test( &info, winhttp_close_handle, __LINE__ );
239  WinHttpCloseHandle( req );
241 
242  setup_test( &info, winhttp_open_request, __LINE__ );
243  req = WinHttpOpenRequest( con, NULL, tests_hello_html, NULL, NULL, NULL, 0 );
244  ok(req != NULL, "failed to open a request %u\n", GetLastError());
245 
246  ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
247  ok(ret, "failed to set context value %u\n", GetLastError());
248 
249  setup_test( &info, winhttp_send_request, __LINE__ );
250  ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
251  err = GetLastError();
253  {
254  skip("connection failed, skipping\n");
255  goto done;
256  }
257  ok(ret, "failed to send request %u\n", GetLastError());
258 
260  ret = WinHttpReceiveResponse( req, NULL );
261  ok(ret, "failed to receive response %u\n", GetLastError());
262 
263  size = sizeof(status);
265  ok(ret, "failed unexpectedly %u\n", GetLastError());
266  ok(status == 200, "request failed unexpectedly %u\n", status);
267 
268  ResetEvent( info.wait );
269  setup_test( &info, winhttp_close_handle, __LINE__ );
270  WinHttpCloseHandle( req );
271  WinHttpCloseHandle( req );
272  WinHttpCloseHandle( con );
274 
275  if (unload)
276  {
278  ok(status == WAIT_TIMEOUT, "got %08x\n", status);
279  }
280 
281  setup_test( &info, winhttp_close_handle, __LINE__ );
282  WinHttpCloseHandle( ses );
284 
285  if (unload)
286  {
287  status = WaitForSingleObject( event, 100 );
288  ok(status == WAIT_OBJECT_0, "got %08x\n", status);
289  }
290 
291 
292  ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 );
293  ok(ses != NULL, "failed to open session %u\n", GetLastError());
294 
295  if (unload)
296  {
298  ok(ret, "failed to set unload option\n");
299  }
300 
302 
303  ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
304  ok(ret, "failed to set context value %u\n", GetLastError());
305 
306  setup_test( &info, winhttp_connect, __LINE__ );
307  con = WinHttpConnect( ses, test_winehq, 0, 0 );
308  ok(con != NULL, "failed to open a connection %u\n", GetLastError());
309 
310  setup_test( &info, winhttp_open_request, __LINE__ );
311  req = WinHttpOpenRequest( con, NULL, tests_hello_html, NULL, NULL, NULL, 0 );
312  ok(req != NULL, "failed to open a request %u\n", GetLastError());
313 
314  ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
315  ok(ret, "failed to set context value %u\n", GetLastError());
316 
317  setup_test( &info, winhttp_send_request, __LINE__ );
318  ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
319  err = GetLastError();
321  {
322  skip("connection failed, skipping\n");
323  goto done;
324  }
325  ok(ret, "failed to send request %u\n", GetLastError());
326 
328  ret = WinHttpReceiveResponse( req, NULL );
329  ok(ret, "failed to receive response %u\n", GetLastError());
330 
331  size = sizeof(status);
333  ok(ret, "failed unexpectedly %u\n", GetLastError());
334  ok(status == 200, "request failed unexpectedly %u\n", status);
335 
336  ResetEvent( info.wait );
337  setup_test( &info, winhttp_close_handle, __LINE__ );
338  WinHttpCloseHandle( req );
340 
341  setup_test( &info, winhttp_open_request, __LINE__ );
342  req = WinHttpOpenRequest( con, NULL, tests_hello_html, NULL, NULL, NULL, 0 );
343  ok(req != NULL, "failed to open a request %u\n", GetLastError());
344 
345  ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
346  ok(ret, "failed to set context value %u\n", GetLastError());
347 
348  setup_test( &info, winhttp_send_request, __LINE__ );
349  ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
350  err = GetLastError();
352  {
353  skip("connection failed, skipping\n");
354  goto done;
355  }
356  ok(ret, "failed to send request %u\n", GetLastError());
357 
359  ret = WinHttpReceiveResponse( req, NULL );
360  ok(ret, "failed to receive response %u\n", GetLastError());
361 
362  size = sizeof(status);
364  ok(ret, "failed unexpectedly %u\n", GetLastError());
365  ok(status == 200, "request failed unexpectedly %u\n", status);
366 
367  setup_test( &info, winhttp_close_handle, __LINE__ );
368 done:
369  WinHttpCloseHandle( req );
370  WinHttpCloseHandle( con );
372 
373  if (unload)
374  {
376  ok(status == WAIT_TIMEOUT, "got %08x\n", status);
377  }
378 
379  setup_test( &info, winhttp_close_handle, __LINE__ );
380  WinHttpCloseHandle( ses );
382  CloseHandle( info.wait );
383  end_test( &info, __LINE__ );
384 
385  if (unload)
386  {
387  status = WaitForSingleObject( event, 100 );
388  ok(status == WAIT_OBJECT_0, "got %08x\n", status);
389  }
390 
391  CloseHandle( event );
392 }
393 
394 static const struct notification redirect_test[] =
395 {
420 };
421 
422 static void test_redirect( void )
423 {
424  HANDLE ses, con, req;
425  DWORD size, status, err;
426  BOOL ret;
427  struct info info, *context = &info;
428 
430  info.count = sizeof(redirect_test) / sizeof(redirect_test[0]);
431  info.index = 0;
433 
434  ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 );
435  ok(ses != NULL, "failed to open session %u\n", GetLastError());
436 
438 
439  ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
440  ok(ret, "failed to set context value %u\n", GetLastError());
441 
442  setup_test( &info, winhttp_connect, __LINE__ );
443  con = WinHttpConnect( ses, test_winehq, 0, 0 );
444  ok(con != NULL, "failed to open a connection %u\n", GetLastError());
445 
446  setup_test( &info, winhttp_open_request, __LINE__ );
447  req = WinHttpOpenRequest( con, NULL, tests_redirect, NULL, NULL, NULL, 0 );
448  ok(req != NULL, "failed to open a request %u\n", GetLastError());
449 
450  setup_test( &info, winhttp_send_request, __LINE__ );
451  ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
452  err = GetLastError();
454  {
455  skip("connection failed, skipping\n");
456  goto done;
457  }
458  ok(ret, "failed to send request %u\n", GetLastError());
459 
461  ret = WinHttpReceiveResponse( req, NULL );
462  ok(ret, "failed to receive response %u\n", GetLastError());
463 
464  size = sizeof(status);
466  ok(ret, "failed unexpectedly %u\n", GetLastError());
467  ok(status == 200, "request failed unexpectedly %u\n", status);
468 
469  setup_test( &info, winhttp_close_handle, __LINE__ );
470 done:
471  WinHttpCloseHandle( req );
472  WinHttpCloseHandle( con );
473  WinHttpCloseHandle( ses );
475  CloseHandle( info.wait );
476  end_test( &info, __LINE__ );
477 }
478 
479 static const struct notification async_test[] =
480 {
500 };
501 
502 static void test_async( void )
503 {
504  HANDLE ses, con, req, event;
505  DWORD size, status, err;
506  BOOL ret, unload = TRUE;
507  struct info info, *context = &info;
508  char buffer[1024];
509 
510  info.test = async_test;
511  info.count = sizeof(async_test) / sizeof(async_test[0]);
512  info.index = 0;
514 
516  ok(ses != NULL, "failed to open session %u\n", GetLastError());
517 
518  event = CreateEventW( NULL, FALSE, FALSE, NULL );
520  if (!ret)
521  {
522  win_skip("Unload event not supported\n");
523  unload = FALSE;
524  }
525 
526  SetLastError( 0xdeadbeef );
528  err = GetLastError();
529  ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
530 
531  SetLastError( 0xdeadbeef );
532  ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
533  err = GetLastError();
534  ok(ret, "failed to set context value %u\n", err);
535  ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
536 
537  setup_test( &info, winhttp_connect, __LINE__ );
538  SetLastError( 0xdeadbeef );
539  con = WinHttpConnect( ses, test_winehq, 0, 0 );
540  err = GetLastError();
541  ok(con != NULL, "failed to open a connection %u\n", err);
542  ok(err == ERROR_SUCCESS || broken(err == WSAEINVAL) /* < win7 */, "got %u\n", err);
543 
544  setup_test( &info, winhttp_open_request, __LINE__ );
545  SetLastError( 0xdeadbeef );
546  req = WinHttpOpenRequest( con, NULL, tests_hello_html, NULL, NULL, NULL, 0 );
547  err = GetLastError();
548  ok(req != NULL, "failed to open a request %u\n", err);
549  ok(err == ERROR_SUCCESS, "got %u\n", err);
550 
551  setup_test( &info, winhttp_send_request, __LINE__ );
552  SetLastError( 0xdeadbeef );
553  ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
554  err = GetLastError();
556  {
557  skip("connection failed, skipping\n");
558  WinHttpCloseHandle( req );
559  WinHttpCloseHandle( con );
560  WinHttpCloseHandle( ses );
561  CloseHandle( info.wait );
562  return;
563  }
564  ok(ret, "failed to send request %u\n", err);
565  ok(err == ERROR_SUCCESS, "got %u\n", err);
566 
568 
570  SetLastError( 0xdeadbeef );
571  ret = WinHttpReceiveResponse( req, NULL );
572  err = GetLastError();
573  ok(ret, "failed to receive response %u\n", err);
574  ok(err == ERROR_SUCCESS, "got %u\n", err);
575 
577 
578  size = sizeof(status);
579  SetLastError( 0xdeadbeef );
581  err = GetLastError();
582  ok(ret, "failed unexpectedly %u\n", err);
583  ok(status == 200, "request failed unexpectedly %u\n", status);
584  ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
585 
586  setup_test( &info, winhttp_query_data, __LINE__ );
587  SetLastError( 0xdeadbeef );
589  err = GetLastError();
590  ok(ret, "failed to query data available %u\n", err);
591  ok(err == ERROR_SUCCESS || err == ERROR_IO_PENDING || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err);
592 
594 
595  setup_test( &info, winhttp_read_data, __LINE__ );
596  ret = WinHttpReadData( req, buffer, sizeof(buffer), NULL );
597  ok(ret, "failed to read data %u\n", err);
598 
600 
601  setup_test( &info, winhttp_close_handle, __LINE__ );
602  WinHttpCloseHandle( req );
603  WinHttpCloseHandle( con );
604 
605  if (unload)
606  {
608  ok(status == WAIT_TIMEOUT, "got %08x\n", status);
609  }
610  WinHttpCloseHandle( ses );
612  end_test( &info, __LINE__ );
613 
614  if (unload)
615  {
616  status = WaitForSingleObject( event, 2000 );
617  ok(status == WAIT_OBJECT_0, "got %08x\n", status);
618  }
619  CloseHandle( event );
620  CloseHandle( info.wait );
621  end_test( &info, __LINE__ );
622 }
623 
624 static const char okmsg[] =
625 "HTTP/1.1 200 OK\r\n"
626 "Server: winetest\r\n"
627 "\r\n";
628 
629 static const char page1[] =
630 "<HTML>\r\n"
631 "<HEAD><TITLE>winhttp test page</TITLE></HEAD>\r\n"
632 "<BODY>The quick brown fox jumped over the lazy dog<P></BODY>\r\n"
633 "</HTML>\r\n\r\n";
634 
635 struct server_info
636 {
638  int port;
639 };
640 
641 static int server_socket;
643 
645 {
646  struct server_info *si = param;
647  int r, c = -1, i, on;
648  SOCKET s;
649  struct sockaddr_in sa;
650  char buffer[0x100];
651  WSADATA wsaData;
652  int last_request = 0;
653 
654  WSAStartup(MAKEWORD(1,1), &wsaData);
655 
656  s = socket(AF_INET, SOCK_STREAM, 0);
657  if (s == INVALID_SOCKET)
658  return 1;
659 
660  on = 1;
661  setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof on);
662 
663  memset(&sa, 0, sizeof sa);
664  sa.sin_family = AF_INET;
665  sa.sin_port = htons(si->port);
666  sa.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
667 
668  r = bind(s, (struct sockaddr *)&sa, sizeof(sa));
669  if (r < 0)
670  return 1;
671 
672  listen(s, 0);
673  SetEvent(si->event);
674  do
675  {
676  if (c == -1) c = accept(s, NULL, NULL);
677 
678  memset(buffer, 0, sizeof buffer);
679  for(i = 0; i < sizeof buffer - 1; i++)
680  {
681  r = recv(c, &buffer[i], 1, 0);
682  if (r != 1)
683  break;
684  if (i < 4) continue;
685  if (buffer[i - 2] == '\n' && buffer[i] == '\n' &&
686  buffer[i - 3] == '\r' && buffer[i - 1] == '\r')
687  break;
688  }
689  if (strstr(buffer, "GET /quit"))
690  {
691  send(c, okmsg, sizeof okmsg - 1, 0);
692  send(c, page1, sizeof page1 - 1, 0);
693  last_request = 1;
694  }
695  else if(strstr(buffer, "GET /socket"))
696  {
697  server_socket = c;
701  }
702  shutdown(c, 2);
703  closesocket(c);
704  c = -1;
705  } while (!last_request);
706 
707  closesocket(s);
708  return 0;
709 }
710 
711 static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
712 {
713  HINTERNET ses, con, req;
714  char buffer[0x100];
716  BOOL ret;
717 
719  ok(ses != NULL, "failed to open session %u\n", GetLastError());
720 
721  con = WinHttpConnect(ses, localhostW, port, 0);
722  ok(con != NULL, "failed to open a connection %u\n", GetLastError());
723 
724  req = WinHttpOpenRequest(con, verb, path, NULL, NULL, NULL, 0);
725  ok(req != NULL, "failed to open a request %u\n", GetLastError());
726 
727  ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
728  ok(ret, "failed to send request %u\n", GetLastError());
729 
731  ok(ret, "failed to receive response %u\n", GetLastError());
732 
733  status = 0xdeadbeef;
734  size = sizeof(status);
736  ok(ret, "failed to query status code %u\n", GetLastError());
737  ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status);
738 
739  count = 0;
740  memset(buffer, 0, sizeof(buffer));
741  ret = WinHttpReadData(req, buffer, sizeof buffer, &count);
742  ok(ret, "failed to read data %u\n", GetLastError());
743  ok(count == sizeof page1 - 1, "count was wrong\n");
744  ok(!memcmp(buffer, page1, sizeof page1), "http data wrong\n");
745 
746  WinHttpCloseHandle(req);
747  WinHttpCloseHandle(con);
748  WinHttpCloseHandle(ses);
749 }
750 
751 static const struct notification open_socket_request_test[] =
752 {
758  { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, NF_ALLOW }, /* some versions call it twice. why? */
763 };
764 
766 {
772 };
773 
774 static void open_async_request(int port, struct test_request *req, struct info *info, const WCHAR *path, BOOL reuse_connection)
775 {
776  BOOL ret;
777 
778  info->index = 0;
779  if (reuse_connection)
780  {
783  }
784  else
785  {
788  }
789 
791  ok(req->session != NULL, "failed to open session %u\n", GetLastError());
792 
793  WinHttpSetOption( req->session, WINHTTP_OPTION_CONTEXT_VALUE, &info, sizeof(struct info *) );
795 
796  setup_test( info, winhttp_connect, __LINE__ );
797  req->connection = WinHttpConnect( req->session, localhostW, port, 0 );
798  ok(req->connection != NULL, "failed to open a connection %u\n", GetLastError());
799 
800  setup_test( info, winhttp_open_request, __LINE__ );
801  req->request = WinHttpOpenRequest( req->connection, NULL, path, NULL, NULL, NULL, 0 );
802  ok(req->request != NULL, "failed to open a request %u\n", GetLastError());
803 
804  setup_test( info, winhttp_send_request, __LINE__ );
805  ret = WinHttpSendRequest( req->request, NULL, 0, NULL, 0, 0, 0 );
806  ok(ret, "failed to send request %u\n", GetLastError());
807 }
808 
809 static void open_socket_request(int port, struct test_request *req, struct info *info)
810 {
811  static const WCHAR socketW[] = {'/','s','o','c','k','e','t',0};
812 
814  open_async_request( port, req, info, socketW, FALSE );
816 }
817 
818 static const struct notification server_reply_test[] =
819 {
823 };
824 
825 static void server_send_reply(struct test_request *req, struct info *info, const char *msg)
826 {
827  BOOL ret;
828 
829  send( server_socket, msg, strlen( msg ), 0 );
831 
833  info->count = sizeof(server_reply_test) / sizeof(server_reply_test[0]);
834  info->index = 0;
835  setup_test( info, winhttp_send_request, __LINE__ );
837  ok(ret, "failed to receive response %u\n", GetLastError());
838 
840  end_test( info, __LINE__ );
841 }
842 
843 #define server_read_data(a) _server_read_data(a,__LINE__)
844 static void _server_read_data(const char *expect_prefix, unsigned int line)
845 {
846  char buf[1024];
847  DWORD size, len;
848 
849  size = recv( server_socket, buf, sizeof(buf), 0 );
850  len = strlen( expect_prefix );
851  ok_(__FILE__,line)(size > len, "data too short\n");
852  if (size >= len)
853  {
854  buf[len] = 0;
855  ok_(__FILE__,line)(!strcmp( buf, expect_prefix ), "unexpected data \"%s\"\n", buf);
856  }
857 }
858 
859 static const struct notification close_request_test[] =
860 {
864 };
865 
867 {
873 };
874 
875 static void close_request(struct test_request *req, struct info *info, BOOL allow_closing_connection)
876 {
877  BOOL ret;
878 
879  if (allow_closing_connection)
880  {
883  }
884  else
885  {
887  info->count = sizeof(close_request_test)/sizeof(*close_request_test);
888  }
889  info->index = 0;
890  setup_test( info, winhttp_close_handle, __LINE__ );
891 
892  ret = WinHttpCloseHandle( req->request );
893  ok(ret, "WinHttpCloseHandle failed: %u\n", GetLastError());
895  ok(ret, "WinHttpCloseHandle failed: %u\n", GetLastError());
896  ret = WinHttpCloseHandle( req->session );
897  ok(ret, "WinHttpCloseHandle failed: %u\n", GetLastError());
898 
900  end_test( info, __LINE__ );
901 }
902 
903 static const struct notification read_test[] =
904 {
908 };
909 
910 static const struct notification read_allow_close_test[] =
911 {
917 };
918 
919 #define read_request_data(a,b,c,d) _read_request_data(a,b,c,d,__LINE__)
920 static void _read_request_data(struct test_request *req, struct info *info, const char *expected_data, BOOL closing_connection, unsigned line)
921 {
922  char buffer[1024];
923  DWORD read, len;
924  BOOL ret;
925 
926  if (closing_connection)
927  {
930  }
931  else
932  {
933  info->test = read_test;
934  info->count = sizeof(read_test)/sizeof(*read_test);
935  }
936  info->index = 0;
937 
939  memset(buffer, '?', sizeof(buffer));
940  read = 0xdeadbeef;
941  ret = WinHttpReadData( req->request, buffer, sizeof(buffer), &read );
942  ok(ret, "failed to read data %u\n", GetLastError());
943 
945 
946  len = strlen(expected_data);
947  ok(!memcmp(buffer, expected_data, len), "unexpected data\n");
948 }
949 
951 {
952  struct test_request req;
953  struct info info;
954 
955  static const WCHAR testW[] = {'/','t','e','s','t',0};
956 
957  trace("Testing persistent connection...\n");
958 
960 
961  open_socket_request( port, &req, &info );
962  server_send_reply( &req, &info,
963  "HTTP/1.1 200 OK\r\n"
964  "Server: winetest\r\n"
965  "Connection: keep-alive\r\n"
966  "Content-Length: 1\r\n"
967  "\r\n"
968  "X" );
969  read_request_data( &req, &info, "X", FALSE );
970  close_request( &req, &info, FALSE );
971 
972  /* chunked connection test */
973  open_async_request( port, &req, &info, testW, TRUE );
974  server_read_data( "GET /test HTTP/1.1\r\n" );
975  server_send_reply( &req, &info,
976  "HTTP/1.1 200 OK\r\n"
977  "Server: winetest\r\n"
978  "Transfer-Encoding: chunked\r\n"
979  "Connection: keep-alive\r\n"
980  "\r\n"
981  "9\r\n123456789\r\n"
982  "0\r\n\r\n" );
983  read_request_data( &req, &info, "123456789", FALSE );
984  close_request( &req, &info, FALSE );
985 
986  /* HTTP/1.1 connections are persistent by default, no additional header is needed */
987  open_async_request( port, &req, &info, testW, TRUE );
988  server_read_data( "GET /test HTTP/1.1\r\n" );
989  server_send_reply( &req, &info,
990  "HTTP/1.1 200 OK\r\n"
991  "Server: winetest\r\n"
992  "Content-Length: 2\r\n"
993  "\r\n"
994  "xx" );
995  read_request_data( &req, &info, "xx", FALSE );
996  close_request( &req, &info, FALSE );
997 
998  open_async_request( port, &req, &info, testW, TRUE );
999  server_read_data( "GET /test HTTP/1.1\r\n" );
1000  server_send_reply( &req, &info,
1001  "HTTP/1.1 200 OK\r\n"
1002  "Server: winetest\r\n"
1003  "Content-Length: 2\r\n"
1004  "Connection: close\r\n"
1005  "\r\n"
1006  "yy" );
1007  close_request( &req, &info, TRUE );
1008 
1010  CloseHandle( info.wait );
1011 }
1012 
1014 {
1015  static const WCHAR quitW[] = {'/','q','u','i','t',0};
1016  struct server_info si;
1017  HANDLE thread;
1018  DWORD ret;
1019 
1021  test_redirect();
1022  test_async();
1023 
1024  si.event = CreateEventW( NULL, 0, 0, NULL );
1025  si.port = 7533;
1026 
1027  thread = CreateThread( NULL, 0, server_thread, (LPVOID)&si, 0, NULL );
1028  ok(thread != NULL, "failed to create thread %u\n", GetLastError());
1029 
1032 
1033  ret = WaitForSingleObject( si.event, 10000 );
1034  ok(ret == WAIT_OBJECT_0, "failed to start winhttp test server %u\n", GetLastError());
1035  if (ret != WAIT_OBJECT_0)
1036  {
1038  return;
1039  }
1040 
1041 #ifdef __REACTOS__
1043 {
1044  skip("Skipping test_persistent_connection due to hang. See ROSTESTS-295.\n");
1045 }
1046 else
1047 #endif
1048  test_persistent_connection( si.port );
1049 
1050  /* send the basic request again to shutdown the server thread */
1051  test_basic_request( si.port, NULL, quitW );
1052 
1053  WaitForSingleObject( thread, 3000 );
1054  CloseHandle( thread );
1057 }
HINTERNET WINAPI WinHttpConnect(HINTERNET hsession, LPCWSTR server, INTERNET_PORT port, DWORD reserved)
Definition: session.c:524
#define WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
Definition: winhttp.h:421
static const struct notification cache_test[]
Definition: notification.c:109
#define trace(...)
Definition: kmt_test.h:217
BOOL WINAPI WinHttpQueryOption(HINTERNET handle, DWORD option, LPVOID buffer, LPDWORD buflen)
Definition: session.c:1211
static const WCHAR localhostW[]
Definition: notification.c:35
#define TRUE
Definition: types.h:120
#define WINHTTP_CALLBACK_STATUS_RESOLVING_NAME
Definition: winhttp.h:380
api
Definition: notification.c:37
#define CloseHandle
Definition: compat.h:398
static void CALLBACK check_notification(HINTERNET handle, DWORD_PTR context, DWORD status, LPVOID buffer, DWORD buflen)
Definition: notification.c:77
BOOL WINAPI WinHttpCloseHandle(HINTERNET handle)
Definition: session.c:1153
SOCKET WSAAPI socket(IN INT af, IN INT type, IN INT protocol)
Definition: socklife.c:143
static const WCHAR tests_redirect[]
Definition: notification.c:34
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
static void close_request(struct test_request *req, struct info *info, BOOL allow_closing_connection)
Definition: notification.c:875
#define WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER
Definition: winhttp.h:382
#define inet_addr(cp)
Definition: inet.h:98
#define ERROR_SUCCESS
Definition: deptool.c:10
const struct notification * test
Definition: notification.c:63
static const struct notification close_allow_connection_close_request_test[]
Definition: notification.c:866
#define read_request_data(a, b, c, d)
Definition: notification.c:919
static const char page1[]
Definition: notification.c:629
#define WINHTTP_ACCESS_TYPE_NO_PROXY
Definition: winhttp.h:63
Definition: http.c:6587
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define MAKEWORD(a, b)
Definition: typedefs.h:247
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
static const WCHAR tests_hello_html[]
Definition: notification.c:33
#define ERROR_WINHTTP_TIMEOUT
Definition: winhttp.h:189
__wchar_t WCHAR
Definition: xmlstorage.h:180
INT WSAAPI bind(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: socklife.c:36
static void _server_read_data(const char *expect_prefix, unsigned int line)
Definition: notification.c:844
static void end_test(struct info *info, unsigned int line)
Definition: notification.c:176
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
#define WSAEINVAL
Definition: winerror.h:1946
#define NF_ALLOW
Definition: notification.c:56
GLuint GLuint GLsizei count
Definition: gl.h:1545
static void _read_request_data(struct test_request *req, struct info *info, const char *expected_data, BOOL closing_connection, unsigned line)
Definition: notification.c:920
HINTERNET connection
Definition: notification.c:73
static const struct notification read_test[]
Definition: notification.c:903
#define ERROR_WINHTTP_CANNOT_CONNECT
Definition: winhttp.h:201
static void setup_test(struct info *info, enum api function, unsigned int line)
Definition: notification.c:163
#define WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE
Definition: winhttp.h:386
#define CALLBACK
Definition: compat.h:27
START_TEST(notification)
#define WINHTTP_QUERY_STATUS_CODE
Definition: winhttp.h:317
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:679
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
GLuint buffer
Definition: glext.h:5915
int winetest_interactive
#define SOL_SOCKET
Definition: winsock.h:398
static void test_async(void)
Definition: notification.c:502
#define ERROR_IO_PENDING
Definition: dderror.h:15
#define WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER
Definition: winhttp.h:383
static void test_connection_cache(void)
Definition: notification.c:182
unsigned int count
Definition: notification.c:64
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:597
struct _test_info info[]
Definition: SetCursorPos.c:19
#define WINHTTP_CALLBACK_STATUS_REDIRECT
Definition: winhttp.h:393
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
GLenum GLclampf GLint i
Definition: glfuncs.h:14
BOOL WINAPI WinHttpQueryHeaders(HINTERNET hrequest, DWORD level, LPCWSTR name, LPVOID buffer, LPDWORD buflen, LPDWORD index)
Definition: request.c:831
#define closesocket
Definition: main.c:39
#define WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION
Definition: winhttp.h:388
static void test_redirect(void)
Definition: notification.c:422
#define WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
Definition: winhttp.h:401
static const WCHAR test_winehq[]
Definition: notification.c:32
static HANDLE server_socket_available
Definition: notification.c:642
#define NF_SIGNAL
Definition: notification.c:58
BOOL WINAPI WinHttpReceiveResponse(HINTERNET hrequest, LPVOID reserved)
Definition: request.c:2692
INT WSAAPI setsockopt(IN SOCKET s, IN INT level, IN INT optname, IN CONST CHAR FAR *optval, IN INT optlen)
Definition: sockctrl.c:421
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:112
INT WINAPI WSAStartup(IN WORD wVersionRequested, OUT LPWSADATA lpWSAData)
Definition: startup.c:113
UINT msg
Definition: msvc.h:92
smooth NULL
Definition: ftsmooth.c:416
#define SO_REUSEADDR
Definition: winsock.h:180
Definition: parser.c:48
HANDLE wait
Definition: notification.c:66
#define ok(value,...)
Definition: CComObject.cpp:34
static const WCHAR user_agent[]
Definition: notification.c:31
static const struct notification async_test[]
Definition: notification.c:479
unsigned int BOOL
Definition: ntddk_ex.h:94
#define WAIT_OBJECT_0
Definition: winbase.h:387
GLsizeiptr size
Definition: glext.h:5919
static void server_send_reply(struct test_request *req, struct info *info, const char *msg)
Definition: notification.c:825
#define INVALID_SOCKET
Definition: winsock.h:332
#define WINHTTP_CALLBACK_STATUS_HANDLE_CREATED
Definition: winhttp.h:390
static const char okmsg[]
Definition: notification.c:624
INT WSAAPI shutdown(IN SOCKET s, IN INT how)
Definition: sockctrl.c:506
#define WINHTTP_QUERY_FLAG_NUMBER
Definition: winhttp.h:377
INT WSAAPI send(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags)
Definition: send.c:23
static const struct notification read_allow_close_test[]
Definition: notification.c:910
#define WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE
Definition: winhttp.h:397
GLfloat param
Definition: glext.h:5796
const GLubyte * c
Definition: glext.h:8905
unsigned long DWORD
Definition: ntddk_ex.h:95
#define WINHTTP_OPTION_CONTEXT_VALUE
Definition: winhttp.h:112
#define HTTP_STATUS_OK
Definition: winhttp.h:240
#define SetLastError(x)
Definition: compat.h:409
static const struct notification close_request_test[]
Definition: notification.c:859
static DWORD CALLBACK server_thread(LPVOID param)
Definition: notification.c:644
static void open_async_request(int port, struct test_request *req, struct info *info, const WCHAR *path, BOOL reuse_connection)
Definition: notification.c:774
#define WAIT_TIMEOUT
Definition: dderror.h:14
WINHTTP_STATUS_CALLBACK WINAPI WinHttpSetStatusCallback(HINTERNET handle, WINHTTP_STATUS_CALLBACK callback, DWORD flags, DWORD_PTR reserved)
Definition: session.c:2022
static HANDLE thread
Definition: service.c:33
static void test_persistent_connection(int port)
Definition: notification.c:950
#define WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
Definition: winhttp.h:391
int ret
char line[200]
Definition: main.c:97
#define WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED
Definition: winhttp.h:387
#define todo_wine
Definition: test.h:154
HINTERNET session
Definition: notification.c:72
static HANDLE server_socket_done
Definition: notification.c:642
GLenum GLsizei len
Definition: glext.h:6722
unsigned int status
Definition: notification.c:52
GLdouble s
Definition: gl.h:2039
#define err(...)
#define WINHTTP_CALLBACK_STATUS_SENDING_REQUEST
Definition: winhttp.h:384
#define WINHTTP_CALLBACK_STATUS_READ_COMPLETE
Definition: winhttp.h:398
struct _cl_event * event
Definition: glext.h:7739
HINTERNET request
Definition: notification.c:74
uint32_t DWORD_PTR
Definition: typedefs.h:63
SOCKET WSAAPI accept(IN SOCKET s, OUT LPSOCKADDR addr, OUT INT FAR *addrlen)
Definition: socklife.c:23
BOOL WINAPI WinHttpSetOption(HINTERNET handle, DWORD option, LPVOID buffer, DWORD buflen)
Definition: session.c:1270
static const struct notification reuse_socket_request_test[]
Definition: notification.c:765
#define broken(x)
Definition: _sntprintf.h:21
#define NF_WINE_ALLOW
Definition: notification.c:57
HANDLE event
Definition: notification.c:637
#define server_read_data(a)
Definition: notification.c:843
static const struct notification redirect_test[]
Definition: notification.c:394
#define skip(...)
Definition: CString.cpp:57
enum api function
Definition: notification.c:62
Definition: services.c:325
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:660
INT WSAAPI listen(IN SOCKET s, IN INT backlog)
Definition: sockctrl.c:123
#define WINHTTP_CALLBACK_STATUS_REQUEST_SENT
Definition: winhttp.h:385
HINTERNET WINAPI WinHttpOpen(LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWSTR bypass, DWORD flags)
Definition: session.c:246
#define c
Definition: ke_i.h:80
#define AF_INET
Definition: tcpip.h:117
#define WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED
Definition: winhttp.h:389
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
Definition: winhttp.h:396
UINT_PTR SOCKET
Definition: winsock.h:47
#define WINHTTP_CALLBACK_STATUS_NAME_RESOLVED
Definition: winhttp.h:381
static const struct notification open_socket_request_test[]
Definition: notification.c:751
unsigned int line
Definition: notification.c:67
#define SOCK_STREAM
Definition: tcpip.h:118
static void open_socket_request(int port, struct test_request *req, struct info *info)
Definition: notification.c:809
#define htons(x)
Definition: module.h:213
#define WINHTTP_FLAG_ASYNC
Definition: winhttp.h:51
#define INFINITE
Definition: serial.h:102
static int server_socket
Definition: notification.c:641
HINTERNET WINAPI WinHttpOpenRequest(HINTERNET hconnect, LPCWSTR verb, LPCWSTR object, LPCWSTR version, LPCWSTR referrer, LPCWSTR *types, DWORD flags)
Definition: session.c:1061
USHORT port
Definition: uri.c:227
#define memset(x, y, z)
Definition: compat.h:39
static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path)
Definition: notification.c:711
static SERVICE_STATUS status
Definition: service.c:31
#define win_skip
Definition: test.h:141
BOOL WINAPI WinHttpSendRequest(HINTERNET hrequest, LPCWSTR headers, DWORD headers_len, LPVOID optional, DWORD optional_len, DWORD total_len, DWORD_PTR context)
Definition: request.c:2168
INT WSAAPI recv(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags)
Definition: recv.c:23
BOOL WINAPI WinHttpQueryDataAvailable(HINTERNET hrequest, LPDWORD available)
Definition: request.c:2763
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
static const WCHAR testW[]
Definition: jsregexp.c:44
BOOL WINAPI WinHttpReadData(HINTERNET hrequest, LPVOID buffer, DWORD to_read, LPDWORD read)
Definition: request.c:2811
static const struct notification server_reply_test[]
Definition: notification.c:818
_CRTIMP int __cdecl read(_In_ int _FileHandle, _Out_writes_bytes_(_MaxCharCount) void *_DstBuf, _In_ unsigned int _MaxCharCount)
unsigned int index
Definition: notification.c:65
#define WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT
Definition: winhttp.h:141
#define ok_(x1, x2)
Definition: CString.cpp:56
Definition: ps.c:97