593 lines
15 KiB
C
593 lines
15 KiB
C
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
iplist9x.c
|
|
|
|
Abstract:
|
|
|
|
Domain Name System (DNS) Library
|
|
|
|
NT4 version of routines to get IP addresses of stack.
|
|
|
|
Contents:
|
|
Dns_GetIpAddressesWin9X
|
|
Dns_GetLocalIpAddressArrayWin9X
|
|
|
|
Author:
|
|
|
|
Glenn A. Curtis (glennc) 05-May-1997
|
|
|
|
Revision History:
|
|
|
|
05-May-1997 glennc
|
|
Copied from the (NT4 SP3) winsock2 directory
|
|
|
|
--*/
|
|
|
|
//
|
|
// includes
|
|
//
|
|
|
|
#include "local.h"
|
|
|
|
#define WIN95_TCPIP_PARAMETERS_KEY "System\\CurrentControlSet\\Services\\VxD\\MSTCP"
|
|
#define WIN95_DHCP_KEY "System\\CurrentControlSet\\Services\\VxD\\DHCP"
|
|
#define WIN95_NET_TRANS_KEY "System\\CurrentControlSet\\Services\\Class\\NetTrans"
|
|
#define DHCP_IP_ADDRESS_VALUE_WIN95 "DhcpIPAddress"
|
|
#define DHCP_SUBNET_VALUE_WIN95 "DhcpSubnetMask"
|
|
#define STATIC_ADDRESS_VALUE "IPAddress"
|
|
#define STATIC_SUBNET_VALUE "IPMask"
|
|
#define DHCP_INFO_VALUE "DhcpInfo"
|
|
#define DRIVER_DESCRIPTION_VALUE "DriverDesc"
|
|
#define TCPIP_DRIVER_DESCRIPTION "TCP/IP"
|
|
#define NDISWAN_DRIVER_DESCRIPTION "NDISWAN"
|
|
#define KEY_CONNECT "\\"
|
|
#define KEY_CONNECT_CHAR '\\'
|
|
#define DHCP_IP_ADDRESS_VALUE_TYPE_WIN95 REG_DWORD
|
|
#define DHCP_SUBNET_VALUE_TYPE_WIN95 REG_DWORD
|
|
#define STATIC_ADDRESS_VALUE_TYPE REG_SZ
|
|
#define STATIC_SUBNET_VALUE_TYPE REG_SZ
|
|
#define DHCP_INFO_VALUE_TYPE REG_BINARY
|
|
#define DRIVER_DESCRIPTION_VALUE_TYPE REG_SZ
|
|
|
|
typedef DWORD IP_ADDRESS, *PIP_ADDRESS;
|
|
|
|
typedef struct _ADAPTER_INFO_
|
|
{
|
|
BOOL IsDhcpEnabled;
|
|
PIP_ARRAY pipAddresses;
|
|
PIP_ARRAY pipSubnetMasks;
|
|
|
|
} ADAPTER_INFO, *LPADAPTER_INFO;
|
|
|
|
|
|
//
|
|
// Heap operations
|
|
//
|
|
|
|
#define ALLOCATE_HEAP(size) Dns_AllocZero( size )
|
|
#define REALLOCATE_HEAP(p,size) Dns_Realloc( (p), (size) )
|
|
#define FREE_HEAP(p) Dns_Free( p )
|
|
#define ALLOCATE_HEAP_ZERO(size) Dns_AllocZero( size )
|
|
|
|
|
|
//
|
|
// functions
|
|
//
|
|
|
|
PIP_ARRAY
|
|
GetIpArray(
|
|
BOOL IsMultiSzString,
|
|
LPSTR IpAddressString )
|
|
{
|
|
DWORD NumberOfAddresses;
|
|
DWORD StringLen;
|
|
LPSTR StringPtr;
|
|
DWORD iter;
|
|
PIP_ARRAY pIpArray = NULL;
|
|
|
|
//
|
|
// determine number of strings in IpAddressString, that many
|
|
// addresses are assigned.
|
|
//
|
|
|
|
StringPtr = IpAddressString;
|
|
NumberOfAddresses = 0;
|
|
while ( ( StringLen = strlen( StringPtr ) ) != 0 )
|
|
{
|
|
//
|
|
// found another NET.
|
|
//
|
|
NumberOfAddresses++;
|
|
if ( IsMultiSzString )
|
|
StringPtr += (StringLen + 1);
|
|
else
|
|
StringPtr += StringLen;
|
|
}
|
|
|
|
//
|
|
// allocate memory for the ADAPTER_INFO array.
|
|
//
|
|
|
|
pIpArray =
|
|
ALLOCATE_HEAP_ZERO( sizeof(IP_ADDRESS) * NumberOfAddresses +
|
|
sizeof(IP_ARRAY) );
|
|
|
|
if( pIpArray == NULL )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// enum the addresses.
|
|
//
|
|
|
|
StringPtr = IpAddressString;
|
|
NumberOfAddresses = 0;
|
|
|
|
while ( ( StringLen = strlen( StringPtr ) ) != 0 )
|
|
{
|
|
IP_ADDRESS ip;
|
|
|
|
ip = inet_addr( StringPtr );
|
|
|
|
if( ip != INADDR_ANY && ip != INADDR_NONE )
|
|
{
|
|
pIpArray->AddrArray[NumberOfAddresses] = ip;
|
|
NumberOfAddresses++;
|
|
}
|
|
|
|
if ( IsMultiSzString )
|
|
StringPtr += (StringLen + 1);
|
|
else
|
|
StringPtr += StringLen;
|
|
}
|
|
|
|
pIpArray->AddrCount = NumberOfAddresses;
|
|
|
|
if ( pIpArray->AddrCount == 0 )
|
|
{
|
|
FREE_HEAP( pIpArray );
|
|
pIpArray = NULL;
|
|
}
|
|
|
|
return pIpArray;
|
|
}
|
|
|
|
|
|
PIP_ARRAY
|
|
GetMaskArray(
|
|
BOOL IsMultiSzString,
|
|
LPSTR SubnetMaskString )
|
|
{
|
|
DWORD NumberOfAddresses;
|
|
DWORD StringLen;
|
|
LPSTR StringPtr;
|
|
DWORD iter;
|
|
PIP_ARRAY pIpArray = NULL;
|
|
|
|
//
|
|
// determine number of strings in SubnetMaskString, that many
|
|
// addresses are assigned.
|
|
//
|
|
|
|
StringPtr = SubnetMaskString;
|
|
NumberOfAddresses = 0;
|
|
while ( ( StringLen = strlen( StringPtr ) ) != 0 )
|
|
{
|
|
//
|
|
// found another NET.
|
|
//
|
|
NumberOfAddresses++;
|
|
if ( IsMultiSzString )
|
|
StringPtr += (StringLen + 1);
|
|
else
|
|
StringPtr += StringLen;
|
|
}
|
|
|
|
//
|
|
// allocate memory for the ADAPTER_INFO array.
|
|
//
|
|
|
|
pIpArray =
|
|
ALLOCATE_HEAP_ZERO( sizeof(IP_ADDRESS) * NumberOfAddresses +
|
|
sizeof(IP_ARRAY) );
|
|
|
|
if( pIpArray == NULL )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// enum the addresses.
|
|
//
|
|
|
|
StringPtr = SubnetMaskString;
|
|
NumberOfAddresses = 0;
|
|
|
|
while ( ( StringLen = strlen( StringPtr ) ) != 0 )
|
|
{
|
|
IP_ADDRESS ip;
|
|
|
|
ip = inet_addr( StringPtr );
|
|
|
|
if( ip != INADDR_ANY )
|
|
{
|
|
pIpArray->AddrArray[NumberOfAddresses] = ip;
|
|
NumberOfAddresses++;
|
|
}
|
|
|
|
if ( IsMultiSzString )
|
|
StringPtr += (StringLen + 1);
|
|
else
|
|
StringPtr += StringLen;
|
|
}
|
|
|
|
pIpArray->AddrCount = NumberOfAddresses;
|
|
|
|
if ( pIpArray->AddrCount == 0 )
|
|
{
|
|
FREE_HEAP( pIpArray );
|
|
pIpArray = NULL;
|
|
}
|
|
|
|
return pIpArray;
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* Dns_GetIpAddressesWin9X
|
|
*
|
|
* Retrieves all active IP addresses from all active adapters on this machine.
|
|
* Returns them as an array
|
|
*
|
|
* ENTRY IpAddressList - pointer to array of IP addresses
|
|
* ListCount - number of IP address IpAddressList can hold
|
|
*
|
|
* EXIT IpAddressList - filled with retrieved IP addresses
|
|
*
|
|
* RETURNS number of IP addresses retrieved, or 0 if error
|
|
*
|
|
* ASSUMES 1. an IP address can be represented in a DWORD
|
|
* 2. ListCount > 0
|
|
*
|
|
******************************************************************************/
|
|
|
|
DWORD
|
|
Dns_GetIpAddressesWin9X(
|
|
IN OUT PDNS_ADDRESS_INFO IpAddressInfoList,
|
|
IN DWORD ListCount
|
|
)
|
|
{
|
|
DWORD status = NO_ERROR;
|
|
DWORD addressCount = 0;
|
|
DWORD iter, iter2;
|
|
DWORD TotalNumberOfNets;
|
|
HKEY AdapterKeyHandle = NULL;
|
|
LPADAPTER_INFO AdapterInfoList = NULL;
|
|
|
|
RtlZeroMemory( IpAddressInfoList, sizeof( DNS_ADDRESS_INFO ) * 10 );
|
|
|
|
//
|
|
// allocate memory for the ADAPTER_INFO array.
|
|
//
|
|
|
|
AdapterInfoList =
|
|
ALLOCATE_HEAP( sizeof(ADAPTER_INFO) * 10 );
|
|
|
|
if( !AdapterInfoList )
|
|
return 0;
|
|
|
|
//
|
|
// enum the static and WAN networks.
|
|
//
|
|
|
|
TotalNumberOfNets = 0;
|
|
|
|
for ( iter = 0; iter < 10; iter++ )
|
|
{
|
|
char AdapterParamKey[256];
|
|
DWORD dwFlags = 0;
|
|
char szCount[4];
|
|
LPSTR DriverDescription = NULL;
|
|
LPSTR IpAddressString = NULL;
|
|
|
|
//
|
|
// open Parameter key of the adapter that is bound to TCPIP.
|
|
//
|
|
sprintf( szCount, "%d", iter );
|
|
|
|
strcpy( AdapterParamKey, WIN95_NET_TRANS_KEY );
|
|
strcat( AdapterParamKey, "\\000" );
|
|
strcat( AdapterParamKey, szCount );
|
|
|
|
status = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
AdapterParamKey,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&AdapterKeyHandle );
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
AdapterKeyHandle = NULL;
|
|
goto Skip1;
|
|
}
|
|
|
|
//
|
|
// See if this is a TCPIP adapter
|
|
//
|
|
status = GetRegistryValue( AdapterKeyHandle,
|
|
TRUE,
|
|
DRIVER_DESCRIPTION_VALUE,
|
|
DRIVER_DESCRIPTION_VALUE_TYPE,
|
|
(LPBYTE)&DriverDescription );
|
|
|
|
if ( status != ERROR_SUCCESS || !DriverDescription )
|
|
goto Skip1;
|
|
|
|
if ( DriverDescription &&
|
|
strlen( DriverDescription ) == 0 )
|
|
{
|
|
FREE_HEAP( DriverDescription );
|
|
goto Skip1;
|
|
}
|
|
|
|
if ( strcmp( DriverDescription, TCPIP_DRIVER_DESCRIPTION ) )
|
|
{
|
|
FREE_HEAP( DriverDescription );
|
|
goto Skip1;
|
|
}
|
|
|
|
FREE_HEAP( DriverDescription );
|
|
|
|
//
|
|
// This is a TCP/IP adapter, now see if there is an address
|
|
// assigned to it
|
|
//
|
|
status = GetRegistryValue( AdapterKeyHandle,
|
|
TRUE,
|
|
STATIC_ADDRESS_VALUE,
|
|
STATIC_ADDRESS_VALUE_TYPE,
|
|
(LPBYTE)&IpAddressString );
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
goto Skip1;
|
|
|
|
AdapterInfoList[TotalNumberOfNets].IsDhcpEnabled = FALSE;
|
|
AdapterInfoList[TotalNumberOfNets].pipAddresses =
|
|
GetIpArray( FALSE, IpAddressString );
|
|
|
|
FREE_HEAP( IpAddressString );
|
|
IpAddressString = NULL;
|
|
|
|
if ( !AdapterInfoList[TotalNumberOfNets].pipAddresses )
|
|
goto Skip1;
|
|
|
|
status = GetRegistryValue( AdapterKeyHandle,
|
|
TRUE,
|
|
STATIC_SUBNET_VALUE,
|
|
STATIC_SUBNET_VALUE_TYPE,
|
|
(LPBYTE)&IpAddressString );
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
FREE_HEAP( AdapterInfoList[TotalNumberOfNets].pipAddresses );
|
|
AdapterInfoList[TotalNumberOfNets].pipAddresses = NULL;
|
|
goto Skip1;
|
|
}
|
|
|
|
AdapterInfoList[TotalNumberOfNets].pipSubnetMasks =
|
|
GetMaskArray( FALSE, IpAddressString );
|
|
|
|
FREE_HEAP( IpAddressString );
|
|
IpAddressString = NULL;
|
|
|
|
if ( !AdapterInfoList[TotalNumberOfNets].pipSubnetMasks )
|
|
{
|
|
FREE_HEAP( AdapterInfoList[TotalNumberOfNets].pipAddresses );
|
|
AdapterInfoList[TotalNumberOfNets].pipAddresses = NULL;
|
|
goto Skip1;
|
|
}
|
|
|
|
TotalNumberOfNets++;
|
|
|
|
Skip1 :
|
|
|
|
status = ERROR_SUCCESS;
|
|
|
|
if ( AdapterKeyHandle )
|
|
{
|
|
RegCloseKey( AdapterKeyHandle );
|
|
AdapterKeyHandle = NULL;
|
|
}
|
|
}
|
|
|
|
if ( TotalNumberOfNets )
|
|
goto Exit;
|
|
|
|
//
|
|
// Loop through each DHCP binding to read the adapter information.
|
|
//
|
|
for ( iter = 0; iter < 8; iter++ )
|
|
{
|
|
char AdapterParamKey[256];
|
|
DWORD dwFlags = 0;
|
|
char szCount[4];
|
|
DWORD IpAddress = 0;
|
|
DWORD SubnetMask = 0;
|
|
|
|
//
|
|
// open Parameter key of the adapter that is bound to DHCP.
|
|
//
|
|
sprintf( szCount, "0%d", iter );
|
|
|
|
strcpy( AdapterParamKey, WIN95_DHCP_KEY );
|
|
strcat( AdapterParamKey, "\\DhcpInfo" );
|
|
strcat( AdapterParamKey, szCount );
|
|
|
|
status = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
AdapterParamKey,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&AdapterKeyHandle );
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
AdapterKeyHandle = NULL;
|
|
goto Skip2;
|
|
}
|
|
|
|
status = GetRegistryValue( AdapterKeyHandle,
|
|
TRUE,
|
|
DHCP_IP_ADDRESS_VALUE_WIN95,
|
|
DHCP_IP_ADDRESS_VALUE_TYPE_WIN95,
|
|
(LPBYTE)&IpAddress );
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
IpAddress = 0;
|
|
|
|
if ( IpAddress == 0xffffffff )
|
|
IpAddress = 0;
|
|
|
|
if ( IpAddress )
|
|
{
|
|
//
|
|
// It is active, now read the subnet mask
|
|
//
|
|
status = GetRegistryValue( AdapterKeyHandle,
|
|
TRUE,
|
|
DHCP_SUBNET_VALUE_WIN95,
|
|
DHCP_SUBNET_VALUE_TYPE_WIN95,
|
|
(LPBYTE)&SubnetMask );
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
SubnetMask = 0;
|
|
}
|
|
else
|
|
{
|
|
LPBYTE DhcpInfo = NULL;
|
|
|
|
//
|
|
// This may be a Win95 machine, the adapter IP address
|
|
// is stored in the DhcpInfo blob.
|
|
//
|
|
status = GetRegistryValue( AdapterKeyHandle,
|
|
TRUE,
|
|
DHCP_INFO_VALUE,
|
|
DHCP_INFO_VALUE_TYPE,
|
|
(LPBYTE)&DhcpInfo );
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
goto Skip2;
|
|
|
|
if ( !DhcpInfo )
|
|
goto Skip2;
|
|
|
|
IpAddress = *((LPDWORD)(DhcpInfo+sizeof(DWORD)));
|
|
SubnetMask = *((LPDWORD)(DhcpInfo+sizeof(DWORD)+sizeof(DWORD)));
|
|
FREE_HEAP( DhcpInfo );
|
|
}
|
|
|
|
if ( IpAddress == 0x00000000 || IpAddress == 0xffffffff )
|
|
goto Skip2;
|
|
|
|
AdapterInfoList[TotalNumberOfNets].IsDhcpEnabled = TRUE;
|
|
AdapterInfoList[TotalNumberOfNets].pipAddresses =
|
|
Dns_CreateIpArray( 1 );
|
|
|
|
if ( !AdapterInfoList[TotalNumberOfNets].pipAddresses )
|
|
goto Skip2;
|
|
|
|
AdapterInfoList[TotalNumberOfNets].pipAddresses->AddrArray[0] =
|
|
IpAddress;
|
|
|
|
AdapterInfoList[TotalNumberOfNets].pipSubnetMasks =
|
|
Dns_CreateIpArray( 1 );
|
|
|
|
if ( !AdapterInfoList[TotalNumberOfNets].pipSubnetMasks )
|
|
{
|
|
FREE_HEAP( AdapterInfoList[TotalNumberOfNets].pipAddresses );
|
|
AdapterInfoList[TotalNumberOfNets].pipAddresses = NULL;
|
|
goto Skip2;
|
|
}
|
|
|
|
AdapterInfoList[TotalNumberOfNets].pipSubnetMasks->AddrArray[0] =
|
|
SubnetMask;
|
|
|
|
TotalNumberOfNets++;
|
|
|
|
Skip2 :
|
|
|
|
status = ERROR_SUCCESS;
|
|
|
|
if ( AdapterKeyHandle )
|
|
{
|
|
RegCloseKey( AdapterKeyHandle );
|
|
AdapterKeyHandle = NULL;
|
|
}
|
|
}
|
|
|
|
Exit :
|
|
|
|
//
|
|
// We now have a data structure that represents the current
|
|
// net adapters and assigned IP addresses based on the binding
|
|
// order described by the adapter protocol bindings for TCPIP.
|
|
//
|
|
// Now stuff as many as we can into the users buffer provided.
|
|
//
|
|
|
|
//
|
|
// Start by putting the first address from each adapter into the
|
|
// IP list.
|
|
//
|
|
for ( iter = 0; iter < TotalNumberOfNets && ListCount; iter++ )
|
|
{
|
|
IpAddressInfoList[addressCount].ipAddress =
|
|
AdapterInfoList[iter].pipAddresses->AddrArray[0];
|
|
IpAddressInfoList[addressCount++].subnetMask =
|
|
AdapterInfoList[iter].pipSubnetMasks->AddrArray[0];
|
|
ListCount--;
|
|
}
|
|
|
|
for ( iter = 0; iter < TotalNumberOfNets && ListCount; iter++ )
|
|
{
|
|
for ( iter2 = 1;
|
|
iter2 < AdapterInfoList[iter].pipAddresses->AddrCount;
|
|
iter2++ )
|
|
{
|
|
IpAddressInfoList[addressCount].ipAddress =
|
|
AdapterInfoList[iter].pipAddresses->AddrArray[iter2];
|
|
IpAddressInfoList[addressCount++].subnetMask =
|
|
AdapterInfoList[iter].pipSubnetMasks->AddrArray[iter2];
|
|
ListCount--;
|
|
}
|
|
}
|
|
|
|
if( AdapterKeyHandle )
|
|
RegCloseKey( AdapterKeyHandle );
|
|
|
|
for ( iter = 0; iter < TotalNumberOfNets; iter++ )
|
|
{
|
|
if( AdapterInfoList[iter].pipAddresses )
|
|
FREE_HEAP( AdapterInfoList[iter].pipAddresses );
|
|
|
|
if( AdapterInfoList[iter].pipSubnetMasks )
|
|
FREE_HEAP( AdapterInfoList[iter].pipSubnetMasks );
|
|
}
|
|
|
|
FREE_HEAP( AdapterInfoList );
|
|
|
|
AdapterInfoList = NULL;
|
|
|
|
return addressCount;
|
|
}
|
|
|
|
//
|
|
// End iplist9x.c
|
|
//
|