Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

581 lines
10 KiB

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corporation, 1999 - 1999 **/
/**********************************************************************/
/*
compinfo.cpp
Computer info class plus helper functions
FILE HISTORY:
*/
#include <stdafx.h>
#include <winsock.h>
#include "compinfo.h"
#define STRING_MAX 256
//
//
//
BOOL
CIpInfoArray::FIsInList(DWORD dwIp)
{
BOOL fFound = FALSE;
for (int i = 0; i < GetSize(); i++)
{
if (GetAt(i).dwIp == dwIp)
{
fFound = TRUE;
break;
}
}
return fFound;
}
//
//
//
CComputerInfo::CComputerInfo(LPCTSTR pszNameOrIp)
{
m_strNameOrIp = pszNameOrIp;
m_nIndex = -1;
}
CComputerInfo::~CComputerInfo()
{
}
HRESULT
CComputerInfo::GetIp(DWORD * pdwIp, int nIndex)
{
HRESULT hr = hrOK;
if (m_nIndex == -1)
{
hr = InitializeData();
}
if (SUCCEEDED(hr))
{
if (pdwIp)
*pdwIp = m_arrayIps[nIndex].dwIp;
}
else
{
if (pdwIp)
*pdwIp = 0xFFFFFFFF;
}
return hr;
}
HRESULT
CComputerInfo::GetIpStr(CString & strIp, int nIndex)
{
HRESULT hr = hrOK;
if (m_nIndex == -1)
{
hr = InitializeData();
}
if (SUCCEEDED(hr))
{
struct in_addr ipaddr ;
//
// Convert the unsigned long to network byte order
//
ipaddr.s_addr = ::htonl( (u_long) m_arrayIps[nIndex].dwIp ) ;
CHAR * pszAddr = inet_ntoa( ipaddr ) ;
::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszAddr, -1, strIp.GetBuffer(IP_ADDDRESS_LENGTH_MAX), IP_ADDDRESS_LENGTH_MAX);
strIp.ReleaseBuffer();
}
else
{
strIp.Empty();
}
return hr;
}
HRESULT
CComputerInfo::GetHostName(CString & strHostName)
{
HRESULT hr = hrOK;
if (m_nIndex == -1)
{
hr = InitializeData();
}
if (SUCCEEDED(hr))
{
strHostName = m_strHostname;
}
else
{
strHostName.Empty();
}
return hr;
}
HRESULT
CComputerInfo::GetFqdn(CString & strFqdn, int nIndex)
{
HRESULT hr = hrOK;
if (m_nIndex == -1)
{
hr = InitializeData();
}
if (SUCCEEDED(hr))
{
strFqdn = m_arrayIps[nIndex].strFqdn;
}
else
{
strFqdn.Empty();
}
return hr;
}
int
CComputerInfo::GetCount()
{
return m_nIndex;
}
//
// Call this function to reset the internal data so that on the next query
// we will rebuild our data.
//
void
CComputerInfo::Reset()
{
// set this to -1 so that we will get the data again on the next call
m_nIndex = -1;
m_arrayIps.RemoveAll();
m_strHostname.Empty();
}
HRESULT
CComputerInfo::GetDomain(CString & strDomain)
{
// not supported right now
strDomain.Empty();
return E_NOTIMPL;
}
HRESULT
CComputerInfo::IsLocalMachine(BOOL * pfIsLocal)
{
HRESULT hr = hrOK;
if (m_nIndex == -1)
{
hr = InitializeData();
}
if (pfIsLocal)
{
if (SUCCEEDED(hr))
{
CString strLocal;
DWORD dwSize = STRING_MAX;
BOOL fSuccess = GetComputerName(strLocal.GetBuffer(dwSize), &dwSize);
strLocal.ReleaseBuffer();
if (fSuccess)
{
*pfIsLocal = (strLocal.CompareNoCase(m_strHostname) == 0) ? TRUE : FALSE;
}
}
else
{
*pfIsLocal = FALSE;
}
}
return hr;
}
COMPUTER_INFO_TYPE
CComputerInfo::GetInputType()
{
// assume a NetBios name
COMPUTER_INFO_TYPE enResult = COMPUTER_INFO_TYPE_NB ;
const TCHAR chDash = '-';
const TCHAR chDot = '.' ;
const TCHAR chSlash = '\\' ;
CString strName( m_strNameOrIp ) ;
int cch = strName.GetLength() ;
// Does the name begin with two slashes??
if ( cch > 2
&& strName.GetAt(0) == chSlash
&& strName.GetAt(1) == chSlash )
{
enResult = COMPUTER_INFO_TYPE_NB ;
}
else
{
//
// Scan the name looking for DNS name or IP address
//
int i = 0,
cDots = 0,
cAlpha = 0,
cDash = 0;
TCHAR ch ;
BOOL bOk = TRUE ;
for ( ; i < cch ; i++ )
{
switch ( ch = strName.GetAt( i ) )
{
case chDot:
if ( ++cDots > 3 )
{
// we keep track of the number of dots,
// but we need to be able to handle fully
// qualified domain names (FQDN) so more than
// 3 dots is ok.
//bOk = FALSE ;
}
break;
default:
if ( _istalpha( ch ) )
{
cAlpha++;
}
else if ( ch == chDash )
{
cDash++;
}
else if ( !_istdigit(ch) )
{
bOk = FALSE;
}
break;
}
if ( ! bOk )
{
break ;
}
}
if ( bOk )
{
if ( cAlpha )
{
enResult = COMPUTER_INFO_TYPE_DNS ;
}
else if ( cDots == 3 )
{
enResult = COMPUTER_INFO_TYPE_IP ;
}
}
}
return enResult ;
}
// internal functions
HRESULT
CComputerInfo::InitializeData()
{
HRESULT hr = hrOK;
switch (GetInputType())
{
case COMPUTER_INFO_TYPE_NB:
case COMPUTER_INFO_TYPE_DNS:
{
DWORD dwIp;
GetHostAddress(m_strNameOrIp, &dwIp);
GetHostInfo(dwIp);
}
break;
case COMPUTER_INFO_TYPE_IP:
{
// convert the string to ansi
CHAR szString [ STRING_MAX ] = {0};
::WideCharToMultiByte(CP_ACP, 0, m_strNameOrIp, -1, szString, sizeof(szString), NULL, NULL);
// get the host info after converting the IP string to a DWORD
GetHostInfo(::ntohl( ::inet_addr( szString ) ) );
}
break;
}
return hr;
}
HRESULT
CComputerInfo::GetHostInfo
(
DWORD dhipa
)
{
CString strFQDN;
CString strHostname;
CString strTemp;
CIpInfo ipInfo;
//
// Call the Winsock API to get host name and alias information.
//
u_long ulAddrInNetOrder = ::htonl( (u_long) dhipa ) ;
HOSTENT * pHostEnt = ::gethostbyaddr( (CHAR *) & ulAddrInNetOrder,
sizeof ulAddrInNetOrder,
PF_INET ) ;
if ( pHostEnt == NULL )
{
return HRESULT_FROM_WIN32(::WSAGetLastError());
}
CHAR * * ppchAlias = pHostEnt->h_aliases ;
//
// Check and copy the host name.
//
::MultiByteToWideChar(CP_ACP,
MB_PRECOMPOSED,
pHostEnt->h_name,
lstrlenA(pHostEnt->h_name),
strTemp.GetBuffer(STRING_MAX * 2),
STRING_MAX * 2);
strTemp.ReleaseBuffer();
// remove any periods at the end
while (strTemp[strTemp.GetLength() - 1] == '.')
{
strTemp = strTemp.Left(strTemp.GetLength() - 1);
}
// gethostbyaddr is returning the hostname only in some cases.
// Make another call to get the fqdn
if (strTemp.Find('.') == -1)
{
// this is not a FQDN
GetHostAddressFQDN(strTemp, &strFQDN, &dhipa);
}
else
{
strFQDN = strTemp;
}
// copy the data into the buffer
strFQDN.MakeLower();
int nDot = strFQDN.Find('.');
m_strHostname = strFQDN.Left(nDot);
// add the primary entry to the array
ipInfo.dwIp = dhipa;
ipInfo.strFqdn = strFQDN;
m_arrayIps.Add(ipInfo);
// now loop through the h_addr_list
int iCount = 0;
while ( (LPDWORD)(pHostEnt->h_addr_list[iCount] ) )
{
if (!m_arrayIps.FIsInList(addrFromHostent(pHostEnt, iCount)))
{
ipInfo.dwIp = addrFromHostent(pHostEnt, iCount);
ipInfo.strFqdn.Empty();
m_arrayIps.Add(ipInfo);
}
iCount++;
}
m_nIndex = m_arrayIps.GetSize();
//
// Find the first acceptable NetBIOS name among the aliases;
// i.e., the first name without a period
//
/*
for ( ; *ppchAlias ; ppchAlias++ )
{
if ( validateNetbiosName( *ppchAlias ) )
{
break ;
}
}
//
// Empty the NetBIOS name in case we didn't get one.
//
pdhsrvi->_chNetbiosName[0] = 0 ;
if ( *ppchAlias )
{
//
// We found a usable name; copy it to output structure.
//
::MultiByteToWideChar(CP_ACP,
MB_PRECOMPOSED,
*ppchAlias,
lstrlenA(*ppchAlias),
pdhsrvi->_chNetbiosName,
sizeof(pdhsrvi->_chNetbiosName));
}
*/
return hrOK ;
}
HRESULT
CComputerInfo::GetHostAddressFQDN
(
LPCTSTR pszHostName,
CString * pstrFQDN,
DWORD * pdhipa
)
{
HRESULT hr = hrOK;
CHAR szString [ MAX_PATH ] = {0};
::WideCharToMultiByte(CP_ACP, 0, pszHostName, -1, szString, sizeof(szString), NULL, NULL);
HOSTENT * pHostent = ::gethostbyname( szString ) ;
if ( pHostent )
{
*pdhipa = addrFromHostent( pHostent ) ;
LPTSTR pName = pstrFQDN->GetBuffer(STRING_MAX * 2);
ZeroMemory(pName, STRING_MAX * 2);
::MultiByteToWideChar(CP_ACP,
MB_PRECOMPOSED,
pHostent->h_name,
strlen(pHostent->h_name),
pName,
STRING_MAX * 2);
pstrFQDN->ReleaseBuffer();
}
else
{
hr = HRESULT_FROM_WIN32(::WSAGetLastError());
}
return hr;
}
DWORD
CComputerInfo::addrFromHostent
(
const HOSTENT * pHostent,
INT index
)
{
return (DWORD) ::ntohl( *((u_long *) pHostent->h_addr_list[index]) );
}
HRESULT
CComputerInfo::GetHostAddress
(
LPCTSTR pszHostName,
DWORD * pdhipa
)
{
HRESULT hr = hrOK;
CHAR szString [ MAX_PATH ] = {0};
::WideCharToMultiByte(CP_ACP, 0, pszHostName, -1, szString, sizeof(szString), NULL, NULL);
HOSTENT * pHostent = ::gethostbyname( szString ) ;
if ( pHostent )
{
*pdhipa = addrFromHostent( pHostent ) ;
}
else
{
hr = HRESULT_FROM_WIN32(::WSAGetLastError());
}
return hr ;
}
HRESULT
CComputerInfo::GetLocalHostAddress
(
DWORD * pdhipa
)
{
HRESULT hr = hrOK;
CHAR chHostName [ STRING_MAX * 2 ];
if ( ::gethostname( chHostName, sizeof(chHostName) ) == 0 )
{
CString strTemp = chHostName;
hr = GetHostAddress( strTemp, pdhipa ) ;
}
else
{
hr = HRESULT_FROM_WIN32(::WSAGetLastError()) ;
}
return hr;
}
HRESULT
CComputerInfo::GetLocalHostName
(
CString * pstrName
)
{
HRESULT hr = hrOK;
CHAR chHostName [ STRING_MAX * 2 ] ;
if ( ::gethostname( chHostName, sizeof (chHostName) ) == 0 )
{
LPTSTR pName = pstrName->GetBuffer(STRING_MAX * 2);
ZeroMemory(pName, STRING_MAX * 2);
::MultiByteToWideChar(CP_ACP,
MB_PRECOMPOSED,
chHostName,
strlen(chHostName),
pName,
STRING_MAX * 2);
pstrName->ReleaseBuffer();
}
else
{
hr = HRESULT_FROM_WIN32(::WSAGetLastError()) ;
}
return hr;
}