2740 lines
63 KiB
Plaintext
2740 lines
63 KiB
Plaintext
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1996 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
proxysup.cxx
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Contains class implementation for proxy server and proxy bypass list
|
|||
|
|
|||
|
Contents:
|
|||
|
IsLocalMacro
|
|||
|
LoadExternalAutoConfigDll
|
|||
|
|
|||
|
PROXY_SERVER_LIST_ENTRY::WriteEntry
|
|||
|
|
|||
|
PROXY_SERVER_LIST::AddList
|
|||
|
PROXY_SERVER_LIST::Find
|
|||
|
PROXY_SERVER_LIST::Add
|
|||
|
PROXY_SERVER_LIST::ProxyScheme
|
|||
|
PROXY_SERVER_LIST::GetProxyInfo
|
|||
|
PROXY_SERVER_LIST::AddToBypassList
|
|||
|
PROXY_SERVER_LIST::GetList
|
|||
|
|
|||
|
PROXY_BYPASS_LIST_ENTRY::WriteEntry
|
|||
|
|
|||
|
PROXY_BYPASS_LIST::AddList
|
|||
|
PROXY_BYPASS_LIST::Find
|
|||
|
PROXY_BYPASS_LIST::Add
|
|||
|
PROXY_BYPASS_LIST::IsBypassed
|
|||
|
PROXY_BYPASS_LIST::GetList
|
|||
|
|
|||
|
PROXY_INFO::SetProxyInfo
|
|||
|
PROXY_INFO::GetProxyInfo
|
|||
|
PROXY_INFO::IsBypassed
|
|||
|
PROXY_INFO::ProxyScheme
|
|||
|
|
|||
|
(GetRegistryProxyParameter)
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Richard L Firth (rfirth) 03-Feb-1996
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
03-Feb-1996 rfirth
|
|||
|
Created
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include <wininetp.h>
|
|||
|
|
|||
|
//
|
|||
|
// private manifests
|
|||
|
//
|
|||
|
|
|||
|
#define DEFAULT_PROXY_BUFFER_LENGTH (4 K)
|
|||
|
#define MAX_IP_ADDRESS_STRING_LENGTH (4 * 4 - 1) // ###.###.###.###
|
|||
|
#define PROXY_REGISTRY_STRING_LENGTH (4 K)
|
|||
|
|
|||
|
//
|
|||
|
// private types
|
|||
|
//
|
|||
|
|
|||
|
typedef enum {
|
|||
|
STATE_START,
|
|||
|
STATE_PROTOCOL,
|
|||
|
STATE_SCHEME,
|
|||
|
STATE_SERVER,
|
|||
|
STATE_PORT,
|
|||
|
STATE_END,
|
|||
|
STATE_ERROR
|
|||
|
} PARSER_STATE;
|
|||
|
|
|||
|
|
|||
|
#define EXT_PROXY_FUNC *
|
|||
|
|
|||
|
typedef BOOL
|
|||
|
(EXT_PROXY_FUNC IS_BYPASSED_FN) (
|
|||
|
IN INTERNET_SCHEME tScheme,
|
|||
|
IN LPSTR lpszHostName,
|
|||
|
IN DWORD dwHostNameLength,
|
|||
|
IN INTERNET_PORT nPort
|
|||
|
);
|
|||
|
|
|||
|
typedef BOOL
|
|||
|
(EXT_PROXY_FUNC PROXY_SCHEME_FN) (
|
|||
|
IN INTERNET_SCHEME tProtocol,
|
|||
|
OUT LPINTERNET_SCHEME lptScheme
|
|||
|
) ;
|
|||
|
|
|||
|
typedef BOOL
|
|||
|
(EXT_PROXY_FUNC GET_PROXY_INFO_FN) (
|
|||
|
IN INTERNET_SCHEME tProtocol,
|
|||
|
IN OUT LPINTERNET_SCHEME lptScheme,
|
|||
|
OUT LPSTR * lplpszHostName,
|
|||
|
OUT LPDWORD lpdwHostNameLength,
|
|||
|
OUT LPINTERNET_PORT lpHostPort
|
|||
|
) ;
|
|||
|
|
|||
|
typedef BOOL
|
|||
|
(EXT_PROXY_FUNC PROXY_DLL_INIT_FN) (
|
|||
|
IN DWORD dwReserved
|
|||
|
);
|
|||
|
|
|||
|
#define IS_BYPASSED_FN_NAME "InternetIsBypassed"
|
|||
|
#define PROXY_SCHEME_FN_NAME "InternetProxyScheme"
|
|||
|
#define GET_PROXY_INFO_FN_NAME "InternetGetProxyInfo"
|
|||
|
#define PROXY_DLL_INIT_FN_NAME "InternetInitalizeAutoProxyDll"
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// private prototypes
|
|||
|
//
|
|||
|
|
|||
|
PRIVATE
|
|||
|
LPSTR
|
|||
|
GetRegistryProxyParameter(
|
|||
|
IN LPSTR lpszParameterName
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// private vars
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// hExternalAutoConfigDLL - NULL when DLL is not Loaded, a specialized
|
|||
|
// DLL that WININET can load, and use to determine what proxies to use.
|
|||
|
//
|
|||
|
|
|||
|
HINSTANCE hExternalAutoConfigDLL = NULL;
|
|||
|
|
|||
|
GET_PROXY_INFO_FN pGetProxyInfo;
|
|||
|
|
|||
|
PROXY_SCHEME_FN pProxyScheme;
|
|||
|
|
|||
|
IS_BYPASSED_FN pIsBypassed;
|
|||
|
|
|||
|
PROXY_DLL_INIT_FN pProxyDllInit;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL fExternalAutoConfigDllInited = FALSE;
|
|||
|
BOOL fExternalAutoConfigDllInitFuncCalled = FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// functions
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
IsLocalMacro(
|
|||
|
IN LPSTR lpszMetaName,
|
|||
|
IN DWORD dwMetaNameLength
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Checks for local macro name
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
lpszMetaName - name to check
|
|||
|
|
|||
|
dwMetaNameLength - length
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOL
|
|||
|
TRUE - it is <local>
|
|||
|
|
|||
|
FALSE - not
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
INET_ASSERT(lpszMetaName != NULL);
|
|||
|
|
|||
|
static const char s_local[] = "<local>";
|
|||
|
|
|||
|
return (strnicmp(s_local, lpszMetaName, dwMetaNameLength) == 0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
LoadExternalAutoConfigDll(
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Loads an external DLL which decides which proxy to use on a per connection basis.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
none.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOL
|
|||
|
TRUE - DLL loaded successfully, and should be used.
|
|||
|
|
|||
|
FALSE - Could not load DLL.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BOOL fReturn = FALSE;
|
|||
|
|
|||
|
if (lpszAutoProxyDll == NULL)
|
|||
|
return FALSE;
|
|||
|
|
|||
|
EnterCriticalSection(&AutoProxyDllCritSec);
|
|||
|
|
|||
|
if ( fExternalAutoConfigDllInited )
|
|||
|
{
|
|||
|
fReturn = TRUE;
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
|
|||
|
hExternalAutoConfigDLL = LoadLibrary(lpszAutoProxyDll);
|
|||
|
|
|||
|
if ( !hExternalAutoConfigDLL )
|
|||
|
{
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
pGetProxyInfo = (GET_PROXY_INFO_FN)
|
|||
|
GetProcAddress(hExternalAutoConfigDLL, GET_PROXY_INFO_FN_NAME);
|
|||
|
|
|||
|
|
|||
|
pProxyScheme = (PROXY_SCHEME_FN)
|
|||
|
GetProcAddress(hExternalAutoConfigDLL, PROXY_SCHEME_FN_NAME);
|
|||
|
|
|||
|
|
|||
|
pIsBypassed = (IS_BYPASSED_FN)
|
|||
|
GetProcAddress(hExternalAutoConfigDLL, IS_BYPASSED_FN_NAME);
|
|||
|
|
|||
|
|
|||
|
pProxyDllInit = (PROXY_DLL_INIT_FN)
|
|||
|
GetProcAddress(hExternalAutoConfigDLL, PROXY_DLL_INIT_FN_NAME );
|
|||
|
|
|||
|
//
|
|||
|
// Don't error out unless we don't succeed on anything
|
|||
|
//
|
|||
|
|
|||
|
if ( !pGetProxyInfo && !pProxyScheme && !pIsBypassed && !pProxyDllInit)
|
|||
|
{
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
fExternalAutoConfigDllInited = TRUE;
|
|||
|
fReturn = TRUE;
|
|||
|
|
|||
|
quit:
|
|||
|
|
|||
|
if ( !fReturn && hExternalAutoConfigDLL )
|
|||
|
{
|
|||
|
FreeLibrary(hExternalAutoConfigDLL);
|
|||
|
}
|
|||
|
|
|||
|
LeaveCriticalSection(&AutoProxyDllCritSec);
|
|||
|
|
|||
|
return fReturn;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
InitalizeAutoConfigDllIfNeeded(
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Executes an initalization callback function exported by an autoproxy DLL.
|
|||
|
This function insures the callback is only executed once.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
none.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOL
|
|||
|
TRUE - success
|
|||
|
|
|||
|
FALSE - failure
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
BOOL fReturn;
|
|||
|
|
|||
|
EnterCriticalSection(&AutoProxyDllCritSec);
|
|||
|
|
|||
|
if ( ! fExternalAutoConfigDllInited )
|
|||
|
{
|
|||
|
fReturn = TRUE;
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
|
|||
|
if ( fExternalAutoConfigDllInitFuncCalled )
|
|||
|
{
|
|||
|
fReturn = TRUE;
|
|||
|
goto quit;
|
|||
|
}
|
|||
|
|
|||
|
if ( pProxyDllInit )
|
|||
|
{
|
|||
|
fReturn = (pProxyDllInit) ( 0 );
|
|||
|
fExternalAutoConfigDllInitFuncCalled = TRUE;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
fReturn = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
quit:
|
|||
|
|
|||
|
LeaveCriticalSection(&AutoProxyDllCritSec);
|
|||
|
|
|||
|
return fReturn;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// member functions
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
PROXY_SERVER_LIST_ENTRY::WriteEntry(
|
|||
|
OUT LPSTR lpszBuffer,
|
|||
|
IN OUT LPDWORD lpdwBufferLength
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Writes this proxy server list entry as a string in the supplied buffer
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
lpszBuffer - pointer to buffer where string is written
|
|||
|
|
|||
|
lpdwBufferLength - IN: amount of space in buffer
|
|||
|
OUT: number of bytes copied, or required size
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOL
|
|||
|
TRUE - entry written to buffer
|
|||
|
|
|||
|
FALSE - entry not written to buffer - *lpdwBufferLength contains
|
|||
|
required size
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD requiredLength;
|
|||
|
LPSTR protocolName;
|
|||
|
DWORD protocolNameLength;
|
|||
|
LPSTR schemeName;
|
|||
|
DWORD schemeNameLength;
|
|||
|
INTERNET_PORT magnitude;
|
|||
|
|
|||
|
protocolName = MapUrlScheme(_Protocol, &protocolNameLength);
|
|||
|
if (protocolName != NULL) {
|
|||
|
requiredLength = protocolNameLength + 1; // for '='
|
|||
|
} else {
|
|||
|
requiredLength = 0;
|
|||
|
}
|
|||
|
schemeName = MapUrlScheme(_Scheme, &schemeNameLength);
|
|||
|
if (schemeName != NULL) {
|
|||
|
requiredLength += schemeNameLength + sizeof("://") - 1;
|
|||
|
}
|
|||
|
requiredLength += _ProxyName.StringLength();
|
|||
|
if (_ProxyPort != INTERNET_INVALID_PORT_NUMBER) {
|
|||
|
for (INTERNET_PORT n = 10000, i = 5; n > 0; n /= 10, --i) {
|
|||
|
if (_ProxyPort / n) {
|
|||
|
requiredLength += i + 1; // for ':'
|
|||
|
magnitude = n;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
BOOL success;
|
|||
|
|
|||
|
if (*lpdwBufferLength > requiredLength) {
|
|||
|
if (protocolName != NULL) {
|
|||
|
memcpy(lpszBuffer, protocolName, protocolNameLength);
|
|||
|
lpszBuffer += protocolNameLength;
|
|||
|
*lpszBuffer++ = '=';
|
|||
|
}
|
|||
|
if (schemeName != NULL) {
|
|||
|
memcpy(lpszBuffer, schemeName, schemeNameLength);
|
|||
|
lpszBuffer += schemeNameLength;
|
|||
|
memcpy(lpszBuffer, "://", sizeof("://") - 1);
|
|||
|
lpszBuffer += sizeof("://") - 1;
|
|||
|
}
|
|||
|
_ProxyName.CopyTo(lpszBuffer);
|
|||
|
lpszBuffer += _ProxyName.StringLength();
|
|||
|
if (_ProxyPort != INTERNET_INVALID_PORT_NUMBER) {
|
|||
|
*lpszBuffer++ = ':';
|
|||
|
for (INTERNET_PORT n = _ProxyPort, i = magnitude; i; i /= 10) {
|
|||
|
*lpszBuffer++ = (char)(n / i) + '0';
|
|||
|
n %= i;
|
|||
|
}
|
|||
|
}
|
|||
|
success = TRUE;
|
|||
|
} else {
|
|||
|
success = FALSE;
|
|||
|
}
|
|||
|
*lpdwBufferLength = requiredLength;
|
|||
|
return success;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
PROXY_SERVER_LIST::AddList(
|
|||
|
IN LPSTR lpszList
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Parses a list of proxy servers and creates a PROXY_SERVER_LIST_ENTRY for
|
|||
|
each one
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
lpszList - pointer to list of proxies of the form:
|
|||
|
|
|||
|
[<scheme>=][<scheme>"://"]<server>[":"<port>][";"*]
|
|||
|
|
|||
|
The list can be NULL, in which case we read it from the
|
|||
|
registry
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
DWORD
|
|||
|
Success - ERROR_SUCCESS
|
|||
|
|
|||
|
Failure - ERROR_INVALID_PARAMETER
|
|||
|
At least one entry in lpszList is bogus
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DEBUG_ENTER((DBG_PROXY,
|
|||
|
Dword,
|
|||
|
"PROXY_SERVER_LIST::AddList",
|
|||
|
"%.80q",
|
|||
|
lpszList
|
|||
|
));
|
|||
|
|
|||
|
DWORD entryLength;
|
|||
|
LPSTR protocolName;
|
|||
|
DWORD protocolLength;
|
|||
|
LPSTR schemeName;
|
|||
|
DWORD schemeLength;
|
|||
|
LPSTR serverName;
|
|||
|
DWORD serverLength;
|
|||
|
PARSER_STATE state;
|
|||
|
DWORD nSlashes;
|
|||
|
INTERNET_PORT port;
|
|||
|
BOOL done;
|
|||
|
|
|||
|
entryLength = 0;
|
|||
|
protocolName = lpszList;
|
|||
|
protocolLength = 0;
|
|||
|
schemeName = NULL;
|
|||
|
schemeLength = 0;
|
|||
|
serverName = NULL;
|
|||
|
serverLength = 0;
|
|||
|
state = STATE_PROTOCOL;
|
|||
|
nSlashes = 0;
|
|||
|
port = 0;
|
|||
|
done = FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// walk the list, pulling out the various scheme parts
|
|||
|
//
|
|||
|
|
|||
|
do {
|
|||
|
|
|||
|
char ch = *lpszList++;
|
|||
|
|
|||
|
if ((nSlashes == 1) && (ch != '/')) {
|
|||
|
state = STATE_ERROR;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
switch (ch) {
|
|||
|
case '=':
|
|||
|
if ((state == STATE_PROTOCOL) && (entryLength != 0)) {
|
|||
|
protocolLength = entryLength;
|
|||
|
entryLength = 0;
|
|||
|
state = STATE_SCHEME;
|
|||
|
schemeName = lpszList;
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// '=' can't legally appear anywhere else
|
|||
|
//
|
|||
|
|
|||
|
state = STATE_ERROR;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case ':':
|
|||
|
switch (state) {
|
|||
|
case STATE_PROTOCOL:
|
|||
|
if (*lpszList == '/') {
|
|||
|
schemeName = protocolName;
|
|||
|
protocolName = NULL;
|
|||
|
schemeLength = entryLength;
|
|||
|
protocolLength = 0;
|
|||
|
state = STATE_SCHEME;
|
|||
|
} else if (*lpszList != '\0') {
|
|||
|
serverName = protocolName;
|
|||
|
serverLength = entryLength;
|
|||
|
state = STATE_PORT;
|
|||
|
} else {
|
|||
|
state = STATE_ERROR;
|
|||
|
}
|
|||
|
entryLength = 0;
|
|||
|
break;
|
|||
|
|
|||
|
case STATE_SCHEME:
|
|||
|
if (*lpszList == '/') {
|
|||
|
schemeLength = entryLength;
|
|||
|
} else if (*lpszList != '\0') {
|
|||
|
serverName = schemeName;
|
|||
|
serverLength = entryLength;
|
|||
|
state = STATE_PORT;
|
|||
|
} else {
|
|||
|
state = STATE_ERROR;
|
|||
|
}
|
|||
|
entryLength = 0;
|
|||
|
break;
|
|||
|
|
|||
|
case STATE_SERVER:
|
|||
|
serverLength = entryLength;
|
|||
|
state = STATE_PORT;
|
|||
|
entryLength = 0;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
state = STATE_ERROR;
|
|||
|
break;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case '/':
|
|||
|
if ((state == STATE_SCHEME) && (nSlashes < 2) && (entryLength == 0)) {
|
|||
|
if (++nSlashes == 2) {
|
|||
|
state = STATE_SERVER;
|
|||
|
serverName = lpszList;
|
|||
|
}
|
|||
|
} else {
|
|||
|
state = STATE_ERROR;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
if (state != STATE_PORT) {
|
|||
|
++entryLength;
|
|||
|
} else if (isdigit(ch)) {
|
|||
|
|
|||
|
//
|
|||
|
// BUGBUG - we will overflow if >65535
|
|||
|
//
|
|||
|
|
|||
|
port = port * 10 + (ch - '0');
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// STATE_PORT && non-digit character - error
|
|||
|
//
|
|||
|
|
|||
|
state = STATE_ERROR;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case '\0':
|
|||
|
done = TRUE;
|
|||
|
|
|||
|
//
|
|||
|
// fall through
|
|||
|
//
|
|||
|
|
|||
|
case '\t':
|
|||
|
case '\n':
|
|||
|
case '\v': // vertical tab, 0x0b
|
|||
|
case '\f': // form feed, 0x0c
|
|||
|
case '\r':
|
|||
|
case ' ':
|
|||
|
case ';':
|
|||
|
case ',':
|
|||
|
if (serverLength == 0) {
|
|||
|
serverLength = entryLength;
|
|||
|
}
|
|||
|
if (serverLength != 0) {
|
|||
|
if (serverName == NULL) {
|
|||
|
serverName = (schemeName != NULL)
|
|||
|
? schemeName
|
|||
|
: protocolName;
|
|||
|
}
|
|||
|
|
|||
|
INET_ASSERT(serverName != NULL);
|
|||
|
|
|||
|
INTERNET_SCHEME protocol;
|
|||
|
|
|||
|
if (protocolLength != 0) {
|
|||
|
protocol = MapUrlSchemeName(protocolName, protocolLength);
|
|||
|
} else {
|
|||
|
protocol = INTERNET_SCHEME_DEFAULT;
|
|||
|
}
|
|||
|
|
|||
|
INTERNET_SCHEME scheme;
|
|||
|
|
|||
|
if (schemeLength != 0) {
|
|||
|
scheme = MapUrlSchemeName(schemeName, schemeLength);
|
|||
|
} else {
|
|||
|
scheme = INTERNET_SCHEME_DEFAULT;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// add an entry if this is a protocol we handle and we don't
|
|||
|
// already have an entry for it
|
|||
|
//
|
|||
|
|
|||
|
if ((protocol != INTERNET_SCHEME_UNKNOWN)
|
|||
|
&& (scheme != INTERNET_SCHEME_UNKNOWN)
|
|||
|
|
|||
|
//
|
|||
|
// we can only currently handle CERN (secure or unsecure) and
|
|||
|
// FTP proxies, so kick out anything that wants to go via any
|
|||
|
// other proxy scheme
|
|||
|
//
|
|||
|
|
|||
|
&& ((scheme == INTERNET_SCHEME_DEFAULT)
|
|||
|
|| (scheme == INTERNET_SCHEME_FTP)
|
|||
|
|| (scheme == INTERNET_SCHEME_HTTP)
|
|||
|
|| (scheme == INTERNET_SCHEME_HTTPS))) {
|
|||
|
if (!Find(protocol)) {
|
|||
|
|
|||
|
//
|
|||
|
// don't worry if Add() fails - we just continue
|
|||
|
//
|
|||
|
|
|||
|
Add(protocol, scheme, serverName, serverLength, port);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
entryLength = 0;
|
|||
|
protocolName = lpszList;
|
|||
|
protocolLength = 0;
|
|||
|
schemeName = NULL;
|
|||
|
schemeLength = 0;
|
|||
|
serverName = NULL;
|
|||
|
serverLength = 0;
|
|||
|
nSlashes = 0;
|
|||
|
port = 0;
|
|||
|
state = STATE_PROTOCOL;
|
|||
|
break;
|
|||
|
}
|
|||
|
if (state == STATE_ERROR) {
|
|||
|
break;
|
|||
|
}
|
|||
|
} while (!done);
|
|||
|
|
|||
|
DWORD error;
|
|||
|
|
|||
|
if (state == STATE_ERROR) {
|
|||
|
error = ERROR_INVALID_PARAMETER;
|
|||
|
} else {
|
|||
|
error = ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
DEBUG_LEAVE(error);
|
|||
|
|
|||
|
return error;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
PROXY_SERVER_LIST::Find(
|
|||
|
IN INTERNET_SCHEME tScheme
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Find a PROXY_SERVER_LIST_ENTRY based on the scheme
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
tScheme - protocol scheme to find
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOL
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DEBUG_ENTER((DBG_PROXY,
|
|||
|
Bool,
|
|||
|
"PROXY_SERVER_LIST::Find",
|
|||
|
"%s",
|
|||
|
InternetMapScheme(tScheme)
|
|||
|
));
|
|||
|
|
|||
|
BOOL found = FALSE;
|
|||
|
|
|||
|
LockSerializedList(&_List);
|
|||
|
|
|||
|
for (PLIST_ENTRY entry = HeadOfSerializedList(&_List);
|
|||
|
entry != (PLIST_ENTRY)SlSelf(&_List);
|
|||
|
entry = entry->Flink) {
|
|||
|
|
|||
|
PROXY_SERVER_LIST_ENTRY * info;
|
|||
|
|
|||
|
info = CONTAINING_RECORD(entry, PROXY_SERVER_LIST_ENTRY, _List);
|
|||
|
|
|||
|
if (info->_Protocol == tScheme) {
|
|||
|
found = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
UnlockSerializedList(&_List);
|
|||
|
|
|||
|
DEBUG_LEAVE(found);
|
|||
|
|
|||
|
return found;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
PROXY_SERVER_LIST::Add(
|
|||
|
IN INTERNET_SCHEME tProtocol,
|
|||
|
IN INTERNET_SCHEME tScheme,
|
|||
|
IN LPSTR lpszHostName,
|
|||
|
IN DWORD dwHostNameLength,
|
|||
|
IN INTERNET_PORT nPort
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Create an add a PROXY_SERVER_LIST_ENTRY to the PROXY_SERVER_LIST
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
tProtocol - protocol which uses the proxy
|
|||
|
|
|||
|
tScheme - scheme used to talk to the proxy
|
|||
|
|
|||
|
lpszHostName - proxy host name
|
|||
|
|
|||
|
dwHostNameLength - length of proxy host name
|
|||
|
|
|||
|
nPort - port at proxy host
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
DWORD
|
|||
|
Success - ERROR_SUCCESS
|
|||
|
|
|||
|
Failure - ERROR_NOT_ENOUGH_MEMORY
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DEBUG_ENTER((DBG_PROXY,
|
|||
|
Dword,
|
|||
|
"PROXY_SERVER_LIST::Add",
|
|||
|
"%s, %s, %.*q, %d, %d",
|
|||
|
InternetMapScheme(tProtocol),
|
|||
|
InternetMapScheme(tScheme),
|
|||
|
dwHostNameLength,
|
|||
|
lpszHostName,
|
|||
|
dwHostNameLength,
|
|||
|
nPort
|
|||
|
));
|
|||
|
|
|||
|
PROXY_SERVER_LIST_ENTRY * entry;
|
|||
|
|
|||
|
entry = new PROXY_SERVER_LIST_ENTRY(tProtocol,
|
|||
|
tScheme,
|
|||
|
lpszHostName,
|
|||
|
dwHostNameLength,
|
|||
|
nPort
|
|||
|
);
|
|||
|
|
|||
|
DWORD error;
|
|||
|
|
|||
|
if (entry != NULL) {
|
|||
|
//error = entry->ResolveAddress();
|
|||
|
//if (error == ERROR_SUCCESS) {
|
|||
|
// InsertAtTailOfSerializedList(&_List, &entry->_List);
|
|||
|
//}
|
|||
|
if (entry->_Protocol == INTERNET_SCHEME_DEFAULT) {
|
|||
|
InsertAtTailOfSerializedList(&_List, &entry->_List);
|
|||
|
} else {
|
|||
|
InsertAtHeadOfSerializedList(&_List, &entry->_List);
|
|||
|
}
|
|||
|
error = ERROR_SUCCESS;
|
|||
|
} else {
|
|||
|
error = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
}
|
|||
|
|
|||
|
DEBUG_LEAVE(error);
|
|||
|
|
|||
|
return error;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
INTERNET_SCHEME
|
|||
|
PROXY_SERVER_LIST::ProxyScheme(
|
|||
|
IN INTERNET_SCHEME tProtocol
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Determines protocol over which tScheme goes through proxy
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
tProtocol - protocol scheme used to retrieve data (e.g. FTP)
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
INTERNET_SCHEME
|
|||
|
Success - scheme by which protocol goes via proxy
|
|||
|
|
|||
|
Failure - INTERNET_SCHEME_UNKNOWN
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DEBUG_ENTER((DBG_PROXY,
|
|||
|
Int,
|
|||
|
"PROXY_SERVER_LIST::ProxyScheme",
|
|||
|
"%s",
|
|||
|
InternetMapScheme(tProtocol)
|
|||
|
));
|
|||
|
|
|||
|
INTERNET_SCHEME tScheme = INTERNET_SCHEME_UNKNOWN;
|
|||
|
|
|||
|
LockSerializedList(&_List);
|
|||
|
|
|||
|
//
|
|||
|
// the list really shouldn't be empty if we're here
|
|||
|
//
|
|||
|
|
|||
|
INET_ASSERT(!IsSerializedListEmpty(&_List));
|
|||
|
|
|||
|
for (PLIST_ENTRY entry = HeadOfSerializedList(&_List);
|
|||
|
entry != (PLIST_ENTRY)SlSelf(&_List);
|
|||
|
entry = entry->Flink) {
|
|||
|
|
|||
|
PROXY_SERVER_LIST_ENTRY * info;
|
|||
|
|
|||
|
info = CONTAINING_RECORD(entry, PROXY_SERVER_LIST_ENTRY, _List);
|
|||
|
|
|||
|
//
|
|||
|
// if we find a match for the protocol, or this protocol is handled by
|
|||
|
// the default proxy entry then we are done
|
|||
|
//
|
|||
|
|
|||
|
if ((info->_Protocol == tProtocol)
|
|||
|
|| (info->_Protocol == INTERNET_SCHEME_DEFAULT)) {
|
|||
|
tScheme = info->_Scheme;
|
|||
|
|
|||
|
//
|
|||
|
// the default scheme is HTTP (CERN proxy)
|
|||
|
//
|
|||
|
|
|||
|
if (tScheme == INTERNET_SCHEME_DEFAULT) {
|
|||
|
tScheme = INTERNET_SCHEME_HTTP;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
UnlockSerializedList(&_List);
|
|||
|
|
|||
|
DEBUG_LEAVE(tScheme);
|
|||
|
|
|||
|
return tScheme;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
PROXY_SERVER_LIST::GetProxyInfo(
|
|||
|
IN INTERNET_SCHEME tProtocol,
|
|||
|
IN OUT LPINTERNET_SCHEME lptScheme,
|
|||
|
OUT LPSTR * lplpszHostName,
|
|||
|
OUT LPDWORD lpdwHostNameLength,
|
|||
|
OUT LPINTERNET_PORT lpHostPort
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Given a protocol, map it to the proxy we use to retrieve the data
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
tProtocol - protocol to map (e.g. find the proxy for FTP)
|
|||
|
|
|||
|
lptScheme - IN: preferred scheme if INTERNET_SCHEME_DEFAULT
|
|||
|
OUT: returned scheme
|
|||
|
|
|||
|
lplpszHostName - pointer to returned pointer to host name
|
|||
|
|
|||
|
lpdwHostNameLength - pointer to returned host name length
|
|||
|
|
|||
|
lpHostPort - pointer to returned host port
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOL
|
|||
|
TRUE - requested info has been returned
|
|||
|
|
|||
|
FALSE - requested info was not found
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DEBUG_ENTER((DBG_PROXY,
|
|||
|
Bool,
|
|||
|
"PROXY_SERVER_LIST::GetProxyInfo",
|
|||
|
"%s, %#x, %#x, %#x, %#x",
|
|||
|
InternetMapScheme(tProtocol),
|
|||
|
lptScheme,
|
|||
|
lplpszHostName,
|
|||
|
lpdwHostNameLength,
|
|||
|
lpHostPort
|
|||
|
));
|
|||
|
|
|||
|
INET_ASSERT(tProtocol != INTERNET_SCHEME_UNKNOWN);
|
|||
|
|
|||
|
//
|
|||
|
// *lptScheme must now be one of the recognized schemes, or the default
|
|||
|
//
|
|||
|
|
|||
|
INET_ASSERT((*lptScheme == INTERNET_SCHEME_DEFAULT)
|
|||
|
|| (*lptScheme == INTERNET_SCHEME_FTP)
|
|||
|
|| (*lptScheme == INTERNET_SCHEME_GOPHER)
|
|||
|
|| (*lptScheme == INTERNET_SCHEME_HTTP)
|
|||
|
|| (*lptScheme == INTERNET_SCHEME_HTTPS)
|
|||
|
|| (*lptScheme == INTERNET_SCHEME_SOCKS)
|
|||
|
);
|
|||
|
|
|||
|
BOOL found = FALSE;
|
|||
|
|
|||
|
LockSerializedList(&_List);
|
|||
|
|
|||
|
//
|
|||
|
// the list really shouldn't be empty if we're here
|
|||
|
//
|
|||
|
|
|||
|
INET_ASSERT(!IsSerializedListEmpty(&_List));
|
|||
|
|
|||
|
for (PLIST_ENTRY entry = HeadOfSerializedList(&_List);
|
|||
|
entry != (PLIST_ENTRY)SlSelf(&_List);
|
|||
|
entry = entry->Flink) {
|
|||
|
|
|||
|
PROXY_SERVER_LIST_ENTRY * info;
|
|||
|
|
|||
|
info = CONTAINING_RECORD(entry, PROXY_SERVER_LIST_ENTRY, _List);
|
|||
|
|
|||
|
//
|
|||
|
// if we find a match for the protocol, or this protocol is handled by
|
|||
|
// the default proxy entry then we are done
|
|||
|
//
|
|||
|
// Hack: But make sure its NOT socks since, socks must be
|
|||
|
// an exact match !!! No defaults.
|
|||
|
//
|
|||
|
|
|||
|
if ((info->_Protocol == tProtocol)
|
|||
|
|| ((info->_Protocol == INTERNET_SCHEME_DEFAULT)
|
|||
|
&& (tProtocol != INTERNET_SCHEME_SOCKS) )) {
|
|||
|
|
|||
|
INTERNET_SCHEME scheme = info->_Scheme;
|
|||
|
|
|||
|
//
|
|||
|
// the returned scheme is the input preferred scheme unless it was
|
|||
|
// the default scheme in which case we return HTTP (CERN proxy)
|
|||
|
//
|
|||
|
|
|||
|
if (scheme == INTERNET_SCHEME_DEFAULT) {
|
|||
|
scheme = (*lptScheme == INTERNET_SCHEME_DEFAULT)
|
|||
|
? INTERNET_SCHEME_HTTP
|
|||
|
: *lptScheme;
|
|||
|
}
|
|||
|
*lptScheme = scheme;
|
|||
|
|
|||
|
//
|
|||
|
// BUGBUG
|
|||
|
//
|
|||
|
// N.B. We are returning a pointer to the ICSTRING's string buffer.
|
|||
|
// While we don't expect this string to be reallocated or the proxy
|
|||
|
// info to change, it may do if we ever reset the proxy list on the
|
|||
|
// fly. Something we may have to enable for Nashville
|
|||
|
//
|
|||
|
|
|||
|
*lplpszHostName = info->_ProxyName.StringAddress();
|
|||
|
*lpdwHostNameLength = info->_ProxyName.StringLength();
|
|||
|
|
|||
|
INTERNET_PORT port = info->_ProxyPort;
|
|||
|
|
|||
|
//
|
|||
|
// map the default port value
|
|||
|
//
|
|||
|
|
|||
|
if (port == INTERNET_INVALID_PORT_NUMBER) {
|
|||
|
switch (scheme) {
|
|||
|
case INTERNET_SCHEME_FTP:
|
|||
|
port = INTERNET_DEFAULT_FTP_PORT;
|
|||
|
break;
|
|||
|
|
|||
|
case INTERNET_SCHEME_GOPHER:
|
|||
|
port = INTERNET_DEFAULT_GOPHER_PORT;
|
|||
|
break;
|
|||
|
|
|||
|
case INTERNET_SCHEME_HTTP:
|
|||
|
port = INTERNET_DEFAULT_HTTP_PORT;
|
|||
|
break;
|
|||
|
|
|||
|
case INTERNET_SCHEME_HTTPS:
|
|||
|
port = INTERNET_DEFAULT_HTTPS_PORT;
|
|||
|
break;
|
|||
|
case INTERNET_SCHEME_SOCKS:
|
|||
|
port = INTERNET_DEFAULT_SOCKS_PORT;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
*lpHostPort = port;
|
|||
|
found = TRUE;
|
|||
|
|
|||
|
DEBUG_PRINT(PROXY,
|
|||
|
INFO,
|
|||
|
("proxy = %s://%s:%d\n",
|
|||
|
MapUrlSchemeToName(scheme),
|
|||
|
info->_ProxyName.StringAddress(),
|
|||
|
port
|
|||
|
));
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
UnlockSerializedList(&_List);
|
|||
|
|
|||
|
DEBUG_LEAVE(found);
|
|||
|
|
|||
|
return found;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
PROXY_SERVER_LIST::AddToBypassList(
|
|||
|
IN PROXY_BYPASS_LIST * lpBypassList
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
For all proxy servers in the server list, we add the details to the bypass
|
|||
|
list. By default, an app mustn't send a request to the proxy via the proxy!
|
|||
|
Additionally, the app should not have to specifically nominate the proxy
|
|||
|
server(s) as bypassing the proxy
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
lpBypassList - pointer to bypass proxy list where proxy servers will be
|
|||
|
added
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
DWORD
|
|||
|
Success - ERROR_SUCCESS
|
|||
|
|
|||
|
Failure - ERROR_NOT_ENOUGH_MEMORY
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD error = ERROR_SUCCESS;
|
|||
|
PLIST_ENTRY entry = HeadOfSerializedList(&_List);
|
|||
|
|
|||
|
while ((entry != (PLIST_ENTRY)SlSelf(&_List)) && (error == ERROR_SUCCESS)) {
|
|||
|
|
|||
|
PROXY_SERVER_LIST_ENTRY * info = (PROXY_SERVER_LIST_ENTRY *)entry;
|
|||
|
|
|||
|
if (!lpBypassList->Find(info->_Scheme,
|
|||
|
info->_ProxyName.StringAddress(),
|
|||
|
info->_ProxyName.StringLength(),
|
|||
|
info->_ProxyPort)) {
|
|||
|
error = lpBypassList->Add(info->_Scheme,
|
|||
|
info->_ProxyName.StringAddress(),
|
|||
|
info->_ProxyName.StringLength(),
|
|||
|
info->_ProxyPort
|
|||
|
);
|
|||
|
}
|
|||
|
entry = entry->Flink;
|
|||
|
}
|
|||
|
return error;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
PROXY_SERVER_LIST::GetList(
|
|||
|
OUT LPSTR * lplpszList,
|
|||
|
IN DWORD dwBufferLength,
|
|||
|
IN OUT LPDWORD lpdwRequiredLength
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Writes the list of proxy servers to a buffer, and/or returns the required
|
|||
|
buffer length
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
lplpszList - pointer to pointer to buffer where list is written, if
|
|||
|
sufficient space
|
|||
|
|
|||
|
dwBufferLength - amount of space in *lplpszList
|
|||
|
|
|||
|
lpdwRequiredLength - OUT: cumulative size of data
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LPSTR lpszList = *lplpszList;
|
|||
|
BOOL firstTime = TRUE;
|
|||
|
BOOL outOfBuffer = FALSE;
|
|||
|
|
|||
|
LockSerializedList(&_List);
|
|||
|
|
|||
|
for (PLIST_ENTRY entry = HeadOfSerializedList(&_List);
|
|||
|
entry != (PLIST_ENTRY)SlSelf(&_List);
|
|||
|
entry = entry->Flink) {
|
|||
|
|
|||
|
PROXY_SERVER_LIST_ENTRY * info;
|
|||
|
|
|||
|
info = CONTAINING_RECORD(entry, PROXY_SERVER_LIST_ENTRY, _List);
|
|||
|
if (!firstTime) {
|
|||
|
|
|||
|
//
|
|||
|
// write delimiter if enough space
|
|||
|
//
|
|||
|
|
|||
|
if (dwBufferLength >= 1) {
|
|||
|
*lpszList++ = ' ';
|
|||
|
--dwBufferLength;
|
|||
|
}
|
|||
|
++*lpdwRequiredLength;
|
|||
|
} else {
|
|||
|
firstTime = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// find the length of the current entry & write it to the buffer if
|
|||
|
// enough space
|
|||
|
//
|
|||
|
|
|||
|
DWORD length = dwBufferLength;
|
|||
|
|
|||
|
info->WriteEntry(lpszList, &length);
|
|||
|
if (dwBufferLength >= length) {
|
|||
|
|
|||
|
//
|
|||
|
// we wrote it
|
|||
|
//
|
|||
|
|
|||
|
dwBufferLength -= length;
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// no buffer left
|
|||
|
//
|
|||
|
|
|||
|
dwBufferLength = 0;
|
|||
|
outOfBuffer = TRUE;
|
|||
|
}
|
|||
|
*lpdwRequiredLength += length;
|
|||
|
lpszList += length;
|
|||
|
}
|
|||
|
|
|||
|
if (!outOfBuffer) {
|
|||
|
if (dwBufferLength > 0) {
|
|||
|
*lpszList++ = '\0';
|
|||
|
*lplpszList = lpszList;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// add 1 for the terminating NUL
|
|||
|
//
|
|||
|
|
|||
|
++*lpdwRequiredLength;
|
|||
|
|
|||
|
UnlockSerializedList(&_List);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
PROXY_BYPASS_LIST_ENTRY::WriteEntry(
|
|||
|
OUT LPSTR lpszBuffer,
|
|||
|
IN OUT LPDWORD lpdwBufferLength
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Writes this proxy bypass list entry as a string in the supplied buffer
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
lpszBuffer - pointer to buffer where string is written
|
|||
|
|
|||
|
lpdwBufferLength - IN: amount of space in buffer
|
|||
|
OUT: number of bytes copied, or required size
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOL
|
|||
|
TRUE - entry written to buffer
|
|||
|
|
|||
|
FALSE - entry not written to buffer - *lpdwBufferLength contains
|
|||
|
required size
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD requiredLength;
|
|||
|
LPSTR schemeName;
|
|||
|
DWORD schemeNameLength;
|
|||
|
INTERNET_PORT magnitude;
|
|||
|
|
|||
|
if (_Scheme != INTERNET_SCHEME_DEFAULT) {
|
|||
|
schemeName = MapUrlScheme(_Scheme, &schemeNameLength);
|
|||
|
requiredLength = schemeNameLength + sizeof("://") - 1;
|
|||
|
} else {
|
|||
|
schemeName = NULL;
|
|||
|
requiredLength = 0;
|
|||
|
}
|
|||
|
if (IsLocal()) {
|
|||
|
requiredLength += sizeof("<local>") - 1;
|
|||
|
} else {
|
|||
|
requiredLength += _Name.StringLength();
|
|||
|
}
|
|||
|
if (_Port != INTERNET_INVALID_PORT_NUMBER) {
|
|||
|
for (INTERNET_PORT n = 10000, i = 5; n > 0; n /= 10, --i) {
|
|||
|
if (_Port / n) {
|
|||
|
requiredLength += i + 1;
|
|||
|
magnitude = n;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
BOOL success;
|
|||
|
|
|||
|
if (*lpdwBufferLength > requiredLength) {
|
|||
|
if (schemeName != NULL) {
|
|||
|
memcpy(lpszBuffer, schemeName, schemeNameLength);
|
|||
|
lpszBuffer += schemeNameLength;
|
|||
|
memcpy(lpszBuffer, "://", sizeof("://") - 1);
|
|||
|
lpszBuffer += sizeof("://") - 1;
|
|||
|
}
|
|||
|
if (IsLocal()) {
|
|||
|
memcpy(lpszBuffer, "<local>", sizeof("<local>") - 1);
|
|||
|
lpszBuffer += sizeof("<local>") - 1;
|
|||
|
} else {
|
|||
|
_Name.CopyTo(lpszBuffer);
|
|||
|
lpszBuffer += _Name.StringLength();
|
|||
|
}
|
|||
|
if (_Port != INTERNET_INVALID_PORT_NUMBER) {
|
|||
|
*lpszBuffer++ = ':';
|
|||
|
for (INTERNET_PORT n = _Port, i = magnitude; i; i /= 10) {
|
|||
|
*lpszBuffer++ = (char)(n / i) + '0';
|
|||
|
n %= i;
|
|||
|
}
|
|||
|
}
|
|||
|
success = TRUE;
|
|||
|
} else {
|
|||
|
success = FALSE;
|
|||
|
}
|
|||
|
*lpdwBufferLength = requiredLength;
|
|||
|
return success;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
PROXY_BYPASS_LIST::AddList(
|
|||
|
IN LPSTR lpszList
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Parses a list of proxy bypass specifiers and adds them to the list
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
lpszList - pointer to string containing list of proxy bypass specifiers.
|
|||
|
The format is:
|
|||
|
|
|||
|
[<scheme>"://"][<server>][":"<port>"]
|
|||
|
|
|||
|
The list can be NULL, in which case we read it from the
|
|||
|
registry
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
DWORD
|
|||
|
Success - ERROR_SUCCESS
|
|||
|
|
|||
|
Failure - ERROR_INVALID_PARAMETER
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DEBUG_ENTER((DBG_PROXY,
|
|||
|
Dword,
|
|||
|
"PROXY_BYPASS_LIST::AddList",
|
|||
|
"%.80q",
|
|||
|
lpszList
|
|||
|
));
|
|||
|
|
|||
|
DWORD entryLength;
|
|||
|
LPSTR schemeName;
|
|||
|
DWORD schemeLength;
|
|||
|
LPSTR serverName;
|
|||
|
DWORD serverLength;
|
|||
|
PARSER_STATE state;
|
|||
|
DWORD nSlashes;
|
|||
|
INTERNET_PORT port;
|
|||
|
BOOL done;
|
|||
|
|
|||
|
entryLength = 0;
|
|||
|
schemeName = lpszList;
|
|||
|
schemeLength = 0;
|
|||
|
serverName = NULL;
|
|||
|
serverLength = 0;
|
|||
|
state = STATE_SCHEME;
|
|||
|
nSlashes = 0;
|
|||
|
port = 0;
|
|||
|
done = FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// walk the list, pulling out the various scheme parts
|
|||
|
//
|
|||
|
|
|||
|
do {
|
|||
|
|
|||
|
char ch = *lpszList++;
|
|||
|
|
|||
|
if ((nSlashes == 1) && (ch != '/')) {
|
|||
|
state = STATE_ERROR;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
switch (ch) {
|
|||
|
case ':':
|
|||
|
switch (state) {
|
|||
|
case STATE_SCHEME:
|
|||
|
if (*lpszList == '/') {
|
|||
|
schemeLength = entryLength;
|
|||
|
} else if (*lpszList != '\0') {
|
|||
|
serverName = schemeName;
|
|||
|
serverLength = entryLength;
|
|||
|
if (serverLength == 0) {
|
|||
|
serverLength = 1;
|
|||
|
serverName = "*";
|
|||
|
}
|
|||
|
state = STATE_PORT;
|
|||
|
} else {
|
|||
|
state = STATE_ERROR;
|
|||
|
}
|
|||
|
entryLength = 0;
|
|||
|
break;
|
|||
|
|
|||
|
case STATE_SERVER:
|
|||
|
serverLength = entryLength;
|
|||
|
state = STATE_PORT;
|
|||
|
entryLength = 0;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
state = STATE_ERROR;
|
|||
|
break;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case '/':
|
|||
|
if ((state == STATE_SCHEME) && (nSlashes < 2) && (entryLength == 0)) {
|
|||
|
if (++nSlashes == 2) {
|
|||
|
state = STATE_SERVER;
|
|||
|
serverName = lpszList;
|
|||
|
}
|
|||
|
} else {
|
|||
|
state = STATE_ERROR;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
if (state != STATE_PORT) {
|
|||
|
++entryLength;
|
|||
|
} else if (isdigit(ch)) {
|
|||
|
|
|||
|
//
|
|||
|
// BUGBUG - we will overflow if >65535
|
|||
|
//
|
|||
|
|
|||
|
port = port * 10 + (ch - '0');
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// STATE_PORT && non-digit character - error
|
|||
|
//
|
|||
|
|
|||
|
state = STATE_ERROR;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case '\0':
|
|||
|
done = TRUE;
|
|||
|
|
|||
|
//
|
|||
|
// fall through
|
|||
|
//
|
|||
|
|
|||
|
case '\t':
|
|||
|
case '\n':
|
|||
|
case '\v': // vertical tab, 0x0b
|
|||
|
case '\f': // form feed, 0x0c
|
|||
|
case '\r':
|
|||
|
case ' ':
|
|||
|
case ';':
|
|||
|
case ',':
|
|||
|
if (serverLength == 0) {
|
|||
|
serverLength = entryLength;
|
|||
|
if ((serverLength == 0)
|
|||
|
&& ((state == STATE_SERVER) || (state == STATE_PORT))) {
|
|||
|
|
|||
|
//
|
|||
|
// we found e.g. "http://" or "http://:80". We allow this as
|
|||
|
// "http://*" or "http://*:80"
|
|||
|
//
|
|||
|
|
|||
|
serverLength = 1;
|
|||
|
serverName = "*";
|
|||
|
}
|
|||
|
}
|
|||
|
if (serverLength != 0) {
|
|||
|
if (serverName == NULL) {
|
|||
|
serverName = schemeName;
|
|||
|
}
|
|||
|
|
|||
|
INTERNET_SCHEME scheme;
|
|||
|
|
|||
|
if (schemeLength != 0) {
|
|||
|
scheme = MapUrlSchemeName(schemeName, schemeLength);
|
|||
|
} else {
|
|||
|
scheme = INTERNET_SCHEME_DEFAULT;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// add an entry if this is a protocol we handle and we don't
|
|||
|
// already have an entry for it
|
|||
|
//
|
|||
|
|
|||
|
if ((scheme != INTERNET_SCHEME_UNKNOWN)
|
|||
|
&& !Find(scheme, serverName, serverLength, port)) {
|
|||
|
|
|||
|
//
|
|||
|
// don't worry if Add() fails - we just continue
|
|||
|
//
|
|||
|
|
|||
|
Add(scheme, serverName, serverLength, port);
|
|||
|
}
|
|||
|
}
|
|||
|
entryLength = 0;
|
|||
|
schemeName = lpszList;
|
|||
|
schemeLength = 0;
|
|||
|
serverName = NULL;
|
|||
|
serverLength = 0;
|
|||
|
nSlashes = 0;
|
|||
|
port = 0;
|
|||
|
state = STATE_SCHEME;
|
|||
|
break;
|
|||
|
}
|
|||
|
if (state == STATE_ERROR) {
|
|||
|
break;
|
|||
|
}
|
|||
|
} while (!done);
|
|||
|
|
|||
|
DWORD error;
|
|||
|
|
|||
|
if (state == STATE_ERROR) {
|
|||
|
error = ERROR_INVALID_PARAMETER;
|
|||
|
} else {
|
|||
|
error = ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
DEBUG_LEAVE(error);
|
|||
|
|
|||
|
return error;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
PROXY_BYPASS_LIST::Find(
|
|||
|
IN INTERNET_SCHEME tScheme,
|
|||
|
IN LPSTR lpszHostName OPTIONAL,
|
|||
|
IN DWORD dwHostNameLength,
|
|||
|
IN INTERNET_PORT nPort
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Determines if a proxy bypass entry matches the criteria.
|
|||
|
|
|||
|
Currently, name matching is simplistic: e.g. "*.com" and "**.com" are
|
|||
|
treated as 2 separate strings, where we should collapse multiple wildcard
|
|||
|
specifiers, etc. Also: "w*" should replace "ww*", etc.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
tScheme - scheme for this entry
|
|||
|
|
|||
|
lpszHostName - host name or address. May contain wildcards (*)
|
|||
|
|
|||
|
dwHostNameLength - length of host name or address
|
|||
|
|
|||
|
nPort - port
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOL
|
|||
|
TRUE - an entry corresponding to the arguments was found
|
|||
|
|
|||
|
FALSE - didn't find entry
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DEBUG_ENTER((DBG_PROXY,
|
|||
|
Bool,
|
|||
|
"PROXY_BYPASS_LIST::Find",
|
|||
|
"%s, %.*q, %d, %d",
|
|||
|
InternetMapScheme(tScheme),
|
|||
|
dwHostNameLength,
|
|||
|
lpszHostName,
|
|||
|
dwHostNameLength,
|
|||
|
nPort
|
|||
|
));
|
|||
|
|
|||
|
BOOL isLocal = IsLocalMacro(lpszHostName, dwHostNameLength);
|
|||
|
BOOL found = FALSE;
|
|||
|
|
|||
|
LockSerializedList(&_List);
|
|||
|
|
|||
|
for (PLIST_ENTRY entry = HeadOfSerializedList(&_List);
|
|||
|
entry != (PLIST_ENTRY)SlSelf(&_List);
|
|||
|
entry = entry->Flink) {
|
|||
|
|
|||
|
PROXY_BYPASS_LIST_ENTRY * info;
|
|||
|
|
|||
|
info = CONTAINING_RECORD(entry, PROXY_BYPASS_LIST_ENTRY, _List);
|
|||
|
|
|||
|
//
|
|||
|
// do the easy bits first
|
|||
|
//
|
|||
|
|
|||
|
if (!((info->_Scheme == tScheme)
|
|||
|
|| (info->_Scheme == INTERNET_SCHEME_DEFAULT))) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
if (!((info->_Port == nPort)
|
|||
|
|| (info->_Port == INTERNET_INVALID_PORT_NUMBER))) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// check for name match
|
|||
|
//
|
|||
|
|
|||
|
if (info->_LocalSemantics) {
|
|||
|
if (isLocal) {
|
|||
|
found = TRUE;
|
|||
|
break;
|
|||
|
} else {
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// not local semantics, have to match target
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// BUGBUG - we only do simplistic matching. If the strings don't match
|
|||
|
// exactly, except for case, they are deemed to be different
|
|||
|
//
|
|||
|
|
|||
|
if (info->_Name.Strnicmp(lpszHostName, (int)dwHostNameLength) != 0) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// any path that didn't continue, or has not already broken out has
|
|||
|
// succeeded in finding a match
|
|||
|
//
|
|||
|
|
|||
|
DEBUG_PRINT(PROXY,
|
|||
|
INFO,
|
|||
|
("Matched: %q, %q\n",
|
|||
|
lpszHostName,
|
|||
|
info->_Name.StringAddress()
|
|||
|
));
|
|||
|
|
|||
|
found = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
UnlockSerializedList(&_List);
|
|||
|
|
|||
|
DEBUG_LEAVE(found);
|
|||
|
|
|||
|
return found;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
PROXY_BYPASS_LIST::Add(
|
|||
|
IN INTERNET_SCHEME tScheme,
|
|||
|
IN LPSTR lpszHostName,
|
|||
|
IN DWORD dwHostNameLength,
|
|||
|
IN INTERNET_PORT nPort
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Create and add a PROXY_BYPASS_LIST_ENTRY to the PROXY_BYPASS_LIST
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
tScheme - scheme to bypass. May be 0 meaning any protocol
|
|||
|
|
|||
|
lpszHostName - name of host to bypass. May be name or IP address and
|
|||
|
may contain wildcard characters
|
|||
|
|
|||
|
dwHostNameLength - length of bypass name string
|
|||
|
|
|||
|
nPort - port to bypass. May be 0, meaning any port
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
DWORD
|
|||
|
Success - ERROR_SUCCESS
|
|||
|
|
|||
|
Failure - ERROR_NOT_ENOUGH_MEMORY
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DEBUG_ENTER((DBG_PROXY,
|
|||
|
Dword,
|
|||
|
"PROXY_BYPASS_LIST::Add",
|
|||
|
"%s, %.*q, %d, %d",
|
|||
|
InternetMapScheme(tScheme),
|
|||
|
dwHostNameLength,
|
|||
|
lpszHostName,
|
|||
|
dwHostNameLength,
|
|||
|
nPort
|
|||
|
));
|
|||
|
|
|||
|
PROXY_BYPASS_LIST_ENTRY * entry;
|
|||
|
|
|||
|
entry = new PROXY_BYPASS_LIST_ENTRY(tScheme,
|
|||
|
lpszHostName,
|
|||
|
dwHostNameLength,
|
|||
|
nPort
|
|||
|
);
|
|||
|
|
|||
|
DWORD error;
|
|||
|
|
|||
|
if (entry != NULL) {
|
|||
|
|
|||
|
//
|
|||
|
// if the bypass entry uses local name matching semantics, then we add
|
|||
|
// it to the end of the list, else the head. The reason we do this is
|
|||
|
// to allow <local> to be a default after all other (possibly also
|
|||
|
// local) entries are checked
|
|||
|
//
|
|||
|
|
|||
|
if (entry->IsLocal()) {
|
|||
|
InsertAtTailOfSerializedList(&_List, &entry->_List);
|
|||
|
} else {
|
|||
|
InsertAtHeadOfSerializedList(&_List, &entry->_List);
|
|||
|
}
|
|||
|
error = ERROR_SUCCESS;
|
|||
|
} else {
|
|||
|
error = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
}
|
|||
|
|
|||
|
DEBUG_LEAVE(error);
|
|||
|
|
|||
|
return error;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
PROXY_BYPASS_LIST::IsBypassed(
|
|||
|
IN INTERNET_SCHEME tScheme,
|
|||
|
IN LPSTR lpszHostName,
|
|||
|
IN DWORD dwHostNameLength,
|
|||
|
IN INTERNET_PORT nPort
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Determines if a scheme/name/port is bypassed
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
tScheme - can be 0, meaning match any scheme
|
|||
|
|
|||
|
lpszHostName - can contain wildcards. May be name or IP address
|
|||
|
|
|||
|
dwHostNameLength - length of name/address part. May be 0, meaning match
|
|||
|
any name/address
|
|||
|
|
|||
|
nPort - can be 0, meaning match any port
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOL
|
|||
|
TRUE - an entry on the bypass list matched the criteria
|
|||
|
|
|||
|
FALSE - the host identified by the parameters is not on this bypass
|
|||
|
list
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DEBUG_ENTER((DBG_PROXY,
|
|||
|
Bool,
|
|||
|
"PROXY_BYPASS_LIST::IsBypassed",
|
|||
|
"%s, %.*q, %d, %d",
|
|||
|
InternetMapScheme(tScheme),
|
|||
|
dwHostNameLength,
|
|||
|
lpszHostName,
|
|||
|
dwHostNameLength,
|
|||
|
nPort
|
|||
|
));
|
|||
|
|
|||
|
INET_ASSERT(lpszHostName != NULL);
|
|||
|
INET_ASSERT(dwHostNameLength != 0);
|
|||
|
|
|||
|
BOOL found = FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// determine if what we were given is an address, in which case we don't
|
|||
|
// perform <local> semantics matching
|
|||
|
//
|
|||
|
|
|||
|
BOOL isAddress = FALSE;
|
|||
|
LPSTR mappedName;
|
|||
|
|
|||
|
if (dwHostNameLength <= MAX_IP_ADDRESS_STRING_LENGTH) {
|
|||
|
|
|||
|
char addressBuffer[MAX_IP_ADDRESS_STRING_LENGTH + 1];
|
|||
|
|
|||
|
//
|
|||
|
// make the host name/address an ASCIIZ string
|
|||
|
//
|
|||
|
|
|||
|
memcpy((LPVOID)addressBuffer, (LPVOID)lpszHostName, dwHostNameLength);
|
|||
|
addressBuffer[dwHostNameLength] = '\0';
|
|||
|
if (_I_inet_addr(addressBuffer) != INADDR_NONE) {
|
|||
|
|
|||
|
//
|
|||
|
// looks like we were given an IP address
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// maybe this is the IP address of a known server (in cache)
|
|||
|
//
|
|||
|
|
|||
|
mappedName = MapNetAddressToName(addressBuffer);
|
|||
|
if (mappedName == addressBuffer) {
|
|||
|
|
|||
|
//
|
|||
|
// BUGBUG - transport independence?
|
|||
|
//
|
|||
|
|
|||
|
isAddress = TRUE;
|
|||
|
} else {
|
|||
|
lpszHostName = mappedName;
|
|||
|
dwHostNameLength = lstrlen(lpszHostName);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// if not an address, determine if the name contains at least one dot
|
|||
|
//
|
|||
|
|
|||
|
BOOL isDot;
|
|||
|
|
|||
|
if (!isAddress) {
|
|||
|
isDot = FALSE;
|
|||
|
for (DWORD i = 0; i < dwHostNameLength; ++i) {
|
|||
|
if (lpszHostName[i] == '.') {
|
|||
|
isDot = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// addresses have dots
|
|||
|
//
|
|||
|
|
|||
|
isDot = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
LockSerializedList(&_List);
|
|||
|
|
|||
|
for (PLIST_ENTRY entry = HeadOfSerializedList(&_List);
|
|||
|
entry != (PLIST_ENTRY)SlSelf(&_List);
|
|||
|
entry = entry->Flink) {
|
|||
|
|
|||
|
PROXY_BYPASS_LIST_ENTRY * info;
|
|||
|
|
|||
|
info = CONTAINING_RECORD(entry, PROXY_BYPASS_LIST_ENTRY, _List);
|
|||
|
|
|||
|
//
|
|||
|
// do the easy bits first
|
|||
|
//
|
|||
|
|
|||
|
if (!((info->_Scheme == tScheme)
|
|||
|
|| (info->_Scheme == INTERNET_SCHEME_DEFAULT))) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
if (!((info->_Port == nPort)
|
|||
|
|| (info->_Port == INTERNET_INVALID_PORT_NUMBER))) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// check local semantics
|
|||
|
//
|
|||
|
|
|||
|
if (info->_LocalSemantics) {
|
|||
|
if (!isDot) {
|
|||
|
|
|||
|
DEBUG_PRINT(PROXY,
|
|||
|
INFO,
|
|||
|
("%q matched by <local>\n",
|
|||
|
lpszHostName
|
|||
|
));
|
|||
|
|
|||
|
found = TRUE;
|
|||
|
|
|||
|
//
|
|||
|
// <local> is in the bypass list and the name does not contain a
|
|||
|
// dot. It bypasses the proxy
|
|||
|
//
|
|||
|
|
|||
|
break;
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// the name contains a dot, but it may be matched by another
|
|||
|
// proxy bypass entry
|
|||
|
//
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// check for name match. Note that we take no special action if the host
|
|||
|
// name contains wildcard characters
|
|||
|
//
|
|||
|
|
|||
|
LPSTR target = info->_Name.StringAddress();
|
|||
|
|
|||
|
//
|
|||
|
// NULL target name matches any server name/address
|
|||
|
//
|
|||
|
|
|||
|
if (target != NULL) {
|
|||
|
|
|||
|
DEBUG_PRINT(PROXY,
|
|||
|
INFO,
|
|||
|
("trying to match %q with %q\n",
|
|||
|
lpszHostName,
|
|||
|
target
|
|||
|
));
|
|||
|
|
|||
|
DWORD i = 0;
|
|||
|
DWORD j = 0;
|
|||
|
DWORD i_back = (DWORD)-1;
|
|||
|
|
|||
|
while ((target[i] != '\0') && (j < dwHostNameLength)) {
|
|||
|
if (target[i] == tolower(lpszHostName[j])) {
|
|||
|
++i;
|
|||
|
++j;
|
|||
|
} else if (target[i] == '*') {
|
|||
|
while (target[i + 1] == '*') {
|
|||
|
++i;
|
|||
|
}
|
|||
|
i_back = i;
|
|||
|
++i;
|
|||
|
while ((tolower(lpszHostName[j]) != target[i])
|
|||
|
&& (j < dwHostNameLength)) {
|
|||
|
++j;
|
|||
|
}
|
|||
|
} else if (i_back != (DWORD)-1) {
|
|||
|
|
|||
|
//
|
|||
|
// '*' is greedy closure. We already saw a '*' but later we
|
|||
|
// discovered a mismatch. We will go back and try to eat as
|
|||
|
// many characters as we can till the next match, or we hit
|
|||
|
// the end of the string
|
|||
|
//
|
|||
|
|
|||
|
i = i_back;
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// no match; quit
|
|||
|
//
|
|||
|
|
|||
|
j = 0;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// if we reached the end of the target, but not the host name
|
|||
|
// AND we already met a '*' then back up
|
|||
|
//
|
|||
|
|
|||
|
if ((target[i] == '\0')
|
|||
|
&& (lpszHostName[j] != '\0')
|
|||
|
&& (i_back != (DWORD)-1)) {
|
|||
|
i = i_back;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// if we hit the end of the host name while matching any character,
|
|||
|
// bump the target to the next non-star character
|
|||
|
//
|
|||
|
|
|||
|
while (target[i] == '*') {
|
|||
|
++i;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// the host name matched if we reached the end of the target and end
|
|||
|
// of the host name
|
|||
|
//
|
|||
|
|
|||
|
if (!((target[i] == '\0') && (j == dwHostNameLength))) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// any path that didn't continue, or has not already broken out has
|
|||
|
// succeeded in finding a match
|
|||
|
//
|
|||
|
|
|||
|
DEBUG_PRINT(PROXY,
|
|||
|
INFO,
|
|||
|
("Matched: %q, %q\n",
|
|||
|
lpszHostName,
|
|||
|
target
|
|||
|
));
|
|||
|
|
|||
|
found = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
UnlockSerializedList(&_List);
|
|||
|
|
|||
|
DEBUG_LEAVE(found);
|
|||
|
|
|||
|
return found;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
PROXY_BYPASS_LIST::GetList(
|
|||
|
OUT LPSTR * lplpszList,
|
|||
|
IN DWORD dwBufferLength,
|
|||
|
IN OUT LPDWORD lpdwRequiredLength
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Writes the list of proxy bypass servers to a buffer, and/or returns the
|
|||
|
required buffer length
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
lplpszList - pointer to pointer to buffer where list is written, if
|
|||
|
sufficient space
|
|||
|
|
|||
|
dwBufferLength - amount of space in *lplpszList
|
|||
|
|
|||
|
lpdwRequiredLength - OUT: cumulative size of data
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LPSTR lpszList = *lplpszList;
|
|||
|
BOOL firstTime = TRUE;
|
|||
|
BOOL outOfBuffer = FALSE;
|
|||
|
|
|||
|
LockSerializedList(&_List);
|
|||
|
|
|||
|
for (PLIST_ENTRY entry = HeadOfSerializedList(&_List);
|
|||
|
entry != (PLIST_ENTRY)SlSelf(&_List);
|
|||
|
entry = entry->Flink) {
|
|||
|
|
|||
|
PROXY_BYPASS_LIST_ENTRY * info;
|
|||
|
|
|||
|
info = CONTAINING_RECORD(entry, PROXY_BYPASS_LIST_ENTRY, _List);
|
|||
|
if (!firstTime) {
|
|||
|
|
|||
|
//
|
|||
|
// write delimiter if enough space
|
|||
|
//
|
|||
|
|
|||
|
if (dwBufferLength >= 1) {
|
|||
|
*lpszList++ = ' ';
|
|||
|
--dwBufferLength;
|
|||
|
}
|
|||
|
++*lpdwRequiredLength;
|
|||
|
} else {
|
|||
|
firstTime = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// find the length of the current entry & write it to the buffer if
|
|||
|
// enough space
|
|||
|
//
|
|||
|
|
|||
|
DWORD length = dwBufferLength;
|
|||
|
|
|||
|
info->WriteEntry(lpszList, &length);
|
|||
|
if (dwBufferLength >= length) {
|
|||
|
|
|||
|
//
|
|||
|
// we wrote it
|
|||
|
//
|
|||
|
|
|||
|
dwBufferLength -= length;
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// no buffer left
|
|||
|
//
|
|||
|
|
|||
|
dwBufferLength = 0;
|
|||
|
outOfBuffer = TRUE;
|
|||
|
}
|
|||
|
*lpdwRequiredLength += length;
|
|||
|
lpszList += length;
|
|||
|
}
|
|||
|
|
|||
|
if (!outOfBuffer) {
|
|||
|
if (dwBufferLength > 0) {
|
|||
|
*lpszList++ = '\0';
|
|||
|
*lplpszList = lpszList;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// add 1 for the terminating NUL
|
|||
|
//
|
|||
|
|
|||
|
++*lpdwRequiredLength;
|
|||
|
UnlockSerializedList(&_List);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
INTERNET_SCHEME
|
|||
|
PROXY_INFO::ProxyScheme(
|
|||
|
IN INTERNET_SCHEME tProtocol
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Determines protocol over which tScheme goes through proxy
|
|||
|
If there is an external proxy DLL, we call down to it for the
|
|||
|
correct scheme to use. In other words, we defer to the DLL.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
tProtocol - protocol scheme used to retrieve data (e.g. FTP)
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
INTERNET_SCHEME
|
|||
|
Success - scheme by which protocol goes via proxy
|
|||
|
|
|||
|
Failure - INTERNET_SCHEME_UNKNOWN
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
INTERNET_SCHEME scheme;
|
|||
|
|
|||
|
Lock(FALSE);
|
|||
|
|
|||
|
if ( _UseExternalAutoConfigDLL && pProxyScheme) {
|
|||
|
|
|||
|
INET_ASSERT(!IsBadCodePtr((FARPROC)pProxyScheme));
|
|||
|
|
|||
|
(pProxyScheme)(tProtocol, &scheme);
|
|||
|
}
|
|||
|
else if (_ProxyServerList != NULL)
|
|||
|
{
|
|||
|
scheme = _ProxyServerList->ProxyScheme(tProtocol);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
scheme = INTERNET_SCHEME_UNKNOWN;
|
|||
|
}
|
|||
|
|
|||
|
Unlock();
|
|||
|
|
|||
|
return scheme;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
PROXY_INFO::SetProxyInfo(
|
|||
|
IN DWORD dwAccessType,
|
|||
|
IN LPCSTR lpszProxy OPTIONAL,
|
|||
|
IN LPCSTR lpszProxyBypass OPTIONAL
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Sets the proxy info. Either creates new proxy server and bypass lists, or
|
|||
|
removes them (proxy to direct)
|
|||
|
|
|||
|
Assumes: 1. The parameters have already been validated in the API that calls
|
|||
|
this method (i.e. InternetOpen(), InternetSetOption())
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
dwAccessType - type of proxy access required
|
|||
|
|
|||
|
lpszProxy - pointer to proxy server list
|
|||
|
|
|||
|
lpszProxyBypass - pointer to proxy bypass list
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
DWORD
|
|||
|
Success - ERROR_SUCCESS
|
|||
|
|
|||
|
Failure - ERROR_INVALID_PARAMETER
|
|||
|
The lpszProxy or lpszProxyBypass list was bad
|
|||
|
|
|||
|
ERROR_NOT_ENOUGH_MEMORY
|
|||
|
Failed to create an object or allocate space for a list,
|
|||
|
etc.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DEBUG_ENTER((DBG_PROXY,
|
|||
|
Dword,
|
|||
|
"PROXY_INFO::SetProxyInfo",
|
|||
|
"%s (%d), %#x (%q), %#x (%q)",
|
|||
|
InternetMapOpenType(dwAccessType),
|
|||
|
dwAccessType,
|
|||
|
lpszProxy,
|
|||
|
lpszProxy,
|
|||
|
lpszProxyBypass,
|
|||
|
lpszProxyBypass
|
|||
|
));
|
|||
|
|
|||
|
//
|
|||
|
// parameters should already be validated by caller
|
|||
|
//
|
|||
|
|
|||
|
INET_ASSERT((dwAccessType == INTERNET_OPEN_TYPE_DIRECT)
|
|||
|
|| (dwAccessType == INTERNET_OPEN_TYPE_PROXY)
|
|||
|
|| (dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG)
|
|||
|
);
|
|||
|
|
|||
|
BOOL isProxy;
|
|||
|
BOOL newList;
|
|||
|
LPSTR serverList;
|
|||
|
LPSTR bypassList;
|
|||
|
|
|||
|
if (dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG) {
|
|||
|
InternetReadRegistryDword("ProxyEnable", (LPDWORD)&isProxy);
|
|||
|
if (isProxy) {
|
|||
|
serverList = GetRegistryProxyParameter("ProxyServer");
|
|||
|
if (serverList != NULL) {
|
|||
|
bypassList = GetRegistryProxyParameter("ProxyOverride");
|
|||
|
newList = TRUE;
|
|||
|
} else {
|
|||
|
|
|||
|
DEBUG_PRINT(PROXY,
|
|||
|
ERROR,
|
|||
|
("PRECONFIG: ProxyEnable TRUE, ProxyServer NULL\n"
|
|||
|
));
|
|||
|
|
|||
|
bypassList = NULL;
|
|||
|
newList = FALSE;
|
|||
|
}
|
|||
|
} else {
|
|||
|
serverList = NULL;
|
|||
|
bypassList = NULL;
|
|||
|
newList = FALSE;
|
|||
|
}
|
|||
|
} else if (dwAccessType == INTERNET_OPEN_TYPE_PROXY) {
|
|||
|
serverList = (LPSTR)lpszProxy;
|
|||
|
bypassList = (LPSTR)lpszProxyBypass;
|
|||
|
newList = TRUE;
|
|||
|
|
|||
|
INET_ASSERT(serverList != NULL);
|
|||
|
|
|||
|
} else {
|
|||
|
newList = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// about to start changing contents - acquire lock
|
|||
|
//
|
|||
|
|
|||
|
Lock(TRUE);
|
|||
|
|
|||
|
//
|
|||
|
// clear out current contents
|
|||
|
//
|
|||
|
|
|||
|
CleanOutLists();
|
|||
|
|
|||
|
DWORD error = ERROR_SUCCESS;
|
|||
|
|
|||
|
if (newList) {
|
|||
|
|
|||
|
INET_ASSERT((serverList != NULL) && (*serverList != 0));
|
|||
|
|
|||
|
_ProxyServerList = new PROXY_SERVER_LIST(serverList);
|
|||
|
_ProxyBypassList = new PROXY_BYPASS_LIST(bypassList);
|
|||
|
if ((_ProxyServerList != NULL) && (_ProxyBypassList != NULL)) {
|
|||
|
_Error = _ProxyServerList->GetError();
|
|||
|
if (_Error == ERROR_SUCCESS) {
|
|||
|
_Error = _ProxyBypassList->GetError();
|
|||
|
if (_Error == ERROR_SUCCESS) {
|
|||
|
|
|||
|
//
|
|||
|
// add all proxy servers to bypass list
|
|||
|
//
|
|||
|
|
|||
|
_ProxyServerList->AddToBypassList(_ProxyBypassList);
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
_Error = ERROR_NOT_ENOUGH_MEMORY;
|
|||
|
CleanOutLists();
|
|||
|
}
|
|||
|
error = _Error;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// if we're setting anything other than preconfig then this PROXY_INFO has
|
|||
|
// been modified. The reason is the new SetInfo semantics. So long as the
|
|||
|
// proxy info is coming from registry, it can be updated automatically when
|
|||
|
// the registry changes, but if an app is using its own global proxy
|
|||
|
// settings then we can no longer update global settings from the registry.
|
|||
|
// We rely on the INTERNET_HANDLE_OBJECT methods to ensure that requests to
|
|||
|
// change global proxy info back to registry settings never make it this far
|
|||
|
//
|
|||
|
|
|||
|
_Modified = (dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG) ? FALSE : TRUE;
|
|||
|
|
|||
|
//
|
|||
|
// other threads free to access this PROXY_INFO again
|
|||
|
//
|
|||
|
|
|||
|
Unlock();
|
|||
|
|
|||
|
//
|
|||
|
// free up the lists we allocated
|
|||
|
//
|
|||
|
|
|||
|
if (dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG) {
|
|||
|
if (serverList != NULL) {
|
|||
|
ResizeBuffer(serverList, 0, FALSE);
|
|||
|
}
|
|||
|
if (bypassList != NULL) {
|
|||
|
ResizeBuffer(bypassList, 0, FALSE);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
DEBUG_LEAVE(error);
|
|||
|
|
|||
|
return error;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
PROXY_INFO::GetProxyInfo(
|
|||
|
IN INTERNET_SCHEME tProtocol,
|
|||
|
IN OUT LPINTERNET_SCHEME lptScheme,
|
|||
|
OUT LPSTR * lplpszHostName,
|
|||
|
OUT LPDWORD lpdwHostNameLength,
|
|||
|
OUT LPINTERNET_PORT lpHostPort
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Given a protocol, map it to the proxy we use to retrieve the data
|
|||
|
If there is an external proxy DLL, we call down to it for the
|
|||
|
correct proxy to use.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
tProtocol - protocol to map (e.g. find the proxy for FTP)
|
|||
|
|
|||
|
lptScheme - IN: preferred scheme if INTERNET_SCHEME_DEFAULT
|
|||
|
OUT: returned scheme
|
|||
|
|
|||
|
lplpszHostName - pointer to returned pointer to host name
|
|||
|
|
|||
|
lpdwHostNameLength - pointer to returned host name length
|
|||
|
|
|||
|
lpHostPort - pointer to returned host port
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOL
|
|||
|
TRUE - requested info has been returned
|
|||
|
|
|||
|
FALSE - requested info was not found
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
BOOL success;
|
|||
|
|
|||
|
Lock(FALSE);
|
|||
|
|
|||
|
if ( _UseExternalAutoConfigDLL && pGetProxyInfo) {
|
|||
|
|
|||
|
INET_ASSERT(!IsBadCodePtr((FARPROC)pGetProxyInfo));
|
|||
|
|
|||
|
success = (pGetProxyInfo)(tProtocol,
|
|||
|
lptScheme,
|
|||
|
lplpszHostName,
|
|||
|
lpdwHostNameLength,
|
|||
|
lpHostPort
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
else if (_ProxyServerList != NULL)
|
|||
|
{
|
|||
|
success = _ProxyServerList->GetProxyInfo(tProtocol,
|
|||
|
lptScheme,
|
|||
|
lplpszHostName,
|
|||
|
lpdwHostNameLength,
|
|||
|
lpHostPort
|
|||
|
);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
success = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
Unlock();
|
|||
|
|
|||
|
return success;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
PROXY_INFO::GetProxyInfo(
|
|||
|
OUT LPVOID lpBuffer,
|
|||
|
IN OUT LPDWORD lpdwBufferLength
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Returns the proxy server and bypass lists in an INTERNET_PROXY_INFO. Called
|
|||
|
by InternetQueryOption(INTERNET_OPTION_PROXY)
|
|||
|
|
|||
|
Assumes: Access to this is serialized while we are getting this info
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
lpBuffer - pointer to buffer where information will be returned
|
|||
|
|
|||
|
lpdwBufferLength - IN: size of lpBuffer in BYTEs
|
|||
|
OUT: number of BYTEs returned in lpBuffer
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
DWORD
|
|||
|
Success - ERROR_SUCCESS
|
|||
|
|
|||
|
Failure - ERROR_INSUFFICIENT_BUFFER
|
|||
|
*lpdwBufferLength contains the required buffer length
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DEBUG_ENTER((DBG_PROXY,
|
|||
|
Dword,
|
|||
|
"PROXY_INFO::GetProxyInfo",
|
|||
|
"%#x, %#x [%d]",
|
|||
|
lpBuffer,
|
|||
|
lpdwBufferLength,
|
|||
|
*lpdwBufferLength
|
|||
|
));
|
|||
|
|
|||
|
DWORD requiredSize = sizeof(INTERNET_PROXY_INFO);
|
|||
|
LPSTR lpVariable = (LPSTR)(((LPINTERNET_PROXY_INFO)lpBuffer) + 1);
|
|||
|
LPSTR lpszProxy;
|
|||
|
|
|||
|
if (_ProxyServerList != NULL) {
|
|||
|
lpszProxy = lpVariable;
|
|||
|
_ProxyServerList->GetList(&lpVariable,
|
|||
|
(*lpdwBufferLength > requiredSize)
|
|||
|
? (*lpdwBufferLength - requiredSize)
|
|||
|
: 0,
|
|||
|
&requiredSize
|
|||
|
);
|
|||
|
} else {
|
|||
|
lpszProxy = NULL;
|
|||
|
}
|
|||
|
|
|||
|
LPSTR lpszProxyBypass;
|
|||
|
|
|||
|
if (_ProxyBypassList != NULL) {
|
|||
|
|
|||
|
DWORD size = requiredSize;
|
|||
|
|
|||
|
lpszProxyBypass = lpVariable;
|
|||
|
_ProxyBypassList->GetList(&lpVariable,
|
|||
|
(*lpdwBufferLength > requiredSize)
|
|||
|
? (*lpdwBufferLength - requiredSize)
|
|||
|
: 0,
|
|||
|
&requiredSize
|
|||
|
);
|
|||
|
if (requiredSize == size) {
|
|||
|
lpszProxyBypass = NULL;
|
|||
|
}
|
|||
|
} else {
|
|||
|
lpszProxyBypass = NULL;
|
|||
|
}
|
|||
|
|
|||
|
DWORD error;
|
|||
|
|
|||
|
if (*lpdwBufferLength >= requiredSize) {
|
|||
|
|
|||
|
LPINTERNET_PROXY_INFO lpInfo = (LPINTERNET_PROXY_INFO)lpBuffer;
|
|||
|
|
|||
|
lpInfo->dwAccessType = (lpszProxy == NULL)
|
|||
|
? INTERNET_OPEN_TYPE_DIRECT
|
|||
|
: INTERNET_OPEN_TYPE_PROXY;
|
|||
|
lpInfo->lpszProxy = lpszProxy;
|
|||
|
lpInfo->lpszProxyBypass = lpszProxyBypass;
|
|||
|
error = ERROR_SUCCESS;
|
|||
|
} else {
|
|||
|
error = ERROR_INSUFFICIENT_BUFFER;
|
|||
|
}
|
|||
|
*lpdwBufferLength = requiredSize;
|
|||
|
|
|||
|
DEBUG_LEAVE(error);
|
|||
|
|
|||
|
return error;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
PROXY_INFO::IsBypassed(
|
|||
|
IN INTERNET_SCHEME tScheme,
|
|||
|
IN LPSTR lpszHostName,
|
|||
|
IN DWORD dwHostNameLength,
|
|||
|
IN INTERNET_PORT nPort
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Determines if a scheme/name/port is bypassed
|
|||
|
If there is an external proxy DLL, we call down to determine whether
|
|||
|
a host should bypass the proxy.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
tScheme - can be 0, meaning match any scheme
|
|||
|
|
|||
|
lpszHostName - can contain wildcards. May be name or IP address
|
|||
|
|
|||
|
dwHostNameLength - length of name/address part. May be 0, meaning match
|
|||
|
any name/address
|
|||
|
|
|||
|
nPort - can be 0, meaning match any port
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOL
|
|||
|
TRUE - an entry on the bypass list matched the criteria
|
|||
|
|
|||
|
FALSE - the host identified by the parameters is not on this bypass
|
|||
|
list
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
BOOL success;
|
|||
|
|
|||
|
Lock(FALSE);
|
|||
|
|
|||
|
if ( _UseExternalAutoConfigDLL && pIsBypassed) {
|
|||
|
|
|||
|
INET_ASSERT(!IsBadCodePtr((FARPROC)pIsBypassed));
|
|||
|
|
|||
|
success = (pIsBypassed) ( tScheme,
|
|||
|
lpszHostName,
|
|||
|
dwHostNameLength,
|
|||
|
nPort
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
else if (_ProxyBypassList != NULL)
|
|||
|
{
|
|||
|
success = _ProxyBypassList->IsBypassed(tScheme,
|
|||
|
lpszHostName,
|
|||
|
dwHostNameLength,
|
|||
|
nPort
|
|||
|
);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
success = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
Unlock();
|
|||
|
|
|||
|
return success;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
PROXY_INFO::IsBypassed(
|
|||
|
IN INTERNET_SCHEME tScheme,
|
|||
|
IN LPSTR lpszHostName,
|
|||
|
IN INTERNET_PORT nPort
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Determines if a scheme/name/port is bypassed
|
|||
|
If there is an external proxy DLL, we call down to determine whether
|
|||
|
a host should bypass the proxy.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
tScheme - can be 0, meaning match any scheme
|
|||
|
|
|||
|
lpszHostName - can contain wildcards. May be name or IP address
|
|||
|
|
|||
|
nPort - can be 0, meaning match any port
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOL
|
|||
|
TRUE - an entry on the bypass list matched the criteria
|
|||
|
|
|||
|
FALSE - the host identified by the parameters is not on this bypass
|
|||
|
list
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
BOOL success;
|
|||
|
|
|||
|
Lock(FALSE);
|
|||
|
|
|||
|
if ( _UseExternalAutoConfigDLL && pIsBypassed) {
|
|||
|
|
|||
|
INET_ASSERT(!IsBadCodePtr((FARPROC)pIsBypassed));
|
|||
|
|
|||
|
success = (pIsBypassed) ( tScheme,
|
|||
|
lpszHostName,
|
|||
|
lstrlen(lpszHostName),
|
|||
|
nPort
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
else if (_ProxyBypassList != NULL)
|
|||
|
{
|
|||
|
success = _ProxyBypassList->IsBypassed(tScheme,
|
|||
|
lpszHostName,
|
|||
|
nPort
|
|||
|
);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
success = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
Unlock();
|
|||
|
|
|||
|
return success;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
PRIVATE
|
|||
|
LPSTR
|
|||
|
GetRegistryProxyParameter(
|
|||
|
IN LPSTR lpszParameterName
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Reads a string from the registry into a buffer, then shrinks the buffer
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
lpszParameterName - name of string to retrieve
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
LPSTR
|
|||
|
Success - pointer to allocated buffer
|
|||
|
|
|||
|
Failure - NULL
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
LPSTR buffer = NULL;
|
|||
|
DWORD length = PROXY_REGISTRY_STRING_LENGTH;
|
|||
|
BOOL done = FALSE;
|
|||
|
|
|||
|
do {
|
|||
|
buffer = (LPSTR)ResizeBuffer(buffer, length, FALSE);
|
|||
|
if (done || (buffer == NULL)) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
DWORD error;
|
|||
|
|
|||
|
error = InternetReadRegistryString(lpszParameterName, buffer, &length);
|
|||
|
length = (error == ERROR_SUCCESS) ? ((length == 0) ? 0 : (length + 1)) : 0;
|
|||
|
done = TRUE;
|
|||
|
} while (TRUE);
|
|||
|
|
|||
|
return buffer;
|
|||
|
}
|