ReactOS  0.4.13-dev-257-gfabbd7c
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
#define ok_(x1, x2)
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
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
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: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
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: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
#define ok(value,...)
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:111
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 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: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
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
#define skip(...)
#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: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
Definition: ps.c:97