/* Copyright (c) 1995, Microsoft Corporation, all rights reserved
**
** devcfg.c
** Remote Access Common Dialog APIs
** Device configuration dialogs
**
** 10/20/95 Steve Cobb
*/

#include "rasdlgp.h"
#include "entry.h"


/*----------------------------------------------------------------------------
** Help maps
**----------------------------------------------------------------------------
*/

static DWORD g_adwIcHelp[] =
{
    CID_IC_ST_LineType,    HID_IC_LB_LineType,
    CID_IC_LB_LineType,    HID_IC_LB_LineType,
    CID_IC_CB_Fallback,    HID_IC_CB_Fallback,
    CID_IC_GB_DownLevel,   HID_IC_CB_DownLevel,
    CID_IC_CB_DownLevel,   HID_IC_CB_DownLevel,
    CID_IC_CB_Compression, HID_IC_CB_Compression,
    CID_IC_ST_Channels,    HID_IC_EB_Channels,
    CID_IC_EB_Channels,    HID_IC_EB_Channels,
    0, 0
};

static DWORD g_adwMcHelp[] =
{
    CID_MC_EB_ModemValue,     HID_MC_EB_ModemValue,
    CID_MC_ST_InitialBps,     HID_MC_LB_InitialBps,
    CID_MC_LB_InitialBps,     HID_MC_LB_InitialBps,
    CID_MC_GB_Features,       HID_MC_GB_Features,
    CID_MC_CB_FlowControl,    HID_MC_CB_FlowControl,
    CID_MC_CB_ErrorControl,   HID_MC_CB_ErrorControl,
    CID_MC_CB_Compression,    HID_MC_CB_Compression,
    CID_MC_CB_ManualDial,     HID_MC_CB_ManualDial,
    CID_MC_CB_DisableSpeaker, HID_MC_CB_DisableSpeaker,
    0, 0
};


/*----------------------------------------------------------------------------
** Local datatypes (alphabetically)
**----------------------------------------------------------------------------
*/

/* ISDN Configuration dialog argument block.
*/
#define ICARGS struct tagICARGS
ICARGS
{
    BOOL    fShowProprietary;
    PBLINK* pLink;
};


/* ISDN Configuration dialog context block.
*/
#define ICINFO struct tagICINFO
ICINFO
{
    /* Stub API arguments including shortcut to link associated with the
    ** entry.
    */
    ICARGS* pArgs;

    /* Handle of this dialog and some of it's controls.
    */
    HWND hwndDlg;
    HWND hwndLbLineType;
    HWND hwndCbFallback;
    HWND hwndCbProprietary;
    HWND hwndCbCompression;
    HWND hwndStChannels;
    HWND hwndEbChannels;
    HWND hwndUdChannels;
};


/* MXS Modem Configuration dialog context block.
*/
#define MCINFO struct tagMCINFO
MCINFO
{
    /* Stub API arguments.  Shortcut to link associated with the entry.
    */
    PBLINK* pLink;

    /* Handle of this dialog and some of it's controls.
    */
    HWND hwndDlg;
    HWND hwndEbModemValue;
    HWND hwndLbBps;
    HWND hwndCbHwFlow;
    HWND hwndCbEc;
    HWND hwndCbEcc;
    HWND hwndCbManualDial;
    HWND hwndCbDisableSpeaker;
};


/*----------------------------------------------------------------------------
** Local prototypes (alphabetically)
**----------------------------------------------------------------------------
*/

BOOL
IcCommand(
    IN HWND hwnd,
    IN WORD wNotification,
    IN WORD wId,
    IN HWND hwndCtrl );

BOOL CALLBACK
IcDlgProc(
    IN HWND   hwnd,
    IN UINT   unMsg,
    IN WPARAM wparam,
    IN LPARAM lparam );

BOOL
IcInit(
    IN HWND    hwndDlg,
    IN ICARGS* pArgs );

VOID
IcTerm(
    IN HWND hwndDlg );

BOOL
IsdnConfigureDlg(
    IN HWND    hwndOwner,
    IN PBLINK* pLink,
    IN BOOL    fShowProprietary );

BOOL
ModemConfigureDlg(
    IN HWND    hwndOwner,
    IN PBLINK* pLink );

BOOL CALLBACK
McDlgProc(
    IN HWND   hwnd,
    IN UINT   unMsg,
    IN WPARAM wparam,
    IN LPARAM lparam );

BOOL
McCommand(
    IN HWND hwnd,
    IN WORD wNotification,
    IN WORD wId,
    IN HWND hwndCtrl );

BOOL
McInit(
    IN HWND    hwndDlg,
    IN PBLINK* pLink );

VOID
McTerm(
    IN HWND hwndDlg );


/*----------------------------------------------------------------------------
** Device configuration dialog
**----------------------------------------------------------------------------
*/

BOOL
DeviceConfigureDlg(
    IN HWND    hwndOwner,
    IN PBLINK* pLink,
    IN BOOL    fSingleLink )

    /* Popup a dialog to edit the device 'PLink'.  'HwndOwner' is the owner of
    ** the dialog.  'FSingleLink' is true if 'pLink' is a single link entry's
    ** link and false if multi-link.
    **
    ** Returns true if user pressed OK and succeeded, false if user pressed
    ** Cancel or encountered an error.
    */
{
    DWORD dwErr;

    switch (pLink->pbport.pbdevicetype)
    {
        case PBDT_Isdn:
        {
            return IsdnConfigureDlg( hwndOwner, pLink, fSingleLink );
        }

        case PBDT_Modem:
            return ModemConfigureDlg( hwndOwner, pLink );

#if 0
        {
            DWORD dwId;

            if (pLink->pbport.fMxsModemPort)
                return ModemConfigureDlg( hwndOwner, pLink );

            dwId = DeviceIdFromDeviceName( pLink->pbport.pszDevice );

            if (dwId == 0xFFFFFFFE)
            {
                MsgDlg( hwndOwner, SID_ModemNotInstalled, NULL );
                return FALSE;
            }

            ASSERT(!pLink->pbport.fMxsModemPort);
            ASSERT(dwId!=0xFFFFFFFF);

            dwErr = TapiConfigureDlg( hwndOwner, dwId,
                        &pLink->pTapiBlob, &pLink->cbTapiBlob );
            if (dwErr != 0)
            {
                ErrorDlg( hwndOwner, SID_OP_LoadTapiInfo, dwErr, NULL );
                return FALSE;
            }
            return TRUE;
        }
#endif

        default:
            MsgDlg( hwndOwner, SID_NoConfigure, NULL );
            return FALSE;
    }
}


/*----------------------------------------------------------------------------
** ISDN configuration dialog
** Listed alphabetically following stub API and dialog proc
**----------------------------------------------------------------------------
*/

BOOL
IsdnConfigureDlg(
    IN HWND    hwndOwner,
    IN PBLINK* pLink,
    IN BOOL    fShowProprietary )

    /* Popup the ISDN device configuration dialog.  'HwndOwner' is the owner
    ** of the dialog.  'PLink' is the link to edit.  'FShowProprietary'
    ** indicates the old proprietary Digiboard options should be shown.
    **
    ** Returns true if user pressed OK and succeeded, false if user pressed
    ** Cancel or encountered an error.
    */
{
    int    nStatus;
    ICARGS args;

    TRACE("IsdnConfigureDlg");

    args.fShowProprietary = fShowProprietary;
    args.pLink = pLink;

    nStatus =
        (BOOL )DialogBoxParam(
            g_hinstDll,
            (fShowProprietary)
                ? MAKEINTRESOURCE( DID_IC_IsdnConfigure )
                : MAKEINTRESOURCE( DID_IC_IsdnConfigureMlink ),
            hwndOwner,
            IcDlgProc,
            (LPARAM )&args );

    if (nStatus == -1)
    {
        ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
        nStatus = FALSE;
    }

    return (BOOL )nStatus;
}


BOOL CALLBACK
IcDlgProc(
    IN HWND   hwnd,
    IN UINT   unMsg,
    IN WPARAM wparam,
    IN LPARAM lparam )

    /* DialogProc callback for the ISDN Configure dialog.  Parameters and
    ** return value are as described for standard windows 'DialogProc's.
    */
{
#if 0
    TRACE4("IcDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
           (DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam);
#endif

    switch (unMsg)
    {
        case WM_INITDIALOG:
            return IcInit( hwnd, (ICARGS* )lparam );

        case WM_HELP:
        case WM_CONTEXTMENU:
            ContextHelp( g_adwIcHelp, hwnd, unMsg, wparam, lparam );
            break;

        case WM_COMMAND:
        {
            return IcCommand(
                hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
        }

        case WM_DESTROY:
        {
            IcTerm( hwnd );
            break;
        }
    }

    return FALSE;
}


BOOL
IcCommand(
    IN HWND hwnd,
    IN WORD wNotification,
    IN WORD wId,
    IN HWND hwndCtrl )

    /* Called on WM_COMMAND.  'Hwnd' is the dialog window.  'WNotification' is
    ** the notification code of the command.  'wId' is the control/menu
    ** identifier of the command.  'HwndCtrl' is the control window handle of
    ** the command.
    **
    ** Returns true if processed message, false otherwise.
    */
{
    DWORD dwErr;

    TRACE3("IcCommand(n=%d,i=%d,c=$%x)",
        (DWORD)wNotification,(DWORD)wId,(DWORD)hwndCtrl);

    switch (wId)
    {
        case CID_IC_CB_DownLevel:
        {
            if (wNotification == BN_CLICKED)
            {
                BOOL    fCheck;
                ICINFO* pInfo;

                pInfo = (ICINFO* )GetWindowLong( hwnd, DWL_USER );
                ASSERT(pInfo);

                if (pInfo->pArgs->fShowProprietary)
                {
                    fCheck = Button_GetCheck( pInfo->hwndCbProprietary );

                    EnableWindow( pInfo->hwndCbCompression, fCheck );
                    EnableWindow( pInfo->hwndStChannels, fCheck );
                    EnableWindow( pInfo->hwndEbChannels, fCheck );
                    EnableWindow( pInfo->hwndUdChannels, fCheck );
                }
            }
            return TRUE;
        }

        case IDOK:
        {
            ICINFO* pInfo;
            INT     iSel;

            TRACE("OK pressed");

            pInfo = (ICINFO* )GetWindowLong( hwnd, DWL_USER );
            ASSERT(pInfo);

            iSel = ComboBox_GetCurSel( pInfo->hwndLbLineType );
            if (iSel >= 0)
                pInfo->pArgs->pLink->lLineType = iSel;

            pInfo->pArgs->pLink->fFallback =
                Button_GetCheck( pInfo->hwndCbFallback );

            pInfo->pArgs->pLink->fProprietaryIsdn =
                Button_GetCheck( pInfo->hwndCbProprietary );

            if (pInfo->pArgs->fShowProprietary)
            {
                BOOL f;
                UINT unValue;

                pInfo->pArgs->pLink->fCompression =
                    Button_GetCheck( pInfo->hwndCbCompression );

                unValue = GetDlgItemInt(
                    pInfo->hwndDlg, CID_IC_EB_Channels, &f, FALSE );
                if (f && unValue >= 1 && unValue <= 999999999)
                    pInfo->pArgs->pLink->lChannels = unValue;
            }

            EndDialog( pInfo->hwndDlg, TRUE );
            return TRUE;
        }

        case IDCANCEL:
        {
            TRACE("Cancel pressed");
            EndDialog( hwnd, FALSE );
            return TRUE;
        }
    }

    return FALSE;
}


BOOL
IcInit(
    IN HWND    hwndDlg,
    IN ICARGS* pArgs )

    /* Called on WM_INITDIALOG.  'hwndDlg' is the handle of the owning window.
    ** 'PArgs' is the caller's stub API arguments.
    **
    ** Return false if focus was set, true otherwise, i.e. as defined for
    ** WM_INITDIALOG.
    */
{
    DWORD   dwErr;
    ICINFO* pInfo;

    TRACE("IcInit");

    /* Allocate the dialog context block.  Initialize minimally for proper
    ** cleanup, then attach to the dialog window.
    */
    {
        pInfo = Malloc( sizeof(*pInfo) );
        if (!pInfo)
        {
            ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL );
            EndDialog( hwndDlg, FALSE );
            return TRUE;
        }

        ZeroMemory( pInfo, sizeof(*pInfo) );
        pInfo->pArgs = pArgs;
        pInfo->hwndDlg = hwndDlg;

        SetWindowLong( hwndDlg, DWL_USER, (LONG )pInfo );
        TRACE("Context set");
    }

    pInfo->hwndLbLineType = GetDlgItem( hwndDlg, CID_IC_LB_LineType );
    ASSERT(pInfo->hwndLbLineType);
    pInfo->hwndCbFallback = GetDlgItem( hwndDlg, CID_IC_CB_Fallback );
    ASSERT(pInfo->hwndCbFallback);
    if (pArgs->fShowProprietary)
    {
        pInfo->hwndCbProprietary = GetDlgItem( hwndDlg, CID_IC_CB_DownLevel );
        ASSERT(pInfo->hwndCbProprietary);
        pInfo->hwndCbCompression = GetDlgItem( hwndDlg, CID_IC_CB_Compression );
        ASSERT(pInfo->hwndCbCompression);
        pInfo->hwndStChannels = GetDlgItem( hwndDlg, CID_IC_ST_Channels );
        ASSERT(pInfo->hwndStChannels);
        pInfo->hwndEbChannels = GetDlgItem( hwndDlg, CID_IC_EB_Channels );
        ASSERT(pInfo->hwndEbChannels);
    }

    /* Initialize fields.
    */
    ComboBox_AddItemFromId( g_hinstDll, pInfo->hwndLbLineType,
        SID_IsdnLineType0, NULL );
    ComboBox_AddItemFromId( g_hinstDll, pInfo->hwndLbLineType,
        SID_IsdnLineType1, NULL );
    ComboBox_AddItemFromId( g_hinstDll, pInfo->hwndLbLineType,
        SID_IsdnLineType2, NULL );
    ComboBox_SetCurSel( pInfo->hwndLbLineType, pArgs->pLink->lLineType );

    Button_SetCheck( pInfo->hwndCbFallback, pArgs->pLink->fFallback );

    if (pArgs->fShowProprietary)
    {
        /* Send click to triggle window enable update.
        */
        Button_SetCheck( pInfo->hwndCbProprietary,
            !pArgs->pLink->fProprietaryIsdn );
        SendMessage( pInfo->hwndCbProprietary, BM_CLICK, 0, 0 );

        Button_SetCheck( pInfo->hwndCbCompression, pArgs->pLink->fCompression );

        pInfo->hwndUdChannels = CreateUpDownControl(
            WS_CHILD + WS_VISIBLE + WS_BORDER +
                UDS_SETBUDDYINT + UDS_ALIGNRIGHT + UDS_NOTHOUSANDS +
                UDS_ARROWKEYS,
            0, 0, 0, 0, hwndDlg, 100, g_hinstDll, pInfo->hwndEbChannels,
            UD_MAXVAL, 1, 0 );
        ASSERT(pInfo->hwndUdChannels);
        Edit_LimitText( pInfo->hwndEbChannels, 9 );
        SetDlgItemInt( hwndDlg, CID_IC_EB_Channels,
            pArgs->pLink->lChannels, FALSE );
    }

    /* Position the dialog centered on the owner window.
    */
    CenterWindow( hwndDlg, GetParent( hwndDlg ) );

    /* Add context help button to title bar.  Dlgedit.exe doesn't currently
    ** support this at resource edit time.  When that's fixed set
    ** DS_CONTEXTHELP there and remove this call.
    */
    AddContextHelpButton( hwndDlg );

    return TRUE;
}


VOID
IcTerm(
    IN HWND hwndDlg )

    /* Dialog termination.  Releases the context block.  'HwndDlg' is the
    ** handle of a dialog.
    */
{
    ICINFO* pInfo;

    TRACE("IcTerm");

    pInfo = (ICINFO* )GetWindowLong( hwndDlg, DWL_USER );
    if (pInfo)
    {
        Free( pInfo );
        TRACE("Context freed");
    }
}


/*----------------------------------------------------------------------------
** Modem configuration dialog
** Listed alphabetically following stub API and dialog proc
**----------------------------------------------------------------------------
*/

BOOL
ModemConfigureDlg(
    IN HWND    hwndOwner,
    IN PBLINK* pLink )

    /* Popup the modem configuration dialog.  'HwndOwner' is the owner of the
    ** dialog.  'PLink' is the link to edit.
    **
    ** Returns true if user pressed OK and succeeded, false if user pressed
    ** Cancel or encountered an error.
    */
{
    int nStatus;

    TRACE("ModemConfigureDlg");

    nStatus =
        (BOOL )DialogBoxParam(
            g_hinstDll,
            (pLink->pbport.fMxsModemPort)
                ? MAKEINTRESOURCE( DID_MC_MxsModemConfigure )
                : MAKEINTRESOURCE( DID_MC_UniModemConfigure ),
            hwndOwner,
            McDlgProc,
            (LPARAM )pLink );

    if (nStatus == -1)
    {
        ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
        nStatus = FALSE;
    }

    return (BOOL )nStatus;
}


BOOL CALLBACK
McDlgProc(
    IN HWND   hwnd,
    IN UINT   unMsg,
    IN WPARAM wparam,
    IN LPARAM lparam )

    /* DialogProc callback for the Modem Settings dialog.  Parameters and
    ** return value are as described for standard windows 'DialogProc's.
    */
{
#if 0
    TRACE4("McDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
           (DWORD)hwnd,(DWORD)unMsg,(DWORD)wparam,(DWORD)lparam);
#endif

    switch (unMsg)
    {
        case WM_INITDIALOG:
            return McInit( hwnd, (PBLINK* )lparam );

        case WM_HELP:
        case WM_CONTEXTMENU:
            ContextHelp( g_adwMcHelp, hwnd, unMsg, wparam, lparam );
            break;

        case WM_COMMAND:
        {
            return McCommand(
                hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
        }

        case WM_DESTROY:
        {
            McTerm( hwnd );
            break;
        }
    }

    return FALSE;
}


BOOL
McCommand(
    IN HWND hwnd,
    IN WORD wNotification,
    IN WORD wId,
    IN HWND hwndCtrl )

    /* Called on WM_COMMAND.  'Hwnd' is the dialog window.  'WNotification' is
    ** the notification code of the command.  'wId' is the control/menu
    ** identifier of the command.  'HwndCtrl' is the control window handle of
    ** the command.
    **
    ** Returns true if processed message, false otherwise.
    */
{
    DWORD dwErr;

    TRACE3("McCommand(n=%d,i=%d,c=$%x)",
        (DWORD)wNotification,(DWORD)wId,(DWORD)hwndCtrl);

    switch (wId)
    {
        case CID_MC_CB_FlowControl:
        {
            if (wNotification == BN_CLICKED)
            {
                MCINFO* pInfo = (MCINFO* )GetWindowLong( hwnd, DWL_USER );
                ASSERT(pInfo);

                if (!Button_GetCheck( pInfo->hwndCbHwFlow ))
                {
                    Button_SetCheck( pInfo->hwndCbEc, FALSE );
                    Button_SetCheck( pInfo->hwndCbEcc, FALSE );
                }
                return TRUE;
            }
            break;
        }

        case CID_MC_CB_ErrorControl:
        {
            if (wNotification == BN_CLICKED)
            {
                MCINFO* pInfo = (MCINFO* )GetWindowLong( hwnd, DWL_USER );
                ASSERT(pInfo);

                if (Button_GetCheck( pInfo->hwndCbEc ))
                    Button_SetCheck( pInfo->hwndCbHwFlow, TRUE );
                else
                    Button_SetCheck( pInfo->hwndCbEcc, FALSE );
                return TRUE;
            }
            break;
        }

        case CID_MC_CB_Compression:
        {
            if (wNotification == BN_CLICKED)
            {
                MCINFO* pInfo = (MCINFO* )GetWindowLong( hwnd, DWL_USER );
                ASSERT(pInfo);

                if (Button_GetCheck( pInfo->hwndCbEcc ))
                {
                    Button_SetCheck( pInfo->hwndCbHwFlow, TRUE );
                    Button_SetCheck( pInfo->hwndCbEc, TRUE );
                }
                return TRUE;
            }
            break;
        }

        case IDOK:
        {
            MCINFO* pInfo;
            PBLINK* pLink;
            PBPORT* pPort;
            INT     iSel;
            DWORD   dwBps;

            TRACE("OK pressed");

            pInfo = (MCINFO* )GetWindowLong( hwnd, DWL_USER );
            ASSERT(pInfo);

            pLink = pInfo->pLink;
            pPort = &pLink->pbport;

            iSel = ComboBox_GetCurSel( pInfo->hwndLbBps );
            dwBps = ComboBox_GetItemData( pInfo->hwndLbBps, iSel );

            if (!Button_GetCheck( pInfo->hwndCbHwFlow ))
            {
                if (pPort->fMxsModemPort
                    && dwBps > pPort->dwMaxCarrierBps)
                {
                    MSGARGS msgargs;
                    TCHAR   szBuf[ MAXLTOTLEN + 1 ];

                    LToT( pPort->dwMaxCarrierBps, szBuf, 10 );
                    ZeroMemory( &msgargs, sizeof(msgargs) );
                    msgargs.dwFlags = MB_ICONWARNING + MB_YESNO;
                    msgargs.apszArgs[ 0 ] = szBuf;
                    msgargs.apszArgs[ 1 ] = NULL;

                    if (MsgDlg( hwnd, SID_BpsWithNoHwFlow, &msgargs ) == IDYES)
                    {
                        /* User chose to lower port speed to maximum
                        ** recommended value.
                        */
                        dwBps = pPort->dwMaxCarrierBps;
                    }
                }
            }

            pLink->dwBps = dwBps;
            pLink->fHwFlow = Button_GetCheck( pInfo->hwndCbHwFlow );
            pLink->fEc = Button_GetCheck( pInfo->hwndCbEc );
            pLink->fEcc = Button_GetCheck( pInfo->hwndCbEcc );
            pLink->fSpeaker = !Button_GetCheck( pInfo->hwndCbDisableSpeaker );

            if (pLink->pbport.fMxsModemPort)
                pLink->fManualDial = Button_GetCheck( pInfo->hwndCbManualDial );

            EndDialog( pInfo->hwndDlg, TRUE );
            return TRUE;
        }

        case IDCANCEL:
        {
            TRACE("Cancel pressed");
            EndDialog( hwnd, FALSE );
            return TRUE;
        }
    }

    return FALSE;
}


BOOL
McInit(
    IN HWND    hwndDlg,
    IN PBLINK* pLink )

    /* Called on WM_INITDIALOG.  'hwndDlg' is the handle of the owning window.
    ** 'PLink' is the link information to be edited.
    **
    ** Return false if focus was set, true otherwise, i.e. as defined for
    ** WM_INITDIALOG.
    */
{
    DWORD   dwErr;
    MCINFO* pInfo;
    PBPORT* pPort;

    TRACE("McInit");

    /* Allocate the dialog context block.  Initialize minimally for proper
    ** cleanup, then attach to the dialog window.
    */
    {
        pInfo = Malloc( sizeof(*pInfo) );
        if (!pInfo)
        {
            ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL );
            EndDialog( hwndDlg, FALSE );
            return TRUE;
        }

        ZeroMemory( pInfo, sizeof(*pInfo) );
        pInfo->pLink = pLink;
        pInfo->hwndDlg = hwndDlg;

        SetWindowLong( hwndDlg, DWL_USER, (LONG )pInfo );
        TRACE("Context set");
    }

    pInfo->hwndEbModemValue = GetDlgItem( hwndDlg, CID_MC_EB_ModemValue );
    ASSERT(pInfo->hwndEbModemValue);
    pInfo->hwndLbBps = GetDlgItem( hwndDlg, CID_MC_LB_InitialBps );
    ASSERT(pInfo->hwndLbBps);
    pInfo->hwndCbHwFlow = GetDlgItem( hwndDlg, CID_MC_CB_FlowControl );
    ASSERT(pInfo->hwndCbHwFlow);
    pInfo->hwndCbEc = GetDlgItem( hwndDlg, CID_MC_CB_ErrorControl );
    ASSERT(pInfo->hwndCbEc);
    pInfo->hwndCbEcc = GetDlgItem( hwndDlg, CID_MC_CB_Compression );
    ASSERT(pInfo->hwndCbEcc);
    pInfo->hwndCbDisableSpeaker = GetDlgItem( hwndDlg, CID_MC_CB_DisableSpeaker );
    ASSERT(pInfo->hwndCbDisableSpeaker);

    Button_SetCheck( pInfo->hwndCbHwFlow, pLink->fHwFlow );
    Button_SetCheck( pInfo->hwndCbEc, pLink->fEc );
    Button_SetCheck( pInfo->hwndCbEcc, pLink->fEcc );
    Button_SetCheck( pInfo->hwndCbDisableSpeaker, !pLink->fSpeaker );

    pPort = &pLink->pbport;

    if (pPort->fMxsModemPort)
    {
        pInfo->hwndCbManualDial = GetDlgItem( hwndDlg, CID_MC_CB_ManualDial );
        ASSERT(pInfo->hwndCbManualDial);
        Button_SetCheck( pInfo->hwndCbManualDial, pLink->fManualDial );
    }

    /* Fill in the modem name.
    */
    {
        TCHAR* psz;
        psz = DisplayPszFromDeviceAndPort( pPort->pszDevice, pPort->pszPort );
        if (psz)
        {
            SetWindowText( pInfo->hwndEbModemValue, psz );
            Free( psz );
        }
    }

    /* Fill in the BPS list.
    */
    {
        TCHAR  szBps[ MAXLTOTLEN + 1 ];
        DWORD* pdwBps;
        INT    i;

        static DWORD adwBps[] =
        {
            1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200,
            0
        };

        for (pdwBps = adwBps; *pdwBps; ++pdwBps)
        {
            LToT( *pdwBps, szBps, 10 );
            i = ComboBox_AddString( pInfo->hwndLbBps, szBps );
            ComboBox_SetItemData( pInfo->hwndLbBps, i, *pdwBps );
            if (*pdwBps == pLink->dwBps)
                ComboBox_SetCurSel( pInfo->hwndLbBps, i );
        }

        if (ComboBox_GetCurSel( pInfo->hwndLbBps ) < 0)
        {
            /* Entry lists an unknown BPS rate.  Add it to the end of the
            ** list.
            */
            TRACE("Irregular BPS");
            LToT( pLink->dwBps, szBps, 10 );
            i = ComboBox_AddString( pInfo->hwndLbBps, szBps );
            ComboBox_SetItemData( pInfo->hwndLbBps, i, pLink->dwBps );
            ComboBox_SetCurSel( pInfo->hwndLbBps, i );
        }
    }

    /* Position the dialog centered on the owner window.
    */
    CenterWindow( hwndDlg, GetParent( hwndDlg ) );

    /* Add context help button to title bar.  Dlgedit.exe doesn't currently
    ** support this at resource edit time.  When that's fixed set
    ** DS_CONTEXTHELP there and remove this call.
    */
    AddContextHelpButton( hwndDlg );

    return TRUE;
}


VOID
McTerm(
    IN HWND hwndDlg )

    /* Dialog termination.  Releases the context block.  'HwndDlg' is the
    ** handle of a dialog.
    */
{
    MCINFO* pInfo;

    TRACE("McTerm");

    pInfo = (MCINFO* )GetWindowLong( hwndDlg, DWL_USER );
    if (pInfo)
    {
        Free( pInfo );
        TRACE("Context freed");
    }
}
