Hans Leidekker : winhttp: Add support for detecting the proxy config URL via DHCP.

Alexandre Julliard julliard at winehq.org
Wed Nov 20 16:49:12 CST 2019


Module: wine
Branch: master
Commit: 4ad4173e3a715d5bd27bedc164718cef9cafe0a4
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=4ad4173e3a715d5bd27bedc164718cef9cafe0a4

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Wed Nov 20 14:29:06 2019 +0100

winhttp: Add support for detecting the proxy config URL via DHCP.

Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/winhttp/Makefile.in |   3 +-
 dlls/winhttp/session.c   | 214 ++++++++++++++++++++++++++---------------------
 2 files changed, 121 insertions(+), 96 deletions(-)

diff --git a/dlls/winhttp/Makefile.in b/dlls/winhttp/Makefile.in
index 659b5821df..f4fc317c5f 100644
--- a/dlls/winhttp/Makefile.in
+++ b/dlls/winhttp/Makefile.in
@@ -1,8 +1,7 @@
 MODULE    = winhttp.dll
 IMPORTLIB = winhttp
 IMPORTS   = uuid jsproxy user32 advapi32 ws2_32
-DELAYIMPORTS = oleaut32 ole32 crypt32 secur32
-EXTRALIBS = $(CORESERVICES_LIBS)
+DELAYIMPORTS = oleaut32 ole32 crypt32 secur32 iphlpapi dhcpcsvc
 
 C_SRCS = \
 	cookie.c \
diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c
index ef4bb17469..042b4f7203 100644
--- a/dlls/winhttp/session.c
+++ b/dlls/winhttp/session.c
@@ -20,14 +20,6 @@
 #include <stdarg.h>
 #include <stdlib.h>
 
-#ifdef HAVE_CORESERVICES_CORESERVICES_H
-#define GetCurrentThread MacGetCurrentThread
-#define LoadResource MacLoadResource
-#include <CoreServices/CoreServices.h>
-#undef GetCurrentThread
-#undef LoadResource
-#endif
-
 #include "windef.h"
 #include "winbase.h"
 #include "winsock2.h"
@@ -36,6 +28,8 @@
 #include "winhttp.h"
 #include "winreg.h"
 #include "winternl.h"
+#include "iphlpapi.h"
+#include "dhcpcsdk.h"
 #define COBJMACROS
 #include "ole2.h"
 #include "dispex.h"
@@ -1310,6 +1304,80 @@ BOOL WINAPI WinHttpSetOption( HINTERNET handle, DWORD option, LPVOID buffer, DWO
     return ret;
 }
 
+static IP_ADAPTER_ADDRESSES *get_adapters(void)
+{
+    ULONG err, size = 1024, flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
+                                    GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;
+    IP_ADAPTER_ADDRESSES *tmp, *ret;
+
+    if (!(ret = heap_alloc( size ))) return NULL;
+    err = GetAdaptersAddresses( AF_UNSPEC, flags, NULL, ret, &size );
+    while (err == ERROR_BUFFER_OVERFLOW)
+    {
+        if (!(tmp = heap_realloc( ret, size ))) break;
+        ret = tmp;
+        err = GetAdaptersAddresses( AF_UNSPEC, flags, NULL, ret, &size );
+    }
+    if (err == ERROR_SUCCESS) return ret;
+    heap_free( ret );
+    return NULL;
+}
+
+static WCHAR *detect_autoproxyconfig_url_dhcp(void)
+{
+    IP_ADAPTER_ADDRESSES *adapters, *ptr;
+    DHCPCAPI_PARAMS_ARRAY send_params, recv_params;
+    DHCPCAPI_PARAMS param;
+    WCHAR name[MAX_ADAPTER_NAME_LENGTH + 1], *ret = NULL;
+    DWORD err, size;
+    BYTE *tmp, *buf = NULL;
+
+    if (!(adapters = get_adapters())) return NULL;
+
+    memset( &send_params, 0, sizeof(send_params) );
+    memset( &param, 0, sizeof(param) );
+    param.OptionId = OPTION_MSFT_IE_PROXY;
+    recv_params.nParams = 1;
+    recv_params.Params  = ¶m;
+
+    for (ptr = adapters; ptr; ptr = ptr->Next)
+    {
+        MultiByteToWideChar( CP_ACP, 0, ptr->AdapterName, -1, name, ARRAY_SIZE(name) );
+        TRACE( "adapter '%s' type %u dhcpv4 enabled %d\n", wine_dbgstr_w(name), ptr->IfType, ptr->Dhcpv4Enabled );
+
+        if (ptr->IfType == IF_TYPE_SOFTWARE_LOOPBACK) continue;
+        /* FIXME: also skip adapters where DHCP is disabled */
+
+        size = 256;
+        if (!(buf = heap_alloc( size ))) goto done;
+        err = DhcpRequestParams( DHCPCAPI_REQUEST_SYNCHRONOUS, NULL, name, NULL, send_params, recv_params,
+                                 buf, &size, NULL );
+        while (err == ERROR_MORE_DATA)
+        {
+            if (!(tmp = heap_realloc( buf, size ))) goto done;
+            buf = tmp;
+            err = DhcpRequestParams( DHCPCAPI_REQUEST_SYNCHRONOUS, NULL, name, NULL, send_params, recv_params,
+                                     buf, &size, NULL );
+        }
+        if (err == ERROR_SUCCESS && param.nBytesData)
+        {
+            int len = MultiByteToWideChar( CP_ACP, 0, (const char *)param.Data, param.nBytesData, NULL, 0 );
+            if ((ret = heap_alloc( (len + 1) * sizeof(WCHAR) )))
+            {
+                MultiByteToWideChar( CP_ACP, 0,  (const char *)param.Data, param.nBytesData, ret, len );
+                ret[len] = 0;
+            }
+            TRACE("returning %s\n", debugstr_w(ret));
+            break;
+        }
+    }
+
+done:
+    heap_free( buf );
+    heap_free( adapters );
+    return ret;
+}
+
 static char *get_computer_name( COMPUTER_NAME_FORMAT format )
 {
     char *ret;
@@ -1362,50 +1430,57 @@ static WCHAR *build_wpad_url( const char *hostname, const struct addrinfo *ai )
     return ret;
 }
 
-static BOOL get_system_proxy_autoconfig_url( char *buf, DWORD buflen )
+static WCHAR *detect_autoproxyconfig_url_dns(void)
 {
-#if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
-    CFDictionaryRef settings = CFNetworkCopySystemProxySettings();
-    const void *ref;
-    BOOL ret = FALSE;
-
-    if (!settings) return FALSE;
+    char *fqdn, *domain, *p;
+    WCHAR *ret;
 
-    if (!(ref = CFDictionaryGetValue( settings, kCFNetworkProxiesProxyAutoConfigURLString )))
+    if (!(fqdn = get_computer_name( ComputerNamePhysicalDnsFullyQualified ))) return NULL;
+    if (!(domain = get_computer_name( ComputerNamePhysicalDnsDomain )))
     {
-        CFRelease( settings );
-        return FALSE;
+        heap_free( fqdn );
+        return NULL;
     }
-    if (CFStringGetCString( ref, buf, buflen, kCFStringEncodingASCII ))
+    p = fqdn;
+    while ((p = strchr( p, '.' )) && is_domain_suffix( p + 1, domain ))
     {
-        TRACE( "returning %s\n", debugstr_a(buf) );
-        ret = TRUE;
+        char *name;
+        struct addrinfo *ai;
+        int res;
+
+        if (!(name = heap_alloc( sizeof("wpad") + strlen(p) )))
+        {
+            heap_free( fqdn );
+            heap_free( domain );
+            return NULL;
+        }
+        strcpy( name, "wpad" );
+        strcat( name, p );
+        res = getaddrinfo( name, NULL, NULL, &ai );
+        if (!res)
+        {
+            ret = build_wpad_url( name, ai );
+            freeaddrinfo( ai );
+            if (ret)
+            {
+                TRACE("returning %s\n", debugstr_w(ret));
+                heap_free( name );
+                break;
+            }
+        }
+       heap_free( name );
+       p++;
     }
-    CFRelease( settings );
+    heap_free( domain );
+    heap_free( fqdn );
     return ret;
-#else
-    static BOOL first = TRUE;
-    if (first)
-    {
-        FIXME( "no support on this platform\n" );
-        first = FALSE;
-    }
-    else
-        TRACE( "no support on this platform\n" );
-    return FALSE;
-#endif
 }
 
-#define INTERNET_MAX_URL_LENGTH 2084
-
 /***********************************************************************
  *          WinHttpDetectAutoProxyConfigUrl (winhttp.@)
  */
 BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR *url )
 {
-    BOOL ret = FALSE;
-    char system_url[INTERNET_MAX_URL_LENGTH + 1];
-
     TRACE("0x%08x, %p\n", flags, url);
 
     if (!flags || !url)
@@ -1413,71 +1488,22 @@ BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR *url )
         SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
-    if (get_system_proxy_autoconfig_url( system_url, sizeof(system_url) ))
-    {
-        WCHAR *urlW;
-
-        if (!(urlW = strdupAW( system_url ))) return FALSE;
-        *url = urlW;
-        SetLastError( ERROR_SUCCESS );
-        return TRUE;
-    }
+    *url = NULL;
     if (flags & WINHTTP_AUTO_DETECT_TYPE_DHCP)
     {
-        static int fixme_shown;
-        if (!fixme_shown++) FIXME("discovery via DHCP not supported\n");
+        *url = detect_autoproxyconfig_url_dhcp();
     }
     if (flags & WINHTTP_AUTO_DETECT_TYPE_DNS_A)
     {
-        char *fqdn, *domain, *p;
-
-        if (!(fqdn = get_computer_name( ComputerNamePhysicalDnsFullyQualified ))) return FALSE;
-        if (!(domain = get_computer_name( ComputerNamePhysicalDnsDomain )))
-        {
-            heap_free( fqdn );
-            return FALSE;
-        }
-        p = fqdn;
-        while ((p = strchr( p, '.' )) && is_domain_suffix( p + 1, domain ))
-        {
-            struct addrinfo *ai;
-            char *name;
-            int res;
-
-            if (!(name = heap_alloc( sizeof("wpad") + strlen(p) )))
-            {
-                heap_free( fqdn );
-                heap_free( domain );
-                return FALSE;
-            }
-            strcpy( name, "wpad" );
-            strcat( name, p );
-            res = getaddrinfo( name, NULL, NULL, &ai );
-            if (!res)
-            {
-                *url = build_wpad_url( name, ai );
-                freeaddrinfo( ai );
-                if (*url)
-                {
-                    TRACE("returning %s\n", debugstr_w(*url));
-                    heap_free( name );
-                    ret = TRUE;
-                    break;
-                }
-            }
-            heap_free( name );
-            p++;
-        }
-        heap_free( domain );
-        heap_free( fqdn );
+        if (!*url) *url = detect_autoproxyconfig_url_dns();
     }
-    if (!ret)
+    if (!*url)
     {
         SetLastError( ERROR_WINHTTP_AUTODETECTION_FAILED );
-        *url = NULL;
+        return FALSE;
     }
-    else SetLastError( ERROR_SUCCESS );
-    return ret;
+    SetLastError( ERROR_SUCCESS );
+    return TRUE;
 }
 
 static const WCHAR Connections[] = {




More information about the wine-cvs mailing list