*RESEND* Fix bug #5800
Daniel Skorka
daniel.skorka at stud.uni-karlsruhe.de
Fri Sep 8 16:50:02 CDT 2006
The function CheckInternetConnection in dlls/wininet/internet.c is too
naive ATM; it just sends a ping to the specified host. This will fail if
the remote system or hops inbetween are misconfigured. A trace of the
network traffic generated by a XP box (see attachments to bug #5800)
reveals that Windows actually opens a TCP connection (port depends on
URL given), then closes it again. This patch changes the behaviour in
wine accordingly.
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);
----- End forwarded message -----
More information about the wine-patches
mailing list