cliphelper.c

来自「PGP8.0源码 请认真阅读您的文件包然后写出其具体功能」· C语言 代码 · 共 613 行

C
613
字号
/*____________________________________________________________________________
	Copyright (C) 2002 PGP Corporation
	All rights reserved.

	$Id: CLiphelper.c,v 1.2 2002/08/06 20:09:19 dallen Exp $
____________________________________________________________________________*/
#include "pgpPFLConfig.h"

// project header files
#include "PGPclx.h"
#include "pgpSockets.h"

#include <iphlpapi.h>

// external globals
extern HINSTANCE		g_hInst;
extern PGPContextRef	g_context;


// The following contants and structures are used for coaxing 
// information out of the WsControl entry
#define CONTROLSIZE (0x100/8)

// Constants for use in the command field 
#define COMMAND_SPANINFO	0
#define COMMAND_BASEINFO	1
#define COMMAND_INFO2		0x102

// Constants for use in various flags fields 
#define PARAMETER	0x301
#define PARAMETER2	0x303

// An array of this is returned by the spaninfo command.  They tell
// what type of info is there and are used as an index to get more
// in-depth info.
struct _span {
	PGPInt32	magicValue1;
	PGPInt32	magicValue2;
};

struct _wsControl {
	PGPInt32	magicValue1;
	PGPInt32	magicValue2;
	PGPInt32	controlFlag1;
	PGPInt32	controlFlag2;
	PGPInt32	command;
};

// This is the control structure
struct _wsxControl {
	struct _wsControl	baseCommand;
	PGPByte				padding[16];
};

// Before retrieving IP info, we retrieve one of these
struct _IPcount /* size 5c */ {
	PGPInt32	ofs0;
	PGPByte		unk[0x50];
	PGPUInt32	basicIPCount;
	PGPInt32	extendedIPCount;
};

// Once we have retrieved the infostruct we retrieve an array of these
// based on the baseInfoCount filed.  This is where we get the IP and
// Subnet
struct _basicIPInfo /* size 0x18 */ {
	PGPInt32 ipAddress;
	PGPInt32 ident;
	PGPInt32 subnetMask;
	PGPInt32 unk2[2];
	PGPInt32 ofs14;
};

// This is the info structure returned by the DHCP VxD
// DHCP block
typedef struct _DHCPblock {
	DWORD    addrOff;       // Physical address offset
	DWORD    unknown1;
	DWORD    unknown2;
	DWORD    unknown3;
	time_t   leaseObtained; // Lease obtained, secs from 1980/1/1
	time_t   leaseExpires;  // Lease obtained, secs from 1980/1/1
	DWORD    ip;            // IP address
	DWORD    dnsLen;        // Size of DNS array
	DWORD    dnsOff;        // DNS array offset
	DWORD    isDomain;      // domainOff is valid
	DWORD    domainOff;     // Domain name offset
};

typedef struct _DHCPinfo {
	int					cnt;           // Number of blocks
	struct _DHCPblock	b[1];
};

// these are the prototypes for the IPHelper calls
typedef DWORD (WINAPI *GetIpAddrTableProc) (
			PMIB_IPADDRTABLE pIpAddrTable,
			PULONG pdwSize,
			BOOL bOrder);
typedef DWORD (WINAPI *GetNetworkParamsProc) (
			PFIXED_INFO pfinfo, 
			PULONG pdwSize);

// the prototype for the WsControl call
typedef DWORD (WINAPI *WsControlProc) (
			DWORD cmd1,
			DWORD cmd2,
			LPVOID inbuf,
			LPDWORD szinbuf,
			LPVOID outbuf,
			LPDWORD szoutbuf);


static GetIpAddrTableProc		s_fpGetIpAddrTable		= NULL;
static GetNetworkParamsProc		s_fpGetNetworkParams	= NULL;
static WsControlProc			s_fpWsControl			= NULL;


//	______________________________________________
//
//	load the needed libraries

static void
sInitializeLibraries()
{
	static BOOL			bIsInitialized		= FALSE;

	HINSTANCE			hLib;
	PGPclWindowsGenus	genus;

	if (bIsInitialized)
		return;
	bIsInitialized = TRUE;

	PGPclGetWindowsVersion (NULL, &genus, NULL);

	if (genus == kPGPclWindowsGenus95)
	{
		// On Win95 we have to use the undocumented call WsControl into
		// the Winsock library
		if (!(hLib = LoadLibrary ("WSOCK32.DLL"))) 
			return;

		s_fpWsControl = (WsControlProc)GetProcAddress (hLib, "WsControl");
	}
	else
	{
		// Otherwise we use the IPHELPER library
		if (!(hLib = LoadLibrary ("IPHLPAPI.DLL"))) 
			return;

		s_fpGetIpAddrTable = 
				(GetIpAddrTableProc)GetProcAddress (hLib, "GetIpAddrTable");
		s_fpGetNetworkParams = 
				(GetNetworkParamsProc)GetProcAddress (hLib, "GetNetworkParams");
	}
}


//	______________________________________________
//
//	a subroutine to read the base adapter array 

static void*
sGetBaseAdapterInfo (
		PGPInt32*	piBufCount)
{
	PGPUInt32			bufsize, controlsize;
	void*				pbuffer;
	struct _wsxControl	commandx;

	// Format the command packet 
	pgpClearMemory (&commandx, sizeof(commandx));
	commandx.baseCommand.magicValue1		= 0;
	commandx.baseCommand.magicValue2		= 0;
	commandx.baseCommand.controlFlag1		= 0x100;
	commandx.baseCommand.controlFlag2		= 0x100;
	commandx.baseCommand.command			= COMMAND_SPANINFO;
	controlsize = sizeof(commandx);

	// allocate the response packet 
	bufsize = CONTROLSIZE*8;
	pbuffer = PGPNewData (PGPPeekContextMemoryMgr (g_context),
			bufsize, kPGPMemoryMgrFlags_Clear);
	if (IsNull (pbuffer))
		return 0;

	// issue the command
	if (s_fpWsControl (6, 0, &commandx, &controlsize, pbuffer, &bufsize)) 
	{
		PGPFreeData (pbuffer);
		return 0;
	}

	// return the count and buffer
	*piBufCount = bufsize / sizeof (struct _span);
	return pbuffer;
}


//	______________________________________________
//
//	returns a valid IP address and subnet mask for this machine

PGPError PGPclExport
PGPclGetIPandSubnetMask (
		PGPUInt32*	puIP,
		PGPUInt32*	puSubnetMask)
{
	PGPError	err			= kPGPError_NoErr;
	PGPInt32	i;
	PGPInt32	iIPcount;

	sInitializeLibraries ();

	// use the IPHLP stuff, if available
	if (IsntNull (s_fpGetIpAddrTable))
	{
		MIB_IPADDRTABLE*	pIPTable		= NULL;
		PGPUInt32			iret			= NO_ERROR;
		PGPUInt32			uIPTableSize	= 0;

		// Get IP addresses table size
		err = kPGPError_Win32_IPHelperLibError;
		iret = s_fpGetIpAddrTable (NULL, &uIPTableSize, TRUE);

		// Now allocate the table and fill it in
		if ((uIPTableSize > 0) && 
			(iret == ERROR_INSUFFICIENT_BUFFER)) 
		{
			pIPTable = (PMIB_IPADDRTABLE)PGPNewData (
					PGPPeekContextMemoryMgr (g_context),
					uIPTableSize, kPGPMemoryMgrFlags_Clear);

			iret = s_fpGetIpAddrTable (pIPTable, &uIPTableSize, TRUE);

			if (iret == NO_ERROR) 
				err = kPGPError_NoErr;
		}

		if (IsntPGPError (err))
		{
			iIPcount = pIPTable->dwNumEntries;

			for (i=0; i<iIPcount; i++) 
			{
				if ((pIPTable->table[i].dwAddr != 0) && 
					(pIPTable->table[i].dwAddr != 0x0100007F))
				{
					if (puIP)
						*puIP = pIPTable->table[i].dwAddr;
					if (puSubnetMask)
						*puSubnetMask = pIPTable->table[i].dwMask;
					break;
				}
			}
		}

		if (pIPTable)
			PGPFreeData (pIPTable);
	}

	// otherwise use the undocumented WsControl entry into the Winsock DLL
	else if (IsntNull (s_fpWsControl))
	{
		struct _span*			pBaseAddr	= NULL;
		struct _span*			pBasePtr	= NULL;
		struct _basicIPInfo*	pBaseIPinfo	= NULL;

		PGPInt32				ibasecount, index;
		PGPUInt32				structsize, commandlen, returnedFlags;
		struct _wsxControl		commandx;
		struct _wsControl		command;
		struct _IPcount			ipCount;

		// Get the adapter list
		if (!(pBaseAddr = (struct _span *)sGetBaseAdapterInfo (&ibasecount))) 
			return kPGPError_OutOfMemory;

		// Now go through the list looking for ip parameter packets 
		for (index=0, pBasePtr=pBaseAddr; index<ibasecount; index++, pBasePtr++)
		{
			if (pBasePtr->magicValue1 == PARAMETER) 
			{
				pgpClearMemory (&commandx, sizeof(commandx));

				command.magicValue1		= pBasePtr->magicValue1;
				command.magicValue2		= pBasePtr->magicValue2;
				command.controlFlag1	= 0x100;
				command.controlFlag2	= 0x100;
				command.command			= COMMAND_BASEINFO;
				commandlen = sizeof(commandx);
				structsize = sizeof(PGPUInt32);

				pgpCopyMemory (&command, 
						&commandx.baseCommand, sizeof(command));
				if (s_fpWsControl (6, 0, &commandx, 
						&commandlen, &returnedFlags, &structsize)) 
				{
					err = kPGPError_Win32_WsControlError;
				}

				// Get the number of IP entries
				if (IsntPGPError (err) &&
					(returnedFlags == PARAMETER2))
				{
					command.controlFlag1	= 0x200;
					command.command			= COMMAND_BASEINFO;

					pgpClearMemory (&commandx, sizeof(commandx));
					pgpCopyMemory (&command,
							&commandx.baseCommand, sizeof(command));

					commandlen = sizeof(commandx);
					structsize = 0x5c;
					if (s_fpWsControl (6, 0, &commandx, 
							&commandlen, &ipCount, &structsize) || 
						(structsize != 0x5c))
					{
						err = kPGPError_Win32_WsControlError;
					}

					// Get the IP information
					if (IsntPGPError (err) &&
						(ipCount.basicIPCount != 0)) 
					{
						structsize = ipCount.basicIPCount * 
								sizeof(struct _basicIPInfo);
						pBaseIPinfo = (struct _basicIPInfo*) PGPNewData (
								PGPPeekContextMemoryMgr (g_context),
								structsize, kPGPMemoryMgrFlags_Clear);

						if (!pBaseIPinfo) 
							err = kPGPError_OutOfMemory;

						if (IsntPGPError (err))
						{
							pgpClearMemory (&commandx, sizeof(commandx));
							command.command = COMMAND_INFO2;

							pgpCopyMemory (&command, 
									&commandx.baseCommand, sizeof(command));
							commandlen = 0x24;

							if (s_fpWsControl (6, 0, &commandx, 
									&commandlen, pBaseIPinfo, &structsize)) 
							{
								err = kPGPError_Win32_WsControlError;
							}
						}

						if (IsntPGPError (err))
						{
							if (structsize / sizeof(struct _basicIPInfo) >= 
									ipCount.basicIPCount)
							{
								iIPcount = 
									structsize / sizeof(struct _basicIPInfo);
							}
							else
								iIPcount = ipCount.basicIPCount;

							for (i=0; i<iIPcount; i++) 
							{
								if ((pBaseIPinfo[i].ipAddress != 0) &&
									(pBaseIPinfo[i].ipAddress != 0x0100007F))
								{
									if (puIP)
										*puIP = pBaseIPinfo[i].ipAddress;
									if (puSubnetMask)
										*puSubnetMask = pBaseIPinfo[i].subnetMask;
									break;
								}
							}
						}

						if (IsntNull (pBaseIPinfo))
							PGPFreeData (pBaseIPinfo);
					}
				}
			}

			if (IsPGPError (err))
				break;
		}
		
		if (IsntNull (pBaseAddr))
			PGPFreeData (pBaseAddr);
	}

	// no libaries to use
	else
		err = kPGPError_Win32DllOpFailed;


	return err;
}


//	______________________________________________
//
//	returns a valid IP address and subnet mask for this machine

PGPBoolean PGPclExport
PGPclIsLocalMachineOnline (void)
{
	PGPUInt32	uIP		= 0;

	if (IsntPGPError (PGPclGetIPandSubnetMask (&uIP, NULL)))
	{
		if (uIP != 0)
		{
			return TRUE;
		}
	}

	return FALSE;
}


//	____________________________________
//
//	Gets list of DNS servers, skips duplicates

static void
sQueryDHCPForDNSServerAddress (
		PGPUInt32*	puDNSAddress)
{
	CHAR		szVxD[32];
	HANDLE		hVxD;

	// attempt to open the DHCP VxD
	lstrcpy (szVxD, "\\\\.\\VDHCP");
	hVxD = CreateFile (szVxD, GENERIC_READ|GENERIC_WRITE,
			FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING,
			FILE_FLAG_DELETE_ON_CLOSE, 0);

	if (hVxD == INVALID_HANDLE_VALUE)
	{
		lstrcat (szVxD, ".VXD");
		hVxD = CreateFile (szVxD, GENERIC_READ|GENERIC_WRITE,
				FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING,
				FILE_FLAG_DELETE_ON_CLOSE, 0);
	}

	if (hVxD != INVALID_HANDLE_VALUE)
	{
		DWORD	dw, dwRet;

		// this first call should fail, returning required buffer size
		if (!DeviceIoControl (hVxD, 0x01, (LPVOID)&dw, sizeof(dw), 
				(LPVOID)&dw, sizeof(dw), &dwRet, 0))
		{
			if (GetLastError () == ERROR_BUFFER_OVERFLOW)
			{
				struct _DHCPinfo*	pDHCPinfo;

				pDHCPinfo = PGPNewData (
						PGPPeekContextMemoryMgr (g_context),
						dw, kPGPMemoryMgrFlags_Clear);

				if (pDHCPinfo)
				{
					if (DeviceIoControl (hVxD, 0x01, (LPVOID)pDHCPinfo, dw, 
							(LPVOID)pDHCPinfo, dw, &dwRet, 0))
					{
						// copy the first DNS server address
						PGPByte*	p	= (PGPByte*)pDHCPinfo;

						p += pDHCPinfo->b[0].dnsOff;
						pgpCopyMemory (p, puDNSAddress, sizeof(PGPUInt32));
					}
					PGPFreeData (pDHCPinfo);
				}
			}
		}

		CloseHandle (hVxD);
	}
}


//	____________________________________
//
//	ask IPHelper for the DNS server IP address for the local machine

static void 
sQueryIPHelperForDNSServerAddress (
		PGPUInt32*	puDNSAddress)
{
	sInitializeLibraries ();

	if (IsntNull (s_fpGetNetworkParams))
	{
		ULONG			ulSize		= 0;
		FIXED_INFO*		pfi;
		DWORD			dwRet;

		dwRet = s_fpGetNetworkParams (NULL, &ulSize);

		if ((dwRet == ERROR_BUFFER_OVERFLOW) && (ulSize > 0))
		{
			pfi = (FIXED_INFO*)PGPNewData (
					PGPPeekContextMemoryMgr (g_context),
					ulSize, kPGPMemoryMgrFlags_Clear);

			if (pfi)
			{
				dwRet = s_fpGetNetworkParams (pfi, &ulSize);
				if (dwRet == ERROR_SUCCESS)
				{
					*puDNSAddress = PGPDottedToInternetAddress (
							pfi->DnsServerList.IpAddress.String);
				}
				PGPFreeData (pfi);
			}
		}
	}
}


//	____________________________________
//
//	get the DNS server IP address for the local machine

PGPError PGPclExport
PGPclGetDNSServerAddress (
		PGPUInt32*	puDNSAddress)
{
	PGPError			err;
	HKEY				hkey;
	LONG				lResult;
	DWORD				dwValueType, dwSize;
	CHAR				sz[32];
	LPSTR				p;

	*puDNSAddress = 0;

	// first try using the IPHelper library
	sQueryIPHelperForDNSServerAddress (puDNSAddress);
	if (*puDNSAddress != 0)
		return kPGPError_NoErr;

	// OK, that didn't work, now look in the WinNT key
	err = kPGPError_ItemNotFound;
	lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE, 
			"System\\CurrentControlSet\\Services\\Tcpip\\Parameters", 
			0, KEY_READ, &hkey);

	if (lResult == ERROR_SUCCESS) 
	{
		dwSize = sizeof(sz);
		lResult = RegQueryValueEx (hkey,
				"NameServer", 0, &dwValueType, (LPBYTE)sz, &dwSize);

		if (lResult == ERROR_SUCCESS)
			err = kPGPError_NoErr;

		RegCloseKey (hkey);
	}

	// if that didn't work, look in the Win9x key
	if (IsPGPError (err))
	{
		lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE, 
				"System\\CurrentControlSet\\Services\\VxD\\MSTCP", 
				0, KEY_READ, &hkey);

		if (lResult == ERROR_SUCCESS) 
		{
			dwSize = sizeof(sz);
			lResult = RegQueryValueEx (hkey,
					"NameServer", 0, &dwValueType, (LPBYTE)sz, &dwSize);

			if (lResult == ERROR_SUCCESS)
				err = kPGPError_NoErr;

			RegCloseKey (hkey);
		}
	}

	// finally try the Win9x DHCP call
	if (IsPGPError (err))
	{
		if (IsntNull (s_fpWsControl))
			sQueryDHCPForDNSServerAddress (puDNSAddress);

		if (*puDNSAddress != 0)
			return kPGPError_NoErr;
	}

	// if here, and no error, then the address came from the registry and
	// is in string format
	if (IsntPGPError (err))
	{
		// string can be a space-separated list
		p = strchr (sz, ' ');
		if (p)
			*p = '\0';

		// or a comma-separated list
		p = strchr (sz, ',');
		if (p)
			*p = '\0';

		*puDNSAddress = PGPDottedToInternetAddress (sz);
	}

	return err;
}


⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?