Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

286 lines
8.5 KiB

#include "stdafx.h"
#if !defined(BITS_V12_ON_NT4)
#include "proxy.tmh"
#endif
HRESULT
CACHED_AUTOPROXY::Generate(
const TCHAR Host[]
)
{
if (GetTickCount() - m_TimeStamp > CACHED_PROXY_LIFETIME_IN_MSEC)
{
m_HostName = L"";
}
if (0 == _tcscmp( Host, m_HostName ))
{
LogInfo("using existing proxy info for '%S'", Host );
return S_OK;
}
LogInfo( "detecting proxy for '%S'", Host );
//
// Detect IE settings and look up proxy if necessary.
// Boilerplate from Stephen Sulzer.
//
WINHTTP_PROXY_INFO ProxyInfo;
WINHTTP_AUTOPROXY_OPTIONS AutoProxyOptions;
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG IEProxyConfig;
LPWSTR AutoConfigUrl = 0;
BOOL fTryAutoProxy = FALSE;
BOOL fSuccess = FALSE;
ZeroMemory(&ProxyInfo, sizeof(ProxyInfo));
ZeroMemory(&AutoProxyOptions, sizeof(AutoProxyOptions));
ZeroMemory(&IEProxyConfig, sizeof(IEProxyConfig));
if (WinHttpGetIEProxyConfigForCurrentUser(&IEProxyConfig))
{
LogInfo("got user's IE info");
if (IEProxyConfig.fAutoDetect)
{
LogInfo("IE specifies auto-detect");
AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
AutoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP |
WINHTTP_AUTO_DETECT_TYPE_DNS_A;
fTryAutoProxy = TRUE;
}
if (IEProxyConfig.lpszAutoConfigUrl)
{
LogInfo("IE specifies auto-config URL '%S'", IEProxyConfig.lpszAutoConfigUrl ? IEProxyConfig.lpszAutoConfigUrl : NullString );
AutoProxyOptions.dwFlags |= WINHTTP_AUTOPROXY_CONFIG_URL;
AutoProxyOptions.lpszAutoConfigUrl = IEProxyConfig.lpszAutoConfigUrl;
AutoConfigUrl = IEProxyConfig.lpszAutoConfigUrl;
fTryAutoProxy = TRUE;
}
AutoProxyOptions.fAutoLogonIfChallenged = TRUE;
}
else
{
LogInfo("no user IE info: %d", GetLastError());
// WinHttpGetIEProxyForCurrentUser failed, try autodetection anyway...
AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
AutoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP |
WINHTTP_AUTO_DETECT_TYPE_DNS_A;
fTryAutoProxy = TRUE;
}
if (fTryAutoProxy)
{
LogInfo("trying auto-detect...");
fSuccess = WinHttpGetProxyForUrl( m_hInternet,
Host,
&AutoProxyOptions,
&ProxyInfo
);
LogInfo("auto-detect returned %d (%d)", fSuccess, fSuccess ? 0 : GetLastError() );
}
// If we didn't do autoproxy or if it failed, see
// if there's an explicit proxy server in the IE
// proxy configuration...
//
// This is where the WinHttpGetIEProxyConfigForCurrentUser API
// really comes in handy: in environments in which autoproxy is
// not supported and so the user's IE browser must be
// configured with an explicit proxy server.
//
if (!fTryAutoProxy || !fSuccess)
{
LogInfo("looking for backup ideas");
if (IEProxyConfig.lpszProxy)
{
LogInfo("using named proxy '%S'", IEProxyConfig.lpszProxy ? IEProxyConfig.lpszProxy : NullString );
ProxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
ProxyInfo.lpszProxy = IEProxyConfig.lpszProxy;
ProxyInfo.lpszProxyBypass = IEProxyConfig.lpszProxyBypass;
}
}
//
// Sometimes the registry contains a single or double colon for the proxy or, oddly, bypass list.
// SetRequestProxy rejects them. Both cases should be treated like a NULL string.
//
static wchar_t SingleColon[] = L":";
static wchar_t DoubleColon[] = L"::";
if (ProxyInfo.lpszProxy)
{
if (0 == wcscmp( ProxyInfo.lpszProxy, SingleColon ) ||
0 == wcscmp( ProxyInfo.lpszProxy, DoubleColon ))
{
LogWarning("suppressing invalid proxy string %S", ProxyInfo.lpszProxy );
GlobalFree( ProxyInfo.lpszProxy );
ProxyInfo.lpszProxy = NULL;
}
}
if (ProxyInfo.lpszProxyBypass)
{
if (0 == wcscmp( ProxyInfo.lpszProxyBypass, SingleColon ) ||
0 == wcscmp( ProxyInfo.lpszProxyBypass, DoubleColon ))
{
LogWarning("suppressing invalid bypass string %S", ProxyInfo.lpszProxyBypass );
GlobalFree( ProxyInfo.lpszProxyBypass );
ProxyInfo.lpszProxyBypass = NULL;
}
}
LogInfo("proxy '%S'", ProxyInfo.lpszProxy ? ProxyInfo.lpszProxy : NullString );
LogInfo("bypass list '%S'", ProxyInfo.lpszProxyBypass ? ProxyInfo.lpszProxyBypass : NullString );
LogInfo("access type %d", ProxyInfo.dwAccessType );
if (AutoConfigUrl)
{
GlobalFree( AutoConfigUrl );
}
Clear();
m_ProxyInfo = ProxyInfo;
m_HostName = Host;
m_fValid = true;
m_TimeStamp = GetTickCount();
//
// We don't have to release the proxy server and proxy bypass strings
// because Clear() will do that.
//
return S_OK;
}
void
CACHED_AUTOPROXY::Clear()
{
if (m_fValid)
{
m_fValid = false;
if (m_ProxyInfo.lpszProxy) GlobalFree(m_ProxyInfo.lpszProxy);
if (m_ProxyInfo.lpszProxyBypass) GlobalFree(m_ProxyInfo.lpszProxyBypass);
}
ZeroMemory(&m_ProxyInfo, sizeof(m_ProxyInfo));
m_HostName = NULL;
}
PROXY_SETTINGS_CONTAINER::PROXY_SETTINGS_CONTAINER(
LPCWSTR Url,
const PROXY_SETTINGS * ProxySettings
) :
m_ProxyUsage( ProxyUsageFromJobProxyUsage( ProxySettings->ProxyUsage )),
m_ProxyList( NULL ),
m_BypassList( NULL ),
m_TokenCursor( NULL )
{
//
// Set up the list of proxy servers.
//
switch (m_ProxyUsage)
{
case INTERNET_OPEN_TYPE_DIRECT:
break;
case INTERNET_OPEN_TYPE_PROXY:
{
m_MasterProxyList = ProxySettings->ProxyList;
m_BypassList = ProxySettings->ProxyBypassList;
break;
}
case INTERNET_OPEN_TYPE_PRECONFIG:
{
THROW_HRESULT( g_ProxyCache->Generate( Url ));
m_MasterProxyList = g_ProxyCache->GetProxyList();
m_BypassList = g_ProxyCache->GetBypassList();
m_AccessType = g_ProxyCache->GetAccessType();
break;
}
default:
ASSERT( 0 );
break;
}
ResetCurrentProxy();
}
HRESULT
SetRequestProxy(
HINTERNET hRequest,
PROXY_SETTINGS_CONTAINER * ProxySettings
)
{
WINHTTP_PROXY_INFO ProxyInfo;
ProxyInfo.dwAccessType = ProxySettings->GetProxyUsage();
ProxyInfo.lpszProxy = const_cast<LPWSTR>( ProxySettings->GetCurrentProxy() );
ProxyInfo.lpszProxyBypass = const_cast<LPWSTR>( ProxySettings->GetBypassList() );
LogInfo("proxy info:");
LogInfo("access: %d", ProxyInfo.dwAccessType );
LogInfo("server '%S'", ProxyInfo.lpszProxy ? ProxyInfo.lpszProxy : NullString );
LogInfo("bypass '%S'", ProxyInfo.lpszProxyBypass ? ProxyInfo.lpszProxyBypass : NullString );
if (ProxyInfo.dwAccessType == INTERNET_OPEN_TYPE_DIRECT)
{
LogInfo("proxy usage disabled");
return S_OK;
}
if (ProxyInfo.lpszProxy == NULL)
{
LogInfo("null proxy");
return S_OK;
}
if (ProxyInfo.dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG)
{
LogInfo("mapping PRECONFIG to named proxy");
ProxyInfo.dwAccessType = INTERNET_OPEN_TYPE_PROXY;
}
if (!WinHttpSetOption( hRequest,
WINHTTP_OPTION_PROXY,
&ProxyInfo,
sizeof(ProxyInfo)
))
{
DWORD err = GetLastError();
LogWarning( "can't set proxy option: %!winerr!", err );
return HRESULT_FROM_WIN32( err );
}
return S_OK;
}
bool IsPossibleProxyFailure( DWORD err )
{
switch (err)
{
case ERROR_WINHTTP_NAME_NOT_RESOLVED:
case ERROR_WINHTTP_CANNOT_CONNECT:
case ERROR_WINHTTP_CONNECTION_ERROR:
case ERROR_WINHTTP_TIMEOUT:
return true;
default:
return false;
}
}