//----------------------------------------------------------------------------
//
// Copyright (c) 1997-1999  Microsoft Corporation
// All rights reserved.
//
// File Name:
//      numcards.c
//
// Description:  
//      This file contains the dialog procedure for the number of network
//      cards page (IDD_NUMBERNETCARDS).
//
//----------------------------------------------------------------------------

#include "pch.h"
#include "resource.h"

#define NET_SPIN_CONTROL_MIN 2
#define NET_SPIN_CONTROL_MAX 20


//----------------------------------------------------------------------------
//
// Function: DeleteList
//
// Purpose: 
//
// Arguments: 
//
// Returns:  
//
//----------------------------------------------------------------------------
VOID
DeleteList( IN OUT NETWORK_ADAPTER_NODE *pNetworkAdapterList ) {

    NETWORK_ADAPTER_NODE *head;

    head = pNetworkAdapterList;

    while( head != NULL ) {

        pNetworkAdapterList = pNetworkAdapterList->next;

        free( head );

        head = pNetworkAdapterList;

    }

    pNetworkAdapterList = NULL;

}

//----------------------------------------------------------------------------
//
// Function: InstallDefaultNetComponents
//
// Purpose:  Marks these three network components as installed and all other
//           network components as NOT installed
//               1. Client for MS networks
//               2. File and Print Sharing
//               3. TCP/IP protocol
//
// Arguments: VOID
//
// Returns:  VOID
//
//----------------------------------------------------------------------------
VOID
InstallDefaultNetComponents( VOID ) {

    NETWORK_COMPONENT *pNetComponent;

    for( pNetComponent = NetSettings.NetComponentsList;
         pNetComponent;
         pNetComponent = pNetComponent->next )
    {

        if( pNetComponent->iPosition == MS_CLIENT_POSITION ||
            pNetComponent->iPosition == FILE_AND_PRINT_SHARING_POSITION  ||
            pNetComponent->iPosition == TCPIP_POSITION )
        {
            pNetComponent->bInstalled = TRUE;
        }
        else
        {
            pNetComponent->bInstalled = FALSE;
        }

    }

}

//----------------------------------------------------------------------------
//
// Function: ResetNetworkAdapter
//
// Purpose:  Sets all network card (specified by the formal argument) settings
//           to their default values
//
// Arguments: 
//
// Returns:  
//
//----------------------------------------------------------------------------
VOID 
ResetNetworkAdapter( OUT NETWORK_ADAPTER_NODE *pNetworkCard )
{

    // ISSUE-2002/02/28-stelo- make sure every network card var is reset here
    if( pNetworkCard != NULL ) {

        pNetworkCard->next = NULL;
        pNetworkCard->previous = NULL;

        pNetworkCard->szPlugAndPlayID[0] = _T('\0');

        pNetworkCard->bObtainIPAddressAutomatically = TRUE;

        pNetworkCard->szDNSDomainName[0] = _T('\0');

        // initialize NetBIOS to "Use value generated by DHCP" option
        pNetworkCard->iNetBiosOption = 0;      

        ResetNameList( &pNetworkCard->Tcpip_IpAddresses );
        ResetNameList( &pNetworkCard->Tcpip_SubnetMaskAddresses );
        ResetNameList( &pNetworkCard->Tcpip_GatewayAddresses );
        ResetNameList( &pNetworkCard->Tcpip_DnsAddresses );
        ResetNameList( &pNetworkCard->Tcpip_WinsAddresses );

        lstrcpyn( pNetworkCard->szFrameType, _T("0xFF"), AS(pNetworkCard->szFrameType) );
        lstrcpyn( pNetworkCard->szNetworkNumber, _T("00000000"), AS(pNetworkCard->szNetworkNumber) );

    }

}

//----------------------------------------------------------------------------
//
// Function: CreateListWithDefaults
//
// Purpose:  
//
// Arguments: 
//
// Returns:  
//
//----------------------------------------------------------------------------
VOID
CreateListWithDefaults( OUT NETWORK_ADAPTER_NODE *pNetworkAdapter )
{

    NETWORK_COMPONENT *pNetComponent;

    //
    //  Initialize all the namelists to 0s
    //
    ZeroOut( pNetworkAdapter );

    ResetNetworkAdapter( pNetworkAdapter );

    //
    //  Initialize the entire list to be NOT installed
    //
    for( pNetComponent = NetSettings.NetComponentsList;
         pNetComponent;
         pNetComponent = pNetComponent->next )
    {

        pNetComponent->bInstalled = FALSE;

    }

}


//----------------------------------------------------------------------------
//
// Function: ZeroOut
//
// Purpose:  fill the namelists with zero's
//           this is necessary to do on namelists before they are used
//
// Arguments: OUT NETWORK_ADAPTER_NODE *pNetworkNode - the node that contains
//     the namelists to be Zeroed
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID 
ZeroOut( OUT NETWORK_ADAPTER_NODE *pNetworkNode) {

    ZeroMemory( &pNetworkNode->Tcpip_IpAddresses,
                sizeof( NAMELIST ) );

    ZeroMemory( &pNetworkNode->Tcpip_SubnetMaskAddresses,
                sizeof( NAMELIST ) );

    ZeroMemory( &pNetworkNode->Tcpip_GatewayAddresses,
                sizeof( NAMELIST ) );

    ZeroMemory( &pNetworkNode->Tcpip_DnsAddresses,
                sizeof( NAMELIST ) );

    ZeroMemory( &pNetworkNode->Tcpip_WinsAddresses,
                sizeof( NAMELIST ) );

}

//----------------------------------------------------------------------------
//
// Function: AddNewNetworkAdapterNode
//
// Purpose:  Adds a new Network Adapter Node (initialized to its default values)
//           onto the list given as the input arg
//
//           This function only adds to the end of a list.  If you do not pass
//           it the end of the list, the result is undefined.
//
// Arguments: IN OUT NETWORK_ADAPTER_NODE *pCurrentAdapter - node to add the
//                   new node to
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID
AddNewNetworkAdapterNode( IN OUT NETWORK_ADAPTER_NODE *pCurrentAdapter ) {

    pCurrentAdapter->next = malloc( sizeof( NETWORK_ADAPTER_NODE ) );
    if (pCurrentAdapter->next == NULL)
    {
        TerminateTheWizard(IDS_ERROR_OUTOFMEMORY);
    }
    CreateListWithDefaults( pCurrentAdapter->next );

    InstallDefaultNetComponents();

    pCurrentAdapter->next->next = NULL;
    pCurrentAdapter->next->previous = pCurrentAdapter;

}

//----------------------------------------------------------------------------
//
// Function: AdjustNetworkCardMemory
//
// Purpose: examines the Global list NetSettings.NetworkCardList
//          if more network cards are necessary, it allocates more lists
//          if fewer network cards are necessary, it deallocates the 
//            appropriate number of lists
//          if they are equal, then do nothing
//          Therefore, when the function returns, the length of 
//          NetSettings.NetworkCardList is equal to the new number of
//          network cards
//
// Arguments: IN int NewNumberOfNetworkCards - 
//            IN int OldNumberOfNetworkCards - 
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID
AdjustNetworkCardMemory( IN int NewNumberOfNetworkCards,
                         IN int OldNumberOfNetworkCards ) {

    INT i;

    NetSettings.pCurrentAdapter = NetSettings.NetworkAdapterHead;

    if( NewNumberOfNetworkCards > OldNumberOfNetworkCards ) {

        //
        //  NewNumberOfNetworkCards-1, the -1 because there is always
        //  at least 1 network adapter list
        //
        for( i = 0; i < NewNumberOfNetworkCards-1; i++ ) {

            //
            //  Allocate more lists, if necessary
            //

            if( NetSettings.pCurrentAdapter->next == NULL ) {

                AddNewNetworkAdapterNode( NetSettings.pCurrentAdapter );

            }

            //
            //  Advance to the next node
            //

            NetSettings.pCurrentAdapter = NetSettings.pCurrentAdapter->next;

        }

    }
    else if( NewNumberOfNetworkCards < OldNumberOfNetworkCards ) {

        NETWORK_ADAPTER_NODE* pTempNode;  // used to hold the current position
        NETWORK_ADAPTER_NODE* pTempNode2; // used delete the list

        //
        //  Advance to the last network list we are keeping and delete all 
        //  the ones after that
        //
        for( i = 0;
             i < (NewNumberOfNetworkCards - 1);
             i++ ) {

            NetSettings.pCurrentAdapter = NetSettings.pCurrentAdapter->next;

        }

        //
        //  save the pointer to the rest of the list
        //

        pTempNode = NetSettings.pCurrentAdapter->next;
            
        NetSettings.pCurrentAdapter->next = NULL;
            
        for( ;
             i < NewNumberOfNetworkCards;
             i++ ) {


             pTempNode2 = pTempNode;

             pTempNode = pTempNode->next;

             //
             // deallocate the rest of the list
             //

             DeleteList( pTempNode2 );

        }

    }

    //
    //  Reset NetSettings.pCurrentNetworkList to the first node in the list
    //

    NetSettings.pCurrentAdapter = NetSettings.NetworkAdapterHead;

}

//----------------------------------------------------------------------------
//
// Function: EnableNetCardControls
//
// Purpose:  Greys or ungreys the 3 controls that let the user change the
//           number of network cards installed
//
// Arguments: 
//
// Returns: VOID
//
//----------------------------------------------------------------------------
VOID 
EnableNetCardControls( IN HWND hwnd, IN BOOL bState ) {

    //
    //  Grab handles to each of the controls
    //
    HWND hHowManyText  = GetDlgItem( hwnd, IDC_HOWMANY_STATIC );
    HWND hCountEditBox = GetDlgItem( hwnd, IDC_NUM_CONNECT );
    HWND hSpinControl  = GetDlgItem( hwnd, IDC_NUMBERNETADAPTERS_SPIN );

    //
    //  Grey or ungrey them appropriately
    //
    EnableWindow( hHowManyText, bState );
    EnableWindow( hCountEditBox, bState );
    EnableWindow( hSpinControl, bState );

    //
    //  Set the initial value of the spin control
    //
    if( bState && NetSettings.iNumberOfNetworkCards > 1 ) {
        TCHAR szNumberOfNetCards[3];

        _itow( NetSettings.iNumberOfNetworkCards, szNumberOfNetCards, 10 );

        SetWindowText( hCountEditBox, szNumberOfNetCards );

    }

}

//----------------------------------------------------------------------------
//
// Function: OnNumCardsInitDialog
//
// Purpose: 
//
// Arguments: IN HWND hwnd - handle to the dialog
//
// Returns:  VOID
//
//----------------------------------------------------------------------------
VOID 
OnNumCardsInitDialog( IN HWND hwnd ) {

    //
    //  Set the range on the spin control: NET_SPIN_CONTROL_MIN to
    //  NET_SPIN_CONTROL_MAX
    //

    SendDlgItemMessage( hwnd,
                        IDC_NUMBERNETADAPTERS_SPIN,
                        UDM_SETRANGE32,
                        NET_SPIN_CONTROL_MIN,
                        NET_SPIN_CONTROL_MAX );

    //
    //  Set the default value for the spin control
    //

    SendDlgItemMessage( hwnd,
                        IDC_NUMBERNETADAPTERS_SPIN,
                        UDM_SETPOS,
                        0,
                        NET_SPIN_CONTROL_MIN );

}

//----------------------------------------------------------------------------
//
// Function: OnNumberNetCardsSetActive
//
// Purpose: 
//
// Arguments: IN HWND hwnd - handle to the dialog
//
// Returns:  VOID
//
//----------------------------------------------------------------------------
VOID
OnNumberNetCardsSetActive( IN HWND hwnd ) {

    if( NetSettings.iNumberOfNetworkCards < 2 ) {
        //
        //  One network adapter radio button chosen
        //
        CheckRadioButton( hwnd,
                          IDC_ONENETWORKADAPTER,
                          IDC_MULTIPLENETWORKADPTERS,
                          IDC_ONENETWORKADAPTER );

        //
        //  The controls under the multiple adapters greyed-out
        //
        EnableNetCardControls( hwnd, FALSE );

    }
    else {
        //
        //  We are in the multiple adapter case
        //

        //
        //  Multiple network adapter radio button chosen
        //
        CheckRadioButton( hwnd,
                          IDC_ONENETWORKADAPTER,
                          IDC_MULTIPLENETWORKADPTERS,
                          IDC_MULTIPLENETWORKADPTERS );

        //
        //  The controls under the multiple adapters enabled
        //
        EnableNetCardControls( hwnd, TRUE );

    }

    PropSheet_SetWizButtons( GetParent(hwnd), PSWIZB_BACK | PSWIZB_NEXT );

}

//----------------------------------------------------------------------------
//
// Function: OnWizNextNumCards
//
// Purpose: 
//
// Arguments: IN HWND hwnd - handle to the dialog
//
// Returns:  VOID
//
//----------------------------------------------------------------------------
VOID 
OnWizNextNumCards( IN HWND hwnd ) {

    if( IsDlgButtonChecked( hwnd, IDC_ONENETWORKADAPTER ) == BST_CHECKED ) {
        //
        //  Single network adapter case
        //

        NetSettings.iNumberOfNetworkCards = 1;

    }
    else {

        //
        //  Multiple network adapter case
        //
 
        TCHAR szNumber[3];
        INT NewNumberOfNetworkCards;

        //
        //  Convert the string number to an int
        //
        GetWindowText( GetDlgItem( hwnd, IDC_NUM_CONNECT ), szNumber, 3 );
                            
        NewNumberOfNetworkCards = _ttoi( szNumber );

        //
        //  Ensure the number of network cards stays within its appropriate
        //  range
        //
        if( NewNumberOfNetworkCards < NET_SPIN_CONTROL_MIN ) {

            NewNumberOfNetworkCards = NET_SPIN_CONTROL_MIN;

        }
        else if( NewNumberOfNetworkCards > NET_SPIN_CONTROL_MAX ) {

            NewNumberOfNetworkCards = NET_SPIN_CONTROL_MAX;

        }

        //
        //  Adjust memory for the network lists accordingly
        //
        AdjustNetworkCardMemory( NewNumberOfNetworkCards,
                                 NetSettings.iNumberOfNetworkCards );

        NetSettings.iNumberOfNetworkCards = NewNumberOfNetworkCards;

    }

}

//----------------------------------------------------------------------------
//
// Function: DlgNumberNetCardsPage
//
// Purpose: 
//
// Arguments: standard Win32 dialog proc arguments
//
// Returns:  standard Win32 dialog proc return value
//
//----------------------------------------------------------------------------
INT_PTR CALLBACK DlgNumberNetCardsPage( IN HWND     hwnd,    
                                    IN UINT     uMsg,        
                                    IN WPARAM   wParam,    
                                    IN LPARAM   lParam) {   

    BOOL bStatus = TRUE;

    switch( uMsg ) {

        case WM_INITDIALOG: {

            OnNumCardsInitDialog( hwnd );

            break;

        }

        case WM_COMMAND: {
            switch ( LOWORD(wParam) ) {

                case IDC_ONENETWORKADAPTER:

                    if ( HIWORD(wParam) == BN_CLICKED ) {

                        EnableNetCardControls( hwnd, FALSE );

                    }

                    break;
                
                case IDC_MULTIPLENETWORKADPTERS:

                    if ( HIWORD(wParam) == BN_CLICKED ) {

                        EnableNetCardControls( hwnd, TRUE );

                    }

                    break;

            }
  
            break;

        }        

        case WM_NOTIFY: {

            LPNMHDR pnmh = (LPNMHDR)lParam;

            switch( pnmh->code ) {

                case PSN_QUERYCANCEL:

                    CancelTheWizard(hwnd); break;

                case PSN_SETACTIVE:

                    OnNumberNetCardsSetActive( hwnd );

                    break;

                case PSN_WIZBACK:

                    bStatus = FALSE; break;

                case PSN_WIZNEXT: 
                    
                    OnWizNextNumCards( hwnd );

                    break;

                default:

                    break;
            }


            break;
        }
            
        default: 
            bStatus = FALSE;
            break;

    }

    return bStatus;

}
