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
|
||||
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 \
|
||||
|
|
|
@ -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 (!settings) return NULL;
|
||||
|
||||
if (!(ref = CFDictionaryGetValue( settings, kCFNetworkProxiesProxyAutoConfigURLString )))
|
||||
if (!(ret = heap_alloc( size ))) return NULL;
|
||||
err = GetAdaptersAddresses( AF_UNSPEC, flags, NULL, ret, &size );
|
||||
while (err == ERROR_BUFFER_OVERFLOW)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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;
|
||||
#else
|
||||
static int once;
|
||||
if (!once++) FIXME( "no support on this platform\n" );
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
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 ))
|
||||
{
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue