windows-nt/Source/XPSP1/NT/inetsrv/iis/svcs/loadbal/cnfg/lbcnfg.cxx
2020-09-26 16:20:57 +08:00

1510 lines
25 KiB
C++

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
lbcnfg.cxx
Abstract:
Classes to handle IIS load balancing configuration
Author:
Philippe Choquier (phillich)
--*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <mbstring.h>
#include <winsock2.h>
#include "lbxbf.hxx"
#include "lbcnfg.hxx"
#if defined(_NOISY_DEBUG)
#define DEBUG_BUFFER char achE[128]
#define DBG_PRINTF(a) wsprintf a; OutputDebugString( achE )
#define DBG_PUTS(a) OutputDebugString(a)
#else
#define DEBUG_BUFFER
#define DBG_PRINTF(a)
#define DBG_PUTS(a)
#endif
CIPMap::CIPMap(
)
/*++
Routine Description:
CIPMap constructor
Arguments:
none
Return Value:
nothing
--*/
{
}
CIPMap::~CIPMap(
)
/*++
Routine Description:
CIPMap destructor
Arguments:
none
Return Value:
nothing
--*/
{
Reset();
}
VOID
CIPMap::Reset(
)
/*++
Routine Description:
Reset a CIPMap to empty content
Arguments:
none
Return Value:
nothing
--*/
{
UINT iComp;
for ( iComp = 0 ;
iComp < m_Servers.GetNbPtr() ;
++iComp )
{
delete (CComputerBalanceCnfg*)m_Servers.GetPtr( iComp );
}
m_Servers.Reset();
m_IpPublic.Reset();
m_Sticky.Reset();
m_Attr.Reset();
}
BOOL
CIPMap::Serialize(
CStoreXBF* pX
)
/*++
Routine Description:
serialize a CIPMap to buffer
Arguments:
buffer where to serialize
Return Value:
TRUE if success, otherwise FALSE
--*/
{
UINT iComp;
if ( !::Serialize( pX, (DWORD)IPLIST_VERSION ) )
{
return FALSE;
}
if ( !::Serialize( pX, (DWORD)m_Servers.GetNbPtr() ) )
{
return FALSE;
}
if ( !::Serialize( pX, (DWORD)m_IpPublic.GetNbEntry() ) )
{
return FALSE;
}
for ( iComp = 0 ;
iComp < m_Servers.GetNbPtr() ;
++iComp )
{
if ( !((CComputerBalanceCnfg*)m_Servers.GetPtr(iComp))->Serialize( pX ) )
{
return FALSE;
}
}
if ( !m_IpPublic.Serialize( pX ) ||
!m_Name.Serialize( pX ) ||
!m_Sticky.Serialize( pX ) ||
!m_Attr.Serialize( pX ) )
{
return FALSE;
}
return TRUE;
}
BOOL
CIPMap::Unserialize(
CStoreXBF* pX
)
/*++
Routine Description:
Unserialize a CIPMap
Arguments:
pX - ptr to buffer
Return Value:
TRUE if success, otherwise FALSE
--*/
{
LPBYTE pb = pX->GetBuff();
DWORD dw = pX->GetUsed();
return Unserialize( &pb, &dw );
}
BOOL
CIPMap::Unserialize(
LPBYTE* ppb,
LPDWORD pc
)
/*++
Routine Description:
Unserialize IP Map
Arguments:
ppb - ptr to addr of buffer to unserialize from
pc - ptr to count of bytes in buffer
Return Value:
TRUE if success, otherwise FALSE
--*/
{
DWORD dwComp;
UINT iComp;
DWORD dwPublicIp;
UINT iPublicIp;
CComputerBalanceCnfg* pComp;
DWORD dwVersion;
DEBUG_BUFFER;
Reset();
if ( !::Unserialize( ppb, pc, &dwVersion ) )
{
return FALSE;
}
if ( !::Unserialize( ppb, pc, &dwComp ) ||
!::Unserialize( ppb, pc, &dwPublicIp ) )
{
DBG_PRINTF(( achE, "CIPMap::Unserialize error 1, pb=%08x c=%d\n", *ppb, *pc));
return FALSE;
}
for ( iComp = 0 ;
iComp < dwComp ;
++iComp )
{
if ( !(pComp = new CComputerBalanceCnfg) ||
m_Servers.AddPtr( pComp ) == INDEX_ERROR ||
!pComp->Unserialize( ppb, pc, dwPublicIp ) )
{
DBG_PUTS("CIPMap::Unserialize error 2\n" );
return FALSE;
}
}
if ( !m_IpPublic.Unserialize( ppb, pc, dwPublicIp ) ||
!m_Name.Unserialize( ppb, pc, dwPublicIp ) ||
!m_Sticky.Unserialize( ppb, pc, dwPublicIp ) ||
!m_Attr.Unserialize( ppb, pc, dwPublicIp ) )
{
DBG_PUTS("CIPMap::Unserialize error 3\n" );
return FALSE;
}
return TRUE;
}
BOOL
LoadBlobFromReg(
HKEY hKey,
LPSTR pszRegKey,
LPSTR pszRegValue,
CStoreXBF* pX
)
/*++
Routine Description:
Load a buffer from registry
Arguments:
hKey - registry handle where to open key to read value
pszRegKey - key where to read value
pszRegValue - value name
pX - ptr to buffer
Return Value:
TRUE if success, otherwise FALSE
--*/
{
BOOL fSt = FALSE;
HKEY hK;
DWORD dwNeed;
DWORD dwType;
DWORD dwStatus;
CHAR achE[128];
if ( (dwStatus = RegOpenKeyEx( hKey,
pszRegKey,
0,
KEY_READ,
&hK )) == ERROR_SUCCESS )
{
dwNeed = 0;
if ( (dwStatus = RegQueryValueEx( hK,
pszRegValue,
0,
&dwType,
NULL,
&dwNeed )) == ERROR_SUCCESS &&
dwType == REG_BINARY &&
pX->Need( dwNeed ) &&
(dwStatus = RegQueryValueEx( hK,
pszRegValue,
0,
&dwType,
pX->GetBuff(),
&dwNeed )) == ERROR_SUCCESS )
{
pX->SetUsed( dwNeed );
fSt = TRUE;
}
RegCloseKey( hK );
}
if ( !fSt )
{
SetLastError( dwStatus );
DBG_PUTS( "Error LoadBlobFromReg\n" );
}
return fSt;
}
BOOL
CIPMap::Load(
HKEY hKey,
LPSTR pszRegKey,
LPSTR pszRegValue
)
/*++
Routine Description:
Load a CIPMap from registry
Arguments:
hKey - registry handle where to open key to read value
pszRegKey - key where to read value
pszRegValue - value name
Return Value:
TRUE if success, otherwise FALSE
--*/
{
CStoreXBF xbf;
return LoadBlobFromReg( hKey,
pszRegKey,
pszRegValue,
&xbf ) &&
Unserialize( &xbf );
}
BOOL
SaveBlobToReg(
HKEY hKey,
LPSTR pszRegKey,
LPSTR pszRegValue,
CStoreXBF* pX
)
/*++
Routine Description:
Save a buffer to registry
Arguments:
hKey - registry handle where to open key to write value
pszRegKey - key where to write value
pszRegValue - value name
pX - ptr to buffer
Return Value:
TRUE if success, otherwise FALSE
--*/
{
BOOL fSt = FALSE;
HKEY hK;
DWORD dwDisposition;
DWORD dwStatus;
if ( (dwStatus = RegCreateKeyEx( hKey,
pszRegKey,
0,
"",
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hK,
&dwDisposition )) == ERROR_SUCCESS )
{
if ( (dwStatus = RegSetValueEx( hK,
pszRegValue,
0,
REG_BINARY,
pX->GetBuff(),
pX->GetUsed() )) == ERROR_SUCCESS )
{
fSt = TRUE;
}
RegCloseKey( hK );
}
if ( !fSt )
{
SetLastError( dwStatus );
}
return fSt;
}
BOOL
CIPMap::Save(
HKEY hKey,
LPSTR pszRegKey,
LPSTR pszRegValue
)
/*++
Routine Description:
Save a CIPMap to registry
Arguments:
hKey - registry handle where to open key to write value
pszRegKey - key where to write value
pszRegValue - value name
Return Value:
TRUE if success, otherwise FALSE
--*/
{
CStoreXBF xbf;
return Serialize( &xbf ) &&
SaveBlobToReg( hKey, pszRegKey, pszRegValue, &xbf );
}
BOOL
CIPMap::AddComputer(
LPWSTR pszName
)
/*++
Routine Description:
Add a computer in CIPMap
Arguments:
pszName - computer name to be added at the end of computer list
Return Value:
TRUE if success, otherwise FALSE
--*/
{
CComputerBalanceCnfg* pComp;
UINT iComp;
LPWSTR pszCheckName;
for ( iComp = 0 ;
iComp < m_Servers.GetNbPtr() ;
++iComp )
{
if ( ((CComputerBalanceCnfg*)m_Servers.GetPtr( iComp ))->GetName( &pszCheckName ) &&
!_wcsicmp( pszCheckName, pszName ) )
{
SetLastError( ERROR_ALREADY_EXISTS );
return FALSE;
}
}
if ( (pComp = new CComputerBalanceCnfg) &&
m_Servers.AddPtr( (LPVOID)pComp ) != INDEX_ERROR &&
pComp->Init( pszName, m_IpPublic.GetNbEntry() ) )
{
return TRUE;
}
delete pComp;
return FALSE;
}
BOOL
CIPMap::EnumComputer(
UINT iComp,
LPWSTR* ppszName
)
/*++
Routine Description:
Enumerate computers in CIPMap
Arguments:
iComp - computer index ( 0-based )
ppszName - updated with read-only computer name on success
Return Value:
TRUE if success, otherwise FALSE
LastError will be set to ERROR_NO_MORE_ITEMS if index out of range
--*/
{
if ( iComp >= m_Servers.GetNbPtr() )
{
SetLastError( ERROR_NO_MORE_ITEMS );
return FALSE;
}
return ((CComputerBalanceCnfg*)m_Servers.GetPtr( iComp ))->GetName( ppszName );
}
BOOL
CIPMap::DeleteComputer(
UINT iComp
)
/*++
Routine Description:
Delete a computer in CIPMap
Arguments:
iComp - computer index ( 0-based )
Return Value:
TRUE if success, otherwise FALSE
--*/
{
if ( iComp >= m_Servers.GetNbPtr() )
{
return FALSE;
}
delete ((CComputerBalanceCnfg*)m_Servers.GetPtr( iComp ));
return m_Servers.DeletePtr( iComp );
}
BOOL
CIPMap::AddIpPublic(
LPWSTR pszIpPublic,
LPWSTR pszName,
DWORD dwSticky,
DWORD dwAttr
)
/*++
Routine Description:
Add a public IP address in CIPMap
Arguments:
pszIpPublic - public IP address to be added at the end of public IP address list
pszName - name associated with IP address
dwSticky - sticky duration ( in seconds )
dwAttr - user defined param
Return Value:
TRUE if success, otherwise FALSE
--*/
{
UINT iComp;
UINT iIp;
for ( iIp = 0 ;
iIp < m_IpPublic.GetNbPtr() ;
++iIp )
{
if ( !_wcsicmp( m_IpPublic.GetEntry( iIp ), pszIpPublic ) )
{
SetLastError( ERROR_ALREADY_EXISTS );
return FALSE;
}
}
if ( m_IpPublic.AddEntry( pszIpPublic ) == INDEX_ERROR ||
m_Name.AddEntry( pszName ) == INDEX_ERROR ||
m_Sticky.AddPtr( (LPVOID)dwSticky) == INDEX_ERROR ||
m_Attr.AddPtr( (LPVOID)dwAttr) == INDEX_ERROR )
{
return FALSE;
}
for ( iComp = 0 ;
iComp < m_Servers.GetNbPtr() ;
++iComp )
{
if ( ((CComputerBalanceCnfg*)m_Servers.GetPtr(iComp))->AddIpPublic() == INDEX_ERROR )
{
return FALSE;
}
}
return TRUE;
}
BOOL
CIPMap::EnumIpPublic(
UINT iIpPublic,
LPWSTR* ppszIpPublic,
LPWSTR* ppszName,
LPDWORD pdwSticky,
LPDWORD pdwAttr
)
/*++
Routine Description:
Enumerate public IP addresses in CIPMap
Arguments:
iIpPublic - public IP address index ( 0-based )
ppszIpPublic - updated with read-only public IP address on success
ppszName - associated name
pdwSticky - associated sticky duration
pdwAttr - associated user attr
Return Value:
TRUE if success, otherwise FALSE
LastError will be set to ERROR_NO_MORE_ITEMS if index out of range
--*/
{
if ( iIpPublic >= m_IpPublic.GetNbEntry() )
{
SetLastError( ERROR_NO_MORE_ITEMS );
return FALSE;
}
*ppszIpPublic = m_IpPublic.GetEntry( iIpPublic );
*ppszName = m_Name.GetEntry( iIpPublic );
*pdwSticky = (DWORD)m_Sticky.GetPtr( iIpPublic ); // BUGBUG64
*pdwAttr = (DWORD)m_Attr.GetPtr( iIpPublic ); // BUGBUG64
return TRUE;
}
BOOL
CIPMap::DeleteIpPublic(
UINT iIpPublic
)
/*++
Routine Description:
Delete a public IP address in CIPMap
Arguments:
iIpPublic - public IP address index ( 0-based )
Return Value:
TRUE if success, otherwise FALSE
--*/
{
UINT iComp;
if ( !m_IpPublic.DeleteEntry( iIpPublic ) ||
!m_Name.DeleteEntry( iIpPublic ) ||
!m_Sticky.DeletePtr( iIpPublic ) ||
!m_Attr.DeletePtr( iIpPublic ) )
{
return FALSE;
}
for ( iComp = 0 ;
iComp < m_Servers.GetNbPtr() ;
++iComp )
{
if ( !((CComputerBalanceCnfg*)m_Servers.GetPtr(iComp))->DeleteIpPublic(iIpPublic) )
{
return FALSE;
}
}
return TRUE;
}
BOOL
CIPMap::SetIpPrivate(
UINT iComp,
UINT iIpPublic,
LPWSTR pszIpPrivate,
LPWSTR pszName
)
/*++
Routine Description:
Set a private IP address in CIPMap
Arguments:
iComp - computer index
iIpPublic - public IP address index
pszIpPrivate - private IP addresse to associate with iComp & iIpPublic
pszName - name associated with private IP address
Return Value:
TRUE if success, otherwise FALSE
LastError will be set to ERROR_INVALID_PARAMETER if indexes out of range
--*/
{
if ( iIpPublic >= m_IpPublic.GetNbEntry() ||
iComp >= m_Servers.GetNbPtr() )
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
return ((CComputerBalanceCnfg*)m_Servers.GetPtr(iComp))->
SetIpPrivate( iIpPublic, pszIpPrivate, pszName);
}
BOOL
CIPMap::GetIpPrivate(
UINT iComp,
UINT iIpPublic,
LPWSTR* ppszIpPrivate,
LPWSTR* ppszName
)
/*++
Routine Description:
Get a private IP address in CIPMap
Arguments:
iComp - computer index
iIpPublic - public IP address index
ppszIpPrivate - updated with read-only private IP addresse associated with iComp & iIpPublic
ppszName - updated with read-pnly name associated with iComp & iIpPublic
Return Value:
TRUE if success, otherwise FALSE
LastError will be set to ERROR_INVALID_PARAMETER if indexes out of range
--*/
{
if ( iIpPublic >= m_IpPublic.GetNbEntry() ||
iComp >= m_Servers.GetNbPtr() )
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
return ((CComputerBalanceCnfg*)m_Servers.GetPtr(iComp))->GetIpPrivate(iIpPublic,ppszIpPrivate,ppszName);
}
BOOL
CComputerBalanceCnfg::Init(
LPWSTR pszName,
UINT cIpPublic
)
/*++
Routine Description:
Initialize a CComputerBalanceCnfg with computer name, creating cIpPublic entries
in private IP addresses list
Arguments:
pszName - computer name
cIpPublic - count of current public IP addresses
Return Value:
TRUE if success, otherwise FALSE
--*/
{
if ( !m_ComputerName.Set( pszName ) )
{
return FALSE;
}
while ( cIpPublic-- )
{
if ( m_IpPrivate.AddEntry(L"") == INDEX_ERROR ||
m_Name.AddEntry(L"") == INDEX_ERROR )
{
return FALSE;
}
}
return TRUE;
}
CComputerPerfCounters::CComputerPerfCounters()
/*++
Routine Description:
CComputerPerfCounters constructor
Arguments:
none
Return Value:
nothing
--*/
{
}
CComputerPerfCounters::~CComputerPerfCounters()
/*++
Routine Description:
CComputerPerfCounters destructor
Arguments:
none
Return Value:
nothing
--*/
{
Reset();
}
VOID
CComputerPerfCounters::Reset(
)
/*++
Routine Description:
Reset a CIPMap to empty content
Arguments:
none
Return Value:
nothing
--*/
{
m_PerfCounters.Reset();
m_Weight.Reset();
}
BOOL
CComputerPerfCounters::Serialize(
CStoreXBF* pX
)
/*++
Routine Description:
serialize a CComputerPerfCounters to buffer
Arguments:
buffer where to serialize
Return Value:
TRUE if success, otherwise FALSE
--*/
{
if ( !::Serialize( pX, (DWORD)PERFLIST_VERSION ) )
{
return FALSE;
}
return ::Serialize( pX, (DWORD)m_PerfCounters.GetNbEntry() ) &&
m_PerfCounterServers.Serialize( pX ) &&
m_PerfCounters.Serialize( pX ) &&
m_Weight.Serialize( pX );
}
BOOL
CComputerPerfCounters::Unserialize(
CStoreXBF* pX
)
/*++
Routine Description:
Unserialize a CComputerPerfCounters
Arguments:
pX - ptr to buffer
Return Value:
TRUE if success, otherwise FALSE
--*/
{
LPBYTE pb = pX->GetBuff();
DWORD dw = pX->GetUsed();
return Unserialize( &pb, &dw );
}
BOOL
CComputerPerfCounters::Unserialize(
LPBYTE* ppb,
LPDWORD pdw
)
/*++
Routine Description:
Unserialize a CComputerPerfCounters
Arguments:
ppB - ptr to addr of buffer to unserialize from
pC - ptr to count of bytes in buffer
Return Value:
TRUE if success, otherwise FALSE
--*/
{
DWORD dwP;
DWORD dwVersion;
if ( !::Unserialize( ppb, pdw, &dwVersion ) )
{
return FALSE;
}
return ::Unserialize( ppb, pdw, &dwP ) &&
m_PerfCounterServers.Unserialize( ppb, pdw, dwP ) &&
m_PerfCounters.Unserialize( ppb, pdw, dwP ) &&
m_Weight.Unserialize( ppb, pdw, dwP );
}
BOOL
CComputerPerfCounters::Load(
HKEY hKey,
LPSTR pszRegKey,
LPSTR pszRegValue
)
/*++
Routine Description:
Load a CComputerPerfCounters from registry
Arguments:
hKey - registry handle where to open key to read value
pszRegKey - key where to read value
pszRegValue - value name
Return Value:
TRUE if success, otherwise FALSE
--*/
{
CStoreXBF xbf;
return LoadBlobFromReg( hKey,
pszRegKey,
pszRegValue,
&xbf ) &&
Unserialize( &xbf );
}
BOOL
CComputerPerfCounters::Save(
HKEY hKey,
LPSTR pszRegKey,
LPSTR pszRegValue
)
/*++
Routine Description:
Save a CComputerPerfCounters to registry
Arguments:
hKey - registry handle where to open key to write value
pszRegKey - key where to write value
pszRegValue - value name
Return Value:
TRUE if success, otherwise FALSE
--*/
{
CStoreXBF xbf;
return Serialize( &xbf ) &&
SaveBlobToReg( hKey, pszRegKey, pszRegValue, &xbf );
}
BOOL
CComputerPerfCounters::AddPerfCounter(
LPWSTR pszServerName,
LPWSTR pszPerfCounter,
DWORD dwWeight
)
/*++
Routine Description:
Add a performance counter in CIPMap
Arguments:
pszServerName - optional server name ( can be NULL )
pszIpPublic - performance counter to be added at the end of performance counter list
dwWeight - weight associated with perf counter to add
Return Value:
TRUE if success, otherwise FALSE
--*/
{
UINT iPerf;
//
// Check if specify normalized flag then to other counter exist.
// if not normalized then existing counter should not be normalized.
//
if ( dwWeight == LB_WEIGHT_NORMALIZED_FLAG &&
m_PerfCounterServers.GetNbEntry() )
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
else if ( dwWeight != LB_WEIGHT_NORMALIZED_FLAG )
{
for ( iPerf = 0 ;
iPerf < m_PerfCounters.GetNbEntry() ;
++iPerf )
{
if ( (DWORD)m_Weight.GetPtr( iPerf ) == LB_WEIGHT_NORMALIZED_FLAG ) // BUGBUG64
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
}
}
return m_PerfCounterServers.AddEntry( pszServerName ? pszServerName : L"") != INDEX_ERROR &&
m_PerfCounters.AddEntry( pszPerfCounter ) != INDEX_ERROR &&
m_Weight.AddPtr( (LPVOID)dwWeight ) != INDEX_ERROR;
}
BOOL
CComputerPerfCounters::EnumPerfCounter(
UINT iPerfCounter,
LPWSTR* ppszPerfCounterServer,
LPWSTR* ppszPerfCounter,
DWORD* pdwWeight
)
/*++
Routine Description:
Enumerate performance counters in CComputerPerfCounters
Arguments:
iPerfCounter - public IP address index ( 0-based )
ppszServerName - updated with read-only server name ( can be NULL )
ppszPerfCounter - updated with read-only performance counter on success
pdwWeight - updated with read-only perf counter weight on success
Return Value:
TRUE if success, otherwise FALSE
LastError will be set to ERROR_NO_MORE_ITEMS if index out of range
--*/
{
if ( iPerfCounter >= m_PerfCounters.GetNbEntry() )
{
SetLastError( ERROR_NO_MORE_ITEMS );
return FALSE;
}
*ppszPerfCounterServer = *m_PerfCounterServers.GetEntry( iPerfCounter ) ?
m_PerfCounterServers.GetEntry( iPerfCounter ) :
NULL;
*ppszPerfCounter = m_PerfCounters.GetEntry( iPerfCounter );
*pdwWeight = (DWORD)m_Weight.GetPtr( iPerfCounter ); // BUGBUG64
return TRUE;
}
BOOL
CComputerPerfCounters::DeletePerfCounter(
UINT iPerfCounter
)
/*++
Routine Description:
Delete a performance counter in CComputerPerfCounters
Arguments:
iPerfCounter - performance counter index ( 0-based )
Return Value:
TRUE if success, otherwise FALSE
--*/
{
return m_PerfCounterServers.DeleteEntry( iPerfCounter ) &&
m_PerfCounters.DeleteEntry( iPerfCounter ) &&
m_Weight.DeletePtr( iPerfCounter );
}
BOOL
CComputerPerfCounters::SetPerfCounterWeight(
UINT iPerfCounter,
DWORD dwWeight
)
/*++
Routine Description:
Set a performance counter weight in CIPMap
Arguments:
iPerfCounter - performance counter index
dwWeight - weight to associate with performance counter indexed by iPerfCounter
Return Value:
TRUE if success, otherwise FALSE
--*/
{
return m_Weight.SetPtr( iPerfCounter, (LPVOID)dwWeight );
}
/////////////////
CIpEndpointList::CIpEndpointList(
)
/*++
Routine Description:
CIpEndpointList constructor
Arguments:
none
Return Value:
nothing
--*/
{
}
CIpEndpointList::~CIpEndpointList(
)
/*++
Routine Description:
CIpEndpointList destructor
Arguments:
none
Return Value:
nothing
--*/
{
Reset();
}
VOID
CIpEndpointList::Reset(
)
/*++
Routine Description:
Reset a CIpEndpointList to empty content
Arguments:
none
Return Value:
nothing
--*/
{
UINT iComp;
m_IpEndpoint.Reset();
}
BOOL
CIpEndpointList::Serialize(
CStoreXBF* pX
)
/*++
Routine Description:
serialize a CIpEndpointList to buffer
Arguments:
buffer where to serialize
Return Value:
TRUE if success, otherwise FALSE
--*/
{
if ( !::Serialize( pX, (DWORD)m_IpEndpoint.GetNbEntry() ) )
{
return FALSE;
}
if ( !m_IpEndpoint.Serialize( pX ) )
{
return FALSE;
}
return TRUE;
}
BOOL
CIpEndpointList::Unserialize(
CStoreXBF* pX
)
/*++
Routine Description:
Unserialize a CIpEndpointList
Arguments:
pX - ptr to buffer
Return Value:
TRUE if success, otherwise FALSE
--*/
{
LPBYTE pb = pX->GetBuff();
DWORD dw = pX->GetUsed();
return Unserialize( &pb, &dw );
}
BOOL
CIpEndpointList::Unserialize(
LPBYTE* ppb,
LPDWORD pc
)
/*++
Routine Description:
Unserialize CIpEndpointList
Arguments:
ppb - ptr to addr of buffer to unserialize from
pc - ptr to count of bytes in buffer
Return Value:
TRUE if success, otherwise FALSE
--*/
{
DWORD dwIp;
Reset();
if ( !::Unserialize( ppb, pc, &dwIp ) )
{
return FALSE;
}
if ( !m_IpEndpoint.Unserialize( ppb, pc, dwIp ) )
{
return FALSE;
}
return TRUE;
}
BOOL
CIpEndpointList::EnumIpEndpoint(
UINT iIp,
LPWSTR* ppszIp
)
/*++
Routine Description:
Enumerate IP endpoints
Arguments:
iIp - IP index ( 0-based )
ppszName - updated with read-only IP addr ( as string ) on success
Return Value:
TRUE if success, otherwise FALSE
LastError will be set to ERROR_NO_MORE_ITEMS if index out of range
--*/
{
if ( iIp >= m_IpEndpoint.GetNbEntry() )
{
SetLastError( ERROR_NO_MORE_ITEMS );
return FALSE;
}
*ppszIp = m_IpEndpoint.GetEntry( iIp );
return TRUE;
}
BOOL
CIpEndpointList::BuildListFromLocalhost(
)
/*++
Routine Description:
Build list of local IP endpoints
Arguments:
None
Return Value:
TRUE if success, otherwise FALSE
--*/
{
char** pAddr;
sockaddr_in SockAddr;
struct hostent* pH;
WCHAR achAddr[128];
DWORD cAddr;
Reset();
if ( pH = gethostbyname( NULL ) )
{
if ( pH->h_addrtype == AF_INET )
{
for ( pAddr = pH->h_addr_list;
*pAddr ;
++pAddr )
{
memcpy( &SockAddr.sin_addr, *pAddr, 4 );
SockAddr.sin_family = AF_INET;
SockAddr.sin_port = 0;
cAddr = sizeof( achAddr ) / sizeof(WCHAR);
if ( WSAAddressToStringW( (struct sockaddr *)&SockAddr,
sizeof(SockAddr),
NULL,
achAddr,
&cAddr ) != 0 ||
m_IpEndpoint.AddEntry( achAddr ) == INDEX_ERROR )
{
return FALSE;
}
}
return TRUE;
}
else
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
}
return FALSE;
}