1227 lines
30 KiB
C++
1227 lines
30 KiB
C++
/**********************************************************************/
|
|
/** Microsoft Windows NT **/
|
|
/** Copyright(c) Microsoft Corporation, 1991 - 1999 **/
|
|
/**********************************************************************/
|
|
|
|
/*
|
|
utils.cpp
|
|
Utility routines for the DHCP admin snapin
|
|
|
|
FILE HISTORY:
|
|
DavidHov 6/15/93 Created
|
|
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
//#include "svcguid.h"
|
|
|
|
#define NUM_OPTION_TYPES 3
|
|
#define NUM_OPTION_POSS NUM_OPTION_TYPES * NUM_OPTION_TYPES
|
|
|
|
int g_OptionPriorityMap[NUM_OPTION_POSS][NUM_OPTION_TYPES] =
|
|
{
|
|
{ICON_IDX_CLIENT_OPTION_LEAF, ICON_IDX_CLIENT_OPTION_LEAF, 0},
|
|
{ICON_IDX_CLIENT_OPTION_LEAF, ICON_IDX_SCOPE_OPTION_LEAF, -1},
|
|
{ICON_IDX_CLIENT_OPTION_LEAF, ICON_IDX_SERVER_OPTION_LEAF, -1},
|
|
{ICON_IDX_SCOPE_OPTION_LEAF, ICON_IDX_CLIENT_OPTION_LEAF, 1},
|
|
{ICON_IDX_SCOPE_OPTION_LEAF, ICON_IDX_SCOPE_OPTION_LEAF, 0},
|
|
{ICON_IDX_SCOPE_OPTION_LEAF, ICON_IDX_SERVER_OPTION_LEAF, -1},
|
|
{ICON_IDX_SERVER_OPTION_LEAF, ICON_IDX_CLIENT_OPTION_LEAF, 1},
|
|
{ICON_IDX_SERVER_OPTION_LEAF, ICON_IDX_SCOPE_OPTION_LEAF, 1},
|
|
{ICON_IDX_SERVER_OPTION_LEAF, ICON_IDX_SERVER_OPTION_LEAF, 0}
|
|
};
|
|
|
|
int
|
|
UtilGetOptionPriority(int nOpt1, int nOpt2)
|
|
{
|
|
int nRet = 0;
|
|
|
|
for (int i = 0; i < NUM_OPTION_POSS; i++)
|
|
{
|
|
if ( (nOpt1 == g_OptionPriorityMap[i][0]) &&
|
|
(nOpt2 == g_OptionPriorityMap[i][1]) )
|
|
{
|
|
nRet = g_OptionPriorityMap[i][2];
|
|
break;
|
|
}
|
|
}
|
|
|
|
return nRet;
|
|
}
|
|
|
|
int ServerBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
|
|
{
|
|
int i;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case BFFM_INITIALIZED:
|
|
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilGetFolderName()
|
|
Gets the folder name for backup/restore.
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
BOOL
|
|
UtilGetFolderName(CString & strInitialPath, CString& strHelpText, CString& strSelectedPath)
|
|
{
|
|
BOOL fOk = FALSE;
|
|
TCHAR szBuffer[MAX_PATH];
|
|
TCHAR szExpandedPath[MAX_PATH * 2];
|
|
HRESULT hr;
|
|
|
|
CString strStartingPath = strInitialPath;
|
|
if (strStartingPath.IsEmpty())
|
|
{
|
|
strStartingPath = _T("%SystemDrive%\\");
|
|
}
|
|
|
|
ExpandEnvironmentStrings(strStartingPath, szExpandedPath, sizeof(szExpandedPath) / sizeof(TCHAR));
|
|
|
|
LPITEMIDLIST pidlPrograms = NULL;
|
|
hr = SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidlPrograms);
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return fOk;
|
|
}
|
|
|
|
BROWSEINFO browseInfo;
|
|
browseInfo.hwndOwner = ::FindMMCMainWindow();
|
|
browseInfo.pidlRoot = pidlPrograms;
|
|
browseInfo.pszDisplayName = szBuffer;
|
|
|
|
browseInfo.lpszTitle = strHelpText;
|
|
browseInfo.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS ;
|
|
browseInfo.lpfn = ServerBrowseCallbackProc;
|
|
|
|
browseInfo.lParam = (LPARAM) szExpandedPath;
|
|
|
|
LPITEMIDLIST pidlBrowse = SHBrowseForFolder(&browseInfo);
|
|
|
|
fOk = SHGetPathFromIDList(pidlBrowse, szBuffer);
|
|
|
|
CString strPath(szBuffer);
|
|
strSelectedPath = strPath;
|
|
|
|
LPMALLOC pMalloc = NULL;
|
|
|
|
if (pidlPrograms && SUCCEEDED(SHGetMalloc(&pMalloc)))
|
|
{
|
|
if (pMalloc)
|
|
pMalloc->Free(pidlPrograms);
|
|
}
|
|
|
|
return fOk;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilConvertLeaseTime
|
|
Converts the lease time from a dword to its day, hour and minute
|
|
values
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
void
|
|
UtilConvertLeaseTime
|
|
(
|
|
DWORD dwLeaseTime,
|
|
int * pnDays,
|
|
int * pnHours,
|
|
int * pnMinutes
|
|
)
|
|
{
|
|
*pnDays = dwLeaseTime / (60 * 60 * 24);
|
|
dwLeaseTime = (dwLeaseTime % (60 * 60 * 24));
|
|
|
|
*pnHours = dwLeaseTime / (60 * 60);
|
|
dwLeaseTime = (dwLeaseTime % (60 * 60));
|
|
|
|
*pnMinutes = dwLeaseTime / 60;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilConvertLeaseTime
|
|
Converts the lease time from its day, hour and minute values to
|
|
a dword
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
DWORD
|
|
UtilConvertLeaseTime
|
|
(
|
|
int nDays,
|
|
int nHours,
|
|
int nMinutes
|
|
)
|
|
{
|
|
return (DWORD) (nDays * 60 * 60 * 24) +
|
|
(nHours * 60 * 60) +
|
|
(nMinutes * 60);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilCvtStringToIpAddr
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
ENUM_HOST_NAME_TYPE
|
|
UtilCategorizeName
|
|
(
|
|
LPCTSTR pszName
|
|
)
|
|
{
|
|
// assume a NetBios name
|
|
ENUM_HOST_NAME_TYPE enResult = HNM_TYPE_NB ;
|
|
const TCHAR chDash = '-';
|
|
const TCHAR chDot = '.' ;
|
|
const TCHAR chSlash = '\\' ;
|
|
CString strName( pszName ) ;
|
|
|
|
int cch = strName.GetLength() ;
|
|
|
|
// Does the name begin with two slashes??
|
|
|
|
if ( cch > 2
|
|
&& strName.GetAt(0) == chSlash
|
|
&& strName.GetAt(1) == chSlash )
|
|
{
|
|
enResult = HNM_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 = HNM_TYPE_DNS ;
|
|
}
|
|
else if ( cDots == 3 )
|
|
{
|
|
enResult = HNM_TYPE_IP ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return enResult ;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilCvtStringToIpAddr
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
DHCP_IP_ADDRESS
|
|
UtilCvtStringToIpAddr
|
|
(
|
|
const CHAR * pszString
|
|
)
|
|
{
|
|
//
|
|
// Convert the string to network byte order, then to host byte order.
|
|
//
|
|
return (DHCP_IP_ADDRESS) ::ntohl( ::inet_addr( pszString ) ) ;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilCvtWstrToIpAddr
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
DHCP_IP_ADDRESS
|
|
UtilCvtWstrToIpAddr
|
|
(
|
|
const LPCWSTR pcwString
|
|
)
|
|
{
|
|
CHAR szString [ MAX_PATH ] = {0};
|
|
|
|
::WideCharToMultiByte(CP_OEMCP, 0, pcwString, -1, szString, sizeof(szString), NULL, NULL);
|
|
|
|
//
|
|
// Convert the string to network byte order, then to host byte order.
|
|
//
|
|
return (DHCP_IP_ADDRESS) ::ntohl( ::inet_addr( szString ) );
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilCvtIpAddrToString
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
void
|
|
UtilCvtIpAddrToString
|
|
(
|
|
DHCP_IP_ADDRESS dhipa,
|
|
CHAR * pszString,
|
|
UINT cBuffSize
|
|
)
|
|
{
|
|
struct in_addr ipaddr ;
|
|
|
|
//
|
|
// Convert the unsigned long to network byte order
|
|
//
|
|
ipaddr.s_addr = ::htonl( (u_long) dhipa ) ;
|
|
|
|
//
|
|
// Convert the IP address value to a string
|
|
//
|
|
CHAR * pszAddr = inet_ntoa( ipaddr ) ;
|
|
|
|
// Copy the string to the caller's buffer.
|
|
ASSERT(cBuffSize > ::strlen(pszAddr));
|
|
ASSERT(pszString);
|
|
if (pszAddr)
|
|
{
|
|
::strcpy( pszString, pszAddr ) ;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilCvtIpAddrToWstr
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
BOOL
|
|
UtilCvtIpAddrToWstr
|
|
(
|
|
DHCP_IP_ADDRESS dhipa,
|
|
CString * pstrIpAddress
|
|
)
|
|
{
|
|
CHAR szString [ MAX_PATH ] ;
|
|
LPCTSTR pbuf;
|
|
|
|
::UtilCvtIpAddrToString( dhipa, szString, MAX_PATH );
|
|
INT cch = ::strlen( szString ) ;
|
|
|
|
LPTSTR pBuf = pstrIpAddress->GetBuffer(IP_ADDDRESS_LENGTH_MAX);
|
|
ZeroMemory(pBuf, IP_ADDDRESS_LENGTH_MAX);
|
|
|
|
::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, szString, -1, pBuf, IP_ADDDRESS_LENGTH_MAX);
|
|
|
|
pstrIpAddress->ReleaseBuffer();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilCvtIpAddrToWstr
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
BOOL
|
|
UtilCvtIpAddrToWstr
|
|
(
|
|
DHCP_IP_ADDRESS dhipa,
|
|
WCHAR * pwcszString,
|
|
INT cBuffCount
|
|
)
|
|
{
|
|
CHAR szString [ MAX_PATH ] ;
|
|
|
|
if ( cBuffCount > sizeof szString - 1 )
|
|
{
|
|
cBuffCount = sizeof szString - 1 ;
|
|
}
|
|
|
|
::UtilCvtIpAddrToString( dhipa, szString, cBuffCount );
|
|
#ifdef FE_SB
|
|
INT cch;
|
|
|
|
cch = ::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, szString, -1, pwcszString, cBuffCount);
|
|
pwcszString[cch] = L'\0';
|
|
#else
|
|
INT cch = ::strlen( szString ) ;
|
|
|
|
//::mbstowcs( pwcszString, szString, cch ) ;
|
|
::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, szString, cch, pwcszString, cBuffCount);
|
|
pwcszString[cch] = 0 ;
|
|
#endif
|
|
return TRUE ;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilDupIpAddrToWstr
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
WCHAR *
|
|
UtilDupIpAddrToWstr
|
|
(
|
|
DHCP_IP_ADDRESS dhipa
|
|
)
|
|
{
|
|
WCHAR wcszString [ MAX_PATH ] ;
|
|
|
|
if ( ! ::UtilCvtIpAddrToWstr( dhipa, wcszString, ( sizeof ( wcszString ) / sizeof( WCHAR ) ) ) )
|
|
{
|
|
return NULL ;
|
|
}
|
|
|
|
return ::UtilWcstrDup( wcszString ) ;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
validateNetbiosName
|
|
Simplistic routine to check to see if the given name is viable
|
|
as a NetBIOS name.
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
static BOOL
|
|
validateNetbiosName
|
|
(
|
|
const CHAR * pchName
|
|
)
|
|
{
|
|
INT nChars = ::strlen( pchName ) ;
|
|
if ( nChars > MAX_COMPUTERNAME_LENGTH || nChars == 0 )
|
|
{
|
|
return FALSE ;
|
|
}
|
|
|
|
for ( ; *pchName ; pchName++ )
|
|
{
|
|
if ( *pchName == '.' )
|
|
{
|
|
break ;
|
|
}
|
|
}
|
|
|
|
return *pchName == 0 ;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilGetHostInfo
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
DWORD
|
|
UtilGetHostInfo
|
|
(
|
|
DHCP_IP_ADDRESS dhipa,
|
|
DHC_HOST_INFO_STRUCT * pdhsrvi
|
|
)
|
|
{
|
|
ZeroMemory(pdhsrvi, sizeof(DHC_HOST_INFO_STRUCT));
|
|
|
|
pdhsrvi->_dhipa = dhipa ;
|
|
|
|
//
|
|
// Call the Winsock API to get host name and alias information.
|
|
//
|
|
u_long ulAddrInNetOrder = ::htonl( (u_long) dhipa ) ;
|
|
|
|
HOSTENT * pHostInfo = ::gethostbyaddr( (CHAR *) & ulAddrInNetOrder,
|
|
sizeof ulAddrInNetOrder,
|
|
PF_INET ) ;
|
|
if ( pHostInfo == NULL )
|
|
{
|
|
return ::WSAGetLastError();
|
|
}
|
|
|
|
CHAR * * ppchAlias = pHostInfo->h_aliases ;
|
|
|
|
//
|
|
// Check and copy the host name.
|
|
//
|
|
if ( sizeof (pdhsrvi->_chNetbiosName) <= ::strlen( pHostInfo->h_name ) )
|
|
{
|
|
return ERROR_INVALID_NAME ;
|
|
}
|
|
|
|
ZeroMemory(pdhsrvi->_chNetbiosName, sizeof(pdhsrvi->_chNetbiosName));
|
|
|
|
::MultiByteToWideChar(CP_ACP,
|
|
MB_PRECOMPOSED,
|
|
pHostInfo->h_name,
|
|
lstrlenA(pHostInfo->h_name),
|
|
pdhsrvi->_chNetbiosName,
|
|
sizeof(pdhsrvi->_chNetbiosName) / sizeof( pdhsrvi->_chNetbiosName[ 0 ]));
|
|
|
|
// remove any periods at the end
|
|
while (pdhsrvi->_chHostName[lstrlen(pdhsrvi->_chNetbiosName) - 1] == '.')
|
|
{
|
|
pdhsrvi->_chHostName[lstrlen(pdhsrvi->_chNetbiosName) - 1] = 0;
|
|
}
|
|
|
|
// gethostbyaddr is returning the hostname only in some cases.
|
|
// Make another call to get the fqdn
|
|
CString strTemp = pdhsrvi->_chNetbiosName;
|
|
if (strTemp.Find('.') == -1)
|
|
{
|
|
// this is not a FQDN
|
|
strTemp.Empty();
|
|
UtilGetHostAddressFQDN(pdhsrvi->_chNetbiosName, &strTemp, &dhipa);
|
|
}
|
|
|
|
// copy the data into the buffer
|
|
strTemp.MakeLower();
|
|
memset(pdhsrvi->_chHostName, 0, sizeof(pdhsrvi->_chHostName));
|
|
lstrcpy(pdhsrvi->_chHostName, strTemp);
|
|
|
|
//
|
|
// 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 NOERROR ;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
addrFromHostent
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
static DHCP_IP_ADDRESS
|
|
addrFromHostent
|
|
(
|
|
const HOSTENT * pHostent,
|
|
INT index = 0
|
|
)
|
|
{
|
|
return (DHCP_IP_ADDRESS) ::ntohl( *((u_long *) pHostent->h_addr_list[index]) ) ;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilGetHostAddress
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT
|
|
UtilGetHostAddressFQDN
|
|
(
|
|
LPCTSTR pszHostName,
|
|
CString * pstrFQDN,
|
|
DHCP_IP_ADDRESS * pdhipa
|
|
)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
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(DHCPSNAP_STRING_MAX * sizeof( WCHAR ));
|
|
ZeroMemory(pName, DHCPSNAP_STRING_MAX * sizeof( WCHAR ));
|
|
|
|
::MultiByteToWideChar(CP_ACP,
|
|
MB_PRECOMPOSED,
|
|
pHostent->h_name,
|
|
strlen(pHostent->h_name),
|
|
pName,
|
|
DHCPSNAP_STRING_MAX );
|
|
|
|
pstrFQDN->ReleaseBuffer();
|
|
|
|
}
|
|
else
|
|
{
|
|
hr = ::WSAGetLastError() ;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilGetHostAddress
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT
|
|
UtilGetHostAddress
|
|
(
|
|
LPCTSTR pszHostName,
|
|
DHCP_IP_ADDRESS * pdhipa
|
|
)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
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 = ::WSAGetLastError() ;
|
|
}
|
|
|
|
return hr ;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilGetLocalHostAddress
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT
|
|
UtilGetLocalHostAddress
|
|
(
|
|
DHCP_IP_ADDRESS * pdhipa
|
|
)
|
|
{
|
|
CHAR chHostName [ DHCPSNAP_STRING_MAX ] ;
|
|
HRESULT hr = NOERROR;
|
|
|
|
if ( ::gethostname( chHostName, sizeof chHostName ) == 0 )
|
|
{
|
|
CString strTemp = chHostName;
|
|
hr = ::UtilGetHostAddress( strTemp, pdhipa ) ;
|
|
}
|
|
else
|
|
{
|
|
//err = ::WSAGetLastError() ;
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilGetLocalHostName
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT
|
|
UtilGetLocalHostName
|
|
(
|
|
CString * pstrName
|
|
)
|
|
{
|
|
CHAR chHostName [ DHCPSNAP_STRING_MAX * 2 ] ;
|
|
HRESULT hr = NOERROR;
|
|
|
|
if ( ::gethostname( chHostName, sizeof (chHostName) ) == 0 )
|
|
{
|
|
LPTSTR pName = pstrName->GetBuffer(DHCPSNAP_STRING_MAX * sizeof( WCHAR ));
|
|
ZeroMemory(pName, DHCPSNAP_STRING_MAX * sizeof( WCHAR ));
|
|
|
|
::MultiByteToWideChar(CP_ACP,
|
|
MB_PRECOMPOSED,
|
|
chHostName,
|
|
strlen(chHostName),
|
|
pName,
|
|
DHCPSNAP_STRING_MAX );
|
|
|
|
pstrName->ReleaseBuffer();
|
|
}
|
|
else
|
|
{
|
|
//err = ::WSAGetLastError() ;
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilGetNetbiosAddress
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
HRESULT
|
|
UtilGetNetbiosAddress
|
|
(
|
|
LPCTSTR pszNetbiosName,
|
|
DHCP_IP_ADDRESS * pdhipa
|
|
)
|
|
{
|
|
//
|
|
// This code presupposes that the "hosts" file maps NetBIOS names
|
|
// and DNS names identically. THIS IS NOT A VALID SUPPOSITION, but is
|
|
// expedient for the on-campus work.
|
|
//
|
|
return UtilGetHostAddress( pszNetbiosName, pdhipa ) ;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilWcstrDup
|
|
"strdup" a WC string
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
WCHAR *
|
|
UtilWcstrDup
|
|
(
|
|
const WCHAR * pwcsz,
|
|
INT * pccwLength
|
|
)
|
|
{
|
|
WCHAR szwchEmpty [2] = { 0 } ;
|
|
|
|
if ( pwcsz == NULL )
|
|
{
|
|
pwcsz = szwchEmpty ;
|
|
}
|
|
|
|
INT ccw = ::wcslen( pwcsz );
|
|
|
|
WCHAR * pwcszNew = new WCHAR [ ccw + 1 ] ;
|
|
if ( pwcszNew == NULL )
|
|
{
|
|
return NULL ;
|
|
}
|
|
::wcscpy( pwcszNew, pwcsz ) ;
|
|
|
|
if ( pccwLength )
|
|
{
|
|
*pccwLength = ccw ;
|
|
}
|
|
|
|
return pwcszNew ;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilWcstrDup
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
WCHAR *
|
|
UtilWcstrDup
|
|
(
|
|
const CHAR * psz,
|
|
INT * pccwLength
|
|
)
|
|
{
|
|
INT ccw = ::strlen( psz ) ;
|
|
|
|
WCHAR * pwcszNew = new WCHAR [ ccw + 1 ] ;
|
|
|
|
if ( pwcszNew == NULL )
|
|
{
|
|
return NULL ;
|
|
}
|
|
|
|
//::mbstowcs( pwcszNew, psz, ccw ) ;
|
|
#ifdef FE_SB
|
|
ccw = ::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, psz, -1, pwcszNew, ccw+1);
|
|
if ( pccwLength )
|
|
{
|
|
*pccwLength = ccw ;
|
|
}
|
|
pwcszNew[ccw] = L'\0';
|
|
#else
|
|
::MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, psz, ccw, pwcszNew, ccw+1);
|
|
if ( pccwLength )
|
|
{
|
|
*pccwLength = ccw ;
|
|
}
|
|
pwcszNew[ccw] = 0 ;
|
|
#endif
|
|
|
|
return pwcszNew ;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilCstrDup
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
CHAR *
|
|
UtilCstrDup
|
|
(
|
|
const WCHAR * pwcsz
|
|
)
|
|
{
|
|
INT ccw = ::wcslen( pwcsz ),
|
|
cch = (ccw + 1) * 2 ;
|
|
CHAR * psz = new CHAR [ cch ] ;
|
|
if ( psz == NULL )
|
|
{
|
|
return NULL ;
|
|
}
|
|
|
|
//::wcstombs( psz, pwcsz, cch ) ;
|
|
::WideCharToMultiByte( CP_OEMCP, WC_COMPOSITECHECK, pwcsz, -1, psz, cch, NULL, NULL ) ;
|
|
|
|
return psz ;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilCstrDup
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
CHAR *
|
|
UtilCstrDup
|
|
(
|
|
const CHAR * psz
|
|
)
|
|
{
|
|
CHAR * pszNew = new CHAR [ ::strlen( psz ) + 1 ] ;
|
|
if ( pszNew == NULL )
|
|
{
|
|
return NULL ;
|
|
}
|
|
::strcpy( pszNew, psz ) ;
|
|
|
|
return pszNew ;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
cvtWcStrToStr
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
static HRESULT
|
|
cvtWcStrToStr
|
|
(
|
|
char * psz,
|
|
size_t cch,
|
|
const WCHAR * pwcsz,
|
|
size_t cwch
|
|
)
|
|
{
|
|
|
|
#ifdef FE_SB
|
|
int cchResult = ::WideCharToMultiByte( CP_ACP, 0,
|
|
pwcsz, -1,
|
|
psz, cch,
|
|
NULL, NULL ) ;
|
|
#else
|
|
int cchResult = ::WideCharToMultiByte( CP_ACP, 0,
|
|
pwcsz, cwch,
|
|
psz, cwch,
|
|
NULL, NULL ) ;
|
|
#endif
|
|
|
|
psz[ cchResult ] = 0 ;
|
|
|
|
//return cchResult ? 0 : ::GetLastError();
|
|
return cchResult ? NOERROR : E_FAIL;
|
|
}
|
|
|
|
|
|
wchar_t rgchHex[] = L"00112233445566778899aAbBcCdDeEfF";
|
|
/*---------------------------------------------------------------------------
|
|
UtilCvtHexString
|
|
Convert a string of hex digits to a byte array
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
BOOL
|
|
UtilCvtHexString
|
|
(
|
|
LPCTSTR pszNum,
|
|
CByteArray & cByte
|
|
)
|
|
{
|
|
int i = 0,
|
|
iDig,
|
|
iByte,
|
|
cDig ;
|
|
int iBase = 16 ;
|
|
BOOL bByteBoundary ;
|
|
|
|
//
|
|
// Skip leading blanks
|
|
//
|
|
for ( ; *pszNum == L' ' ; pszNum++ ) ;
|
|
|
|
//
|
|
// Skip a leading zero
|
|
//
|
|
if ( *pszNum == L'0' )
|
|
{
|
|
pszNum++ ;
|
|
}
|
|
|
|
//
|
|
// Look for hexadecimal marker
|
|
//
|
|
if ( *pszNum == L'x' || *pszNum == L'X' )
|
|
{
|
|
pszNum++ ;
|
|
}
|
|
|
|
bByteBoundary = ::wcslen( pszNum ) % 2 ;
|
|
|
|
for ( iByte = cDig = 0 ; *pszNum ; )
|
|
{
|
|
wchar_t * pszDig = ::wcschr( rgchHex, *pszNum++ ) ;
|
|
if ( pszDig == NULL )
|
|
{
|
|
break;
|
|
// return FALSE;
|
|
}
|
|
|
|
iDig = ((int) (pszDig - rgchHex)) / 2 ;
|
|
if ( iDig >= iBase )
|
|
{
|
|
break ;
|
|
// return FALSE;
|
|
}
|
|
|
|
iByte = (iByte * 16) + iDig ;
|
|
|
|
if ( bByteBoundary )
|
|
{
|
|
cByte.SetAtGrow( cDig++, (UCHAR) iByte ) ;
|
|
iByte = 0 ;
|
|
}
|
|
bByteBoundary = ! bByteBoundary ;
|
|
}
|
|
|
|
cByte.SetSize( cDig ) ;
|
|
|
|
//
|
|
// Return TRUE if we reached the end of the string.
|
|
//
|
|
return *pszNum == 0 ;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
UtilCvtByteArrayToString
|
|
Description
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
BOOL
|
|
UtilCvtByteArrayToString
|
|
(
|
|
const CByteArray & abAddr,
|
|
CString & str
|
|
)
|
|
{
|
|
int i ;
|
|
DWORD err = 0 ;
|
|
|
|
// TRY
|
|
{
|
|
str.Empty() ;
|
|
|
|
//
|
|
// The hex conversion string has two characters per nibble,
|
|
// to allow for upper case.
|
|
//
|
|
for ( i = 0 ; i < abAddr.GetSize() ; i++ )
|
|
{
|
|
int i1 = ((abAddr.GetAt(i) & 0xF0) >> 4) * 2 ,
|
|
i2 = (abAddr.GetAt(i) & 0x0F) * 2 ;
|
|
str += rgchHex[ i1 ] ;
|
|
str += rgchHex[ i2 ] ;
|
|
}
|
|
}
|
|
|
|
// CATCH(CMemoryException, pMemException)
|
|
|
|
// if ( pMemException )
|
|
// {
|
|
// str.Empty() ;
|
|
// err = 1;
|
|
// }
|
|
|
|
return err == 0 ;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
PchParseUnicodeString
|
|
Parse a unicode string by copying its content
|
|
into a CString object.
|
|
The parsing ends when the null-terminator ('\0')is
|
|
reached or the comma (',') is reached.
|
|
|
|
Return pointer to the character where parsing
|
|
ended('\0') or (',')
|
|
|
|
Author: EricDav
|
|
---------------------------------------------------------------------------*/
|
|
WCHAR *
|
|
PchParseUnicodeString
|
|
(
|
|
CONST WCHAR * szwString, // IN: String to parse
|
|
DWORD dwLength,
|
|
CString& rString // OUT: Content of the substring
|
|
)
|
|
{
|
|
ASSERT(szwString != NULL);
|
|
ASSERT(BOOT_FILE_STRING_DELIMITER_W == L','); // Just in case
|
|
|
|
WCHAR szwBufferT[1024]; // Temporary buffer
|
|
WCHAR * pchwDst = szwBufferT;
|
|
|
|
while (*szwString != L'\0')
|
|
{
|
|
if (*szwString == BOOT_FILE_STRING_DELIMITER_W)
|
|
break;
|
|
*pchwDst++ = *szwString++;
|
|
if ((DWORD) (pchwDst - szwBufferT) > dwLength)
|
|
{
|
|
// we've gone past the end of our buffer!! ouch
|
|
Panic0("PchParseUnicodeString: Gone past end of buffer");
|
|
break;
|
|
}
|
|
|
|
ASSERT((pchwDst - szwBufferT < sizeof(szwBufferT)) && "Buffer overflow");
|
|
} // while
|
|
|
|
*pchwDst = L'\0';
|
|
rString = szwBufferT; // Copy the string into the CString object
|
|
|
|
return const_cast<WCHAR *>(szwString);
|
|
} // PchParseUnicodeString()
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// FGetCtrlDWordValue()
|
|
//
|
|
// Return a 32-bit unsigned integer from an edit control
|
|
//
|
|
// This function is like GetDlgItemInt() except it accepts hexadecimal values,
|
|
// has range checking and/or overflow checking.
|
|
// If value is out of range, function will display a friendly message and will
|
|
// set the focus to control.
|
|
// Range: dwMin to dwMax inclusive
|
|
// - If both dwMin and dwMax are zero, no range checking is performed
|
|
// - Return TRUE if successful, otherwise FALSE
|
|
// - On error, pdwValue remains unchanged.
|
|
//
|
|
BOOL FGetCtrlDWordValue(HWND hwndEdit, DWORD * pdwValue, DWORD dwMin, DWORD dwMax)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
TCHAR szT[256];
|
|
|
|
DWORD Len, dwResult;
|
|
BOOL Success;
|
|
|
|
ASSERT(IsWindow(hwndEdit));
|
|
ASSERT(pdwValue);
|
|
ASSERT(dwMin <= dwMax);
|
|
|
|
::GetWindowText(hwndEdit, szT, (sizeof(szT)-1)/sizeof(TCHAR));
|
|
szT[ 255 ] = _T('\0');
|
|
Success = FCvtAsciiToInteger( szT, OUT &dwResult );
|
|
*pdwValue = dwResult;
|
|
if (( !Success ) || (dwResult < dwMin) || (dwResult > dwMax)) {
|
|
CString strBuffer;
|
|
|
|
strBuffer.LoadString( IDS_ERR_INVALID_INTEGER );
|
|
::wsprintf( szT, strBuffer, dwMin, dwMax, dwMin, dwMax );
|
|
|
|
ASSERT( wcslen( szT ) < sizeof( szT ));
|
|
::SetFocus( hwndEdit );
|
|
::AfxMessageBox( szT );
|
|
::SetFocus( hwndEdit );
|
|
return FALSE;
|
|
} // if
|
|
|
|
return TRUE;
|
|
} // FGetCtrlDWordValue
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Convert a string to a binary integer
|
|
// - String is allowed to be decimal or hexadecimal
|
|
// - Minus sign is not allowed
|
|
// If successful, set *pdwValue to the integer and return TRUE.
|
|
// If not successful (overflow or illegal integer) return FALSE.
|
|
//
|
|
BOOL
|
|
FCvtAsciiToInteger(
|
|
IN const TCHAR * pszNum,
|
|
OUT DWORD * pdwValue
|
|
)
|
|
{
|
|
DWORD dwResult = 0;
|
|
DWORD Res = 0;
|
|
BOOL IsHex = FALSE;
|
|
LPWSTR Format;
|
|
const TCHAR *pBuf;
|
|
|
|
ASSERT(pszNum != NULL);
|
|
ASSERT(pdwValue != NULL);
|
|
|
|
pBuf = pszNum;
|
|
|
|
// Skip leading blanks and/or zeroes
|
|
while (( *pszNum == _T(' ')) ||
|
|
( *pszNum == _T('\t')) ||
|
|
( *pszNum == _T('0'))) {
|
|
pszNum++;
|
|
}
|
|
|
|
// If there is just '0' in the buffer, make sure we don't ignore it
|
|
|
|
// Check if we are using hexadecimal base
|
|
if (( *pszNum == _T('x')) || ( *pszNum == _T('X'))) {
|
|
IsHex = TRUE;
|
|
pszNum++;
|
|
}
|
|
else if (( pszNum != pBuf ) &&
|
|
( *(pszNum - 1) == _T('0'))) {
|
|
// back track the 0 we skipped
|
|
pszNum--;
|
|
}
|
|
|
|
// -ve numbers are not valid
|
|
if ( *pszNum == L'-' ) {
|
|
*pdwValue = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
// if we are the end of the string, then return success
|
|
if ( *pszNum == L'\0' ) {
|
|
*pdwValue = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
Format = ( IsHex ) ? L"%lx" : L"%lu";
|
|
|
|
Res = swscanf( pszNum, Format, &dwResult );
|
|
if ( Res == 0 ) {
|
|
*pdwValue = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
ASSERT( Res == 1 );
|
|
|
|
*pdwValue = dwResult;
|
|
return TRUE;
|
|
} // FCvtAsciiToInteger
|
|
|
|
|
|
void UtilConvertStringToDwordDword(LPCTSTR pszString, DWORD_DWORD * pdwdw)
|
|
{
|
|
ULARGE_INTEGER value;
|
|
BOOL hex = FALSE;
|
|
|
|
value.QuadPart = 0;
|
|
|
|
// skip white spaces
|
|
while (( *pszString == L' ' ) ||
|
|
( *pszString == L'\t' )) {
|
|
pszString++;
|
|
}
|
|
|
|
hex = (( pszString[ 0 ] == L'0' ) &&
|
|
( pszString[ 1 ] == L'x' ))
|
|
? TRUE : FALSE;
|
|
if ( hex ) {
|
|
if ( 1 != _stscanf( pszString + 2, _T( "%I64x" ), &value.QuadPart )) {
|
|
value.QuadPart = 0;
|
|
}
|
|
}
|
|
else { // decimal
|
|
if ( 1 != _stscanf( pszString, _T( "%I64u" ), &value.QuadPart )) {
|
|
value.QuadPart = 0;
|
|
}
|
|
}
|
|
|
|
// Use 0 for all -ve numbers
|
|
|
|
if ( *pszString == L'-' ) {
|
|
value.QuadPart = 0;
|
|
}
|
|
|
|
pdwdw->DWord1 = value.HighPart;
|
|
pdwdw->DWord2 = value.LowPart;
|
|
} // UtilConvertStringToDwordDword()
|
|
|
|
void UtilConvertDwordDwordToString(DWORD_DWORD * pdwdw, CString * pstrString, BOOL bDecimal)
|
|
{
|
|
TCHAR szNum [ STRING_LENGTH_MAX ] ;
|
|
ULARGE_INTEGER Temp;
|
|
|
|
Temp.HighPart = pdwdw->DWord1;
|
|
Temp.LowPart = pdwdw->DWord2;
|
|
|
|
if (bDecimal)
|
|
{
|
|
::wsprintf( szNum, L"%I64u", Temp.QuadPart );
|
|
}
|
|
else
|
|
{
|
|
::wsprintf( szNum, L"0x%I64x", Temp.QuadPart );
|
|
}
|
|
|
|
*pstrString = szNum ;
|
|
}
|
|
|
|
// End of DHCPUTIL.CPP
|