ReactOS  0.4.14-dev-606-g14ebc0b
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;
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 
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;
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 
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  {
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 len;
924  BOOL ret;
925 
926  if (closing_connection)
927  {
930  }
931  else
932  {
933  info->test = read_test;
935  }
936  info->index = 0;
937 
939  memset(buffer, '?', sizeof(buffer));
940  ret = WinHttpReadData( req->request, buffer, sizeof(buffer), NULL );
941  ok(ret, "failed to read data %u\n", GetLastError());
942 
944 
945  len = strlen(expected_data);
946  ok(!memcmp(buffer, expected_data, len), "unexpected data\n");
947 }
948 
950 {
951  struct test_request req;
952  struct info info;
953 
954  static const WCHAR testW[] = {'/','t','e','s','t',0};
955 
956  trace("Testing persistent connection...\n");
957 
959 
960  open_socket_request( port, &req, &info );
961  server_send_reply( &req, &info,
962  "HTTP/1.1 200 OK\r\n"
963  "Server: winetest\r\n"
964  "Connection: keep-alive\r\n"
965  "Content-Length: 1\r\n"
966  "\r\n"
967  "X" );
968  read_request_data( &req, &info, "X", FALSE );
969  close_request( &req, &info, FALSE );
970 
971  /* chunked connection test */
972  open_async_request( port, &req, &info, testW, TRUE );
973  server_read_data( "GET /test HTTP/1.1\r\n" );
974  server_send_reply( &req, &info,
975  "HTTP/1.1 200 OK\r\n"
976  "Server: winetest\r\n"
977  "Transfer-Encoding: chunked\r\n"
978  "Connection: keep-alive\r\n"
979  "\r\n"
980  "9\r\n123456789\r\n"
981  "0\r\n\r\n" );
982  read_request_data( &req, &info, "123456789", FALSE );
983  close_request( &req, &info, FALSE );
984 
985  /* HTTP/1.1 connections are persistent by default, no additional header is needed */
986  open_async_request( port, &req, &info, testW, TRUE );
987  server_read_data( "GET /test HTTP/1.1\r\n" );
988  server_send_reply( &req, &info,
989  "HTTP/1.1 200 OK\r\n"
990  "Server: winetest\r\n"
991  "Content-Length: 2\r\n"
992  "\r\n"
993  "xx" );
994  read_request_data( &req, &info, "xx", FALSE );
995  close_request( &req, &info, FALSE );
996 
997  open_async_request( port, &req, &info, testW, TRUE );
998  server_read_data( "GET /test HTTP/1.1\r\n" );
999  server_send_reply( &req, &info,
1000  "HTTP/1.1 200 OK\r\n"
1001  "Server: winetest\r\n"
1002  "Content-Length: 2\r\n"
1003  "Connection: close\r\n"
1004  "\r\n"
1005  "yy" );
1006  close_request( &req, &info, TRUE );
1007 
1009  CloseHandle( info.wait );
1010 }
1011 
1013 {
1014  static const WCHAR quitW[] = {'/','q','u','i','t',0};
1015  struct server_info si;
1016  HANDLE thread;
1017  DWORD ret;
1018 
1020  test_redirect();
1021  test_async();
1022 
1023  si.event = CreateEventW( NULL, 0, 0, NULL );
1024  si.port = 7533;
1025 
1026  thread = CreateThread( NULL, 0, server_thread, &si, 0, NULL );
1027  ok(thread != NULL, "failed to create thread %u\n", GetLastError());
1028 
1031 
1032  ret = WaitForSingleObject( si.event, 10000 );
1033  ok(ret == WAIT_OBJECT_0, "failed to start winhttp test server %u\n", GetLastError());
1034  if (ret != WAIT_OBJECT_0)
1035  {
1037  return;
1038  }
1039 
1040 #ifdef __REACTOS__
1042 {
1043  skip("Skipping test_persistent_connection due to hang. See ROSTESTS-295.\n");
1044 }
1045 else
1046 {
1048 }
1049 #else
1051 #endif
1052 
1053  /* send the basic request again to shutdown the server thread */
1054  test_basic_request( si.port, NULL, quitW );
1055 
1056  WaitForSingleObject( thread, 3000 );
1057  CloseHandle( thread );
1060 }
HINTERNET WINAPI WinHttpConnect(HINTERNET hsession, LPCWSTR server, INTERNET_PORT port, DWORD reserved)
Definition: session.c:533
#define WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS
Definition: winhttp.h:421
static const struct notification cache_test[]
Definition: notification.c:109
BOOL WINAPI WinHttpQueryOption(HINTERNET handle, DWORD option, LPVOID buffer, LPDWORD buflen)
Definition: session.c:1245
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:406
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:1187
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:7098
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
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 closesocket
Definition: precomp.h:57
#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:733
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:651
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
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
BOOL WINAPI WinHttpQueryHeaders(HINTERNET hrequest, DWORD level, LPCWSTR name, LPVOID buffer, LPDWORD buflen, LPDWORD index)
Definition: request.c:856
#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
unsigned int BOOL
Definition: ntddk_ex.h:94
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:2924
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:136
INT WINAPI WSAStartup(IN WORD wVersionRequested, OUT LPWSADATA lpWSAData)
Definition: startup.c:113
smooth NULL
Definition: ftsmooth.c:416
#define SO_REUSEADDR
Definition: winsock.h:180
Definition: parser.c:48
HANDLE wait
Definition: notification.c:66
static const WCHAR user_agent[]
Definition: notification.c:31
static const struct notification async_test[]
Definition: notification.c:479
#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 trace
Definition: atltest.h:70
#define INVALID_SOCKET
Definition: winsock.h:332
__wchar_t WCHAR
Definition: xmlstorage.h:180
#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:417
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:2048
static HANDLE thread
Definition: service.c:33
static void test_persistent_connection(int port)
Definition: notification.c:949
#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:163
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:1304
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 ARRAY_SIZE(a)
Definition: main.h:24
#define ok(value,...)
Definition: atltest.h:57
enum api function
Definition: notification.c:62
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:714
INT WSAAPI listen(IN SOCKET s, IN INT backlog)
Definition: sockctrl.c:123
#define WINHTTP_CALLBACK_STATUS_REQUEST_SENT
Definition: winhttp.h:385
#define skip(...)
Definition: atltest.h:64
#define msg(x)
Definition: auth_time.c:54
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:1109
USHORT port
Definition: uri.c:228
#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:150
BOOL WINAPI WinHttpSendRequest(HINTERNET hrequest, LPCWSTR headers, DWORD headers_len, LPVOID optional, DWORD optional_len, DWORD total_len, DWORD_PTR context)
Definition: request.c:2350
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:3005
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:3053
static const struct notification server_reply_test[]
Definition: notification.c:818
unsigned int index
Definition: notification.c:65
#define WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT
Definition: winhttp.h:141
#define ok_(x1, x2)
Definition: atltest.h:61
Definition: ps.c:97