You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
953 lines
15 KiB
953 lines
15 KiB
/*++
|
|
|
|
Copyright (c) 1994-1999 Microsoft Corporation
|
|
|
|
Module Name :
|
|
|
|
ipa.cpp
|
|
|
|
Abstract:
|
|
|
|
IP Address value and helper functions
|
|
|
|
Author:
|
|
|
|
Ronald Meijer (ronaldm)
|
|
|
|
Project:
|
|
|
|
Internet Services Manager
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
|
|
//
|
|
// Include Files
|
|
//
|
|
#include "stdafx.h"
|
|
#include "common.h"
|
|
#include "util.h"
|
|
#include <winsock2.h>
|
|
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
|
|
|
|
//
|
|
// Calling instance
|
|
//
|
|
extern HINSTANCE hDLLInstance;
|
|
|
|
|
|
|
|
/* static */
|
|
DWORD
|
|
CIPAddress::StringToLong(
|
|
IN LPCTSTR lpstr,
|
|
IN int nLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Static function to convert an ip address string of the form "1.2.3.4"
|
|
to a a single 32 bit number.
|
|
|
|
Arguments:
|
|
|
|
LPCTSTR lpstr : String ip address
|
|
int nLength : Length of string
|
|
|
|
Return Value:
|
|
|
|
32 bit ip address.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwIPValue = 0L;
|
|
|
|
if (nLength > 0)
|
|
{
|
|
u_long ul = 0;
|
|
|
|
#ifdef UNICODE
|
|
|
|
try
|
|
{
|
|
//
|
|
// Convert to ANSI
|
|
//
|
|
LPSTR pszDest = AllocAnsiString(lpstr);
|
|
if (NULL != pszDest)
|
|
{
|
|
ul = ::inet_addr(pszDest);
|
|
FreeMem(pszDest);
|
|
}
|
|
}
|
|
catch(CException * e)
|
|
{
|
|
TRACEEOLID("!!!Exception converting string to ip address");
|
|
e->ReportError();
|
|
e->Delete();
|
|
}
|
|
|
|
#else
|
|
|
|
ul = ::inet_addr(lpstr);
|
|
|
|
#endif // UNICODE
|
|
|
|
//
|
|
// Convert to host byte order.
|
|
//
|
|
dwIPValue = (DWORD)::ntohl(ul);
|
|
}
|
|
|
|
return dwIPValue;
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
LPTSTR
|
|
CIPAddress::LongToString(
|
|
IN const DWORD dwIPAddress,
|
|
OUT LPTSTR lpStr,
|
|
IN int cbSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Static function to convert a 32 bit number to a CString of the format
|
|
"1.2.3.4"
|
|
|
|
Arguments:
|
|
|
|
const DWORD dwIPAddress : 32 bit ip address to be converted to string
|
|
LPTSTR lpStr : Destination string
|
|
int cbSize : Size of destination string
|
|
|
|
Return Value:
|
|
|
|
Pointer to string buffer
|
|
|
|
--*/
|
|
{
|
|
struct in_addr ipaddr;
|
|
|
|
//
|
|
// Convert the unsigned long to network byte order
|
|
//
|
|
ipaddr.s_addr = ::htonl((u_long)dwIPAddress);
|
|
|
|
//
|
|
// Convert the IP address value to a string
|
|
//
|
|
LPCSTR pchAddr = ::inet_ntoa(ipaddr);
|
|
|
|
#ifdef UNICODE
|
|
|
|
VERIFY(::MultiByteToWideChar(CP_ACP, 0L, pchAddr, -1, lpStr, cbSize));
|
|
|
|
#else
|
|
|
|
::lstrcpy(lpStr, pchAddr);
|
|
|
|
#endif // UNICODE
|
|
|
|
return lpStr;
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
LPCTSTR
|
|
CIPAddress::LongToString(
|
|
IN const DWORD dwIPAddress,
|
|
OUT CString & str
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Static function to convert a 32 bit number to a CString of the format
|
|
"1.2.3.4"
|
|
|
|
Arguments:
|
|
|
|
const DWORD dwIPAddress : 32 bit ip address to be converted to string
|
|
CString & str : Destination string
|
|
|
|
Return Value:
|
|
|
|
Pointer to string buffer
|
|
|
|
--*/
|
|
{
|
|
struct in_addr ipaddr;
|
|
|
|
//
|
|
// Convert the unsigned long to network byte order
|
|
//
|
|
ipaddr.s_addr = ::htonl((u_long)dwIPAddress);
|
|
|
|
//
|
|
// Convert the IP address value to a string
|
|
//
|
|
LPCSTR pchAddr = ::inet_ntoa(ipaddr);
|
|
|
|
try
|
|
{
|
|
str = pchAddr;
|
|
}
|
|
catch(CMemoryException * e)
|
|
{
|
|
TRACEEOLID("!!!Exception converting ip address to string");
|
|
e->ReportError();
|
|
e->Delete();
|
|
}
|
|
|
|
return (LPCTSTR)str;
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
LPCTSTR
|
|
CIPAddress::LongToString(
|
|
IN const DWORD dwIPAddress,
|
|
OUT CComBSTR & bstr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Static function to convert a 32 bit number to a CComBSTR of the format
|
|
"1.2.3.4"
|
|
|
|
Arguments:
|
|
|
|
const DWORD dwIPAddress : 32 bit ip address to be converted to string
|
|
CComBSTR & bstr : Destination string
|
|
|
|
Return Value:
|
|
|
|
Pointer to string buffer
|
|
|
|
--*/
|
|
{
|
|
struct in_addr ipaddr;
|
|
|
|
//
|
|
// Convert the unsigned long to network byte order
|
|
//
|
|
ipaddr.s_addr = ::htonl((u_long)dwIPAddress);
|
|
|
|
//
|
|
// Convert the IP address value to a string
|
|
//
|
|
bstr = ::inet_ntoa(ipaddr);
|
|
|
|
return bstr;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* static */
|
|
LPBYTE
|
|
CIPAddress::DWORDtoLPBYTE(
|
|
IN DWORD dw,
|
|
OUT LPBYTE lpBytes
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert a DWORD to a byte array of 4 bytes. No size
|
|
checking is performed.
|
|
|
|
Arguments:
|
|
|
|
DWORD dw : 32 bit ip address
|
|
LPBYTE lpBytes : Byte stream
|
|
|
|
Return Value:
|
|
|
|
Pointer to the input buffer.
|
|
|
|
--*/
|
|
{
|
|
lpBytes[0] = (BYTE)GETIP_FIRST(dw);
|
|
lpBytes[1] = (BYTE)GETIP_SECOND(dw);
|
|
lpBytes[2] = (BYTE)GETIP_THIRD(dw);
|
|
lpBytes[3] = (BYTE)GETIP_FOURTH(dw);
|
|
|
|
return lpBytes;
|
|
}
|
|
|
|
|
|
|
|
CIPAddress::CIPAddress()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
: m_dwIPAddress(0L)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
CIPAddress::CIPAddress(
|
|
IN DWORD dwIPAddress,
|
|
IN BOOL fNetworkByteOrder
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor.
|
|
|
|
Arguments:
|
|
|
|
DWORD dwIPAddress : IP address value
|
|
BOOL fNetworkByteOrder : if TRUE, value must be converted to host byte
|
|
order, otherwise is assumed to already be in
|
|
host byte order.
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
{
|
|
if (fNetworkByteOrder)
|
|
{
|
|
//
|
|
// Convert to host byte order
|
|
//
|
|
dwIPAddress = (DWORD)::ntohl((u_long)dwIPAddress);
|
|
}
|
|
|
|
m_dwIPAddress = dwIPAddress;
|
|
}
|
|
|
|
|
|
|
|
CIPAddress::CIPAddress(
|
|
IN BYTE b1,
|
|
IN BYTE b2,
|
|
IN BYTE b3,
|
|
IN BYTE b4
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor.
|
|
|
|
Arguments:
|
|
|
|
BYTE b1 : First octet
|
|
BYTE b2 : Second octet
|
|
BYTE b3 : Third octet
|
|
BYTE b4 : Fourth octet
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
Notes:
|
|
|
|
This is already assumed to be in host order
|
|
|
|
--*/
|
|
: m_dwIPAddress(MAKEIPADDRESS(b1, b2, b3, b4))
|
|
{
|
|
}
|
|
|
|
|
|
|
|
CIPAddress::CIPAddress(
|
|
IN LPBYTE lpBytes,
|
|
IN BOOL fNetworkByteOrder OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Construct from byte stream
|
|
|
|
Arguments:
|
|
|
|
LPBYTE lpBytes : Byte stream
|
|
BOOL fNetworkByteOrder : TRUE if the byte stream is in network byte order
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
{
|
|
lpBytes;
|
|
fNetworkByteOrder;
|
|
}
|
|
|
|
|
|
|
|
CIPAddress::CIPAddress(
|
|
IN const CIPAddress & ia
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copy Constructor.
|
|
|
|
Arguments:
|
|
|
|
const CIPAddress & ia
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
: m_dwIPAddress(ia.m_dwIPAddress)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
CIPAddress::CIPAddress(
|
|
IN LPCTSTR lpstr,
|
|
IN int nLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor.
|
|
|
|
Arguments:
|
|
|
|
LPCTSTR lpstr : string ip value
|
|
int nLength : length of string
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
{
|
|
m_dwIPAddress = CIPAddress::StringToLong(lpstr, nLength);
|
|
}
|
|
|
|
|
|
|
|
CIPAddress::CIPAddress(
|
|
const CString & str
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor.
|
|
|
|
Arguments:
|
|
|
|
const CString & str : IP Address string
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
{
|
|
m_dwIPAddress = CIPAddress::StringToLong(str);
|
|
}
|
|
|
|
|
|
|
|
const CIPAddress &
|
|
CIPAddress::operator =(
|
|
IN const CIPAddress & ia
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Assignment operator
|
|
|
|
Arguments:
|
|
|
|
const CIPAddress & ia : Source ip address
|
|
|
|
Return Value:
|
|
|
|
Current object
|
|
|
|
--*/
|
|
{
|
|
m_dwIPAddress = ia.m_dwIPAddress;
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
|
|
const CIPAddress &
|
|
CIPAddress::operator =(
|
|
IN const DWORD dwIPAddress
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Assignment operator
|
|
|
|
Arguments:
|
|
|
|
const DWORD dwIPAddress : Source ip address
|
|
|
|
Return Value:
|
|
|
|
Current object
|
|
|
|
--*/
|
|
{
|
|
m_dwIPAddress = dwIPAddress;
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
|
|
const CIPAddress &
|
|
CIPAddress::operator =(
|
|
IN LPCTSTR lpstr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Assignment operator
|
|
|
|
Arguments:
|
|
|
|
LPCTSTR lpstr : Source string
|
|
|
|
Return Value:
|
|
|
|
Current object
|
|
|
|
--*/
|
|
{
|
|
m_dwIPAddress = CIPAddress::StringToLong(lpstr, ::lstrlen(lpstr));
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
|
|
const CIPAddress &
|
|
CIPAddress::operator =(
|
|
IN const CString & str
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Assignment operator
|
|
|
|
Arguments:
|
|
|
|
const CString & str : Source string
|
|
|
|
Return Value:
|
|
|
|
Current object
|
|
|
|
--*/
|
|
{
|
|
m_dwIPAddress = CIPAddress::StringToLong(str);
|
|
|
|
return *this;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
CIPAddress::CompareItem(
|
|
IN const CIPAddress & ia
|
|
) const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Compare two ip addresses
|
|
|
|
Arguments:
|
|
|
|
const CIPAddress & ia : IP Address to compare this to
|
|
|
|
Return Value:
|
|
|
|
+1 if the current ip address is greater,
|
|
0 if the two ip addresses are the same
|
|
-1 if the current ip address is less,
|
|
|
|
--*/
|
|
{
|
|
return (DWORD)ia < m_dwIPAddress
|
|
? +1
|
|
: (DWORD)ia == m_dwIPAddress
|
|
? 0
|
|
: -1;
|
|
}
|
|
|
|
|
|
|
|
CIPAddress::operator LPCTSTR() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Conversion operator
|
|
|
|
Arguments:
|
|
|
|
N/A
|
|
|
|
Return Value:
|
|
|
|
Pointer to converted string
|
|
|
|
--*/
|
|
{
|
|
static TCHAR szIPAddress[] = _T("xxx.xxx.xxx.xxx");
|
|
|
|
return CIPAddress::LongToString(
|
|
m_dwIPAddress,
|
|
szIPAddress,
|
|
ARRAY_SIZE(szIPAddress)
|
|
);
|
|
}
|
|
|
|
|
|
|
|
CIPAddress::operator CString() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Conversion operator
|
|
|
|
Arguments:
|
|
|
|
N/A
|
|
|
|
Return Value:
|
|
|
|
Converted string
|
|
|
|
--*/
|
|
{
|
|
CString str;
|
|
|
|
CIPAddress::LongToString(m_dwIPAddress, str);
|
|
|
|
return str;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
CIPAddress::QueryIPAddress(
|
|
IN BOOL fNetworkByteOrder
|
|
) const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the ip address as a 32 bit number
|
|
|
|
Arguments:
|
|
|
|
BOOL fNetworkByteOrder : If TRUE, convert to network byte order
|
|
|
|
Return Value:
|
|
|
|
32 bit ip address
|
|
|
|
--*/
|
|
{
|
|
return fNetworkByteOrder
|
|
? ::htonl((u_long)m_dwIPAddress)
|
|
: m_dwIPAddress;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// IP Address helper functions
|
|
//
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
|
|
|
|
DWORD
|
|
PopulateComboWithKnownIpAddresses(
|
|
IN LPCTSTR lpszServer,
|
|
IN CComboBox & combo,
|
|
IN CIPAddress & iaIpAddress,
|
|
OUT CObListPlus & oblIpAddresses,
|
|
OUT int & nIpAddressSel
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Fill a combo box with known ip addresses
|
|
|
|
Arguments:
|
|
|
|
LPCTSTR lpszServer : Server whose ip addresses to obtain
|
|
(can be computer name or ip address)
|
|
|
|
CComboBox & combo : Combo box to populate
|
|
CIPAddress & iaIpAddress : IP Address to select
|
|
CObListPlus & oblIpAddresses : Returns an oblist of CIPAddress objects
|
|
int & nIpAddressSel : Returns selected IP address
|
|
|
|
Return Value:
|
|
|
|
Error return code
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Start clean
|
|
//
|
|
oblIpAddresses.RemoveAll();
|
|
combo.ResetContent();
|
|
|
|
//
|
|
// Don't like \\names
|
|
//
|
|
lpszServer = PURE_COMPUTER_NAME(lpszServer);
|
|
struct hostent * pHostEntry = NULL;
|
|
|
|
if (LooksLikeIPAddress(lpszServer))
|
|
{
|
|
//
|
|
// Get by ip address
|
|
//
|
|
u_long ul = (DWORD)CIPAddress(lpszServer);
|
|
ul = ::htonl(ul); // convert to network order.
|
|
pHostEntry = ::gethostbyaddr((CHAR *)&ul, sizeof(ul), PF_INET);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Get by domain name
|
|
//
|
|
const char FAR * lpszAnsiServer = NULL;
|
|
|
|
#ifdef UNICODE
|
|
|
|
CHAR szAnsi[255];
|
|
|
|
if (::WideCharToMultiByte(CP_ACP, 0L, lpszServer, -1, szAnsi,
|
|
sizeof(szAnsi), NULL, NULL) > 0)
|
|
{
|
|
lpszAnsiServer = szAnsi;
|
|
}
|
|
#else
|
|
lpszAnsiServer = lpszServer;
|
|
#endif // UNICODE
|
|
|
|
if (lpszAnsiServer)
|
|
{
|
|
pHostEntry = ::gethostbyname(lpszAnsiServer);
|
|
}
|
|
}
|
|
|
|
//
|
|
// We'll always have the 'default' server id
|
|
// selected
|
|
//
|
|
CComBSTR bstr, bstrDefault;
|
|
VERIFY(bstrDefault.LoadString(hDLLInstance, IDS_ALL_UNASSIGNED));
|
|
|
|
nIpAddressSel = -1;
|
|
CIPAddress * pia = new CIPAddress;
|
|
|
|
if (!pia)
|
|
{
|
|
TRACEEOLID("PopulateComboWithKnownIpAddresses: OOM");
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
oblIpAddresses.AddTail(pia);
|
|
int nNewSel = combo.AddString(bstrDefault);
|
|
|
|
if (iaIpAddress == *pia)
|
|
{
|
|
//
|
|
// Remember selection
|
|
//
|
|
nIpAddressSel = nNewSel;
|
|
}
|
|
|
|
if (pHostEntry != NULL)
|
|
{
|
|
int n = 0;
|
|
while (((DWORD *)pHostEntry->h_addr_list[n]) != NULL)
|
|
{
|
|
//
|
|
// Convert from network byte order
|
|
//
|
|
pia = new CIPAddress(
|
|
*((DWORD *)(pHostEntry->h_addr_list[n++])), TRUE);
|
|
|
|
if (!pia)
|
|
{
|
|
TRACEEOLID("PopulateComboWithKnownIpAddresses: OOM");
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
nNewSel = combo.AddString(pia->QueryIPAddress(bstr));
|
|
oblIpAddresses.AddTail(pia);
|
|
|
|
if (iaIpAddress == *pia)
|
|
{
|
|
//
|
|
// This is our current ip address, save index
|
|
// for selection
|
|
//
|
|
nIpAddressSel = nNewSel;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nIpAddressSel < 0)
|
|
{
|
|
//
|
|
// Ok, the IP address selected is not part of the
|
|
// list. Add it to the list, and select it.
|
|
//
|
|
pia = new CIPAddress(iaIpAddress);
|
|
|
|
if (!pia)
|
|
{
|
|
TRACEEOLID("PopulateComboWithKnownIpAddresses: OOM");
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
nIpAddressSel = combo.AddString(pia->QueryIPAddress(bstr));
|
|
oblIpAddresses.AddTail(pia);
|
|
}
|
|
|
|
combo.SetCurSel(nIpAddressSel);
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
FetchIpAddressFromCombo(
|
|
IN CComboBox & combo,
|
|
IN CObListPlus & oblIpAddresses,
|
|
OUT CIPAddress & ia
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Helper function to fetch an ip address from the combo box.
|
|
The combo box may not have a selection, in which case whatever
|
|
is in the edit box is used
|
|
|
|
Arguments:
|
|
|
|
CComboBox & combo : Combo box
|
|
CObListPlus & oblIpAddresses : Oblist of ip addresses
|
|
CIPAddress & ia : Returns the ip address
|
|
|
|
Return Value:
|
|
|
|
TRUE if a valid IP address is found, FALSE otherwise.
|
|
|
|
--*/
|
|
{
|
|
int nSel = combo.GetCurSel();
|
|
CString str;
|
|
combo.GetWindowText(str);
|
|
// after touching (All unassigned) combo loses selection,
|
|
// but text still could be the same
|
|
if (nSel < 0)
|
|
{
|
|
nSel = combo.FindStringExact(-1, str);
|
|
}
|
|
if (nSel >= 0)
|
|
{
|
|
//
|
|
// Fetch selected item
|
|
//
|
|
CIPAddress * pia = (CIPAddress *)oblIpAddresses.Index(nSel);
|
|
ASSERT_PTR(pia);
|
|
if (pia != NULL)
|
|
{
|
|
ia = *pia;
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Try to make an ip address out of what's in the editbox
|
|
//
|
|
if (!str.IsEmpty())
|
|
{
|
|
ia = str;
|
|
if (!ia.IsZeroValue() && !ia.IsBadValue())
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// No good
|
|
//
|
|
::AfxMessageBox(IDS_INVALID_IP_ADDRESS);
|
|
|
|
return FALSE;
|
|
}
|