windows-nt/Source/XPSP1/NT/base/ntsetup/opktools/setupmgr/net/tcpip.c
2020-09-26 16:20:57 +08:00

987 lines
26 KiB
C

//----------------------------------------------------------------------------
//
// Copyright (c) 1997-1999 Microsoft Corporation
// All rights reserved.
//
// File Name:
// tcpip.c
//
// Description:
// This file contains the dialog procedure for the base TCP/IP page
// (IDD_TCP_IPADDR). Let's the user set DHCP or specific IPs or go to
// Advanced TCP/IP settings.
//
//----------------------------------------------------------------------------
#include "pch.h"
#include "resource.h"
BOOL Create_TCPIPProp_PropertySheet( HWND hwndParent );
BOOL ValidateIPAddress( IN TCHAR szIPAddress[] );
BOOL ValidateSubnetMask( IN TCHAR szIPAddress[] );
UINT CALLBACK TCPIP_PropertiesPageProc( HWND hwnd,
UINT uMsg,
LPPROPSHEETPAGE ppsp );
INT_PTR CALLBACK TCPIP_PropertiesDlgProc( IN HWND hwnd,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam );
static PROPSHEETHEADER pshead;
static PROPSHEETPAGE pspage;
static const TCHAR Period = _T('.');
//----------------------------------------------------------------------------
//
// Function: ValidatePage
//
// Purpose: tests to see if the contents of the TCP/IP page are valid ( to
// see if it is safe to move off this page )
//
// Arguments: IN HWND hwnd - handle to the dialog
//
// Returns: BOOL - TRUE if all fields are valid
// False if some are not valid
//
//----------------------------------------------------------------------------
BOOL
ValidatePage( IN HWND hwnd )
{
INT_PTR iNumBlankFields;
DWORD dwIpValue;
//
// If using DHCP, then no need to check any of the settings
//
if( IsDlgButtonChecked( hwnd, IDC_IP_DHCP ) )
{
return( TRUE );
}
else
{
//
// Check that the IP and Subnet mask fields are completely
// filled-out. I only check these 2 fields because that is all the
// system checks to get off this dialog.
//
iNumBlankFields = 4 - SendDlgItemMessage( hwnd,
IDC_IPADDR_IP,
IPM_GETADDRESS,
(WPARAM) 0,
(LPARAM) &dwIpValue );
if( iNumBlankFields > 0 )
{
ReportErrorId( hwnd,
MSGTYPE_ERR,
IDS_ERROR_NEED_IP_ADDRESS );
return( FALSE );
}
iNumBlankFields = 4 - SendDlgItemMessage( hwnd,
IDC_IPADDR_SUB,
IPM_GETADDRESS,
(WPARAM) 0,
(LPARAM) &dwIpValue );
if( iNumBlankFields > 0 )
{
ReportErrorId( hwnd,
MSGTYPE_ERR,
IDS_ERROR_NEED_SUB_ADDRESS );
return( FALSE );
}
}
return( TRUE );
}
//----------------------------------------------------------------------------
//
// Function: StoreIPSettings
//
// Purpose: takes the values currently in the IP edit boxes and stores them
// into the NetSettings global variable
//
// Arguments: IN HWND hwnd - handle to the dialog
//
// Returns: BOOL - TRUE if all the IP address are valid and they get stored
// FALSE if there was an error
//
//----------------------------------------------------------------------------
BOOL
StoreIPSettings( IN HWND hwnd )
{
INT_PTR iIsBlank;
INT iFoundStatus;
if( IsDlgButtonChecked( hwnd, IDC_IP_DHCP ) == BST_CHECKED )
{
NetSettings.pCurrentAdapter->bObtainIPAddressAutomatically = TRUE;
}
else
{
TCHAR szIpBuffer[IPSTRINGLENGTH + 1];
HWND hIPEditBox = GetDlgItem( hwnd, IDC_IPADDR_IP );
HWND hSubnetEditBox = GetDlgItem( hwnd, IDC_IPADDR_SUB );
HWND hGatewayEditBox = GetDlgItem( hwnd, IDC_IPADDR_GATE );
NetSettings.pCurrentAdapter->bObtainIPAddressAutomatically = FALSE;
//
// Only store the data if the IP isn't blank
// - if it's not blank then grab it and store it in a buffer
// - if the IP is not already in the list then add it to the front
// - if it is already in the list, remove it and add it to the front
//
iIsBlank = SendMessage( hIPEditBox, IPM_ISBLANK, 0, 0 );
if( ! iIsBlank )
{
GetWindowText( hIPEditBox,
szIpBuffer,
IPSTRINGLENGTH + 1 ); // +1 for null character
iFoundStatus = FindNameInNameList( &NetSettings.pCurrentAdapter->Tcpip_IpAddresses,
szIpBuffer );
if( iFoundStatus != NOT_FOUND )
{
RemoveNameFromNameListIdx( &NetSettings.pCurrentAdapter->Tcpip_IpAddresses,
iFoundStatus );
RemoveNameFromNameListIdx( &NetSettings.pCurrentAdapter->Tcpip_SubnetMaskAddresses,
iFoundStatus );
}
AddNameToNameListIdx( &NetSettings.pCurrentAdapter->Tcpip_IpAddresses,
szIpBuffer,
0 );
}
iIsBlank = SendMessage( hSubnetEditBox, IPM_ISBLANK, 0, 0 );
if( ! iIsBlank )
{
GetWindowText( hSubnetEditBox,
szIpBuffer,
IPSTRINGLENGTH + 1 ); // +1 for null character
AddNameToNameListIdx( &NetSettings.pCurrentAdapter->Tcpip_SubnetMaskAddresses,
szIpBuffer,
0 );
}
iIsBlank = SendMessage( hGatewayEditBox, IPM_ISBLANK, 0, 0 );
if( ! iIsBlank )
{
GetWindowText( hGatewayEditBox,
szIpBuffer,
IPSTRINGLENGTH + 1 ); // +1 for null character
iFoundStatus = FindNameInNameList( &NetSettings.pCurrentAdapter->Tcpip_GatewayAddresses,
szIpBuffer );
if( iFoundStatus != NOT_FOUND )
{
RemoveNameFromNameListIdx( &NetSettings.pCurrentAdapter->Tcpip_GatewayAddresses,
iFoundStatus );
}
AddNameToNameListIdx( &NetSettings.pCurrentAdapter->Tcpip_GatewayAddresses,
szIpBuffer,
0 );
}
}
if( IsDlgButtonChecked(hwnd, IDC_DNS_DHCP) == BST_CHECKED )
{
NetSettings.bObtainDNSServerAutomatically = TRUE;
}
else
{
TCHAR szDnsBuffer[IPSTRINGLENGTH + 1];
HWND hPrimaryDNSEditBox = GetDlgItem( hwnd, IDC_DNS_PRIMARY );
HWND hSecondaryDNSEditBox = GetDlgItem( hwnd, IDC_DNS_SECONDARY );
NetSettings.bObtainDNSServerAutomatically = FALSE;
//
// Only store the data if the IP isn't blank
//
iIsBlank = SendMessage( hSecondaryDNSEditBox, IPM_ISBLANK, 0, 0 );
if( ! iIsBlank )
{
GetWindowText( hSecondaryDNSEditBox,
szDnsBuffer,
IPSTRINGLENGTH + 1 ); // +1 for null character
TcpipNameListInsertIdx( &NetSettings.pCurrentAdapter->Tcpip_DnsAddresses,
szDnsBuffer,
0 );
}
iIsBlank = SendMessage( hPrimaryDNSEditBox, IPM_ISBLANK, 0, 0 );
if( ! iIsBlank )
{
GetWindowText( hPrimaryDNSEditBox,
szDnsBuffer,
IPSTRINGLENGTH + 1 ); // +1 for null character
TcpipNameListInsertIdx( &NetSettings.pCurrentAdapter->Tcpip_DnsAddresses,
szDnsBuffer,
0 );
}
}
return( TRUE );
}
//----------------------------------------------------------------------------
//
// Function: EnableIPAddressControls
//
// Purpose: Greys or ungreys the IP Address text and edit boxes
//
// Arguments: IN HWND hwnd - handle to the dialog
// IN BOOL bVisible - TRUE to enable the IP address controls
// FALSE to grey them
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID
EnableIPAddressControls( IN HWND hwnd, IN BOOL bVisible )
{
EnableWindow( GetDlgItem( hwnd, IDC_IPADDR_IPTEXT ),
bVisible );
EnableWindow( GetDlgItem( hwnd, IDC_IPADDR_SUBTEXT ),
bVisible );
EnableWindow( GetDlgItem( hwnd, IDC_IPADDR_GATETEXT ),
bVisible );
EnableWindow( GetDlgItem( hwnd, IDC_IPADDR_IP ),
bVisible );
EnableWindow( GetDlgItem( hwnd, IDC_IPADDR_SUB ),
bVisible );
EnableWindow( GetDlgItem( hwnd, IDC_IPADDR_GATE ),
bVisible );
}
//----------------------------------------------------------------------------
//
// Function: EnableServerAddressControls
//
// Purpose: Greys or ungreys the Server Address text and edit boxes
//
// Arguments: IN HWND hwnd - handle to the dialog
// IN BOOL bVisible - TRUE to enable the Server address controls
// FALSE to grey them
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID
EnableServerAddressControls( IN HWND hwnd, IN BOOL bVisible )
{
EnableWindow( GetDlgItem( hwnd, IDC_DNS_PRIMARY_TEXT ),
bVisible );
EnableWindow( GetDlgItem( hwnd, IDC_DNS_SECONDARY_TEXT ),
bVisible );
EnableWindow( GetDlgItem( hwnd, IDC_DNS_PRIMARY ),
bVisible );
EnableWindow( GetDlgItem( hwnd, IDC_DNS_SECONDARY ),
bVisible );
}
//----------------------------------------------------------------------------
//
// Function: SetTCPIPControls
//
// Purpose: uses settings in global variable NetSettings to set the TCP/IP
// window states appropriately and fill the edit boxes with data
// where appropriate
//
// Arguments: IN HWND hwnd - handle to the dialog
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID
SetTCPIPControls( IN HWND hwnd )
{
//
// Set the button and window states for IP
//
if( NetSettings.pCurrentAdapter->bObtainIPAddressAutomatically )
{
CheckRadioButton( hwnd, IDC_IP_DHCP, IDC_IP_FIXED, IDC_IP_DHCP );
//
// Gray out the IP address strings and boxes
//
EnableIPAddressControls( hwnd, FALSE );
}
else
{
CheckRadioButton( hwnd, IDC_IP_DHCP, IDC_IP_FIXED, IDC_IP_FIXED );
//
// Fill in the IP, Subnet Mask and Gateway data
//
SetWindowText( GetDlgItem( hwnd, IDC_IPADDR_IP ),
GetNameListName( &NetSettings.pCurrentAdapter->Tcpip_IpAddresses, 0 ) );
SetWindowText( GetDlgItem( hwnd, IDC_IPADDR_SUB ),
GetNameListName( &NetSettings.pCurrentAdapter->Tcpip_SubnetMaskAddresses, 0 ) );
SetWindowText( GetDlgItem( hwnd, IDC_IPADDR_GATE ),
GetNameListName( &NetSettings.pCurrentAdapter->Tcpip_GatewayAddresses, 0 ) );
}
//
// Set the button and window states for DNS
//
if( NetSettings.bObtainDNSServerAutomatically )
{
CheckRadioButton( hwnd, IDC_DNS_DHCP, IDC_DNS_FIXED, IDC_DNS_DHCP );
//
// Gray out the IP address strings and boxes
//
EnableServerAddressControls( hwnd, FALSE );
}
else
{
TCHAR *szDns;
CheckRadioButton( hwnd, IDC_DNS_DHCP, IDC_DNS_FIXED, IDC_DNS_FIXED );
//
// Ensure the controls are visible and fill in the strings for
// Primary and Secondary DNS
//
EnableServerAddressControls( hwnd, TRUE );
szDns = GetNameListName( &NetSettings.pCurrentAdapter->Tcpip_DnsAddresses,
0 );
SetWindowText( GetDlgItem( hwnd, IDC_DNS_PRIMARY ), szDns );
szDns = GetNameListName( &NetSettings.pCurrentAdapter->Tcpip_DnsAddresses,
1 );
SetWindowText( GetDlgItem( hwnd, IDC_DNS_SECONDARY ), szDns );
}
}
//----------------------------------------------------------------------------
//
// Function: OnAdvancedClicked
//
// Purpose: Creates the Advanced TCP/IP property sheet for the user to specify
// additional TCP/IP settings.
//
// Arguments: standard Win32 dialog proc arguments passed through from the
// dialog proc
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID
OnAdvancedClicked( IN HWND hwnd,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam )
{
HWND hGatewayEditBox = GetDlgItem( hwnd, IDC_IPADDR_GATE );
//
// store the IP settings in the NetSettings global variable so the
// advanced pages can access data in it
//
StoreIPSettings( hwnd );
Create_TCPIPProp_PropertySheet( hwnd );
//
// Fill boxes with (potentially) new data from the TCP/IP Advanced screens
//
SetTCPIPControls( hwnd );
//
// always set the gateway because a user can still set this even if they
// have DHCP enabled
//
SetWindowText( hGatewayEditBox,
GetNameListName( &NetSettings.pCurrentAdapter->Tcpip_GatewayAddresses, 0 ) );
}
//----------------------------------------------------------------------------
//
// Function: OnDNSRadioButtonsClicked
//
// Purpose: Grey/Ungrey the DNS controls appropriately and clear DNS entries,
// as necessary.
//
// Arguments: standard Win32 dialog proc arguments passed through from the
// dialog proc
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID
OnDNSRadioButtonsClicked( IN HWND hwnd,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam )
{
INT nButtonId = LOWORD( wParam );
if ( HIWORD( wParam ) == BN_CLICKED )
{
CheckRadioButton( hwnd, IDC_DNS_DHCP, IDC_DNS_FIXED, nButtonId );
if( nButtonId == IDC_DNS_FIXED )
{
//
// User clicked the radio button to have fixed DNS servers so
// Un-grey the DNS strings and boxes so the user can
// edit them
//
EnableServerAddressControls( hwnd, TRUE );
}
else
{
//
// User clicked the radio button to have assigned DNS servers so
// Grey the DNS strings and boxes so the user can not
// edit them
//
EnableServerAddressControls( hwnd, FALSE );
//
// clear the DNS Address list
//
ResetNameList( &NetSettings.pCurrentAdapter->Tcpip_DnsAddresses );
//
// clear the contents of the Primary and Secondary edit boxes
//
SetWindowText( GetDlgItem( hwnd, IDC_DNS_PRIMARY ), _T("") );
SetWindowText( GetDlgItem( hwnd, IDC_DNS_SECONDARY ), _T("") );
}
}
}
//----------------------------------------------------------------------------
//
// Function: OnIPRadioButtonsClicked
//
// Purpose: Grey/Ungrey the IP controls appropriately and clear the IP data
// structures, as necessary.
//
// Arguments: standard Win32 dialog proc arguments passed through from the
// dialog proc
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID
OnIPRadioButtonsClicked( IN HWND hwnd,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam )
{
INT nButtonId = LOWORD(wParam);
if ( HIWORD(wParam) == BN_CLICKED )
{
CheckRadioButton( hwnd,
IDC_IP_DHCP,
IDC_IP_FIXED,
nButtonId );
if ( nButtonId == IDC_IP_FIXED )
{
//
// User chose the radio button to specify and IP, Subnet Mask
// and Gateway
//
// Un-grey the IP address strings and boxes
// so the user can specify them
//
EnableIPAddressControls( hwnd, TRUE );
//
// If the user is going to specify their IP addresses then
// they must specify their DNS server addresses so force
// the manual radio box to be checked and un-grey the boxes
//
CheckRadioButton( hwnd,
IDC_DNS_DHCP,
IDC_DNS_FIXED,
IDC_DNS_FIXED );
EnableServerAddressControls( hwnd, TRUE );
//
// clear the list to avoid the string "DHCP enabled" from being
// placed in the IP edit box
//
ResetNameList( &NetSettings.pCurrentAdapter->Tcpip_IpAddresses );
//
// Don't allow user to click the 'obtain DNS server automatically'
//
EnableWindow( GetDlgItem( hwnd, IDC_DNS_DHCP ),
FALSE );
}
else
{
//
// User to chose DHCP (have an IP assigned automatically)
//
// Grey out the IP address strings and boxes because they are
// using DHCP
//
EnableIPAddressControls( hwnd, FALSE );
//
// clear the contents of the IP, Subnet and Gateway edit boxes
// because using DHCP
//
SetWindowText( GetDlgItem( hwnd, IDC_IPADDR_IP ), _T("") );
SetWindowText( GetDlgItem( hwnd, IDC_IPADDR_SUB ), _T("") );
SetWindowText( GetDlgItem( hwnd, IDC_IPADDR_GATE ), _T("") );
//
// Clear the lists that contain the IP, Subnet and
// Gateway data
//
ResetNameList( &NetSettings.pCurrentAdapter->Tcpip_IpAddresses );
ResetNameList( &NetSettings.pCurrentAdapter->Tcpip_SubnetMaskAddresses );
ResetNameList( &NetSettings.pCurrentAdapter->Tcpip_GatewayAddresses );
//
// Allow the user to be able to select 'obtain DNS server
// automatically'
//
EnableWindow( GetDlgItem( hwnd, IDC_DNS_DHCP ), TRUE );
}
}
}
//----------------------------------------------------------------------------
//
// Function: OnTcpipInitDialog
//
// Purpose: Sets the text limits on the edit boxes and fills in initial data
// and greys controls appropriately.
//
// Arguments: IN HWND hwnd - handle to the dialog box
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID
OnTcpipInitDialog( IN HWND hwnd )
{
//
// Set the text limit on the edit boxes to IPSTRINGLENGTH
//
SendDlgItemMessage( hwnd,
IDC_IPADDR_IP,
EM_LIMITTEXT,
(WPARAM) IPSTRINGLENGTH,
(LPARAM) 0 );
SendDlgItemMessage( hwnd,
IDC_IPADDR_SUB,
EM_LIMITTEXT,
(WPARAM) IPSTRINGLENGTH,
(LPARAM) 0 );
SendDlgItemMessage( hwnd,
IDC_IPADDR_GATE,
EM_LIMITTEXT,
(WPARAM) IPSTRINGLENGTH,
(LPARAM) 0 );
SendDlgItemMessage( hwnd,
IDC_DNS_PRIMARY,
EM_LIMITTEXT,
(WPARAM) IPSTRINGLENGTH,
(LPARAM) 0 );
SendDlgItemMessage( hwnd,
IDC_DNS_SECONDARY,
EM_LIMITTEXT,
(WPARAM) IPSTRINGLENGTH,
(LPARAM) 0 );
SetTCPIPControls( hwnd );
}
//----------------------------------------------------------------------------
//
// Function: TCPIP_PropertiesDlgProc
//
// Purpose:
//
// Arguments: standard Win32 dialog proc arguments
//
// Returns:
//
//----------------------------------------------------------------------------
INT_PTR CALLBACK
TCPIP_PropertiesDlgProc( IN HWND hwnd,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam )
{
BOOL bStatus = TRUE;
switch( uMsg )
{
case WM_INITDIALOG:
OnTcpipInitDialog( hwnd );
break;
case WM_NOTIFY:
{
LPNMHDR pnmh = (LPNMHDR) lParam;
switch( pnmh->code )
{
case PSN_APPLY:
{
//
// store the IP settings in the NetSettings global variable
//
if( ValidatePage( hwnd ) )
{
StoreIPSettings( hwnd );
}
else
{
//
// if the validation fails then stay on this page
//
SetWindowLongPtr( hwnd, DWLP_MSGRESULT, -1 );
return( PSNRET_INVALID_NOCHANGEPAGE );
}
}
}
} // end case WM_NOTIFY
case WM_COMMAND:
{
int nButtonId;
switch ( nButtonId = LOWORD(wParam) )
{
case IDC_IP_DHCP:
case IDC_IP_FIXED:
OnIPRadioButtonsClicked( hwnd,
uMsg,
wParam,
lParam );
break;
case IDC_DNS_DHCP:
case IDC_DNS_FIXED:
OnDNSRadioButtonsClicked( hwnd,
uMsg,
wParam,
lParam );
break;
case IDC_IPADDR_ADVANCED:
{
OnAdvancedClicked( hwnd,
uMsg,
wParam,
lParam );
break;
}
default:
bStatus = FALSE;
break;
}
break;
}
default:
bStatus = FALSE;
break;
}
return( bStatus );
}
//----------------------------------------------------------------------------
//
// Function: TCPIP_PropertySheetProc
//
// Purpose: Standard Property Sheet dialog proc. Very boring.
//
//----------------------------------------------------------------------------
int CALLBACK
TCPIP_PropertySheetProc( HWND hwndDlg, UINT uMsg, LPARAM lParam )
{
switch( uMsg ) {
case PSCB_INITIALIZED :
// Process PSCB_INITIALIZED
break;
case PSCB_PRECREATE :
// Process PSCB_PRECREATE
break;
default :
// Unknown message
break;
}
return( 0 );
}
//----------------------------------------------------------------------------
//
// Function: TCPIP_PropertiesPageProc
//
// Purpose: Standard Property Page dialog proc.
//
//----------------------------------------------------------------------------
UINT CALLBACK
TCPIP_PropertiesPageProc( HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp )
{
switch( uMsg ) {
case PSPCB_CREATE :
return( TRUE );
case PSPCB_RELEASE :
return( 0 );
}
return( 0 );
}
//----------------------------------------------------------------------------
//
// Function: Create_TCPIP_PropertySheet
//
// Purpose: Sets up settings for the property sheet and the TCP/IP page (in
// this case the property sheet is just 1 page). Lastly, calls the
// PropertySheet function to display the property sheet, the return
// value of this function is what is passed back as the return value
//
// Arguments: IN HWND hwndParent - handle to the dialog that is spawning the
// property sheet
//
// Returns: BOOL - the returned value from the Property Sheet
//
//----------------------------------------------------------------------------
BOOL
Create_TCPIP_PropertySheet( IN HWND hwndParent )
{
INT i;
// Initialize property sheet HEADER data
ZeroMemory (&pshead, sizeof (PROPSHEETHEADER)) ;
pshead.dwSize = sizeof (PROPSHEETHEADER) ;
pshead.dwFlags = PSH_PROPSHEETPAGE |
PSH_USECALLBACK |
PSH_USEHICON |
PSH_NOAPPLYNOW;
pshead.hwndParent = hwndParent ;
pshead.hInstance = FixedGlobals.hInstance;
pshead.pszCaption = g_StrTcpipTitle;
pshead.nPages = 1 ;
pshead.nStartPage = 0 ;
pshead.ppsp = &pspage ;
pshead.pfnCallback = TCPIP_PropertySheetProc ;
// Zero out property PAGE data
ZeroMemory (&pspage, 1 * sizeof (PROPSHEETPAGE)) ;
pspage.dwSize = sizeof (PROPSHEETPAGE) ;
pspage.dwFlags = PSP_USECALLBACK ;
pspage.hInstance = FixedGlobals.hInstance;
pspage.pszTemplate = MAKEINTRESOURCE(IDD_TCP_IPADDR) ;
pspage.pfnDlgProc = TCPIP_PropertiesDlgProc ;
pspage.pfnCallback = TCPIP_PropertiesPageProc ;
// --------- Create & display property sheet ---------
return( PropertySheet( &pshead ) ? TRUE : FALSE);
}