[PATCH] wininet: Add support for detecting the proxy config URL.

Hans Leidekker hans at codeweavers.com
Fri Nov 22 09:32:25 CST 2019


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/wininet/Makefile.in |   4 +-
 dlls/wininet/internet.c  | 201 +++++++++++++++++++++++++++++++++------
 2 files changed, 173 insertions(+), 32 deletions(-)

diff --git a/dlls/wininet/Makefile.in b/dlls/wininet/Makefile.in
index 6eeb7cf85b..e1d4979d87 100644
--- a/dlls/wininet/Makefile.in
+++ b/dlls/wininet/Makefile.in
@@ -2,9 +2,9 @@ EXTRADEFS = -D_WINX32_
 MODULE    = wininet.dll
 IMPORTLIB = wininet
 IMPORTS   = mpr shlwapi shell32 user32 ws2_32 advapi32
-DELAYIMPORTS = secur32 crypt32 cryptui
+DELAYIMPORTS = secur32 crypt32 cryptui dhcpcsvc iphlpapi
 EXTRAINCL = $(Z_CFLAGS)
-EXTRALIBS = $(CORESERVICES_LIBS) $(Z_LIBS)
+EXTRALIBS = $(Z_LIBS)
 
 C_SRCS = \
 	cookie.c \
diff --git a/dlls/wininet/internet.c b/dlls/wininet/internet.c
index 266100861d..3e8be9fa2b 100644
--- a/dlls/wininet/internet.c
+++ b/dlls/wininet/internet.c
@@ -28,14 +28,6 @@
 
 #include "config.h"
 
-#ifdef HAVE_CORESERVICES_CORESERVICES_H
-#define GetCurrentThread MacGetCurrentThread
-#define LoadResource MacLoadResource
-#include <CoreServices/CoreServices.h>
-#undef GetCurrentThread
-#undef LoadResource
-#endif
-
 #include "winsock2.h"
 #include "ws2ipdef.h"
 
@@ -56,6 +48,10 @@
 #include "winerror.h"
 #define NO_SHLWAPI_STREAM
 #include "shlwapi.h"
+#include "ws2tcpip.h"
+#include "winternl.h"
+#include "iphlpapi.h"
+#include "dhcpcsdk.h"
 
 #include "wine/exception.h"
 
@@ -2295,38 +2291,183 @@ BOOL WINAPI InternetReadFileExW(HINTERNET hFile, LPINTERNET_BUFFERSW lpBuffer,
     return res == ERROR_SUCCESS;
 }
 
-static WCHAR *get_proxy_autoconfig_url(void)
+static IP_ADAPTER_ADDRESSES *get_adapters(void)
 {
-#if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+    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;
 
-    CFDictionaryRef settings = CFNetworkCopySystemProxySettings();
-    WCHAR *ret = NULL;
-    SIZE_T len;
-    const void *ref;
+    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_proxy_autoconfig_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;
+        }
+    }
 
-    if (!settings) return NULL;
+done:
+    heap_free( buf );
+    heap_free( adapters );
+    return ret;
+}
 
-    if (!(ref = CFDictionaryGetValue( settings, kCFNetworkProxiesProxyAutoConfigURLString )))
+static char *get_computer_name( COMPUTER_NAME_FORMAT format )
+{
+    char *ret;
+    DWORD size = 0;
+
+    GetComputerNameExA( format, NULL, &size );
+    if (GetLastError() != ERROR_MORE_DATA) return NULL;
+    if (!(ret = heap_alloc( size ))) return NULL;
+    if (!GetComputerNameExA( format, ret, &size ))
     {
-        CFRelease( settings );
+        heap_free( ret );
         return NULL;
     }
-    len = CFStringGetLength( ref );
-    if (len)
-        ret = heap_alloc( (len+1) * sizeof(WCHAR) );
-    if (ret)
+    return ret;
+}
+
+static BOOL is_domain_suffix( const char *domain, const char *suffix )
+{
+    int len_domain = strlen( domain ), len_suffix = strlen( suffix );
+
+    if (len_suffix > len_domain) return FALSE;
+    if (!_strnicmp( domain + len_domain - len_suffix, suffix, -1 )) return TRUE;
+    return FALSE;
+}
+
+static int reverse_lookup( const struct addrinfo *ai, char *hostname, size_t len )
+{
+    return getnameinfo( ai->ai_addr, ai->ai_addrlen, hostname, len, NULL, 0, 0 );
+}
+
+static WCHAR *build_wpad_url( const char *hostname, const struct addrinfo *ai )
+{
+    static const WCHAR httpW[] = {'h','t','t','p',':','/','/',0};
+    static const WCHAR wpadW[] = {'/','w','p','a','d','.','d','a','t',0};
+    char name[NI_MAXHOST];
+    WCHAR *ret, *p;
+    int len;
+
+    while (ai && ai->ai_family != AF_INET && ai->ai_family != AF_INET6) ai = ai->ai_next;
+    if (!ai) return NULL;
+
+    if (!reverse_lookup( ai, name, sizeof(name) )) hostname = name;
+
+    len = lstrlenW( httpW ) + strlen( hostname ) + lstrlenW( wpadW );
+    if (!(ret = p = GlobalAlloc( 0, (len + 1) * sizeof(WCHAR) ))) return NULL;
+    lstrcpyW( p, httpW );
+    p += lstrlenW( httpW );
+    while (*hostname) { *p++ = *hostname++; }
+    lstrcpyW( p, wpadW );
+    return ret;
+}
+
+static WCHAR *detect_proxy_autoconfig_url_dns(void)
+{
+    char *fqdn, *domain, *p;
+    WCHAR *ret;
+
+    if (!(fqdn = get_computer_name( ComputerNamePhysicalDnsFullyQualified ))) return NULL;
+    if (!(domain = get_computer_name( ComputerNamePhysicalDnsDomain )))
+    {
+        heap_free( fqdn );
+        return NULL;
+    }
+    p = fqdn;
+    while ((p = strchr( p, '.' )) && is_domain_suffix( p + 1, domain ))
     {
-        CFStringGetCharacters( ref, CFRangeMake(0, len), ret );
-        ret[len] = 0;
+        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++;
     }
-    TRACE( "returning %s\n", debugstr_w(ret) );
-    CFRelease( settings );
+    heap_free( domain );
+    heap_free( fqdn );
+    return ret;
+}
+
+static WCHAR *get_proxy_autoconfig_url(void)
+{
+    WCHAR *ret = detect_proxy_autoconfig_url_dhcp();
+    if (!ret) ret = detect_proxy_autoconfig_url_dns();
     return ret;
-#else
-    static int once;
-    if (!once++) FIXME( "no support on this platform\n" );
-    return NULL;
-#endif
 }
 
 static DWORD query_global_option(DWORD option, void *buffer, DWORD *size, BOOL unicode)
-- 
2.20.1




More information about the wine-devel mailing list