Introduction
I had the need to test a local (on the same machine I was using) Internet proxy.
Every time I had to browse the network for info, I had to go reset Internet Explorer
settings, or use a different browser.
Since I did it for a customer with a totally different environment, I devised a small
settings toggler, that just stores the previous values in the registry and can restore
them. I made it a tray button, so a double-click was sufficient to set the proxy on and off.
There is another article "Change
Internet Proxy settings" that deals with this topic. This article
present an alternate method.
Using the code
I just put the activate/deactivate functions and an initialize method for file-scope
variables. It is quite easy to make them method of your class, and use them. Double activation
or deactivation just do nothing.
const char *sKeyName, *sValName, *sAccName, *sFlgName, *sBypName;
void initialize( )
{
sKeyName = "Software\\ProxyToggle";
sValName = "SavedProxyConfig";
sAccName = "AccessType";
sFlgName = "ProxyActive";
sBypName = "BypassList";
}
void activate( const char *address )
{
unsigned long nSize = 4096;
char szBuf[4096] = { 0 };
INTERNET_PROXY_INFO* pInfo = (INTERNET_PROXY_INFO*)szBuf;
if(!InternetQueryOption(NULL, INTERNET_OPTION_PROXY, pInfo, &nSize))
{
printf("InternetQueryOption failed! (%d)\n", GetLastError());
exit( 100 );
}
const char *save = pInfo->lpszProxy;
HKEY kValue;
int res;
BYTE Value[0x100];
ULONG length = 0x100, Type;
res = RegOpenKeyEx( HKEY_CURRENT_USER, sKeyName, 0,
KEY_SET_VALUE | KEY_QUERY_VALUE, &kValue );
if (res==ERROR_SUCCESS)
{
BYTE retVal = 0;
if( ( res = RegQueryValueEx(kValue, sFlgName, NULL,
&Type, Value, &length) ) == ERROR_SUCCESS )
{
if( Type != REG_SZ )
{
printf("Corrupted registry entry\n" );
exit( 400 );
}
retVal = *Value;
}
if( retVal )
{
RegCloseKey( kValue );
return;
}
}
else
if( ( res = RegCreateKey( HKEY_CURRENT_USER, sKeyName, &kValue ) ) != ERROR_SUCCESS )
{
printf("Unable to save configuration\n" );
exit( 600 );
}
*Value = 1;
if( ( res = RegSetValueEx( kValue, sFlgName, 0, REG_SZ,
Value, sizeof( BYTE ) ) ) != ERROR_SUCCESS)
{
printf("Unable to update configuration\n" );
exit( 500 );
}
if( ( res = RegSetValueEx( kValue, sAccName, 0, REG_SZ, (BYTE*)&(pInfo->dwAccessType),
sizeof( DWORD ) ) ) != ERROR_SUCCESS)
{
printf("Unable to save configuration\n" );
exit( 400 );
}
if( pInfo->dwAccessType != PROXY_TYPE_DIRECT )
{
if( ( res = RegSetValueEx( kValue, sValName, 0, REG_SZ,
(BYTE*)pInfo->lpszProxy, 1 + strlen( pInfo->lpszProxy ) ) )
!= ERROR_SUCCESS)
{
printf("Unable to save configuration\n" );
exit( 400 );
}
if( ( res = RegSetValueEx( kValue, sBypName, 0, REG_SZ,
(BYTE*)pInfo->lpszProxyBypass,
1 + strlen( pInfo->lpszProxyBypass ) ) ) != ERROR_SUCCESS)
{
printf("Unable to save configuration\n" );
exit( 400 );
}
}
RegCloseKey( kValue );
RegCloseKey( HKEY_CURRENT_USER );
INTERNET_PER_CONN_OPTION_LIST list;
BOOL bReturn;
DWORD dwBufSize = sizeof(list);
list.dwSize = sizeof(list);
list.pszConnection = NULL;
list.dwOptionCount = 3;
list.pOptions = new INTERNET_PER_CONN_OPTION[3];
if(NULL == list.pOptions)
{
return;
}
list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS;
list.pOptions[0].Value.dwValue = PROXY_TYPE_DIRECT |
PROXY_TYPE_PROXY;
list.pOptions[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER;
list.pOptions[1].Value.pszValue = (char*)address;
CString sAddr = address, bypass = pInfo->lpszProxyBypass;
if( bypass.GetLength( ) )
bypass += ";";
int idx;
if( ( idx = sAddr.Find( "//" ) ) >= 0 )
sAddr = sAddr.Mid( idx + 2 );
if( ( idx = sAddr.FindOneOf( ":/" ) ) >= 0 )
sAddr = sAddr.Left( idx );
bypass += sAddr;
list.pOptions[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS;
list.pOptions[2].Value.pszValue = bypass.GetBuffer( 0 );
bReturn = InternetSetOption(NULL,
INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize);
bReturn = InternetSetOption(NULL,
INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0 );
bypass.ReleaseBuffer( );
delete [] list.pOptions;
}
void deactivate( )
{
HKEY kValue;
LONG res;
BYTE Value[0x100], Bypass[0x100];
ULONG length = 0x100, blength = 0x100, Type;
unsigned long nSize = 4096;
char szBuf[4096] = { 0 };
res = RegOpenKeyEx( HKEY_CURRENT_USER, sKeyName, 0,
KEY_SET_VALUE | KEY_QUERY_VALUE, &kValue );
if (res==ERROR_SUCCESS)
{
BYTE retVal = 0;
if( ( res = RegQueryValueEx(kValue, sFlgName, NULL,
&Type, Value, &length) ) == ERROR_SUCCESS )
{
if( Type != REG_SZ )
{
printf("Corrupted registry entry\n" );
exit( 400 );
}
retVal = *Value;
}
if( retVal )
{
*Value = 0;
if( ( res = RegSetValueEx( kValue, sFlgName, 0, REG_SZ, Value,
sizeof( BYTE ) ) ) != ERROR_SUCCESS)
{
printf("Unable to update configuration\n" );
exit( 500 );
}
INTERNET_PER_CONN_OPTION_LIST list;
BOOL bReturn;
DWORD dwBufSize = sizeof(list);
list.dwSize = sizeof(list);
list.pszConnection = NULL;
list.dwOptionCount = 2;
list.pOptions = new INTERNET_PER_CONN_OPTION[3];
if(NULL == list.pOptions)
{
return;
}
list.pOptions[0].dwOption = INTERNET_PER_CONN_FLAGS;
length = sizeof( DWORD );
if( ( res = RegQueryValueEx( kValue, sAccName, NULL, &Type,
(BYTE*)&(list.pOptions[0].Value.dwValue), &length ) )
!= ERROR_SUCCESS )
{
printf("Unable to restore configuration\n" );
exit( 700 );
}
if( list.pOptions[0].Value.dwValue != PROXY_TYPE_DIRECT )
{
list.dwOptionCount = 3;
length = 0x100;
if( ( res = RegQueryValueEx( kValue, sValName, NULL,
&Type, Value, &length ) ) != ERROR_SUCCESS )
{
printf("Unable to restore configuration\n" );
exit( 700 );
}
list.pOptions[1].dwOption = INTERNET_PER_CONN_PROXY_SERVER;
list.pOptions[1].Value.pszValue = (char*)Value;
if( ( res = RegQueryValueEx( kValue, sBypName, NULL,
&Type, Bypass, &blength ) ) != ERROR_SUCCESS )
{
printf("Unable to restore configuration\n" );
exit( 700 );
}
list.pOptions[2].dwOption = INTERNET_PER_CONN_PROXY_BYPASS;
list.pOptions[2].Value.pszValue = (char*)Bypass;
}
bReturn = InternetSetOption(NULL,
INTERNET_OPTION_PER_CONNECTION_OPTION, &list, dwBufSize);
bReturn = InternetSetOption(NULL,
INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0 );
delete [] list.pOptions;
RegCloseKey( kValue );
}
}
RegCloseKey( HKEY_CURRENT_USER );
}
Points of Interest
I noticed two things: the behavior was slightly different with different flavours
of Windows until I met the last version of SDK. The whole thing is very poorly documented,
as usual. After a lot of trial and error, now I have an intoxicated IE installation, that
often hang while talking with proxy. So, DON'T MESS WITH THE REGISTRY. EVER.
Programming enthusiast since 1982, I experienced many different technologies: this lets me appreciate the strong points of each and avoid pitfalls.
Since I started using .Net and C# I grew more and more passionate with this new fascinating course of Microsoft.
Recently, I concentrated less on web technologies to investigate mobile and IoT technologies.
The most recent project is Desktop again, though.