mirror of https://github.com/tongzx/nt5src
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
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;
|
|
}
|
|
}
|