#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wininet.h>
#include <urlmon.h>
#include <stdio.h>
#pragma comment(lib, "wininet.lib")
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "urlmon.lib")
/* ==================================================================
HELPER FUNCTIONS
================================================================== */
/////////////////////////////////////////////////////////////////////
// ResolveHostName (a helper function)
/////////////////////////////////////////////////////////////////////
DWORD __stdcall ResolveHostName(LPSTR lpszHostName,
LPSTR lpszIPAddress, LPDWORD lpdwIPAddressSize)
{
DWORD dwIPAddressSize;
struct addrinfo Hints;
LPADDRINFO lpAddrInfo;
LPADDRINFO IPv4Only;
DWORD error;
// Figure out first whether to resolve a name or an address literal.
// If getaddrinfo( ) with the AI_NUMERICHOST flag succeeds, then
// lpszHostName points to a string representation of an IPv4 or IPv6
// address. Otherwise, getaddrinfo( ) should return EAI_NONAME.
ZeroMemory(&Hints, sizeof (struct addrinfo));
Hints.ai_flags = AI_NUMERICHOST; // Only check for address literals.
Hints.ai_family = PF_UNSPEC; // Accept any protocol family.
Hints.ai_socktype = SOCK_STREAM; // Constrain results to stream socket.
Hints.ai_protocol = IPPROTO_TCP; // Constrain results to TCP.
error = getaddrinfo(lpszHostName, NULL, &Hints, &lpAddrInfo);
if (error != EAI_NONAME) {
if (error != 0) {
error = (error == EAI_MEMORY) ?
ERROR_NOT_ENOUGH_MEMORY : ERROR_INTERNET_NAME_NOT_RESOLVED;
goto quit;
}
freeaddrinfo(lpAddrInfo);
// An IP address (either v4 or v6) was passed in, so if there is
// room in the lpszIPAddress buffer, copy it back out and return.
dwIPAddressSize = lstrlen(lpszHostName);
if ((*lpdwIPAddressSize < dwIPAddressSize) || (lpszIPAddress == NULL)) {
*lpdwIPAddressSize = dwIPAddressSize + 1;
error = ERROR_INSUFFICIENT_BUFFER;
goto quit;
}
strcpy_s(lpszIPAddress, *lpdwIPAddressSize, lpszHostName);
goto quit;
}
// Call getaddrinfo( ) again, this time with no flag set.
Hints.ai_flags = 0;
error = getaddrinfo(lpszHostName, NULL, &Hints, &lpAddrInfo);
if (error != 0) {
error = (error == EAI_MEMORY) ?
ERROR_NOT_ENOUGH_MEMORY : ERROR_INTERNET_NAME_NOT_RESOLVED;
goto quit;
}
// Convert the IP address in addrinfo into a string.
// (the following code only handles IPv4 addresses)
IPv4Only = lpAddrInfo;
while (IPv4Only->ai_family != AF_INET) {
IPv4Only = IPv4Only->ai_next;
if (IPv4Only == NULL) {
error = ERROR_INTERNET_NAME_NOT_RESOLVED;
goto quit;
}
}
error = getnameinfo(IPv4Only->ai_addr,
IPv4Only->ai_addrlen,
lpszIPAddress,
*lpdwIPAddressSize, NULL, 0, NI_NUMERICHOST);
if (error != 0)
error = ERROR_INTERNET_NAME_NOT_RESOLVED;
quit:
return (error);
}
/////////////////////////////////////////////////////////////////////
// IsResolvable (a helper function)
/////////////////////////////////////////////////////////////////////
BOOL __stdcall IsResolvable(LPSTR lpszHost)
{
char szDummy[255];
DWORD dwDummySize = sizeof (szDummy) - 1;
if (ResolveHostName(lpszHost, szDummy, &dwDummySize))
return (FALSE);
return TRUE;
}
/////////////////////////////////////////////////////////////////////
// GetIPAddress (a helper function)
/////////////////////////////////////////////////////////////////////
DWORD __stdcall GetIPAddress(LPSTR lpszIPAddress, LPDWORD lpdwIPAddressSize)
{
char szHostBuffer[255];
if (gethostname(szHostBuffer, sizeof (szHostBuffer) - 1) != ERROR_SUCCESS)
return (ERROR_INTERNET_INTERNAL_ERROR);
return (ResolveHostName(szHostBuffer, lpszIPAddress, lpdwIPAddressSize));
}
/////////////////////////////////////////////////////////////////////
// IsInNet (a helper function)
/////////////////////////////////////////////////////////////////////
BOOL __stdcall IsInNet(LPSTR lpszIPAddress, LPSTR lpszDest, LPSTR lpszMask)
{
DWORD dwDest;
DWORD dwIpAddr;
DWORD dwMask;
dwIpAddr = inet_addr(lpszIPAddress);
dwDest = inet_addr(lpszDest);
dwMask = inet_addr(lpszMask);
if ((dwDest == INADDR_NONE) ||
(dwIpAddr == INADDR_NONE) || ((dwIpAddr & dwMask) != dwDest))
return (FALSE);
return (TRUE);
}
/////////////////////////////////////////////////////////////////////
// reportFuncErr (simple error reporting)
/////////////////////////////////////////////////////////////////////
void reportFuncErr(TCHAR * funcName)
{
printf("\n ERROR: %s failed with error number %d.\n", funcName,
GetLastError());
exit(1);
}
/* ==================================================================
* * * The main( ) function of the test application * * *
================================================================== */
int __cdecl main(int argc, char * argv[])
{
char url[1025] = "http://www.microsoft.com/windows/default.mspx";
char host[256] = "www.microsoft.com";
char WPADLocation[1024] = "";
char TempPath[MAX_PATH];
char TempFile[MAX_PATH];
char proxyBuffer[1024];
char *proxy = proxyBuffer;
DWORD dwProxyHostNameLength = 1024;
DWORD returnVal;
HMODULE hModJS;
// Declare and populate an AutoProxyHelperVtbl structure, and then
// place a pointer to it in a containing AutoProxyHelperFunctions
// structure, which will be passed to InternetInitializeAutoProxyDll
AutoProxyHelperVtbl OurVtbl = {
IsResolvable,
GetIPAddress,
ResolveHostName,
IsInNet,
NULL,
NULL,
NULL,
NULL
};
// Declare function pointers for the three autoproxy functions
pfnInternetInitializeAutoProxyDll pInternetInitializeAutoProxyDll;
pfnInternetDeInitializeAutoProxyDll pInternetDeInitializeAutoProxyDll;
pfnInternetGetProxyInfo pInternetGetProxyInfo;
AutoProxyHelperFunctions HelperFunctions;
HelperFunctions.lpVtbl = &OurVtbl;
ZeroMemory(proxy, 1024);
printf("\nWinINet Proxy Test Program output:\n");
if (!(hModJS = LoadLibrary("jsproxy.dll")))
reportFuncErr("LoadLibrary");
if (!(pInternetInitializeAutoProxyDll = (pfnInternetInitializeAutoProxyDll)
GetProcAddress(hModJS, "InternetInitializeAutoProxyDll")) ||
!(pInternetDeInitializeAutoProxyDll =
(pfnInternetDeInitializeAutoProxyDll)
GetProcAddress(hModJS, "InternetDeInitializeAutoProxyDll"))
|| !(pInternetGetProxyInfo = (pfnInternetGetProxyInfo)
GetProcAddress(hModJS, "InternetGetProxyInfo")))
reportFuncErr("GetProcAddress");
if (!DetectAutoProxyUrl(WPADLocation, sizeof (WPADLocation),
PROXY_AUTO_DETECT_TYPE_DHCP |
PROXY_AUTO_DETECT_TYPE_DNS_A))
reportFuncErr("DetectAutoProxyUrl");
printf("\n WPAD Location is: %s\n", WPADLocation);
GetTempPathA(sizeof (TempPath) / sizeof (TempPath[0]), TempPath);
GetTempFileNameA(TempPath, NULL, 0, TempFile);
URLDownloadToFileA(NULL, WPADLocation, TempFile, 0, NULL);
if (!(returnVal = pInternetInitializeAutoProxyDll(0, TempFile,
NULL,
&HelperFunctions, NULL)))
reportFuncErr("InternetInitializeAutoProxyDll");
printf("\n InternetInitializeAutoProxyDll returned: %d\n", returnVal);
// Delete the temporary file
// (or, to examine the auto-config script, comment out the
// file delete and substitute the following printf call)
// printf( "\n The auto-config script temporary file is:\n %s\n", TempFile);
DeleteFileA(TempFile);
if (!pInternetGetProxyInfo((LPSTR) url, strlen (url),
(LPSTR) host, strlen (host),
&proxy, &dwProxyHostNameLength))
reportFuncErr("InternetGetProxyInfo");
printf("\n Proxy is: %s\n", proxy);
if (!pInternetDeInitializeAutoProxyDll(NULL, 0))
reportFuncErr("InternetDeInitializeAutoProxyDll");
printf("\n...end of test program!\n");
return (0);
}