Windows2003-3790/inetcore/winhttp/proxycfg/proxycfg.cxx
2020-09-30 16:53:55 +02:00

536 lines
14 KiB
C++

// ===========================================================================
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright 2000 Microsoft Corporation. All Rights Reserved.
// ===========================================================================
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <io.h>
#include <winhttp.h>
#include <ntverp.h>
#include <common.ver>
#include "proxymsg.h"
// Global module handles for error message lookup
HMODULE g_hModWinHttp = NULL;
//
// MessageCleanup
//
// Free DLL loaded for message lookup
//
void
MessageCleanup(void)
{
if (g_hModWinHttp)
FreeLibrary(g_hModWinHttp);
}
//
// GetMessage
//
// Get localized message text from WinHTTP or System.
// Caller responsible for LocalFree'ing the returned string.
//
PWSTR
GetMessage(
IN DWORD dwError
)
{
PWSTR pwszMessage = NULL;
DWORD dwCount = 0;
if (dwError > WINHTTP_ERROR_BASE && dwError <= WINHTTP_ERROR_LAST)
{
if (g_hModWinHttp == NULL)
{
g_hModWinHttp = LoadLibraryEx(
"winhttp.dll",
NULL,
LOAD_LIBRARY_AS_DATAFILE
);
}
dwCount = FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER | // allocate space for message
FORMAT_MESSAGE_IGNORE_INSERTS | // don't expand printf tokens
FORMAT_MESSAGE_FROM_HMODULE, // get message from module
g_hModWinHttp,
dwError,
0, // default language
(PWSTR)&pwszMessage,
0, // allocate as much as necessary
NULL // no args
);
}
else
{
dwCount = FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER | // allocate space for message
FORMAT_MESSAGE_IGNORE_INSERTS | // don't expand printf tokens
FORMAT_MESSAGE_FROM_SYSTEM, // get system message
NULL,
dwError,
0, // default language
(PWSTR)&pwszMessage,
0, // allocate as much as necessary
NULL // no args
);
}
if (dwCount > 0 && pwszMessage != NULL)
return pwszMessage;
return L"\n";
}
//
// PrintMessage
//
// Prints messages using localized strings from the resources
// of this application.
//
void
PrintMessage(
IN DWORD dwMsg,
...
)
{
va_list pArg;
PWSTR pwszUnicode = NULL;
PSTR pszStr = NULL;
DWORD dwLen = 0;
HANDLE hOut;
DWORD dwBytesWritten;
DWORD fdwMode;
va_start(pArg, dwMsg);
dwLen = FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER | // allocate space for message and
FORMAT_MESSAGE_FROM_HMODULE, // get message from module and
NULL, // NULL means this application
dwMsg,
0, // default language
(PWSTR)&pwszUnicode,
0, // allocate as much as necessary
&pArg // args for printf inserts
);
va_end(pArg);
if (dwLen == 0 || pwszUnicode == NULL)
return;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
if ((GetFileType(hOut) & FILE_TYPE_CHAR) && GetConsoleMode(hOut, &fdwMode))
{
// output not redirected - output UNICODE to console directly
WriteConsoleW(hOut, pwszUnicode, wcslen(pwszUnicode), &dwBytesWritten, 0);
}
else
{
// output redirected - convert to multi-byte and output to file
dwLen = WideCharToMultiByte(
GetConsoleOutputCP(),
0,
pwszUnicode,
-1,
NULL,
0,
NULL,
NULL);
pszStr = new CHAR[dwLen];
if (pszStr == NULL)
return;
dwLen = WideCharToMultiByte(
GetConsoleOutputCP(),
0,
pwszUnicode,
-1,
pszStr,
dwLen,
NULL,
NULL);
WriteFile(hOut, pszStr, dwLen-1, &dwBytesWritten, 0);
if (pszStr) delete [] pszStr;
}
return;
}
//
// AnsiToWideChar
//
// Used to convert command line input to UNICODE
//
DWORD
AnsiToWideChar(const char * pszA, LPWSTR * ppszW)
{
DWORD cchW;
*ppszW = NULL;
if (!pszA)
return ERROR_SUCCESS;
// Determine how big the widechar string will be
cchW = MultiByteToWideChar(CP_ACP, 0, pszA, -1, NULL, 0);
*ppszW = new WCHAR[cchW];
if (!*ppszW)
return ERROR_NOT_ENOUGH_MEMORY;
// now convert it
cchW = MultiByteToWideChar(CP_ACP, 0, pszA, -1, *ppszW, cchW);
return ERROR_SUCCESS;
}
typedef struct
{
DWORD dwAccessType; // see WINHTTP_ACCESS_* types below
LPSTR lpszProxy; // proxy server list
LPSTR lpszProxyBypass; // proxy bypass list
}
WINHTTP_PROXY_INFOA;
// MigrateProxySettings is defined in ProxyMigrate.cxx
DWORD MigrateProxySettings (void);
/*
usage:
proxycfg -? : to view help information
proxycfg : to view current WinHTTP proxy settings
proxycfg [-d] [-p <server-name> [<bypass-list>]]
-d : set direct access
-p : set proxy server(s), and optional bypass list
proxycfg -u : import proxy settings from current user's
Microsoft Internet Explorer manual settings (in HKCU)
*/
enum ARGTYPE
{
ARGS_HELP,
ARGS_SET_PROXY_SETTINGS,
ARGS_VIEW_PROXY_SETTINGS,
ARGS_INITIALIZE_PROXY_SETTINGS, // updates from HKCU only if never init
ARGS_MIGRATE_PROXY_SETTINGS // forces update from HKCU
};
struct ARGS
{
ARGTYPE Command;
DWORD Flags;
char * ProxyServer;
char * BypassList;
};
#define INTERNET_SETTINGS_KEY L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
static const WCHAR szRegPathConnections[] = INTERNET_SETTINGS_KEY L"\\Connections";
void ParseArguments(int argc, char ** argv, ARGS * Args)
{
Args->Command = ARGS_VIEW_PROXY_SETTINGS;
Args->Flags = WINHTTP_ACCESS_TYPE_NO_PROXY;
Args->ProxyServer = NULL;
Args->BypassList = NULL;
if (argc == 0)
return;
for (;;)
{
if ((argv[0][0] != '-') || (lstrlen(argv[0]) != 2))
{
Args->Command = ARGS_HELP;
goto Exit;
}
switch (tolower(argv[0][1]))
{
default:
Args->Command = ARGS_HELP;
goto Exit;
case 'd':
Args->Command = ARGS_SET_PROXY_SETTINGS;
Args->Flags = WINHTTP_ACCESS_TYPE_NO_PROXY;
argc--;
argv++;
if (argc == 0)
goto Exit;
continue;
case 'i':
Args->Command = ARGS_INITIALIZE_PROXY_SETTINGS;
goto Exit;
case 'p':
argc--;
argv++;
if (argc == 0)
{
// error: no proxy specified
Args->Command = ARGS_HELP;
}
else
{
Args->Command = ARGS_SET_PROXY_SETTINGS;
Args->Flags |= WINHTTP_ACCESS_TYPE_NAMED_PROXY;
Args->ProxyServer = argv[0];
argc--;
argv++;
if (argc >= 1)
{
Args->BypassList = argv[0];
}
}
goto Exit;
case 'u':
Args->Command = ARGS_MIGRATE_PROXY_SETTINGS;
goto Exit;
}
}
Exit:
return;
}
DWORD WriteProxySettings( WINHTTP_PROXY_INFOA * pInfo)
{
DWORD error = ERROR_SUCCESS;
WINHTTP_PROXY_INFO proxyInfo;
memset( &proxyInfo, 0, sizeof( proxyInfo));
switch( pInfo->dwAccessType)
{
case WINHTTP_ACCESS_TYPE_NAMED_PROXY:
case WINHTTP_ACCESS_TYPE_NO_PROXY:
proxyInfo.dwAccessType = pInfo->dwAccessType;
break;
default:
// When migrating, we get some weird flags in dwAccessType.
// Be smart about guessing if there is a proxy or not.
proxyInfo.dwAccessType = pInfo->lpszProxy != NULL
? WINHTTP_ACCESS_TYPE_NAMED_PROXY
: WINHTTP_ACCESS_TYPE_NO_PROXY;
}
// we only support ANSI hostnames so only try to convert from ANSI to UNICODE
if( NULL != pInfo->lpszProxy)
{
error = AnsiToWideChar( pInfo->lpszProxy, &proxyInfo.lpszProxy);
if( error != ERROR_SUCCESS)
goto quit;
}
if( NULL != pInfo->lpszProxyBypass)
{
error = AnsiToWideChar( pInfo->lpszProxyBypass, &proxyInfo.lpszProxyBypass);
if( error != ERROR_SUCCESS)
goto quit;
}
error = ERROR_SUCCESS;
if( TRUE != WinHttpSetDefaultProxyConfiguration( &proxyInfo))
{
error = GetLastError();
}
quit:
if( proxyInfo.lpszProxy != NULL)
delete[] proxyInfo.lpszProxy;
if( proxyInfo.lpszProxyBypass != NULL)
delete[] proxyInfo.lpszProxyBypass;
return error;
}
DWORD SetProxySettings(DWORD Flags, char * ProxyServer, char * BypassList)
{
WINHTTP_PROXY_INFOA proxyInfo;
DWORD error;
LPWSTR pwszString = NULL;
// initialize structure
memset(&proxyInfo, 0, sizeof(proxyInfo));
proxyInfo.dwAccessType = Flags;
proxyInfo.lpszProxy = ProxyServer;
proxyInfo.lpszProxyBypass = BypassList;
error = WriteProxySettings(&proxyInfo);
if (error != ERROR_SUCCESS)
{
pwszString = GetMessage(error);
PrintMessage(MSG_ERROR_WRITING_PROXY_SETTINGS, error,
pwszString ? pwszString : L"");
if (pwszString) LocalFree(pwszString);
}
else
{
PrintMessage(MSG_UPDATE_SUCCESS);
}
return error;
}
void ViewProxySettings()
{
WINHTTP_PROXY_INFO proxyInfo;
DWORD error;
PWSTR pwszString = NULL;
if( TRUE != WinHttpGetDefaultProxyConfiguration( &proxyInfo))
{
error = GetLastError();
pwszString = GetMessage(error);
PrintMessage(MSG_ERROR_READING_PROXY_SETTINGS, error,
pwszString ? pwszString : L"");
if (pwszString ) LocalFree(pwszString );
return;
}
PrintMessage(MSG_CURRENT_SETTINGS_HEADER, szRegPathConnections);
switch( proxyInfo.dwAccessType)
{
case WINHTTP_ACCESS_TYPE_NO_PROXY:
PrintMessage(MSG_DIRECT_ACCESS);
break;
case WINHTTP_ACCESS_TYPE_NAMED_PROXY:
if( proxyInfo.lpszProxy != NULL)
PrintMessage(MSG_PROXY_SERVERS, proxyInfo.lpszProxy);
else
PrintMessage(MSG_ERROR_PROXY_SERVER_MISSING);
if( proxyInfo.lpszProxyBypass != NULL)
PrintMessage(MSG_BYPASS_LIST, proxyInfo.lpszProxyBypass);
else
PrintMessage(MSG_BYPASS_LIST_NONE);
break;
default:
PrintMessage(MSG_UNKNOWN_PROXY_ACCESS_TYPE);
break;
}
if( NULL != proxyInfo.lpszProxy)
GlobalFree( proxyInfo.lpszProxy);
if( NULL != proxyInfo.lpszProxyBypass)
GlobalFree( proxyInfo.lpszProxyBypass);
}
int __cdecl main (int argc, char **argv)
{
ARGS Args;
DWORD dwErr;
PWSTR pwszString = NULL;
PrintMessage(MSG_STARTUP_BANNER);
PrintMessage(MSG_COPYRIGHT);
// Discard program arg.
argv++;
argc--;
ParseArguments(argc, argv, &Args);
switch (Args.Command)
{
case ARGS_HELP:
default:
PrintMessage(MSG_USAGE);
break;
case ARGS_SET_PROXY_SETTINGS:
SetProxySettings(Args.Flags, Args.ProxyServer, Args.BypassList);
ViewProxySettings();
break;
case ARGS_INITIALIZE_PROXY_SETTINGS:
// intentional fall through
case ARGS_MIGRATE_PROXY_SETTINGS:
dwErr = MigrateProxySettings();
if (dwErr != ERROR_SUCCESS)
{
pwszString = GetMessage(dwErr);
PrintMessage(MSG_MIGRATION_FAILED_WITH_ERROR, dwErr,
pwszString ? pwszString : L"");
if (pwszString) LocalFree(pwszString);
exit (dwErr);
}
ViewProxySettings();
break;
case ARGS_VIEW_PROXY_SETTINGS:
ViewProxySettings();
break;
}
MessageCleanup();
return 0;
}