Fix bug #5800

Daniel Skorka daniel.skorka at stud.uni-karlsruhe.de
Sat Aug 26 11:09:04 CDT 2006


This patch is intended to fix bug #5800. The comments contain an
analysis of the behaviour under windows, which this patch tries to
emulate as good as possible.

Changelog:
Daniel Skorka <skorka at gmx.net>
	* dlls/wininet/internet.c:
	wininet: fix bug #5800 InternetCheckConnection is too naive


--- dlls/wininet/internet.c.old	2006-08-24 16:11:45.000000000 +0200
+++ dlls/wininet/internet.c	2006-08-26 17:45:41.000000000 +0200
@@ -47,6 +47,7 @@
 # include <unistd.h>
 #endif
 #include <assert.h>
+#include <netdb.h>
 
 #include "windef.h"
 #include "winbase.h"
@@ -2759,7 +2760,8 @@
 /***********************************************************************
  *	InternetCheckConnectionW (WININET.@)
  *
- * Pings a requested host to check internet connection
+ * <quote MSDN> Allows an application to check if a connection to the
+ * Internet can be established. </quote MSDN>
  *
  * RETURNS
  *   TRUE on success and FALSE on failure. If a failure then
@@ -2769,20 +2771,22 @@
 BOOL WINAPI InternetCheckConnectionW( LPCWSTR lpszUrl, DWORD dwFlags, DWORD dwReserved )
 {
 /*
- * this is a kludge which runs the resident ping program and reads the output.
- *
- * Anyone have a better idea?
+ * For a discussion on this function, see bug #5800
  */
 
-  BOOL   rc = FALSE;
-  static const CHAR ping[] = "ping -w 1 ";
-  static const CHAR redirect[] = " >/dev/null 2>/dev/null";
-  CHAR *command = NULL;
-  WCHAR hostW[1024];
-  DWORD len;
-  int status = -1;
+  WCHAR default_url[] = {'h', 't', 't', 'p', ':', '/', '/',
+	      'w', 'i', 'n', 'e', 'h', 'q', '.', 'o', 'r', 'g', '/', 0};
+  BOOL use_default = FALSE;
+  URL_COMPONENTSW components;
+  WCHAR hostW[MAXHOSTNAME];
+  char host[MAXHOSTNAME];
+  char port[5];
+
+  struct addrinfo *result = NULL, *ptr = NULL, hints;
+  int s = -1;
 
-  FIXME("\n");
+  BOOL rc = FALSE;
+  int res;
 
   /*
    * Crack or set the Address
@@ -2794,47 +2798,96 @@
       * server in the WnInet internal server database. I have
       * no idea what that is or how to get it.
       *
-      * So someone needs to implement this.
+      * Until someone thinks of a better solution, this case will be
+      * treated as if *lpszUrl==http://winehq.org/
       */
-     FIXME("Unimplemented with URL of NULL\n");
-     return TRUE;
-  }
-  else
-  {
-     URL_COMPONENTSW components;
+     FIXME("lpszUrl==NULL : Always trying http://winehq.org/\n");
+     use_default=TRUE;
 
-     ZeroMemory(&components,sizeof(URL_COMPONENTSW));
-     components.lpszHostName = (LPWSTR)&hostW;
-     components.dwHostNameLength = 1024;
-
-     if (!InternetCrackUrlW(lpszUrl,0,0,&components))
-       goto End;
-
-     TRACE("host name : %s\n",debugstr_w(components.lpszHostName));
   }
 
+  if(dwFlags == 0) {
+  /*
+   * This case is undocumented. All we know is that no network traffic is
+   * generated.
+   */
+	  TRACE("dwFlags == 0: Behaviour undefined. Returning TRUE\n");
+	  rc = TRUE;
+	  goto End;
+
+  } else if (dwFlags== FLAG_ICC_FORCE_CONNECTION) {
   /*
-   * Build our ping command
+   * Try to open a connection, then close it. Return TRUE on success.
    */
-  len = WideCharToMultiByte(CP_UNIXCP, 0, hostW, -1, NULL, 0, NULL, NULL);
-  command = HeapAlloc( GetProcessHeap(), 0, strlen(ping)+len+strlen(redirect) );
-  strcpy(command,ping);
-  WideCharToMultiByte(CP_UNIXCP, 0, hostW, -1, command+strlen(ping), len, NULL, NULL);
-  strcat(command,redirect);
 
-  TRACE("Ping command is : %s\n",command);
+      ZeroMemory(&components,sizeof(URL_COMPONENTSW));
+      components.lpszHostName = (LPWSTR)&hostW;
+      components.dwHostNameLength = 1024;
+
+      if(use_default) {
+          if (!InternetCrackUrlW((LPWSTR)&default_url,0,0,&components))
+              goto End;
+      } else
+          if (!InternetCrackUrlW(lpszUrl,0,0,&components))
+              goto End;
+
+      res = WideCharToMultiByte(CP_UNIXCP, 0, components.lpszHostName, -1,
+		      host, 1024, NULL, NULL);
+      if(!res)
+	      WARN("conversion of host name failed!\n");
+      snprintf(port, 5, "%d",components.nPort);
+
+      TRACE("host:port = %s:%s\n",host,port);
+
+      ZeroMemory(&hints, sizeof(hints));
+      hints.ai_family = AF_INET;
+      hints.ai_socktype = SOCK_STREAM;
+      hints.ai_protocol = IPPROTO_TCP;
+      
+      res = getaddrinfo(host, port,
+		      &hints, &result);
+      if(res) {
+          TRACE("getaddrinfo failed: %d\n", res);
+	  goto End;
+      }
+
+
+      for(ptr = result; ptr != NULL; ptr = ptr->ai_next) {
+          s = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
+          if(s == -1) {
+	      break;
+          }
+
+          res = connect(s, ptr->ai_addr, (int)ptr->ai_addrlen);
+          if(res)
+          {
+	      close(s);
+	      TRACE("connection failed: %d\n",res);
+	      s = -1;
+          }
+      }
+
+      freeaddrinfo(result);
 
-  status = system(command);
+      if(s == -1) {
+          TRACE("unable to connect\n");
+	  goto End;
+      }
+
+      close(s);
+      rc = TRUE;
 
-  TRACE("Ping returned a code of %i\n",status);
+  } else {
+  /*
+   * We don't know of other flags
+   */
+      FIXME("dwFlags == %ld is undocumented. Returning FALSE\n", dwFlags);
+      goto End;
+  }
 
-  /* Ping return code of 0 indicates success */
-  if (status == 0)
-     rc = TRUE;
 
 End:
 
-  HeapFree( GetProcessHeap(), 0, command );
   if (rc == FALSE)
     SetLastError(ERROR_NOT_CONNECTED);
 



More information about the wine-patches mailing list