wininet: Add support for detecting the proxy config URL.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
5bf055a62d
commit
a4357043ff
|
@ -2,9 +2,9 @@ EXTRADEFS = -D_WINX32_
|
||||||
MODULE = wininet.dll
|
MODULE = wininet.dll
|
||||||
IMPORTLIB = wininet
|
IMPORTLIB = wininet
|
||||||
IMPORTS = mpr shlwapi shell32 user32 ws2_32 advapi32
|
IMPORTS = mpr shlwapi shell32 user32 ws2_32 advapi32
|
||||||
DELAYIMPORTS = secur32 crypt32 cryptui
|
DELAYIMPORTS = secur32 crypt32 cryptui dhcpcsvc iphlpapi
|
||||||
EXTRAINCL = $(Z_CFLAGS)
|
EXTRAINCL = $(Z_CFLAGS)
|
||||||
EXTRALIBS = $(CORESERVICES_LIBS) $(Z_LIBS)
|
EXTRALIBS = $(Z_LIBS)
|
||||||
|
|
||||||
C_SRCS = \
|
C_SRCS = \
|
||||||
cookie.c \
|
cookie.c \
|
||||||
|
|
|
@ -28,14 +28,6 @@
|
||||||
|
|
||||||
#include "config.h"
|
#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 "winsock2.h"
|
||||||
#include "ws2ipdef.h"
|
#include "ws2ipdef.h"
|
||||||
|
|
||||||
|
@ -56,6 +48,10 @@
|
||||||
#include "winerror.h"
|
#include "winerror.h"
|
||||||
#define NO_SHLWAPI_STREAM
|
#define NO_SHLWAPI_STREAM
|
||||||
#include "shlwapi.h"
|
#include "shlwapi.h"
|
||||||
|
#include "ws2tcpip.h"
|
||||||
|
#include "winternl.h"
|
||||||
|
#include "iphlpapi.h"
|
||||||
|
#include "dhcpcsdk.h"
|
||||||
|
|
||||||
#include "wine/exception.h"
|
#include "wine/exception.h"
|
||||||
|
|
||||||
|
@ -2295,38 +2291,183 @@ BOOL WINAPI InternetReadFileExW(HINTERNET hFile, LPINTERNET_BUFFERSW lpBuffer,
|
||||||
return res == ERROR_SUCCESS;
|
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();
|
if (!(ret = heap_alloc( size ))) return NULL;
|
||||||
WCHAR *ret = NULL;
|
err = GetAdaptersAddresses( AF_UNSPEC, flags, NULL, ret, &size );
|
||||||
SIZE_T len;
|
while (err == ERROR_BUFFER_OVERFLOW)
|
||||||
const void *ref;
|
|
||||||
|
|
||||||
if (!settings) return NULL;
|
|
||||||
|
|
||||||
if (!(ref = CFDictionaryGetValue( settings, kCFNetworkProxiesProxyAutoConfigURLString )))
|
|
||||||
{
|
{
|
||||||
CFRelease( settings );
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
heap_free( buf );
|
||||||
|
heap_free( adapters );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ))
|
||||||
|
{
|
||||||
|
heap_free( ret );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
len = CFStringGetLength( ref );
|
|
||||||
if (len)
|
|
||||||
ret = heap_alloc( (len+1) * sizeof(WCHAR) );
|
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
CFStringGetCharacters( ref, CFRangeMake(0, len), ret );
|
|
||||||
ret[len] = 0;
|
|
||||||
}
|
|
||||||
TRACE( "returning %s\n", debugstr_w(ret) );
|
|
||||||
CFRelease( settings );
|
|
||||||
return ret;
|
return ret;
|
||||||
#else
|
}
|
||||||
static int once;
|
|
||||||
if (!once++) FIXME( "no support on this platform\n" );
|
static BOOL is_domain_suffix( const char *domain, const char *suffix )
|
||||||
return NULL;
|
{
|
||||||
#endif
|
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 ))
|
||||||
|
{
|
||||||
|
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++;
|
||||||
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DWORD query_global_option(DWORD option, void *buffer, DWORD *size, BOOL unicode)
|
static DWORD query_global_option(DWORD option, void *buffer, DWORD *size, BOOL unicode)
|
||||||
|
|
Loading…
Reference in New Issue