[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( ¶m, 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