1247 lines
29 KiB
C++
1247 lines
29 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));
|
||
|
|
||
|
// 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 * 2);
|
||
|
ZeroMemory(pName, DHCPSNAP_STRING_MAX * 2);
|
||
|
|
||
|
::MultiByteToWideChar(CP_ACP,
|
||
|
MB_PRECOMPOSED,
|
||
|
pHostent->h_name,
|
||
|
strlen(pHostent->h_name),
|
||
|
pName,
|
||
|
DHCPSNAP_STRING_MAX * 2);
|
||
|
|
||
|
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 * 2);
|
||
|
ZeroMemory(pName, DHCPSNAP_STRING_MAX * 2);
|
||
|
|
||
|
::MultiByteToWideChar(CP_ACP,
|
||
|
MB_PRECOMPOSED,
|
||
|
chHostName,
|
||
|
strlen(chHostName),
|
||
|
pName,
|
||
|
DHCPSNAP_STRING_MAX * 2);
|
||
|
|
||
|
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 dwResult;
|
||
|
|
||
|
ASSERT(IsWindow(hwndEdit));
|
||
|
ASSERT(pdwValue);
|
||
|
ASSERT(dwMin <= dwMax);
|
||
|
|
||
|
::GetWindowText(hwndEdit, szT, (sizeof(szT)-1)/sizeof(TCHAR));
|
||
|
if (!FCvtAsciiToInteger(szT, OUT &dwResult))
|
||
|
{
|
||
|
// Syntax Error and/or integer overflow
|
||
|
goto Error;
|
||
|
}
|
||
|
|
||
|
if ((dwMin == 0) && (dwMax == 0))
|
||
|
goto Success;
|
||
|
|
||
|
if ((dwResult < dwMin) || (dwResult > dwMax))
|
||
|
Error:
|
||
|
{
|
||
|
CString strBuffer;
|
||
|
|
||
|
strBuffer.LoadString(IDS_ERR_INVALID_INTEGER);
|
||
|
//::LoadString(theApp.m_hInstance, IDS_ERR_INVALID_INTEGER, szBuffer, sizeof(szBuffer)-1);
|
||
|
::wsprintf (szT, strBuffer, (int)dwMin, (int)dwMax);
|
||
|
ASSERT(wcslen(szT)<sizeof(szT));
|
||
|
::SetFocus(hwndEdit);
|
||
|
::AfxMessageBox(szT);
|
||
|
::SetFocus(hwndEdit);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
Success:
|
||
|
*pdwValue = dwResult;
|
||
|
|
||
|
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 dwResultPrev = 0;
|
||
|
int iBase = 10; // Assume a decimal base
|
||
|
|
||
|
ASSERT(pszNum != NULL);
|
||
|
ASSERT(pdwValue != NULL);
|
||
|
|
||
|
while (*pszNum == ' ' || *pszNum == '0') // Skip leading blanks and/or zeroes
|
||
|
pszNum++;
|
||
|
|
||
|
if (*pszNum == 'x' || *pszNum == 'X') // Check if we are using hexadecimal base
|
||
|
{
|
||
|
iBase = 16;
|
||
|
pszNum++;
|
||
|
}
|
||
|
|
||
|
while (*pszNum)
|
||
|
{
|
||
|
int iDigit;
|
||
|
// Search the character in the hexadecimal string
|
||
|
TCHAR const * const pchDigit = wcschr(rgchHex, *pszNum);
|
||
|
|
||
|
if (!pchDigit)
|
||
|
{
|
||
|
// Character is not found
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
iDigit = ((int) (pchDigit - rgchHex)) >> 1;
|
||
|
if (iDigit >= iBase)
|
||
|
{
|
||
|
// Hexadecimal character in a decimal integer
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
dwResultPrev = dwResult;
|
||
|
dwResult *= iBase;
|
||
|
dwResult += iDigit;
|
||
|
if (dwResult < dwResultPrev)
|
||
|
{
|
||
|
// Integer Overflow
|
||
|
return(FALSE);
|
||
|
}
|
||
|
pszNum++; // Parse the next character
|
||
|
|
||
|
} // while
|
||
|
|
||
|
// Convertion has been successful
|
||
|
*pdwValue = dwResult;
|
||
|
return(TRUE);
|
||
|
} // FCvtAsciiToInteger
|
||
|
|
||
|
|
||
|
void UtilConvertStringToDwordDword(LPCTSTR pszString, DWORD_DWORD * pdwdw)
|
||
|
{
|
||
|
BOOL bHex = FALSE;
|
||
|
|
||
|
while (*pszString == ' ' || *pszString == '0') // Skip leading blanks and/or zeroes
|
||
|
pszString++;
|
||
|
|
||
|
if (*pszString == 'x' || *pszString == 'X') // Check if we are using hexadecimal base
|
||
|
{
|
||
|
bHex = TRUE;
|
||
|
pszString++;
|
||
|
}
|
||
|
|
||
|
CString str = pszString;
|
||
|
int j = str.GetLength();
|
||
|
|
||
|
if (bHex)
|
||
|
{
|
||
|
TCHAR sz[] = _T("0000000000000000");
|
||
|
TCHAR *pch;
|
||
|
|
||
|
::_tcscpy(sz + 16 - j, (LPCTSTR)str);
|
||
|
pch = sz + 8;
|
||
|
::_stscanf(pch, _T("%08lX"), &pdwdw->DWord2);
|
||
|
*pch = '\0';
|
||
|
::_stscanf(sz, _T("%08lX"), &pdwdw->DWord1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
::_stscanf(pszString, _T("%I64u"), pdwdw);
|
||
|
|
||
|
// is this true on alpha as well? Processor dependant?
|
||
|
// an __int64 is dword swapped, so to get the correct value we want,
|
||
|
// swap the dwords in our struct
|
||
|
DWORD dwTemp = pdwdw->DWord2;
|
||
|
pdwdw->DWord2 = pdwdw->DWord1;
|
||
|
pdwdw->DWord1 = dwTemp;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void UtilConvertDwordDwordToString(DWORD_DWORD * pdwdw, CString * pstrString, BOOL bDecimal)
|
||
|
{
|
||
|
const TCHAR * pszDwordDwordMask = _T("0x%08lX%08lX");
|
||
|
TCHAR szNum [ STRING_LENGTH_MAX ] ;
|
||
|
|
||
|
if (bDecimal)
|
||
|
{
|
||
|
unsigned __int64 ui64;
|
||
|
|
||
|
// is this true on alpha as well? Processor dependant?
|
||
|
// an __int64 is dword swapped, so to get the correct value we want,
|
||
|
// swap the dwords in our struct
|
||
|
DWORD dwTemp = pdwdw->DWord2;
|
||
|
pdwdw->DWord2 = pdwdw->DWord1;
|
||
|
pdwdw->DWord1 = dwTemp;
|
||
|
|
||
|
memcpy (&ui64, pdwdw, sizeof(DWORD_DWORD));
|
||
|
_ui64tot(ui64, szNum, 10);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
::wsprintf( szNum, pszDwordDwordMask, pdwdw->DWord1, pdwdw->DWord2 ) ;
|
||
|
}
|
||
|
|
||
|
*pstrString = szNum ;
|
||
|
}
|
||
|
|
||
|
// End of DHCPUTIL.CPP
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|