|
|
// ===========================================================================
// 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; }
|